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))) ]]--