[Math] Finding force for trajectory

physicstrigonometry

Using the trajectory equations provided on hyperphysics, I have developed some code to plot the trajectory of an object. I now need to work out the x and y forces to apply to make the object follow said path.

I know that F=MA but I can't seem to reverse this to find the x and y force values to cause an object of given mass to follow the trajectory curve plotted by general ballistic code.

Sorry for the lengthy question but I can provide code and more of my equations if necessary. Sorry if this if the wrong forum.

EDIT:
The equations I am working with are:

velocity = Impulse / mass

velocity = Distance / time

Velocity = speed / time

Force = mass * acceleration

Momentum = mass * velocity

Impulse = avg force * time

[2ND EDIT:]
The code follows – lua language, using the Corona SDK…

Matt

main.lua

local trajlibapi = require("trajectorylib")
local mathlibapi = require("mathlib")
local physics = require("physics")

physics.start()
physics.setGravity(0,10)


--[[ environment setup ]]--

local start, sling = nil, nil

local offsetX, offsetY = 50, 300

local iteration = 0.1 -- gap between increments of trajectory points
--local velocity = 40 -- launch velocity v/ms
--local angle = 60 -- launch angle (theta) degrees


--[[ trajectory plotting ]]--

function trajectory( velocity, angle, iteration )
    local points, r, h, f = trajlibapi.calcTrajectoryPoints( 0, 0, velocity, angle, iteration )

    print( 'angle: ', angle )
    print( 'velocity: ', velocity )
    print( 'range: ', r )
    print( 'height: ', h )
    print( 'flight time: ', f )

    for i=1, #points do
        --print( math.round( points[i].x ), math.round( points[i].y ) )
        display.newCircle( start.x + points[i].x, start.y - points[i].y, (points[i].velocityx + points[i].velocityy) * 0.1 )
    end

    return points
end


--[[ throwing the ball ]]--

function throw( points, sling, start, distance, angle )
    local radius = 50
    local ball = display.newCircle( start.x, start.y, radius )
    ball.alpha = .7
    ball:setFillColor( 90,90,200 )
    physics.addBody( ball, "dynamic", {friction=.1, bounce=.1, density=1, radius=radius } )

    local point = points[2]
    local area = trajlibapi.calcAreaOfCircle( radius )
    local gm = 1 * area
    local g = 2.1
    print('area: '..area)
    print('gm: '..gm)
    print('dist: '.. distance)

    --ball:applyLinearImpulse( start.x-sling.x, start.y-sling.y, ball.x, ball.y )
    --ball:applyForce( (start.x-sling.x)*gm, (start.y-sling.y)*gm, ball.x, ball.y )

    local vx, vy = trajlibapi.calcInitialVelocity( start.x, start.y, angle, distance )
    print('velocity: '..vx,vy)
    ball:setLinearVelocity( vx, vy )

    --print('applied: ', point.x, -point.y )

    function ball:timer(event)
        timer.cancel( ball.t )
        Runtime:removeEventListener("enterFrame", ball)
        ball:removeSelf()
    end
    ball.t = timer.performWithDelay(2000, ball, 1)

    function ball:enterFrame(event)
        local c = display.newCircle(ball.x,ball.y,2)
        c:setFillColor(255,0,0)
    end
    Runtime:addEventListener("enterFrame", ball)
end


--[[ initial point capture ]]--

function touch(event)
    if (not start) then
        start = event
        display.newCircle( event.x, event.y, 2 )
    elseif (not sling) then
        sling = event
        display.newCircle( event.x, event.y, 2 )
        local c = display.newCircle( start.x, start.y, mathlibapi.lengthOf( start, sling ) )
        c:setStrokeColor( 0,0,255 )
        c:setFillColor( 0,0,0,0 )
        c.strokeWidth = 2

        local angle = math.abs( mathlibapi.angleOf( sling, start ) )
        local distance = mathlibapi.lengthOf( sling, start )
        local points = trajectory( distance, angle, iteration )
        throw( points, sling, start, distance, angle )
    end
end

Runtime:addEventListener("tap", touch)

trajlib.lua:

module(..., package.seeall)


--[[ references ]]--

-- The code in this listing was derived from this first URL:
-- http://hyperphysics.phy-astr.gsu.edu/hbase/traj.html
-- http://en.wikipedia.org/wiki/Trajectory_of_a_projectile


--[[ support functions ]]--

local function vxf( velocity, acceleration )
    return velocity * math.cos( acceleration * math.pi / 180 )
end

local function vyt( velocity, acceleration, time )
    return velocity * math.sin( acceleration * math.pi / 180 ) - 9.8 * time
end

local function yt( velocity, acceleration, time )
    return velocity * math.sin( acceleration * math.pi / 180 ) * time - 0.5 * 9.8 * time * time
end


--[[ worker functions ]]--

function totalRangeHeightFlightTime( v, ag )
    local h = vyt(v, ag, 0) * vyt(v, ag, 0) / (2 * 9.8)
    local t = 2 * vyt(v, ag, 0) / 9.8
    local r = v * v * math.sin( 2 * ag * math.pi / 180 ) / 9.8
    return r, h, t
end

function positionAtTime(v, ag, t)
    local vx = vxf(v,ag) -- horizontal velocity
    local x = vxf(v,ag) * t -- horizontal distance
    local vy = vyt(v, ag, t) -- vertical velocity
    local y = yt(v, ag, t) -- height at time 't'

    return x, y, vx, vy
end


--[[ calculate trajectories ]]--

