I'm writing this issue request as a follow-up on this question on Gazebo Answers, which as I expected did not get any useful reactions as of yet (because I am all but certain it isn't possible).
Modeling a servo motor in Gazebo seems like a common task that should be made both possible and straightforward. A real-life servo typically specifies two properties:
- A maximum torque
- A maximum angular velocity
Having the ability to specify these two constraints in a stable manner therefore seems like a desirable property to me. Currently the only way to approach the behavior is by using PID controller, the performance of which depending on the type of servo and the load attached to it may range from good to very unstable. In my personal project, I've had a PID controller that would spin a joint at 1000% of its maximum angular velocity rating in a single (1/1000s) timestep applying only a fraction of the maximum torque. The same controller would not get the joint to move at all if something was leaning on it - even if the maximum torque would allow it to do so. The problem is that there is no way to enforce both constraints in the same timestep, meaning adaptations cannot be made until it is too late, or we end up specifying a way too small force initially to prevent it. Now I'm not saying that it is impossible to create a PID controller that would handle both these scenarios well, but it is very hard, and more importantly unnecessary when it is quite easy to achieve the functionality in separate physics engines.
ODE exposes a joint motor functionality through the combination of setting
dParamVel on a joint. Bullet Physics supports the same thing with
btHingeConstraint::enableAngularMotor(). AFAIK Dart has no direct mechanism for it, but it does allow you to write a stable controller by integrating one timestep ahead. I'm not sure about SimBody.
Currently, the joint motor functionality of ODE and Bullet is cleverly used to implement Coulomb joint friction (issue
#381, pull request #1221). When modeling a servo motor, this functionality is irrelevant: the friction will already be factored into the speed and torque ratings. I therefore propose exposing the joint motor functionality for at least Bullet and ODE, in which it is trivial to do so. It is currently possible to do this for ODE specifically by calling "Joint->SetParam("fmax", ...)" in conjunction with
Joint::SetParam("vel", ...), but as of aforementioned pull request it throws a warning, and it is obviously very engine specific and a very hacky way of doing things. For Bullet, there is no way to reach the functionality through the Gazebo API. I would very much like to see this exposed, even if it is only for the Bullet and ODE users.