# Human Joint Limits

## Introduction

This code is the implementation of [_Data-Driven Approach to Simulating Realistic Human Joint Constraints_][1].

This example program sets realistic human joint limits to a simulated human agent, so that the agent’s movements under laws of physics will never exceed human range of motion.

Specifically, naively setting upper and lower bounds for each DoF is far from accurate for simulating our four limbs. (For example, our elbow has a smaller range when the arm is behind the torso.) We thus represent the joint limit constraints for the limbs in more general, mutual-dependent forms C_{arm}(q_arm) > 0.5 and C_{leg}(q_leg) > 0.5, where q is the joint configuration for the whole limb. (For the arm excluding the hand, we consider q_arm as 3DoF in shoulder plus 1DoF in elbow; for the leg, q_leg is 3DoF in hip, 1DoF in knee and 2DoF in ankle.) Just like how upper/lower bounds are handled in DART, when C(q) is about to decrease below 0.5 at next time step, a constraint force in dC/dq direction is generated by LCP solver to push q back to valid region.

The C(q) functions are trained neural nets from real human data. In this way, we do not need to use sophisticated biomechanics models, and both C(q) and dC/dq can be quickly evaluated through forward evaluation and back-propagation of the neural nets.

The code for training neural nets is [here][2].

## Implementation details 

1. The neural nets are trained specific to a certain joint configuration space. In the .skel file, one should not modify the axis orders for shoulder/hip Euler joints, or the rest poses defining q=0, unless one wants to modify the training code and retrain the neural nets as well.

    Specifically, the axis order for all Euler joints are set to zxy. The rest pose is almost defined the same as the usual human rest pose, except for the shoulder rotation - for humans, if you start to bend your elbow from rest pose, your lower arm will start to move to the other side of torso besides lifting up. In our model, however, rest position for shoulder rotation in defined such that when bending elbow, the agent’s lower up will only lift up, while keeping perpendicular to the torso plane.

2. There are only two trained neural nets for the left arm and leg respectively. For right arm and leg, we just mirror the q values before feeding them into neural nets. For users, one just need to turn on an additional isMirror flag when specifying a right limb joint-limit constraint.

3. The "left" and "right" are defined from the perspective of the agent itself.

4. We do not directly input the q values into neural nets, instead, we input sin(q) and cos(q). As such, the trained functions still work when q exceeds 2pi range.

5. We still define some naive upper and lower bounds in the .skel file to exclude clearly infeasible poses. Be sure to make them in effect in your code by applying joint->setPositionLimitEnforced(true); to each joint.

For more details, please refer to the [paper][1].

## Installation

This project is dependent on DART. Please make sure a proper version of DART is installed before building this project.

### Build Instructions

From this directory:

    $ mkdir build
    $ cd build
    $ cmake ..
    $ make

### Execute Instructions

Launch the executable from the build directory above:

    $ ./humanJointLimits

Follow the instructions detailed in the console.

## Author

Yifeng Jiang \<yjiang340@gatech.edu\>

[1]:https://arxiv.org/abs/1709.08685
[2]:https://github.com/jyf588/Human-Joint-Constraints-Training
