# [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
position.

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.

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?
>
>Thanks,
>Andy
>
>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
>>vertically.
>>
>>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.
>>>
>>>Thanks
>>>
>>>Gerald Boone
>>>
>>>------------------------------------------------------------------------
>>>
>>>_______________________________________________
>>>ODE mailing list
>>>ODE at q12.org
>>>http://q12.org/mailman/listinfo/ode
>>>
>>>
>>>
>>>
>>_______________________________________________
>>ODE mailing list
>>ODE at q12.org
>>http://q12.org/mailman/listinfo/ode
>>
>>
>>
>_______________________________________________
>ODE mailing list
>ODE at q12.org
>http://q12.org/mailman/listinfo/ode
>
>
>
>

```