Atan2 and object facing direction angle offset need.?

Started by
1 comment, last by ankhd 8 years, 7 months ago

Hey all.

I'm starting a small test app to test out atan2 to rotate object's facing directions. I normaly use the dotproduct and the cross to get a signed angle

to pass to a direct X rotateY axis, This works fine.

But I can not figure out how to do the same with atan2, I've tryed in the passed and just gave up and used the above method.

This time I googled all I could and tryed a number of post methods but am still unable to rotate the object to the correct direction.

Going by this link Wiki atan2.

For any real number (e.g., floating point) arguments x and y not both equal to zero, atan2(y, x) is the angle in radians between the positive x-axis of a plane and the point given by the coordinates (x, y) on it. The angle is positive for counter-clockwise angles (upper half-plane, y > 0), and negative for clockwise angles (lower half-plane, y < 0).

Using the following I was able to map out the quadrant.

.


Angle = atan2(y, x);
if(Angle < 0.0)
{
   --side;
}
else
{
   ++side;
}

That looks like this.

2DAtan2YX.jpg?psid=1

Going by that above. I have a object that starts at 3d(0,0,0) and it has 4 way points to move to

waypoint[0](-400,0,400)

waypoint[1](400,0,400)

waypoint[2](400,0,-400)

waypoint[3](-400,0,-400)

The tank has this facing direction.

TankZ.jpg?psid=1

.

Now the field is mapped out on the X, Z plane with Y+ up.

Depending on the direction if its post - target or target - pos as well as the params passed to atan2() Z,X, or X,Z

I get the following atan2 mapping.

.

TargetPosAtan2XZ.jpg?psid=1

.

TargetPosAtan2ZX.jpg?psid=1

.

PosTargetAtan2XZ.jpg?psid=1

.

PosTargetAtan2ZX.jpg?psid=1

.

Ive tryed adding 90° and - 90°, in fact Ive tryed all the ways the numerous post on the net have it layed out.

So what do I need to map my Z+ facing tank to atan2.

the following works but I would like to do the same as this with atan2.

.

D3DXVECTOR3 objfacing= D3DXVECTOR3(0.0, 0.0, 1.0);

D3DXVECTOR3 currentdir = m_vHeading;//current travel heading

FLOAT dot = D3DXVec3Dot(&currentdir, &objfacing);

double Angle = acos(dot);

if(dot < 0.0)

Angle*=-1;

D3DXMatrixRotationY(&Rotation, Angle);

Advertisement
Your current code computes the angle between the current orientation of the tank, and the target.

atan (and atan2) computes angle relative to an axis. To get rotation angle that you need to perform, you have to subtract current angle of tank from angle of target.

tank = Vec(0, 0, 0) # Tank position

for angle in range(0, 360, 10):
    rad_angle = math.radians(angle)

    # Compute target position for the given angle, relative to tank position.
    dz = 400 * math.cos(rad_angle)
    dx = 400 * math.sin(rad_angle)
    target = Vec(tank.x + dx, tank.y, tank.z + dz)

    # Here we go, compute angle for the target relative to the target.
    rel_target = Vec(target.x - tank.x, target.y - tank.y, target.z - tank.z)
    dx = float(rel_target.x)
    dz = float(rel_target.z)

    # Map dx/dz into the first quadrant
    invert_angle = False
    if dx < 0:
        # Fold around x axis
        dx = -dx
        invert_angle = True

    angle_180 = False
    if dz < 0:
        # Fold around z axis
        dz = -dz
        angle_180 = True

    angle_90 = False
    if dx > dz:
        # Fold around 45 degrees
        dx, dz = dz, dx # Swap
        angle_90 = True

    target_angle = math.degrees(math.atan(dx / dz)) # angle relative to +Z

    # Unfold back to original quadrant
    if angle_90:
        target_angle = 90 - target_angle
    if angle_180:
        target_angle = 180 - target_angle
    if invert_angle:
        target_angle = -target_angle

    # 0..180 for positive X
    # 0..-180 for negative X
It's Python code, but the idea should be clear.
I have a "for" loop over an angle, and compute the position of the target relative to the tank first.
At the bottom you can add checking code to compare angle of the for loop with the computed angle.

Then I start where you start:
"# Here we go, compute angle for the target relative to the target."
- rel_target is the difference in position between the target and the tank.
- atan has problems with 90 degrees angles. For this reason I fold dz, dx back into the 0..45 degrees first.
- The atan gives the target_angle relative to +Z, in folded space.
- After unfolding back to -180 .. 180, you get the absolute angle to move to.
- Rotate tank by "target_angle - current_tank_angle"

atan(dx / dz) == atan2(dx, dz) afaik

Hey Thanks Alberth.

Nice.

I was using the objects heading vector and not its position and also I was reusing the facing direction in the caluclation for dd in stead of the way points world locations.

So now all the code is this and works fine. I've tryed it with and with out the facing direction and it works in both cases but the tank is facing the same direction as atan2 0°

if the model facing direction changes it may be needed.

.


//for atan2 we need the objects facing direction added to the current position
D3DXVECTOR3 facing = D3DXVECTOR3(0.0, 0.0, 1.0);
currentdir = facing + ComponentMotion->m_vPos;//
	
//now create the totarget heading vector
D3DXVECTOR3 dd = WayPoints[CurrentWayPoint] - currentdir;
	

// angle relative to +Z
double Angle =  atan2(dd.x, dd.z);
 
D3DXMatrixRotationY(&Rotation, Angle);

This topic is closed to new replies.

Advertisement