Motorizing the Cannon Hinge Joint

Hi gang. I got a question posted in Q&A about calculating the angle on a CannonJS hinge joint, which remains open to more ideas. I thank ya. (I’m not totally against a little real-mesh disk-like protractor, sitting adjacent to the hinge joint, demarcated in 30 degree increments… with an indicator needle.)

Anyway, I didn’t want to contaminate that other Q&A thread… with my incessant yapping, so I came here and started a thread. Anyway, I have learned some things about motorizing CannonJS hinge joints, and I wanted to share those, and invite discussion.

As some of you already know, I am working on a project to retract/deploy 4 landing-gear legs… to/from an orbiter/lunar-lander. It is important in this sim… that the landing gear is physics-active for contact with ground, whether fully-deployed/retracted, or not. (NO removing physics during animations). “Coming-in too fast” is an important factor in this sim… and partially-deployed landing gear… is part of that fun (better crashes). :slight_smile:

Now let’s get juicy. BJS physics impostors have a setMotor function… making it easy to activate a motor on a hinge joint. BUT… that motor… suffers from some problems.

  1. It back-slides/back-spins after being turned-off, no matter its speed or maxforce settings. It takes very little leg mass and scene gravity… to make the landing-gear leg… start “sinking” from its folded-up (retracted) position.

  2. It drastically changes speeds… because of leg mass and gravity. When the leg is deploying (unfolding), the motor runs faster. When retracting, the motor runs slower. I’d rather have my lander… have consistent 22 seconds to deploy/retract landing gear, no matter the gravity, no matter the leg mass, no matter the orbiter orientation (tilt).

So, I went looking for a different “motor”… and I found it… with leg1.physicsImpostor.setAngularVelocity(). But… IT TOO… had backslide problems. I discovered that you couldn’t set it JUST ONCE, and expect the gear to nicely fold/unfold at a constant speed. Instead… it needed to be done… constantly, by putting it within an onBeforeRenderObervable eventHandler (ie. in the render loop).

Early tests looked fine, but without being able to monitor hinge angle (yet) (see my other forum thread)… I needed another way to REMOVE the continuous leg1.setAngularVelocity… from the render loop… at the PERFECT isFolded stopping angle/point.

SO… I made some “sensors”… tiny, yellow non-physics objects… that could “watch-for” intersectsMesh(leg1). Micro-switches! The intersectsMesh system worked PERFECT for this. These little yellow sensors are parented to the lander greenbox, and can be set invisible.

Wingnut runs the “Continuous Angular Velocity Engine” (CAVE)… and when the leg touches the yellow non-physics sensor, it REMOVES the CAVE from the render loop (removes the CAVE from beforeRenderObserver). :wink:

When I did that… the leg went limp… instantly dropped from folded position, and swung back and forth like a pendulum. “Oh no! Gravity and mass are still nearby.” :slight_smile: How was I going to “latch” the landing leg in folded position… after I turned-off the CAV engine?

(think think think. latch = umm… uhh… lock) LOCK! LOCKJOINT!!! YAY!

And that’s what I did.

Two yellow non-physics sensors for intersectsMesh with leg1, one for retracted, one for deployed. The moment a trigger “throws”, a previously-placed lockJoint between greenbox and leg1 NEAR the sensor… is enabled. The yellow sensors themselves are NOT physics objects, so they cannot be attached to a lockJoint (a latch). Maybe later. :slight_smile: To “unlatch”… the lockJoint/latch is disabled.

As you can see, the leg still deploys substantially faster than it retracts… due to gravity and legMass, but it is still far more consistent-speed than CannonJS native hinge motors. The maxForce for Cannon hinges is not really very powerful, no matter how large. (esp true with slow motor speeds, like I need)

Also, you can see some “jiggle” at the point of “deployed”… at sensor2, near latch2. (rem… no yellow sensor is a latch-to point for the lockJoints.) I’m always latching leg1 to greenbox, no matter which sensor triggers.

Speaking of which… line 146… erf. I spent HOURS hand-tweaking those Y and Z values. Those are the LOCALspace coordinates… on blue leg1… where the “latch” (isDeployed lock) attaches. I was trying to remove the jiggle that happens when leg finishes deploying (when latch2 lockJoint enables). HARD!!! :slight_smile: SO many 45 degree angles involved! :slight_smile:

