shortest_angular_distance
helper function may be able to live upstream if useful for general cases
I've tried your patch and found it running smoothly. Nice work!
My simulation uses a hinge joint with possible values from
-2pi to +2pi (two complete rotations). The joint maintains its
position by having histop and lostop set to the same value,
which can be outside [-pi,pi]. With your patch, it works great,
without any extra hacks.
A little glitch though: dJointGetHingeAngle should return the
unwrapped angle (cumulative_angle), not the wrapped one.
with dJointGetHingeAngle returning unwrapped angle
Alex,
Thanks for the feedback, new patch has dJointGetHingeAngle() returning wrapped angle.
John
I'm using your patch since you posted it and did not found any stability problems, or other negative effects. The application is a robotic arm simulation; some joints have a range from -360 to +360, others have 0 ... 360. Thanks!
Before, I have tried to create a ContinuousHingeJoint class in PyODE to achieve the same effect, but it didn't work very well.
I really like this patch. It deserves, perhaps, to carry the caveat that if the relative orientation changes by more than PI in a single frame, the hinge will think it rotated the opposite direction; e.g., if both bodies rotate inward by just over .5PI over a single frame, the hinge will think they rotated outward by just under .5PI. But then again, if the bodies are spinning that fast, the simulation is probably going to be facing bigger problems than this.
In addition to inefficiencies in three angle operation functions at beginning the thing I don't like about this patch is that dJointGetHingeAngle() which is supposed to be a constant method by its name, alters value of joint's cumulaive_angle field.
Unwrapped joint angles also make it so that joints store dynamic information. Without them, all dynamic state is stored in the bodies and joint state is always computed directly from body state (except for AMotor angles in user mode, which are really ugly). If we're going to store dynamic data in joints, then it seems the right thing to do would be to `step' joints like we step bodies, rather than sticking the accumulation code into the getInfo() methods where it feels rather out-of-place.
Storing cumulative angle as a dReal introduces potential numeric problems. As the value grows larger, its ability to precisely represent the actual angle decreases. Granted, the joint may need to wrap a lot of time for this to be an issue, but it's easily possible in extended simulation. It might be better to use an integer count of the number of times wrapped.
Still, I like the idea of allowing joint angles to exceed +/- pi, if we could work through the issues.
I was saying that constant methods like dJointGetHingeAngle() must not modify object's fields. Otherwise it is potentially possible to call the same function twice in a row and get different results.
Thanks for the feedbacks, let me see if there are alternative ways of incorporating this functionality without breaking const-ness of dJointGetHingeAngle()
, and clean up the helper functions at the beginnning, possibly moving them into odemath.h
?
Just coding them more optimally would be enough. :)
Storing cumulative angle as a dReal introduces potential numeric problems. As the value grows larger, its ability to precisely represent the actual angle decreases.
Simple estimation reveals that with minimal precision of 0.001 radian (which is about 1/100 of angular minute) and 1000 hinge rotations per second the precision of double is sufficient to work for more than 35 thousand years.
Well, a bit more precise estimation ;) shows that the correct number in previous post was 285 years. But still, you should not probably be afraid to be sued for potential losses after your application works that long. ;)
[EDIT]
Well, with yet a bit more precise estimation ;) the value gets down to 45 years. This gets somewhat dangerously close to retirement age. How old are you, by the way?
Log in to post a comment.