#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Locomotive using joints

edited April 1 Posts: 9,106

Here’s something I was playing with the last few days. It’s a locomotive demo using Revolute, Distance and Prismatic joints. The piston uses Prismatic, the wheels use Revolute, and the joints connecting the wheels and piston uses Distance. The only piece the gets any value to move is the piston. When the piston moves, it causes wheel number 3 to start rotating by the distance joint connecting them. Wheel 3 then rotates wheel 2 and wheel 4 with their connecting joints. When 2 rotates wheel 1 with their connecting joint. By increasing the pressure slider, the piston moves faster causing wheel 3 and the other wheels to move faster. You can slide the parameter “piston joint” to break the joint between the piston and wheel 3 causing them to slow down. Parameter “Joints 1_2, 2_3, and 3_4” breaks the joints between those wheels and they will slow down. Wheels 1, 2, and 3 have angularDamping, so they will slow down faster. Wheel 4 has no damping, so it will rotate for awhile.

PS. Run in landscape orientation.

``````viewer.mode=STANDARD

-- locomotive

function setup()
rectMode(CENTER)
parameter.integer("pressure",1,100,5)
parameter.boolean("piston joint",false)
parameter.boolean("joint1_2",false)
parameter.boolean("joint2_3",false)
parameter.boolean("joint3_4",false)

-- create wheels
w1=wheel(200,200,200,200,200,260)
w2=wheel(380,200,380,200,380,260)
w3=wheel(560,200,560,200,560,260)
w4=wheel(740,200,740,200,740,260)

createPiston()
createJoints()
end

function draw()
background(142, 95, 31)
fill(255)
text("Angular velocity (1)   "..w1.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-25)
text("Angular velocity (2)   "..w2.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-50)
text("Angular velocity (3)   "..w3.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-75)
text("Angular velocity (4)   "..w4.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-100)

w1:draw()
w2:draw()
w3:draw()
w4:draw()
drawPiston()
drawJoints()

if r1.linearVelocity.x>0 then
r1.linearVelocity=vec2(pressure*10,0)
else
r1.linearVelocity=vec2(pressure*-10,0)
end

if piston_joint and j5~=nil then
j5:destroy()
j5=nil
end
if joint1_2 and j61~=nil then
j61:destroy()
j61=nil
w1.wheel.angularDamping=1
end
if joint2_3 and j62~=nil then
j62:destroy()
j62=nil
w2.wheel.angularDamping=1
end
if joint3_4 and j63~=nil then
j63:destroy()
j63=nil
w3.wheel.angularDamping=1
end

end

function createPiston()
p1=physics.body(CIRCLE,0)   -- anchor piston
p1.x=100
p1.y=350
p1.type=STATIC

r1=physics.body(CIRCLE,0)  -- piston rect
r1.x=100
r1.y=350
end

function drawPiston()
if j5==nil then
return
end
pushStyle()
strokeWidth(8)
fill(255)
stroke(0)
rect(110,350,200,50) -- piston cylinder
fill(0)
rect(r1.x,r1.y,20,50) -- piston
strokeWidth(0)
rectMode(CORNER)
if pressure>0 then
if r1.linearVelocity.x>0 then
fill(255,0,0,pressure*2+55)
rect(p1.x-84,r1.y-20,r1.x-24,40)   -- red pressure
elseif r1.linearVelocity.x<0 then
fill(255,0,0,pressure*2+55)
rect(r1.x+8,r1.y-20,p1.x-r1.x+96,40)   -- red pressure
end
end
popStyle()
end

function drawJoints()
pushStyle()
stroke(172)
strokeWidth(4)
if j61~=nil then
line(j61.bodyA.x,j61.bodyA.y,j61.bodyB.x,j61.bodyB.y)
end
if j62~=nil then
line(j62.bodyA.x,j62.bodyA.y,j62.bodyB.x,j62.bodyB.y)
end
if j63~=nil then
line(j63.bodyA.x,j63.bodyA.y,j63.bodyB.x,j63.bodyB.y)
end
if j5~=nil then
line(j5.bodyA.x,j5.bodyA.y,j5.bodyB.x,j5.bodyB.y)
end
popStyle()
end

function createJoints()
j31=physics.joint(REVOLUTE,w1.anchor1,w1.wheel,vec2(w1.anchor1.x,w1.anchor1.y))
j32=physics.joint(REVOLUTE,w2.anchor1,w2.wheel,vec2(w2.anchor1.x,w2.anchor1.y))
j33=physics.joint(REVOLUTE,w3.anchor1,w3.wheel,vec2(w3.anchor1.x,w3.anchor1.y))
j34=physics.joint(REVOLUTE,w4.anchor1,w4.wheel,vec2(w4.anchor1.x,w4.anchor1.y))

j41=physics.joint(REVOLUTE,w1.wheel,w1.anchor2,vec2(w1.wheel.x,w1.wheel.y+60))
j42=physics.joint(REVOLUTE,w2.wheel,w2.anchor2,vec2(w2.wheel.x,w2.wheel.y+60))
j43=physics.joint(REVOLUTE,w3.wheel,w3.anchor2,vec2(w3.wheel.x,w3.wheel.y+60))
j44=physics.joint(REVOLUTE,w4.wheel,w4.anchor2,vec2(w4.wheel.x,w4.wheel.y+60))

j61=physics.joint(DISTANCE,w1.anchor2,w2.anchor2,
vec2(w1.anchor2.x,w1.anchor2.y),vec2(w2.anchor2.x,w2.anchor2.y))
j62=physics.joint(DISTANCE,w2.anchor2,w3.anchor2,
vec2(w2.anchor2.x,w2.anchor2.y),vec2(w3.anchor2.x,w3.anchor2.y))
j63=physics.joint(DISTANCE,w3.anchor2,w4.anchor2,
vec2(w3.anchor2.x,w3.anchor2.y),vec2(w4.anchor2.x,w4.anchor2.y))

j1=physics.joint(PRISMATIC,p1,r1,p1.position,vec2(1,0))
j5=physics.joint(DISTANCE,r1,w3.anchor2,r1.position,w3.anchor2.position)
end

wheel=class()

function wheel:init(a1x,a1y,wx,wy,a2x,a2y)
self.anchor1=physics.body(CIRCLE,0)
self.anchor1.x=a1x
self.anchor1.y=a1y
self.anchor1.type=STATIC

self.wheel=physics.body(CIRCLE,80)
self.wheel.x=wx
self.wheel.y=wy

self.anchor2=physics.body(CIRCLE,0)
self.anchor2.x=a2x
self.anchor2.y=a2y
end

function wheel:draw()
pushMatrix()
pushStyle()
stroke(255)
strokeWidth(6)
fill(46, 30, 29)
translate(self.anchor1.x,self.anchor1.y)
rotate(self.wheel.angle)
fill(255)
strokeWidth(3)
stroke(103, 66, 64)
for z=0,360,30 do
line(0,0,x,y)
end
ellipse(0,0,30)                 -- center circle
ellipse(0,60,20)                -- outer circle
fill(0)
ellipse(0,0,10)                -- small center circle
popStyle()
popMatrix()
end
``````

• Posts: 977

neat. now i'll have to figure out what you did • Posts: 9,106

@RonJeffries Thanks, if you have questions about anything, just ask. It took a lot of trial and error writing this because I wasn’t sure how the joints actually worked. I spent a lot of time on small programs playing with a single joint until I understood what was happening.

• Posts: 977

yes, that's what i'd do too. that's a neat example, should be added to the examples that ship with codea