[ODE] Has anybody had any luck with dJointSetAMotorAngle?

Patrick McColgan patrick at torcinteractive.com
Mon Jan 31 16:33:11 MST 2005

I made an effort to try and document my findings with AMotors on this 
list as when I was working them out there seemed to be a lack of 
knowledge sharing yet a lot of people who wanted help.  I did get it to 
work although recently I've spotted a few things so I doubt I have them 
nailed to be honest.  I'll go over what I did again, hopefully clearing 
a few things up, then maybe if you have any luck with it you can come 
back with corrections, improvements or even a proper way to use them.

First things first rotate a cyclinder,  I do 90 degrees about the X 
axis.  This gives you your 'standing' position, what you have to 
remember now is that the cylinder's rotation  when you query it from ODE 
is off by this adjustment but you'll want to recognise this as its rest 

Initialise an AMotor between the cylinder and the world (i.e. nothing), 
so create an AMotor joint, attach it between the body and the world, 
then set the AMotorMode to Euler.  To start with a played with Euler 
mode, to try and see exactly what it did and give me an idea of what an 
Amotor could do and it was really helpful in understanding what I was 
dealing with.

You have to specify the AMotor axes.  Initially I wanted to constrain 
the body except for rotations about the y (technically by y I mean the 
cylinders z, due to the rotation to make it stand but I've transformed 
it now so I consider the cylinder's local axes to be parallel to the 
global axes) so I set 3 axes, relative to the world corresponding to 
arbitrary x, y and z axes.  I maybe only need to set 2 axes, for the two 
constrained dimensions but I was very tentative setting this up and 
didn't want to leave anything out, I'm trying to talk you through what I 
did hopefully you'll experiment and refine all this, I'd be very curious 
to hear any improvements and insights.  Next I call dJointSetAMotorAngle 
for each axes and set the angle to zero, perhaps it defaults to this at 
initialisation anyway, again I wasn't taking risks.

So hopefully now you have a cylinder standing on one of its capped ends, 
and you can think of it now as having it's local axes parallel to that 
of the standard world axes.

Now set the Motor joint parameters, there were some bugs with this but I 
believe they were fixed, for the X and Z axes I set the Hi and Lo stops 
to 0 and -0 (more than likely don't need the minus) and for the y axes I 
set dInfinity and -dInfinity.  This should mean that the AMotor will not 
allow any rotation about the x and z and free rotation about the y.  So 
ideally your cylinder will never fall over but spin happily around its 
'long' axes.

So in User mode the amotor is essentially done by  hand and its up to 
you to calculate the angles, you wonder how this will maintain the 
cylinder well you're welcome to look through the internals (check the 
amotor joint call inside the stepper) I'm pretty sure given the offsets 
and the limits ODE simply works out the any infringements and applies 
sufficient corrective torque (velocity) in the timestep to fix it.

So when the Amotor was set up and the axes defined, we were trying to 
say the local axes of the cylinder and those of the world were relative, 
what the amotor is going to do is take each of the cylinders local axes 
and compare it to the worlds (which should never change), it will use 
the difference in orientation (angle) to correct the cylinder via the 
amotor.  So get the rotation of the cylinder from ODE, it returns a 
matrix of rotations applied to the cylinder right?  Well yes, but we 
don't want that, if we use that the cylinder will be locked to the 
initial lying down position of the cylinder so first you have to 
concatenate the matrix with the rotation applied to stand it up.  Just 
remember the rotation you applied, build a rotation matrix for it and 
multiply the two, now you have the corrected rotation matrix.Using this 
take three vectors (representing arbitrary x, y and z axes) and 
transform these by the matrix, this gives the local x, y and z axes for 
the cylinder.  So now you have the local axes of the cylinder and you 
always have the world axes (static arbitrary unit vectors for the x, y 
and z) now you want to consider each dimension and work out the angular 
difference.  To do this, well how I do it probably not the best 
approach, is to flatten the cyclinder axes; in the case of the y axes 
for example set the x OR z coefficient to zero, the world axes will 
always be perfect 0 1 0 but there's a chance the amotor will exist in 
all three dimensions and I assumed the amotor rotation only really work 
in 2 dimensions.  I don't know if that's clear, I'm pretty sure that a 
post on here by Geoff Carlton recommended flattening them too, it based 
on the way I assume the AMotor corrects rotations and if the axes is 
active in 3 dimensions the angle will be bigger than it should be.  
After flattening it get the angle between this and the relative global 
axes (i.e. between the local y and global y), do this by a dot product, 
you'll have to do a winding order calculation to determine if its 
negative or not (do a cross product of the two axes, the direction of 
the vector formed will dictate the direction of the angle which may be 
negative).  Then set this as the amotor axes for the appropriate axes.  
Repeat for remaining axes.

