The main objective of the tutorial is to implement a simple torque control inside a home-made contact simulator.
We are going to use a 4-finger hand, whose model is defined in Python (no urdf model) using capsule volumes. The code of the robot is available here. It needs a Display class wrapping the Gepetto-viewer client available here, and contains a Robot class implementing the robot hand and a simple example si available here.
Take care that the hand is small: zoom in to see it in the window (or press the space bar).
We will need a proper QP solver with inequality. QuadProg is a Python wrap of a nice Golub-based solver. Install it with PIP
QuadProg main function is solve_qp. You have a bit of documentation using the Python help command help(solve_qp). A simple example follows:
Choosing an arbitrary joint torque
The dynamic equation of the robot is
These terms correspond to the inverse dynamics. They can be numerically inverted to compute the direct dynamics.
Using
Once
In the particular case of only simple joints (like the robot hand), the same integration
Implement the simulation of the robot hand moving freely with constant (possibly 0) torques. Implement a variation where the torques are only joint friction (
Now choose a reference joint position (possibly time varying, like in the hand example). The joint torques can then be computed to track the desired position, with
Implement then simulate a PD, by compute the torques from a PD law, then integrate it using the simulator of question 2.
Here, there is a strong coupling between joints, due to the mass matrix that is not compensated in the simple PD law. In theory, the computed torques is to compute the joint torque by inverse dynamics from a reference joint acceleration. With boils down to canceling the simulation equation by choosing the proper terms in the control law. It is now very interesting to implement in case of perfect dynamics knowledge. It might be more interesting to study in case the simulation is done with the perfect M, while the control is computed with approximate M (for example, using only the diagonal terms of the mass matrix). Let's rather simulate contact.
The robot hand is composed of capsules, i.e. level-set of constant distance to a segment. Collision checking and distances are then easy to implement. The source code of collision checking is available in the robot_hand.py file. Pinocchio also implement a complete and efficient collision checking based on FCL, also not used in the tutorial.
Collision checking are done for a set of collision pairs that must be specified to the robot. The collision checking method indeed compute the distance between the two objects, along with the so-called witness points. A method can also be used to display them.
The Jacobian of the corresponding pair can be computed using the collisionJacobian method
The jacobian is a 1xN matrix (row matrix) corresponding to the contact normal. Take care that some information are stored in the visual objects when calling checkCollision, that are later used by collisionJacobian. You have to call collisionJacobian right after checkCollision, or the resulting jacobian might not be coherent.
For all collision pairs in contact (distance below 1e-3), the Jacobian must be collected and stacked in a single J matrix (which has as many rows as active constraints). Similarly, distances must be stacked in a vector (same number of rows as the jacobian).
Now, the joint acceleration is constrained by the contact constraint. It can be written as a minimization problem using Gauss principle
where
In theory, the acceleration should be above the "centrifugal" acceleration (i.e. the acceleration caused by joint velocity only, often written
In case of penetration or negative velocity, having only position acceleration is not enough. A "trick" is often to require the contact acceleration to be above a proportional depending of the penetration distance:
Implement a contact simulator using QuadProg, the results of Question 2 and the jacobian matrix of constraints whose distance is below 1e-3.
A better solution to avoid penetration is to implement an impact model. The simplest one is the inelastic impact, where normal velocity is simply canceled at impact. For that, remember inactive contact (i.e. those that were not in collision at previous simulation step). When a collision pair is detected that was not previously active, project the current velocity on the null space of all contacts:
The complete loop should be as follows: