Dynamics and Control
Dynamics
All force and torque acting on the system can be represented as a single vector in the generalized velocity space. This representation is called generalized force
We can also combine the mass and inertia of the whole articulated system and represent them in a single matrix. This matrix is called mass matrix or inertia matrix and denoted by
The total kinetic energy of the system is computed as getKineticEnergy().
The total potential energy due to the gravity is a sum of getPotentialEnergy(gravity). The gravity vector must be passed because only the world stores it (e.g., world.getGravity()).
The equation of motion of an articulated system is shown below:
Here
The following methods are used to obtain dynamic quantities
getMassMatrix()(it includes the rotor inertia on its diagonal)getNonlinearities(gravity)getInverseMassMatrix()(callgetMassMatrix()first)
Inverse Dynamics
RaiSim can compute inverse dynamics using the recursive Newton-Euler algorithm. It is the only option for computing the force and torque acting at joints. Joint force/torque are the sum of the constraint joint force/torque and actuation force/torque. For example, a revolute joint constrains motions in 5 degrees of freedom, which means that there are 5-dimensional constraint forces/torque and 1-dimensional joint actuation torque acting at a revolute joint.
In minimal coordinate simulation (such as RaiSim), these constraint forces/torques are not computed in the simulation loop. These forces/torques can be computed after a simulation loop using the inverse dynamics pipeline.
To enable inverse dynamics, call raisim::ArticulatedSystem::setComputeInverseDynamics(true). This flag is set automatically if the robot has an IMU sensor. Note that the inverse dynamics pipeline will slow down the simulation by about 10%.
After a simulation loop, you can call raisim::ArticulatedSystem::getForceAtJointInWorldFrame() and raisim::ArticulatedSystem::getTorqueAtJointInWorldFrame() to get forces and torques acting at the specified joint.
Assuming that there are no joint position/velocity limit forces acting at the joint, you can compute the joint actuation as a dot product of the joint axis and the joint torque. The inverse_dynamics example (Server Example: Inverse Dynamics) does this for ANYmal and compares the result with the applied generalized force.
PD Controller
When naively implemented, a PD controller can often make a robot unstable. However, this is often less problematic for robotics since this instability is also present in real systems (discrete-time control systems).
For other applications like animation and graphics, it is often desirable to have a PD controller that stays stable with a large time step. Therefore, the built-in PD controller is integrated implicitly and stays stable with much larger time steps and gains than a naive implementation.
The built-in PD torque and the feedforward generalized force are clamped together to the joint actuation limits (URDF effort or setActuationLimits()). Joint damping and actuator torques are added after this clamp and are not clipped by it. Because PD is integrated implicitly, the clamp bounds only its explicit part, and getGeneralizedForce() reports the applied PD torque only approximately (see Joint torque of a simulation step). The built-in PD torque is not an actuator torque, so the motor operating regions of actuators do not clip it (see Actuators below).
To use this PD controller, set the desired control gains first:
Eigen::VectorXd pGain(robot->getDOF()), dGain(robot->getDOF());
pGain<< ...; // set your proportional gain values here
dGain<< ...; // set your differential gain values here
robot->setPdGains(pGain, dGain);Note that the dimension of the pGain vector is the same as that of the generalized velocity NOT that of the coordinate. For a floating base, the first six gains are forced to zero. setPdGains() also switches the control mode to ControlMode::PD_PLUS_FEEDFORWARD_TORQUE.
Finally, the target position and the velocity can be set as follows:
Eigen::VectorXd pTarget(robot->getGeneralizedCoordinateDim()), vTarget(robot->getDOF());
pTarget<< ...; // set your position target
vTarget<< ...; // set your velocity target
robot->setPdTarget(pTarget, vTarget);Here, the dimension of the pTarget vector is the same as that of the generalized coordinate NOT that of the velocity. This can be confusing and may seem inconsistent. However, this is a valid convention. The only reason the two dimensions differ is the quaternion representation. The quaternion target is represented by a quaternion whereas the virtual spring stiffness between the two orientations can be represented by a 3D vector, which is composed of motions in each angular velocity components.
A feedforward force term can be added by setGeneralizedForce() if desired. This term is set to zero by default. Note that this value is stored in the class instance and does not change unless the user specifies it so. If this feedforward force should be applied for a single time step, set it to zero in the subsequent control loop (after the integrate() call of the world).
The theory of the implemented PD controller can be found in chapter 1.2 of this article. This document is intended for advanced users and is not required to use RaiSim.
Actuators
The URDF effort limit is a constant bound per joint on the feedforward generalized force plus the built-in PD torque; joint damping is passive and is not clipped. Actuator torques set with setActuatorTorque() or setActuatorTorques() are clipped separately, to the motor operating regions (MOR) of their motors, mapped to the joints (with their couplings), and added after the effort clamp. Effort limits do not clip actuator torques, and MOR does not clip setGeneralizedForce() or the built-in PD controller. The combined generalized force is not clamped again. To keep a PD controller inside the motor operating regions, compute its torques explicitly and send them with setActuatorTorques(). See Actuators.
Apply External Forces/Torques
The following two methods are used to apply external force and torque respectively
setExternalForcesetExternalTorque
You will find the above methods in the ArticulatedSystem API.
Joint torque of a simulation step
This section gives exactly what a simulation step of length
1. The command, clamped to the actuation limits.
setGeneralizedForce(), setPdGains(), and setPdTarget(). In the FORCE_AND_TORQUE control mode, effort or those of setActuationLimits(); a joint without them is not clamped.
2. The actuator torques. Take an actuator with the gear ratio setActuatorTorques() (see Actuators). Its motor has the stall torque
The actuator adds setMotorOperatingRegionEnforced(false),
3. The explicit torque. Everything evaluated at the beginning of the step is summed, and the sum is not clamped:
damping or setJointDamping(), see Joint Damping and Friction) and <dynamics stiffness spring_mount> or addSpring(), see getSprings()). setExternalForce(), setExternalTorque() and setConstraintForce(), mapped through their Jacobians.
4. The velocity. The PD gains, the damping and the springs are integrated implicitly: the diagonal getMassMatrix(), which includes the rotor inertia). With the nonlinear term getNonlinearities()), the articulated-body algorithm computes the velocity without contacts,
A position-limit impulse acts on a joint outside its range. A velocity-limit impulse acts on a joint whose entry of
5. The applied joint torque. With
The torque on the joints over the step is therefore, term by term:
| Source | Torque over the step |
|---|---|
| feedforward and PD | |
| damping | |
| actuators | |
| springs | |
| external forces | |
| joint friction | |
| contacts and joint limits | the rest of |
The friction impulse
Only the explicit part of the feedforward and PD torque is clamped. The implicit part is not, so the applied PD torque can exceed the actuation limits by
6. The position. The position is integrated with the average velocity setIntegrationScheme() (a quaternion with the same angular velocity):
| Integration scheme | |
|---|---|
SEMI_IMPLICIT (default) | |
TRAPEZOID | |
EULER |
The torque is the same for the three. SEMI_IMPLICIT moves the robot with the velocity the contact solver leaves, so a foot that an impact stops stays at the surface. TRAPEZOID follows a body under a constant force exactly (a thrown ball), but under forces that change with the state (gravity on a joint, springs, the PD torque, the gyroscopic force) it gains energy: an undamped pendulum's swing grows by about 9% in 20 s at SEMI_IMPLICIT keeps it within 0.1%. On an impact, TRAPEZOID also goes into the ground by up to half the step's travel. RUNGE_KUTTA_4 applies the velocity change of the contact solver at the beginning of the step and then evaluates steps 1-4 without contacts at each of its four stages, at the state of the stage; the actuator bounds use the motor speeds of the stage, and getActuatorStates() describes the last stage. In the PD control mode, SEMI_IMPLICIT replaces EULER and RUNGE_KUTTA_4 once the robot has been in contact (from the step after its first contact), until its state is set again with setState(), setGeneralizedCoordinate() or an applied solveIK() solution. SEMI_IMPLICIT also replaces RUNGE_KUTTA_4 while the robot has loop or mimic constraints, which are eliminated from the velocity of one step (see Closed-Loop Systems).
getGeneralizedForce() returns
Kinematic loops
An articulated system is simulated in the generalized coordinates of a kinematic tree. A loop constraint closes a loop of the tree again: it ties an anchor point on body1 to the coincident point on body2. A pin holds the two points together in all three directions. An equality constraint holds them together only along one or two axes fixed in body1; along the remaining directions the points slide freely. A mimic constraint couples two joint coordinates linearly. The three are handled in the same way. This section derives the dynamics with the equality constraint as the main case; Closed-Loop Systems describes how to model loops and how they behave, and Mimic Joints the mimic constraints. The symbols are those of Joint torque of a simulation step above.
The constraints are not iterated by the contact solver. In every step, each articulated system eliminates them exactly, before the contacts are solved:
- it takes the velocity
that the system would reach without them (step 4 above), - applies the one impulse that makes that velocity satisfy them, and
- replaces the response of everything else that acts on the system (contacts, joint limits, joint friction, tendons) by its response on the constrained mechanism.
The contact solver then works on a smaller problem whose every solution already satisfies the constraints.
Notation
| Symbol | Meaning |
|---|---|
| generalized coordinate and velocity of the tree ( | |
| the mass matrix, and the mass matrix with the implicit diagonal of step 4 | |
world positions of the anchor on body1 and on body2 | |
constrained unit axes of an equality constraint in the world frame. They are fixed in body1's frame | |
| velocity of the material point of body | |
| Jacobian of that point, | |
| all constraint rows stacked ( | |
| the rows and impulses of the contacts, the joint limits and the joint friction (step 4) | |
| the position errors of the rows | |
| the coupling of the rows (their inverse effective mass, the Delassus matrix of the constraints), | |
| the time step and the error-correction rate, |
The constraint and its rate
For each of its axes, the equality constraint requires
A pin uses three fixed world directions as its axes
The exact rate of an equality row. The step is solved for velocities, so each row needs the time derivative of its error, linear in the generalized velocity
- the axis: it is fixed in
body1, so it turns withbody1's angular velocity,; body1's anchor:is a material point of body1, so; body2's anchor:is a material point of body2, so.
One more fact is needed, the velocity field of a rigid body. The material point of body1 that currently sits at a world point
The product rule gives
. Inserting the three rates, the first term is the axis turning and the second the anchors moving:
Move
body1's velocity fromto . By the velocity field, , so term B splits into The scalar triple product is invariant under a cyclic permutation and changes sign when two factors are swapped, so the last term is
: term A with the opposite sign. Term A and the rest of term B cancel:
Nothing was approximated: the rate holds at every instant, however far the anchors have slid apart. An equality constraint with two axes has one such row per axis.
The same result, seen from body1. In body1's frame, body2's anchor relative to body1. That relative velocity is body2's velocity at the anchor minus the velocity of the point of body1 that coincides with it, body2's anchor stays on a plane (one axis) or a line (two axes) fixed in body1; what matters is how that anchor moves relative to body1, measured where the anchor is.
Body1's own anchor would give a wrong row. Evaluating body1 at its own anchor keeps only term B, body1's rotation: a 5 cm slide at 2 rad/s gives 0.1 m/s along the constrained axis. RaiSim uses the exact row above.
A pin. Its axes are fixed in the world, so
Where the force acts. By virtual work, a row
the point impulse body1 at body2 at the same point. The two are equal, opposite and collinear, so they apply no net force or torque to the system. They have no component along the free directions, and their power
Equations of motion of a step
With the constraint impulses
The constraints are imposed on the velocity at the end of the step, with the position error fed back:
As one linear system in
The impulses
Eliminating the constraints
1. The free velocity. Without any impulse, the velocity at the end of the step is
2. Solve the first block row for
3. Substitute it into the constraints (1). This leaves a system for
Its solution splits into a part that depends only on the free motion and a part induced by the other impulses:
4. Substitute
These are the reduced dynamics, in two parts:
is the free velocity moved onto the constraints; by construction, . Each step applies the impulse before the contacts are solved. Every other impulse acts through the inverse mass of the constrained mechanism,
whose response to an impulse is the unconstrained response minus its constrained part:
.
Three properties make this exact:
- No impulse can open a constraint.
, so for any . The constraints hold whatever the contact solver does and however many iterations it runs. - The contact problem keeps its form.
is symmetric and positive semidefinite. The contacts' apparent inverse inertia becomes : the same kind of quantity as without constraints, only smaller, because the closed mechanism is stiffer. - The constraint impulse is still known. Equation (2) gives
once the solver has found ; this is the impulse reported for each constraint (see Reading constraint forces).
In short, RaiSim solves the KKT system by block elimination: it eliminates
If the rows of
Why these are the reduced dynamics
Constrained dynamics can equivalently be written in coordinates of the allowed motion. Let the columns of
Both sides map a generalized impulse along the constraints,
The right-hand form needs only
Integration Steps
Integration of an articulated system is performed in two stages: integrate1 and integrate2.
The following steps are performed in integrate1
- If the time step, the control mode, the PD gains, the damping or the springs changed, update the diagonal
added to the mass matrix (the effective inertia of the implicit springs, dampers and PD gains) - Update positions of the collision bodies
- Detect collisions (called by the world instance)
- The world assigns contacts on each object and computes the contact normal
- Compute the mass matrix, nonlinear term, and inverse inertia matrix
- Compute (Sparse) Jacobians of contacts
After this step, all kinematic/dynamic properties are computed. Users can access them if they are necessary for the controller. Next, integrate2 computes the rest of the simulation.
- If the controller changed the control mode, the PD gains, the damping or the springs after
integrate1, updateas in step 1, then compute contact properties - Compute the PD torque (if used), add the feedforward generalized force, clamp this sum to the joint effort limits, and add the joint damping (never clipped, see Joint Damping and Friction)
- Clip the actuator torques to the motor operating regions, map them to the joints and add them; then add the springs and the external forces/torques, and compute the velocity without contacts
- Contact solver (called by the world instance). It also solves the joint limits and the joint friction
- Integrate the velocity
- Integrate the position with the integration scheme
Steps 8-12 are written out exactly in Joint torque of a simulation step.