Anyway, watch the CAVE retract/deploy the landing gear leg… have a good time. Yes, when the orbiter has a severe tilt, things start a little rough, but eventually recover.

I’m working-on a re-visit of the setMotor version, still using the “locking latches”… here, but it’s still a little broken.

Ok, that’s the story, so far, as best I understand it. C’mon along for the ride… steal ALL this code… call it yours… have a good time. Try not to injure your children or pets with it. Cya.

Extra Show’n’Tell stuff: The “lander” might eventually look like this: For thruster/auto-pilot testing, with particles… this. Advanced daddy-long-legs landing gear work… here (using spring restLength deploy/retract system)(elastic puppet strings). Someday, it will all come-together (I hope).


As usual, summoning @Cedric for the physix FYI

1 Like

Ok, Chapter 2…

Look at that baby. I built a class… which, for me, is a friggin’ miracle.

In our last chapter, I told the story about the Cannon hingeJoint native motor…being weak-maxForce’d… when at real slow speeds.

And so… I sort of made a “kludge-engine”… which I call C.A.V.E. Constant Angular Velocity Engine… which doesn’t do anything to the hinge itself, but rotates the shape that is attached to the hinge (in my case, leg1 landing gear leg).

Anyway, I have dreams of making each leg… have 3 sections… which means… 3 motors running on 4 different landing legs… all at the same time. 12-16 motors/engines… running all at the same time, each with their own start/stop angle/latches and speed (if ever wanted).

And what’s the first thing a person thinks about when one needs… “start’n’forget” hinge motors? Yep, instantiations of motor-manager-class objects. Not only that, but the very same class… ALSO handles installing a distanceJoint or lockJoint… that freezes the leg… at the place of motor-off.

So, I tried to do that… but I’m still only using one hinge.

One of the fun things about these CAVE-instances (m1 is such)… is that IT must “hang” a function on the renderLoop… to operate. Each instance needs power from the scene’s master crankshaft. :wink:

But… when the CAVE instance hangs a function on the renderLoop (lines 35-42)… this keyword CANNOT be used inside the hanger function. I needed to use m1 variable, inside hanger func. INTERESTING. Yeah, as soon as I set hanger on the render loop (line 42)… hanger entered a different scope, right? Cool… and annoying. :slight_smile:

The other fun thing… is disposing these instantiations… when the motor shuts-off. I’ve heard… that if no more “references” to an instance/object exists… it will be scheduled for GC… and no reason to fret.

BUT, I was scared. Lines 207-273… is essentially a “motor event sequencer”, right? Look at all those delete m1 in there. Talk about Fisher-Price level OOP-management, huh? Yikes. I have much to learn.

And check-out lines 209-217. An error-absorbing try-catch… for “first time” scene run… before m1 exists. Apparently if (m1 && m1.latch) { just isn’t enough conditional-test… to keep the m1 is not defined error… from happening.

About the latches: I think I am NOT disposing the “latch-joint” that each motor instance… installs at motor-stop. I want the leg-latch to hold-tight, even if motor instance has disposed. BUT… latch is a member (property) of each motor instance. SO… by keeping the latch alive… am I preventing the motor instance from disposing? Bet so. I might need to somehow separate my latch-joints (currently distanceJoints) from the motor-class objects. Latch-class objects? I suppose, huh? sigh.

Ahh, class instantiations that do their own hanging/removing functions from the render loop. Scary. I wonder if I can give each instance… its own private renderLoop crankshaft… and then when it hangs a hanger function onto that private crankshaft… then we CAN use this again… inside hanger func. That would be cool. I bet that is what a “custom observable” is all about.

As soon as an instance is made… the object gets its own renderloop crankshaft… and it can add/remove observers to it. Yeah. hmm.

But I got a class! I MADE A FRIGGIN’ CLASS! Kenya Bleevit? I can’t. It only hurt a little bit.

Ok, sit back and enjoy four motor-mover sequences with lock-in-place-at-stop

Then one final “swingin’-in-the-wind” de-latch at the 1 minute mark.

Help me improve my motor class and other things, if you wish. Try not to make it too complicated and technical, though, eh? (thx)