Generic6DofConstraint motor problem at different unit scales
-
- Posts: 14
- Joined: Mon Feb 18, 2013 3:38 pm
Generic6DofConstraint motor problem at different unit scales
I need my physics simulations to work at a variety of different mass/distance scales. I am following the guidelines in this post (http://www.bulletphysics.org/mediawiki- ... _The_World), and in some others I have seen in the forum. This works well for contacts and constraint limits, but I am having a problem with the motor on the Generic6DofConstraint. When I am in the normal Kg/m range the motor works fine, but when I start going down the scale the motor begins having problems, and then quits being able to move the part at all. I am scaling the maximum force the motor can apply as well, but it seems as if something is limiting this value regardless of what I set. I created a demo for this and attached it. You should be able to unzip this into the bullet-2.82 folder. It is setup for vs2010. There is a #define SCALE_CM_DG at the top of the UnitScalingDemo.cpp that turns on the scaled values. It is on by default. When scaling is off the motor works great, when you turn scaling on the motor is essentially non-functional. It tries, but gravity overwhelms it even though I am setting the max motor force to a very large value. Does anyone have any experience with this and can point me to a way to overcome this problem, or is it a bug. I have been trying to step through the motor code to try and see why it is doing this, but so far have not been able to figure it out. I was hoping someone may have an idea.
You do not have the required permissions to view the files attached to this post.
-
- Posts: 43
- Joined: Sat May 26, 2012 1:09 am
Re: Generic6DofConstraint motor problem at different unit sc
Projected Gauss Seidel, which is used to solve the constraints, does not converge very quickly
so the resulting constraint force can be too low(or too high) if large forces/gravity are involved.
Try increasing the number of solver iterations (btDynamicsWorld::getSolverInfo().m_numIterations)
to 100-1000. Reducing the time step to around 1/300 seconds (the third parameter of stepSimulation())
should also help. In general, decreasing the time step by a larger amount should mean that the number
of solver iterations does not need to be increased as much.
so the resulting constraint force can be too low(or too high) if large forces/gravity are involved.
Try increasing the number of solver iterations (btDynamicsWorld::getSolverInfo().m_numIterations)
to 100-1000. Reducing the time step to around 1/300 seconds (the third parameter of stepSimulation())
should also help. In general, decreasing the time step by a larger amount should mean that the number
of solver iterations does not need to be increased as much.
-
- Posts: 14
- Joined: Mon Feb 18, 2013 3:38 pm
Re: Generic6DofConstraint motor problem at different unit sc
Thanks. You are correct that I forgot to scale down the timestep for the posted example. However, I was scaling it down for the real application. I did look into this more systematically though based on your feedback and it helped a little. By reducing the time step even more, and then playing with the substeps and supstep times I was able to get the motor to converge correctly. However, I had to reduce these to the point that the simulation is horrendously slow for it to work. I am trying to replace the vortex physics engine with bullet in my app, and there is a huge difference in the behavior of the two simulators on this same problem. The vortex motor is able to work correctly even at a large time step, whereas with Bullet I have to increase the substeps so much that it is significantly slower. I have no idea what motor model that vortex is actually using, but I assume it must not be using the same method as Bullet. Do you think this is just an inherent difference in the two models used? The odd thing is that the constraint limits appear to behave fine even at larger timesteps. Does anyone have any suggestions that may be able to help in this situation. I really need better performance than this. One idea I have begun looking into is the possibility of giving the motor an assist from a PID controller. While playing with this example I found that if I take the gravitation load away from the part being moved that the motor is able to produce the correct velocity even at very high dt. I was going to try and add a PID controller that would detect when the motor was running into trouble and add some torque to try and help it overcome the issue.
-
- Posts: 43
- Joined: Sat May 26, 2012 1:09 am
Re: Generic6DofConstraint motor problem at different unit sc
Before looking at the model, it would be best to make sure that the issue is not caused by
the solver or configuration.
For both physics engines, what time step is used?
How many solver iterations are needed to make the simulation stable?
How many rigid bodies and constraints are used?
What is the performance difference between Bullet and Vortex with those settings?
In my tests, the motor in the UnitScalingDemo is stable with a time step of 1/120 seconds
and 100 iterations when SCALE_CM_DG is defined. Of course, this result does not necessarily
scale to larger, more complex scenes. Bullet's DynamicControlDemo and RagdollDemo also show
issues with a gravity of -1000. Could you give an example of the time step and the number of
solver iterations needed for an acceptable result in either of these demos?
Edit:
Now that I think about it, isn't the unit for angular momentum kg * m^2 / s?
angular_momentum = inertia_tensor * angular_velocity
Where inertia_tensor is in units of kg * m^2 and angular_velocity is in units of (1 / s).
If so, then to convert kg * m^2 into dg * cm^2 it would be necessary to apply the conversion factors:
By default, the btCollisionShape can be considered to be created in units of meters, and the mass
parameter of btCollisionShape::calculateLocalInertia() in kilograms. In order to fix this, the result
from calculateLocalInertia() can be scaled by the factor above.
Alternatively, it is possible to create a second duplicate btCollisionShape with dimensions 100 times larger,
as 100 cm = 1 m, and scale the mass parameter of calculateLocalInertia by 10000, as 10000 dg = 1 kg.
(For reference, scaling the result from btCollisionShape::calculateLocalInertia() by a factor of 13-15x
seems to fix the motor issue.)
Edit 2:
Actually, please disregard most of the above post. I made a mistake in assuming that the input
is in meters and not centimeters. In any case it does seem to be related to the inertia though.
the solver or configuration.
For both physics engines, what time step is used?
How many solver iterations are needed to make the simulation stable?
How many rigid bodies and constraints are used?
What is the performance difference between Bullet and Vortex with those settings?
In my tests, the motor in the UnitScalingDemo is stable with a time step of 1/120 seconds
and 100 iterations when SCALE_CM_DG is defined. Of course, this result does not necessarily
scale to larger, more complex scenes. Bullet's DynamicControlDemo and RagdollDemo also show
issues with a gravity of -1000. Could you give an example of the time step and the number of
solver iterations needed for an acceptable result in either of these demos?
Edit:
Now that I think about it, isn't the unit for angular momentum kg * m^2 / s?
angular_momentum = inertia_tensor * angular_velocity
Where inertia_tensor is in units of kg * m^2 and angular_velocity is in units of (1 / s).
If so, then to convert kg * m^2 into dg * cm^2 it would be necessary to apply the conversion factors:
Code: Select all
10000 cm^2 = 1 m^2
10000 dg = 1 kg (decigram or decagram?)
1 kg * m^2 * (10000 cm^2 / 1 m^2) * (10000 dg / 1 kg) = 100 000 000 dg * cm^2
parameter of btCollisionShape::calculateLocalInertia() in kilograms. In order to fix this, the result
from calculateLocalInertia() can be scaled by the factor above.
Alternatively, it is possible to create a second duplicate btCollisionShape with dimensions 100 times larger,
as 100 cm = 1 m, and scale the mass parameter of calculateLocalInertia by 10000, as 10000 dg = 1 kg.
Code: Select all
btCollisionShape* collisionShape = new btSphereShape(radius); //Use this for collision
btCollisionShape* inertiaCalculationShape = new btSphereShape(radius*100.0); //Delete/discard after calculating the inertia
inertiaCalculationShape->calculateLocalInertia(mass*10000.0, ...);
seems to fix the motor issue.)
Edit 2:
Actually, please disregard most of the above post. I made a mistake in assuming that the input
is in meters and not centimeters. In any case it does seem to be related to the inertia though.
-
- Posts: 14
- Joined: Mon Feb 18, 2013 3:38 pm
Re: Generic6DofConstraint motor problem at different unit sc
Well, my idea to add a motor assist went bust. It worked fine when my some of my parts were frozen in my simple tests, but when I tried it on more complicated situations it just resulted in weird behaviors. This was for the hinge joint, the prismatic seemed to work fine with a motor assist under all occasions. However, this problem with the hinge joint may have been because I could not seem to actually apply torques to the bodies while the motor was running, so I was trying apply forces. For some reason while the motor was active all of the torques I tried to apply seemed to be simply ignored or written over. When the motor was off my torques produced the expected behaviors. If I could have done this then it may have worked.
I am a little confused by your last post. If I setup my mass and volumes correctly for the unit scale values that I am using then should not the inertia tensor be calculated correctly? If I arbitrarily scale it then it will no longer match the physics I want, unless I am missing something?
Thanks
David
I am a little confused by your last post. If I setup my mass and volumes correctly for the unit scale values that I am using then should not the inertia tensor be calculated correctly? If I arbitrarily scale it then it will no longer match the physics I want, unless I am missing something?
Thanks
David
-
- Posts: 463
- Joined: Fri Nov 30, 2012 4:50 am
Re: Generic6DofConstraint motor problem at different unit sc
1) Bullet will need to have motor strengths scaled differently than just 1:1 scaling if you use the PGS solver
2) Hinge motors need both high FPS and high joint iterations to function correctly. If you have fairly weak motors, use something like 300fps and 500 iterations and work down from there (or up)
3) Try using featherstone (multibody) or MLCP solver, they work wonders with motor joints. I was able to drop calculation costs by ten by simply using MLCP with lower frame-rates, and accuracy actually increased.
Motor PID works just fine if you do the above, I have a simulation of three motors that approximate Dynamixel AX-12 motors to within 5% even above their maximum loading specs (i.e. they stop moving when the real one stops, same backlash, even contoller latency and resolution). You can have as complicated a controller as you want, and bullet seems to take it in stride. Just remember motors are controlled by velocity and torque rather than angles and torque, so if you use a PID on top of the position controller you'll have to deal with with the side-effects.
2) Hinge motors need both high FPS and high joint iterations to function correctly. If you have fairly weak motors, use something like 300fps and 500 iterations and work down from there (or up)
3) Try using featherstone (multibody) or MLCP solver, they work wonders with motor joints. I was able to drop calculation costs by ten by simply using MLCP with lower frame-rates, and accuracy actually increased.
Motor PID works just fine if you do the above, I have a simulation of three motors that approximate Dynamixel AX-12 motors to within 5% even above their maximum loading specs (i.e. they stop moving when the real one stops, same backlash, even contoller latency and resolution). You can have as complicated a controller as you want, and bullet seems to take it in stride. Just remember motors are controlled by velocity and torque rather than angles and torque, so if you use a PID on top of the position controller you'll have to deal with with the side-effects.
-
- Posts: 14
- Joined: Mon Feb 18, 2013 3:38 pm
Re: Generic6DofConstraint motor problem at different unit sc
Do you have any example code I could look at for your motor model? What you are doing is very similar to what I am trying to produce. In fact, the Dynamixel is even the motor I am targeting. I tried to just cut out the bullet motor entirely and control it using my own PID controller but it simply blows up spectacularly when I try and run it. So I am obviously doing something wrong.
Also, what all is involved in switching out the solver. Is it simply a matter of changing the solver supplied to the dynamics world? Or is more involved? When 2.82 came out with featherstone I looked into this with the featherstone demo, but it appeared that it would require a lot of changes. It looked like it had entirely different world, body and joint definitions that were required throughout.
Also, what all is involved in switching out the solver. Is it simply a matter of changing the solver supplied to the dynamics world? Or is more involved? When 2.82 came out with featherstone I looked into this with the featherstone demo, but it appeared that it would require a lot of changes. It looked like it had entirely different world, body and joint definitions that were required throughout.
-
- Posts: 463
- Joined: Fri Nov 30, 2012 4:50 am
Re: Generic6DofConstraint motor problem at different unit sc
dcofer wrote:Do you have any example code I could look at for your motor model? What you are doing is very similar to what I am trying to produce. In fact, the Dynamixel is even the motor I am targeting. I tried to just cut out the bullet motor entirely and control it using my own PID controller but it simply blows up spectacularly when I try and run it. So I am obviously doing something wrong.
Unfortunately you'll have to wait until I have my papers published for in depth code (maybe a month or two until I have feedback on it), but I can give a few pointers:
1) Those motors have massive friction, and PID controllers will show stepping and simulation will go nuts if you don't deal with it.
2) You're going to want to use Dantzig solver or Featherstone, otherwise you're looking at some pretty high iteration counts on PGS for it to work.
3) Motor strength depends on framerate, once you pick a stable framerate don't change it unless you like recalibration
But yes, dynamixel servos tend to be the most simulated ones, and they are quite annoying to get right. You can apply a PID to them though, and they can work relatively well in simulation (3 motors @ 1~2kHz, faster than you can control them even without USB limitations)
Using MLCP requires exactly four lines of code:dcofer wrote:Also, what all is involved in switching out the solver. Is it simply a matter of changing the solver supplied to the dynamics world? Or is more involved? When 2.82 came out with featherstone I looked into this with the featherstone demo, but it appeared that it would require a lot of changes. It looked like it had entirely different world, body and joint definitions that were required throughout.
Code: Select all
#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
#include "BulletDynamics/MLCPSolvers/btMLCPSolver.h"
btDantzigSolver* mlcp = new btDantzigSolver();
m_solver = new btMLCPSolver(mlcp);
-
- Posts: 14
- Joined: Mon Feb 18, 2013 3:38 pm
Re: Generic6DofConstraint motor problem at different unit sc
I tried switching to the MLCP solver like you suggested, but it actually made my simulations much less stable and did not fix the motor problems. At the standard Kg/m unit scales it seemed to work fine, but at any other unit scale it did not work well. My parts fell through the floor, the constraints were all way more bouncy, and the motors were not able to move the parts. I tried looking through the source code a bit to see if there were some configuration options I might be able to play with, but I did not see anything obvious. So it looks like I am stuck with the sequential solver for the moment unless anyone has any ideas on why the MLCP is not working at different scales.
Please let me know when you are able to release some source code. I would like to look over your implementation to see what I am doing wrong on these things, and how you have modeled the motor. What are your papers about? If it is related to modeling of motors then it maybe something I am interested in reading.
Thanks for your help
David
Please let me know when you are able to release some source code. I would like to look over your implementation to see what I am doing wrong on these things, and how you have modeled the motor. What are your papers about? If it is related to modeling of motors then it maybe something I am interested in reading.
Thanks for your help
David
-
- Posts: 463
- Joined: Fri Nov 30, 2012 4:50 am
Re: Generic6DofConstraint motor problem at different unit sc
Modeling and control for use in snake and quadruped robots, unfortunately it will take a bit. I'll send you a PM when I get the OK.dcofer wrote:Please let me know when you are able to release some source code. I would like to look over your implementation to see what I am doing wrong on these things, and how you have modeled the motor. What are your papers about? If it is related to modeling of motors then it maybe something I am interested in reading.
Are you sure you are using higher simulation rates? Sounds like you are stuck at 1/60 rather than 1/300 or so. You'll also have to recalibrate the motor strength, but in general just multiply by the fps change.dcofer wrote:My parts fell through the floor, the constraints were all way more bouncy, and the motors were not able to move the parts.