pid_controller
It is generally not recommended to move a rigid-body by setting its pose directly: teleporting it would ignore every obstacle on the way. The recommended alternative is generally to push it with a force (or an impulse) that is strong enough to reach the target. However, pushing with a single constant force/impulse will generally overshoot the target. Thus, ideally, the force or impulse should be carefully selected and updated each frame as the rigid-body gets closer to its target.
This is what a PID controller (Proportional-Integral-Derivative) is designed to calculate: given the target pose, it computes the ideal velocity change bringing the body closer to it. This is the building block of the velocity-based character controllers, but it is useful for anything that must follow a target without being teleported: a dynamic moving platform, an object held by the player, a following camera, etc.
The gains of the controller are what makes it reach its target quickly or smoothly. The proportional gain is applied to the position errors and is usually set to a multiple of the inverse of the timestep length (e.g. for a timestep of seconds). The derivative gain is applied to the velocity errors and is usually set in , where means no damping and means that the velocity errors are corrected within a single timestep.
The coordinate axes (linear and/or angular) controlled by the controller can be selected in order, for example, to only control the translations of a body while leaving its rotations to the simulation:
- Example 2D
- Example 3D
// The proportional, integral, and derivative gains of the controller, acting on the linear
// axes only: the body is pushed toward its target without its rotation being controlled.
let pid = world.createPidController(60.0, 0.0, 0.8, RAPIER.PidAxesMask.AllLin);
let target = { x: 3.0, y: 2.0 };
for (let k = 0; k < 200; ++k) {
// The correction is applied to the velocity of the rigid-body.
pid.applyLinearCorrection(body, target, { x: 0.0, y: 0.0 });
world.step();
}
// The proportional, integral, and derivative gains of the controller, acting on the linear
// axes only: the body is pushed toward its target without its rotation being controlled.
let pid = world.createPidController(60.0, 0.0, 0.8, RAPIER.PidAxesMask.AllLin);
let target = { x: 3.0, y: 2.0, z: 0.0 };
for (let k = 0; k < 200; ++k) {
// The correction is applied to the velocity of the rigid-body.
pid.applyLinearCorrection(body, target, { x: 0.0, y: 0.0, z: 0.0 });
world.step();
}