Jump to content
  • Advertisement
Sign in to follow this  

Calculating speed from angle of turn

This topic is 2936 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I have this mathproblem that's been bugging me.
I'm writing the pathing code for a tank, that is, an entity which cannot turn on spot, but rather needs to rotate to his target while moving.
Up unitl now I've been using some code as described in this article and it has done me well (sorta). A problem has occured however, which has led me to
rewrite the movement-code. Previously I calculated the turns and stretches beforehand, but now I want to do it while driving.
Every time I update i find the direction toward the current pathnode, and the direction I'm currently facing. Since I know the rotationspeed of the tank, i limit the
new direction by interpolating between the current direction and the target direction, using the max rotation as t.
Like this:

function Tank:get_path_direction(dt)
local old_pos = self.position:unbox()
local forward = self.target_dir:unbox()
local current_path_node = self.path[self.path_index]:unbox()
local to_next = current_path_node - old_pos
local dir_to_next = Vector3.normalize(to_next)
local dp = Vector3.dot(forward, dir_to_next)
local backing = false
if dp < 0 then -- backing
backing = true
forward = -forward
dp = Vector3.dot(forward, dir_to_next)

local angle = math.acos(dp)
local path_dir = Vector3.zero()
local rotation_speed = self.rotation_speed
local rotation_this_frame = rotation_speed * dt
if math.abs(dp) < 0.995 then
if angle < rotation_this_frame then -- if the angle is less than our maximum rotation this frame
path_dir = dir_to_next
local alpha = rotation_this_frame / angle
path_dir = vector_slerp(forward, dir_to_next, alpha)
path_dir = dir_to_next

if Vector3.length(to_next) < 0.1 then
path_dir = path_dir * 0.1
self.path_index = self.path_index + 1
if self.path_index > #self.path then

if path then
if Vector3.distance(old_pos, self.path[#self.path]:unbox()) < self.target_radius then
return Vector3.zero(), false

return path_dir, backing

This works fine. I would however like to limit the speed to the steepness of the curve. The tank has got to slow down for steeper curves and so on.
I have illustrated the problem like this:

Where P is the starting-point, d is the starting direction of the tank, and G is the goal point.
After moving and rotating for a number of frames i'm heading in the right direction, thus I have no need to keep rotating.
The problem is finding the length of the curve beforehand so I know what my speedlimit is.

Any ideas?

Share this post

Link to post
Share on other sites
As a crude first attempt you could do something like:

At any moment you know the linear distance from P->G
You know the angle between vectors PD and PG
You know the angular rate allowable at a given linear velocity.
So, you can do
TimeToCompleteAngularTurn = AngleToTurn / MaxAngularRateAllowedAtOurCurrentLinearSpeed
TimeToArriveAtG = PG.length() / Linear Speed

If the time taken to rotate to face point G is greater than the time to arrive there at the current speed, your arc would overshoot, and you have to slow down.
This is crude because in reality the distance from P->G is not a straight line, but I think it might be a close enough approximation for what you want to do.

Share this post

Link to post
Share on other sites
Further thought:

Given a max (current) turn rate of "PHI" in deg/s and a velocity "V".
The time, "t", to complete an entire 360 turn is (360 deg / PHI)
The circumferential distance traveled is V*t.
Circumference is 2*PI*r
so r = can be calculated from V*360 / 2*PI*PHI

So now you have a circle of radius "r"
It's center point will be "r" units away from "P" the current location of your tank, perpendicular from it's velocity vector (towards the side that point "G" is on).
Now you have a circle of radius "r" centered at "O", with a chord created by the line described by points "P" and "G"
Find the length of this chord. If that chord length is greater than the distance from P-G, then your radius of turn is too shallow and you will overshoot point "G".

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!