Calculating speed from angle of turn

Started by
1 comment, last by CombatWombat 12 years, 6 months ago
Hi!
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)
end

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
else
local alpha = rotation_this_frame / angle
path_dir = vector_slerp(forward, dir_to_next, alpha)
end
else
path_dir = dir_to_next
end

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
self:abort()
end
end

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

return path_dir, backing
end



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:
curveproblem.png

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?
Thanks
/Christoffer
Advertisement
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.
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".

This topic is closed to new replies.

Advertisement