Setting up a rig for a trolley bus, with overhead wires

jmanningHM88L
Explorer

Setting up a rig for a trolley bus, with overhead wires

jmanningHM88L
Explorer
Explorer

Can anyone share some tips about how you would rig this? I have a bus that travels freely over the road. Attached to the top of the bus is a set of poles that reach up to the overhead electric power wires. The base of the poles are attached to a mechanism on the roof of the bus that swivels on the z axis. As the bus is animated driving forward around a curve, the arms (poles) swivel so the tips of the poles are always in contact with the overhead wires.

jmanningHM88L_0-1643755134407.png

 

0 Likes
Reply
Accepted solutions (1)
885 Views
5 Replies
Replies (5)

leeminardi
Mentor
Mentor

This is an interesting rigging challenge.  I have limited Max script experience but thought I would give it a try so here is my work-in-progress partial solution.

 

In the attached file a green box represents the bus (trolley) and a red cylinder the boom from the bus to the overhead cable.    PointBus is a point linked to the bus and is at the location of the boom.  Boom is also linked to the bus and has a LookAt constraint pointing at PointCable

 

leeminardi_0-1644166231600.png

 

The following script can be used to position PointCable on the cable a distance L (the length of the boom) from PointBus.

-- positions PointCable on line001 a distance LabelControl
-- from PointBus
-- v .01 2/6/2022 L. Minardi
select $line001
cable = $
select $PointCable
pCable = $
sM = [0,0,0]
global delta = 0.1
global s = delta
global L= 20.
select $Bus
BusT = $.transform
select $PointBus
pBus = $.position 
sA = 0.0
sB = delta
flag = true
pA = interpCurve3D cable 1 sA
pB = interpCurve3D cable 1 sB
dA = distance pBus pA 
dB = distance pBus pB 
-- get to intervale containing solution
for i = 1 to 10 while flag do
(if dB > L then
  (
	pA = pB 
    sA = sB
    sB = sB + delta
	pB =  interpCurve3D cable 1 sB
	dB = distance pBus pB 
  )	
else
  ( flag = false
  )
  )
-- now iterate between A and B
flag = true
for i = 1 to 5 while flag do
(
  sM = (sA + sB)/2.
  pM =  interpCurve3D cable 1 sM
  dM = distance pBus pM
  err = abs(dm - L) 
  if (err < (0.01 * L)) then 
  (	flag = false	
   format ("i = %, error = %   ") i err
  )
if dM < L then
(
   pB = pM
   sB = sM 
)	
else
(
   pA = pM 
   sA = sM 
)
) -- end for
  
pCable.pos = pM
  
  
  

The program searches the cable from its end to a location delta along the cable. It does not examine the entire cable at the start because there could be multiple solutions and we seek the point that will keep the boom to towards the rear of the bus. An interval pA to pB is examined and if both points are further from PointBus then L, then  pA become pB and a new pB is determined a distance delta along the cable from pB.  The search is continued until the segment where distance to pA is greater than L and the distance to pB is less than L.  This interval is then searched using the bisection numerical approach to find point pM, midway between pA and pB  that is within sufficient tolerance.

There are several implied assumptions in this solution including that the first end of the cable is closest to the desired direction of the boom.

 

Experiment with the attached file by moving the bus and then executing the script.  Please let me know if this approach looks like it has promise and what modifications you would like to see.

 

 

 

lee.minardi
0 Likes

jmanningHM88L
Explorer
Explorer

Wow, thanks so much, this is definitely what I am trying to do! In fact I got as far as creating a the look at controller for the boom, but I had the "pointcable" object on a path controller and was animating it manually to get the boom to meet the cable at the right spot.
So with this script I have been able to successfully animate the bus object, and then go to any frame (with Animate on), run the script, and the boom pole rotates right to the correct angle to meet the wire. Is there a way now to add a line to the script that increments through each frame (with animate on) and performs the same operation on every single frame?

Again, thanks @leeminardi for answering this so quickly, I wasn't expecting such a great response!

 

0 Likes

leeminardi
Mentor
Mentor

@jmanningHM88L   I'm glad you like the script and find it helpful.  I have tried to enhance it to automatically create keyframes but have yet to be successful due to my limited Maxscript knowledge. I have posted  a question regarding this on the Max programming forum.  Hopefully I will get the information I need to make the enhancement.  I'll let you know if I do.

 

Lee

lee.minardi
0 Likes

leeminardi
Mentor
Mentor
Accepted solution

@jmanningHM88L Here's a new improved version of the rigging.    You can move the bus and the pole automatically adjusts so that it ends on the overhead cable. All you need to do is key frame the location of the bus as desired.

 

The script boom.21.ms contains the function CalculateCablePoint. It has three parameters, a cable (spline), a point in world coordinates, and the length of the boom. PointCable has a PathContraint to the spline. It has a Float Script for the Percent parameter.

 

p = PtOnBus * busTransform
CalculateCablePoint path p length

 

PtOnBus is a point linked to the bus.  Multiplying its position times the transformation matrix of the bus yields its world coordinates.  Path is the spline  and length is a constant equal to the length of the pole connecting the bus to the cable.

 

leeminardi_0-1644459227487.png

leeminardi_1-1644460239477.png

 

 

Run the script boom.21.ms  then open the file trolley rig21.max. You should be able to select the bus and drag it with the pole following while maintaining contact with the cable!

 

 

-- Calculates the position of a point on a cable the is fixed distance
--  from a point.
--  cable = a spline that has a point with a path constraint
--  pBus = a point in world coordinates 
-- len = the distance to  be maintained as pBus moves.
--  L. Minardi  v3.0  2/9/2022
--
fn CalculateCablePoint cable pBus len =
(	
global delta = 0.1
--global s = delta 
global L = len
global sM = 0.0	
sA = 0.0  -- % along value for A
sB = delta  -- initial % along guess for B
flag = true
pA = interpCurve3D cable 1 sA  -- point A 
pB = interpCurve3D cable 1 sB   -- point B
dA = distance pBus pA 
dB = distance pBus pB 
	
-- get to intervale containing solution
for i = 1 to 10 while flag do
(if dB > L then
	(
		pA = pB 
		sA = sB
		dA = dB  
		sB = sB + delta
		pB =  interpCurve3D cable 1 sB
		dB = distance pBus pB 
	)	
	else
	( flag = false
	)
) -- end for
-- interval found, now iterate between A and B using bisection method
flag = true
for i = 1 to 10 while flag do  -- do up to 10 iterations
(
	sM = (sA + sB)/2.  -- % along for midpoint between A and B
	pM =  interpCurve3D cable 1 sM
	dM = distance pBus pM
	err = abs(dm - L) 
	if (err < (0.01 * L)) then 
	(	flag = false	
	    --   format ("i = %, error = %   ") i err
	)
	if dM < L then
	(
		pB = pM
		sB = sM 
	)	
	else
	(
		pA = pM 
		sA = sM 
	)
) -- end for
sM
) 


  
  

 

I'd like to thank @denisT.MaxDoctor for his help with the Maxscript programming language.

 

lee.minardi

jmanningHM88L
Explorer
Explorer

I can't wait to try this later today! I will let you know how it goes!

0 Likes