Thats a bit long winded.  The best thing I can recommend if you have 
time is to experiment.  One thing I've found is that in updating the 
angle I don't need to update the x and z angles, but I haven't tested 
that fully.  I haven't looked to hard at the amotor recently but I may 
go back because just writing this I can see some avenues I neglected.

Good luck with it and please feel free to post your findings or ask more 
questions, hope it helped!

Andrew Schroeder wrote:

>In browsing the mailings I see that you seem to have figured out
>exaclty how to do what I've been trying (and failing) to do.  I want
>to have an aMotor that keeps a body upright like you talk about below,
>but I have some questions you can probably answer.
>When you say:
> > each frame I calculate the angular difference between the
>cylinder's local x, y
> > and z axes and the global x, y and z axes 
>How do you do that? I tried a few things but I have problems with
>gimbal lock and other issues.
>Also, you say: 
>>The differences I find between each (axis?) I set as new AMotor angles for the > corresponding AMotor axes.
>Does this mean you call setAMotorAngle again now with the newly
>rotated angle? If so, how does that serve to keep the cylinder upright
>as now ODE since all that call does is tell ode what the angle is?  I
>have been trying to use atan of the dot product to find the angle, and
>then setting the desired velocity of the motor to stand it upright but
>I'm having all kinds of problems with that.  Would you mind sharing
>more details on your appoach to this?
>On Mon, 24 Jan 2005 16:16:25 +0000, Patrick McColgan
><patrick at torcinteractive.com> wrote:
>>I finally (hopefully) have AMotors working the way I want so here's my
>>take on it:
>>setAMotorAngle is exclusively for User mode meaning that you are
>>completely responsible for updating the motor, as far as I can see you
>>aren't telling the amotor what the angle should be; you're informing it
>>of what it is.
>>I use an AMotor to stand a cylinder upright, normally the cylinder lies
>>along the z axis so what I do is first rotate the cylinder 90 degrees
>>about its local x axis and position it's bottom end on a surface.  Then
>>I set up the AMotor, I use 3 axis set as a unit vector along the global
>>x, y and z axis.  Then I call setAMotorAngle to initialise all the axis
>>to zero degrees, so in spite of ODE knowing that I have rotated the body
>>I have told the amotor that this upright cylinder is unrotated initially
>>with respect to the amotor.  Then each frame I calculate the angular
>>difference between the cylinder's local x, y and z axes and the global
>>x, y and z axes (as I use the internal rotational matrix of the body I
>>have to account for my initial rotation).  The differences I find
>>between each I set as new AMotor angles for the corresponding AMotor
>>axes.  And that's all I have to do, the motor maintains the cylinder
>>I hope that makes sense, as I say I finally have AMotors working the way
>>I want them.  But it wasn't easy.
>>Gerritt Brownlee wrote:
>>>I am trying to set the initial conditions of my motor.  It doesn't
>>>move the joint to any angle.
>>>If I can't get the setAMotorAngle to work I guess I will have to use
>>>quaternions to set the inital conditions.
>>>Please respond if you got this function to work.
>>>Gerald Boone
>>>ODE mailing list
>>>ODE at q12.org
>>ODE mailing list
>>ODE at q12.org
>ODE mailing list
>ODE at q12.org

More information about the ODE mailing list