Calculating Negative Angles

Hello, I need help on calculating angles. I’m trying to find the angle between a tank’s turret and the mouse’s position in order to rotate the gun to point at the mouse. Currently, I’m just using a HingeConstraint with limits for gun depression and elevation and BodyGyro to rotate the gun, with this CFrame:

bg.CFrame = CFrame.new(gunBase.Position, mouse.Position)

And this works perfectly fine to rotate the gun with no complaints, and it obeys the limits set by the hinge. However, the problem is when the mouse is position in such a way that would make the gun rotate past the limits set by the hinge. When the gun hits the limits, the BodyGyro is still applying a force to the gun to rotate it, so I would like to calculate the angle between where the turret is facing and the mouse’s position to enable/disable the BodyGyro when the limit is hit. Alternatively, I could use the angle to set the TargetAngle of the hinge if it were a servo.

And here’s my current setup:

The red line is a unit vector that describes the direction the turret is facing, and the black line is a unit vector describing the vector between the mouse’s position and the turret’s position. I find the angle between these two vectors by taking the inverse cosine of the dot product between the two, like this:

math.deg(math.acos(dot(turretFaceVector.Unit, turretMouseVector.Unit)))

This works fine for finding the angle when the mouse is above that red line (the elevation angle of the gun) – but not for the depression angle of the gun. It basically returns the absolute value of the angle. It’s always positive, so even when the gun is depressed it will return a positive angle. I want it to return a positive angle when the gun is elevated, and negative when it’s depressed. I’ve also tried using atan2 with the vector between the turret and the mouse, but it only worked when the turret was facing straight forward (I think because atan2 returns the angle between the x-axis and that vector). Is there any way to make this function return negative angles when the gun is supposed to be depressed?

1 Like

While I am interested in hearing about the optimal solution to the problem you describe, a partial response is that:

http://www.mathwords.com/c/cosine_inverse.htm

In other words, the range of cos-1 is restricted to [0, 180°] or [0, π].

So inverse cosine always produces a positive result.

I am also curious, do you need a Body Gyro with a HingeConstraint or can you set the HingeConstraint.ActuatorType to Servo to move the turret barrel up and down relative to the vehicle model?

Either way works fine. With the BodyGyro method, the hinge only acts to keep the gun on the turret and to set limits, the BodyGyro does the rest to actually move the gun. The advantage of this is that you don’t need to calculate any angles, you can just use one line to move the gun by setting the CFrame of the BodyGyro. Setting the hinge to a servo would require you to find an angle, and it also works fine. The advantage of this is that there isn’t a force acting on the gun when you reach the limits that you set. When you reach the limits using BodyGyro, the BodyGyro will still try to move the gun with its force that can have some adverse effects.