## Jacobian’s joint limits

When trying to physically simulate the Jacobian robot is necessary to know what are the servos maximum and minimum angle for each joint so that we don’t rely on the collision, easing the simulation (the physics simulator will still emulate collision as if the rotation axis had a mechanical limit).

The Robotis’ Bioloid kit we are using has AX-12 servos. These servos can return the current position of the servo on a given moment. To get the maximum and minimum angle of each joint, we simply adjusted the real servos to the extremes and sampled the position using the Bioloid’s CM5 default firmware and a serial terminal emulator on the PC.
The process of sampling the position is fairly simple, upon connecting the robot with the Boiloid software in the computer, the serial terminal allows interactive chat with the CM5. There is a unique ID to every servo on the bus. To change the servo ID context the command is “cid id”. Once in the servos’s scope inserting “read 36 2” will return two bytes: the first for the Low value and the second for the High value. This represents a range from 0 to 1023 which is mapped to 0º to 300º (See below). The values increase clockwise if moving the part and not the rotation cylinder, vice-versa if you are thinking in the perspective of the cylinder.

The sampled data for the Jacobian:

Right Leg:

```(Joint 1) CID 6    ->  166-821 (3*(768)+53)            48º633-240º527 (range 655 191º895 ~ 2x96º)
(Joint 2) CID 4    -> 209-866 (3*+98)                 61º230-256º347 (range 657 192º480 ~ 2x96º)
(Joint 3) CID 15  -> 416-875 (1*(256)+160)-(3*+107) 121º875-256º348 (range 459 134º473 ~ 2x67º)
(Joint 4) CID 17  -> 246-769 (3*+1)                  72º070-225º293 (range 523 153º223 ~ 2x76º5)
(Joint 5) CID 40  -> 000-613 (2*(512)+101)            0º000-179º590```

Left Leg:

```(Joint 6) CID 41     -> 753-1023(2*+241)-(3*+Null+65)  120º605-300º000
(Joint 7) CID 19    -> 270-764 (1*+14)-(2*+252)        79º102-223º828 (range 494 144º727 ~ 2x72º)
(Joint 8) CID 11    -> 157-601 (2*+89)                 45º996-176º074 (range 444 130º078 ~ 2x65º)
(Joint 9) CID 18    -> 174-797                         51º026-233º496 (range 623 182º520 ~ 2x91º)
(Joint 10) CID 14 -> 203-858                         59º472-251º367 (range 655 191º895 ~ 2x96º)```

Model Lying down values:

Right Leg:

```(1)   6 - (1*+244)         ~ 150º
(2)   4 - (1*+246)         ~ 150º
(3)  15 - (1*+246)         ~ 150º
(4)  17 - (2*+001)         ~ 150º
(5)  40 - (2*+001)         ~ 150º```

Left Leg:

```(6)  41 - (2*+001)         ~ 150º
(7)  19 - (2*+010)         ~ 150º
(8)  11 - (2*+004) 151º172 ~ 150º
(9)  18 - (1*+254)         ~ 150º
(10) 14 - (1*+252)         ~ 150º```

As you can see, the precision of this mechanism may not be great, however for the current purpose of applying some limits in the simulation this values are good enough. Also keep in mind that some positions (in our case the lying down position with 150º on all engines) should be easy to model in 3D (all aligned, parallel or perpendicular), because it will serve as our reference orientation in the simulation.

As previously mentioned, the servo only returns a valid position between 0º and 300º. This can be an issue, for instance, in the 40 and 41 servos we sampled. Although previous planing ensures that this servos can reach this positions it will not be necessary or desired.

This sampling lead to this approximate value:

To apply this limits to the PhysX representation of the model we use the joint object properties. In our case, we only need the NxD6Joint’s twist limit property, this property takes a high and a low value that represent the limit angles of twist. However, these values need to respect the following relation:

Hence, determining where the 0º angle is going to be is important. To place the 0º degree angle at the right place it is necessary to use the NxJoint local normal property. Modeling all the parts in the same axis will help to determine this values, please refer to the PhysX documentation on how these values should be set for they will be different depending on the way the models are built.

PhysX servo’s limit implementation:

```//It is predefined that all actors have the same axis
joint.localAxis[0] = joint.localAxis[1] = localAxis;
joint.localNormal[0] = joint.localNormal[1] = normalAxis;

joint.twistMotion = NX_D6JOINT_MOTION_LIMITED;
joint.twistLimit.high.value = highTwistLimit;
joint.twistLimit.low.value = lowTwistLimit;```