-- returns a collection of points determined as the trajectory of the object
function calcTrajectoryPoints( startX, startY, velocity, angle, iteration )
    if (not iteration) then
        iteration = 0.1
    end

    local r, h, f = totalRangeHeightFlightTime(velocity, angle) -- total range, height and flight time
    local points = {}

    for t=0, f, iteration do
        local x, y, vx, vy = positionAtTime(velocity, angle, t)
        points[ #points+1 ] = { x=x, y=y, time=t, velocityx=vx, velocityy=vy }
    end

    return points, r, h, f
end

-- http://answers.yahoo.com/question/index?qid=20080617223556AA8DD8M
function calcInitialVelocity( startX, startY, angle, force )
    return force * math.cos(angle), force * math.sin(angle)
end


--[[ area functions ]]--

function calcAreaOfCircle( radius )
    return math.pi * radius * radius
end

mathlib.lua:

module(..., package.seeall)


-- returns the distance between points a and b
function lengthOf( a, b )
    local width, height = b.x-a.x, b.y-a.y
    return math.sqrt(width*width + height*height)
end

-- converts degree value to radian value, useful for angle calculations
function convertDegreesToRadians( degrees )
--  return (math.pi * degrees) / 180
    return math.rad(degrees)
end

function convertRadiansToDegrees( radians )
    return math.deg(radians)
end

-- rotates a point around the (0,0) point by degrees
-- returns new point object
function rotatePoint( point, degrees )
    local x, y = point.x, point.y

    local theta = convertDegreesToRadians( degrees )

    local pt = {
        x = x * math.cos(theta) - y * math.sin(theta),
        y = x * math.sin(theta) + y * math.cos(theta)
    }

    return pt
end

-- rotates point around the centre by degrees
-- rounds the returned coordinates using math.round() if round == true
-- returns new coordinates object
function rotateAboutPoint( point, centre, degrees, round )
    local pt = { x=point.x - centre.x, y=point.y - centre.y }
    pt = rotatePoint( pt, degrees )
    pt.x, pt.y = pt.x + centre.x, pt.y + centre.y
    if (round) then
        pt.x = math.round(pt.x)
        pt.y = math.round(pt.y)
    end
    return pt
end

-- returns the degrees between (0,0) and pt
-- note: 0 degrees is 'east'
function angleOfPoint( pt )
    local x, y = pt.x, pt.y
    local radian = math.atan2(y,x)
    --print('radian: '..radian)
    local angle = radian*180/math.pi
    --print('angle: '..angle)
    if angle < 0 then angle = 360 + angle end
    --print('final angle: '..angle)
    return angle
end

-- returns the degrees between two points
-- note: 0 degrees is 'east'
function angleBetweenPoints( a, b )
    local x, y = b.x - a.x, b.y - a.y
    return angleOfPoint( { x=x, y=y } )
end

function angleOf( a, b )
    return math.atan2( b.y - a.y, b.x - a.x ) * 180 / math.pi
end

-- Takes a centre point, internal point and radius of a circle and returns the location of the extruded point on the circumference
-- In other words: Gives you the intersection between a line and a circle, if the line starts from the centre of the circle
function calcCirclePoint( centre, point, radius )
    local distance = lengthOf( centre, point )
    local fraction = distance / radius

    local remainder = 1 - fraction

    local width, height = point.x - centre.x, point.y - centre.y

    local x, y = centre.x + width / fraction, centre.y + height / fraction

    local px, py = x - point.x, y - point.y

    return px, py
end

-- returns the smallest angle between the two angles
-- ie: the difference between the two angles via the shortest distance
function smallestAngleDiff( target, source )
    local a = target - source

    if (a > 180) then
        a = a - 360
    elseif (a < -180) then
        a = a + 360
    end

    return a
end

-- is clockwise is false this returns the shortest angle between the points
--[[
function AngleDiff( pointA, pointB, clockwise )
    local angleA, angleB = AngleOfPoint( pointA ), AngleOfPoint( pointB )

    if angleA == angleB then
        return 0
    end

    if clockwise then
        if angleA > angleB then
            return angleA - angleB
            else
            return 360 - (angleB - angleA)
        end
    else
        if angleA > angleB then
            return angleB + (360 - angleA)
            else
            return angleB - angleA
        end
    end

end
]]--

-- test code...
--[[
local pointA = { x=10, y=-10 } -- anticlockwise 45 deg from east
local pointB = { x=-10, y=-10 } -- clockwise 45 deg from east

print('Angle of point A: '..tostring(AngleOfPoint( pointA )))
print('Angle of point B: '..tostring(AngleOfPoint( pointB )))

print('Clockwise: '..tostring(AngleDiff(pointA,pointB,true)))
print('Anti-Clockwise: '..tostring(AngleDiff(pointA,pointB,false)))
]]--

Best Answer

This can be analyzed easily using differential equations. Given that you refer to x and y coordinates, I'll restrict my answer to trajectories which can be modeled as $(x(t),y(t))$, $t$ representing time, for some continuous functions $x(t),y(t)$. I will use $\vec{F}(t) = (f_x(t),f_y(t))$ to denote the force applied to the object at time $t$. Your problem can then be written as the system of differential equations $$x''(t) = Mf_x(t)$$ $$y''(t) = Mf_y(t)$$ so the desired force vector is simply $\vec{F}(t) = \begin{pmatrix}x''(t)/M \\ y''(t)/M\end{pmatrix}$.

Also, is the trajectory is given by a function $y = h(x)$, then set $t = x$ to get $\vec{F}(x) = \begin{pmatrix}0 \\ h''(x)/M\end{pmatrix}$.

Related Question