# Trajectory given max initial speed, initial position, and target position?

How would you compute the most optimal trajectory (one that has the smallest initial speed/magnitude) given the maximum initial speed, initial position, and target position.

Also if it is impossible to find a trajectory with speed <= max speed, it should return a trajectory that gets as close to the target position as possible (probably smallest 3D magnitude)

But it only lets you calculate a trajectory with the EXACT initial speed and it returns nil if you need more speed to reach the goal.

You can probably just approximate it using binary searching, but Iâ€™m wondering if theres any way to achieve this behavior with some kind of magical formula or something

1 Like

You need to define â€śoptimalâ€ť better here. The computed trajectory will inherently be a tradeoffâ€”if you have a smaller initial velocity then youâ€™ll have a larger distance traveled before reaching the target, neither of those options is inherently more â€śoptimalâ€ť than the other.

Unless youâ€™re exactly on the edge case, there will be a family of solutions with initial speed less than the maximum initial speed, you need some way to decide between them.

2 Likes

If you know the most optimal for both initial speed AND the most optimal for fastest arrival time, is there a clear way to interpolate between them and get a result that is like (this assumes linear interpolation I think) 90% as fast as fastest arrival but uses 10% less speed than fastest arrival?

Yeah, both of those solutions will have an initial velocity. You can then choose `velocity = 0.9*clampedMaxVelocity + 0.1*minVelocity`, and solve back for the angle that you have to use given that `velocity`.

This Wikipedia page has all the equations you should need if you want to implement it yourself (The â€śAngle theta required to hit coordinate (x,y)â€ť sectionâ€¦ holy obnoxious link thatâ€™s actually impossible to post in a Markdown comment): https://en.wikipedia.org/wiki/Projectile_motion

How would that help? Doesnâ€™t it just find the angle needed for a given initial speed? (what the code in the link in the OP does) I want the option to use a speed smaller (if possible) and the ability to overshoot undershoot as well if the required speed is too great.

This equation gives you the lowest possible launch velocity for the projectile to reach the target.

``````v_min = sqrt((y + sqrt(y^2 + x^2))/g)
``````

There is no â€śmaximum velocityâ€ť to reach the target, you can always use more velocity as long as you have an unobstructed path to the target (ie: Youâ€™re not trying to lob something over a wall). So the max velocity to reach the target is just whatever your desired max velocity is.

``````v_max = [your max velocity]
``````

Then apply a mix of the two based on what you want

``````v_to_use = f(v_min, v_max) -- f returns something between v_min and v_max
``````

Then finally you solve the angle for that velocity:

``````theta_inclination = arctan((v^2 +/- sqrt(v^4 - g*(g*x^2 + 2*y*v^2))) / (g*x))
``````

Where `v = v_to_use` Now you can use the `theta_inclination` and `v_to_use` to construct a velocity vector to fire the projectile with.

1 Like

Am I doing something wrong finding the minimal velocity (calling it InitialSpeed since Iâ€™m just plugging it into AxisAngleâ€™s code)?

``````local x = ((target.X - origin.X)^2 + (target.Z - origin.Z)^2)^0.5
local y = (target.Y - origin.Y)
local InitialSpeed = ((y + (y^2 + x^2))^0.5/g)^0.5
``````

The numbers seem to be really small

Looks the same as the Wikipedia page. Are you sure you have the right constant for g? I think itâ€™s 20*9.81 on Robloxâ€”though that would only make your result smaller.

Try it out and see if it works, the difference between the max velocity and min velocity should be pretty large.

This is the code Iâ€™m using xd:

If you uncomment the part at the end then it will use the formula to find the min initial speed but it doesnâ€™t work at all.

``````--By Axis Angle
--function Trajectory(Vector3 Origin,Vector3 Target,Number InitialVelocity)
--Returns two possible paths from Origin to Target where the magnitude of the initial velocity is InitialVelocity
--The first returned Vector3 is the Low Trajectory, the second Vector3 is the High Trajectory
--If no trajectory can be calculated, it returns nil
local Trajectory
do
local v3=Vector3.new
local g=-196.2
function Trajectory(Origin,Target,InitialVelocity)
local ox,oy,oz=Origin.x,Origin.y,Origin.z
local rx,rz=Target.x-ox,Target.z-oz
local tx2=rx*rx+rz*rz
local ty=Target.y-oy
if tx2>0 then
local v2=InitialVelocity*InitialVelocity
local c0=tx2/(2*(tx2+ty*ty))
local c1=g*ty+v2
local c22=v2*(2*g*ty+v2)-g*g*tx2
if c22>0 then
local c2=c22^0.5
local t0x2=c0*(c1+c2)
local t1x2=c0*(c1-c2)
local tx,t0x,t1x=tx2^0.5,t0x2^0.5,t1x2^0.5
local v0x,v0y,v0z=rx/tx*t0x,(v2-t0x2)^0.5,rz/tx*t0x
local v1x,v1y,v1z=rx/tx*t1x,(v2-t1x2)^0.5,rz/tx*t1x
local v0=v3(v0x,ty>g*tx2/(2*v2) and v0y or -v0y,v0z)
local v1=v3(v1x,v1y,v1z)
return v0,v1
end
else
local v=v3(0,InitialVelocity*(ty>0 and 1 or ty<0 and -1 or 0),0)
return v,v
end
end
end
--Example
wait(1)

local g = 196.2
local Origin=Vector3.new(0,10,0)
local TargetPart=game.Players.LocalPlayer.Character.HumanoidRootPart
local InitialSpeed=100
while true do
wait()
local target = TargetPart.Position
--[[local x = ((target.X - Origin.X)^2 + (target.Z - Origin.Z)^2)^0.5
local y = (target.Y - Origin.Y)
local InitialSpeed = ((y + (y^2 + x^2))^0.5/g)^0.5]]

local LowTrajectory,HighTrajectory=Trajectory(Origin,target,InitialSpeed)
local Part=Instance.new("Part",game.Workspace)
Part.CanCollide=false
Part.Position=Vector3.new(0,10,0)
Part.Velocity=LowTrajectory
local Part=Instance.new("Part",game.Workspace)
Part.CanCollide=false
Part.Position=Vector3.new(0,10,0)
Part.Velocity=HighTrajectory
end
``````

Well thatâ€™s your problem. Everyone knows you shouldnâ€™t use my code!

8 Likes