Calc Current Hinge Angle of Running Motorized Joints - CannonJS

Ok, hi friends. 'Bout sick-of me and my physics challenges? Bet so. But I’m “hot into physics” right now, and I could use all the help I can beg-up. :slight_smile:

https://playground.babylonjs.com/#7YV8E0#22

‘Bout sick-of seeing the leg-lifter, too, I bet. ME, TOO! :slight_smile: Anyway, motor running, consistent… lookin’ good. Now I need on-the-fly current hinge angle… in positive degrees, ideally. Can ya help?

First, look at the mess in lines 117-125. As best I can tell, I am continuously grabbing the worldspace positions… of the hinge’s main and connected pivots… converting the Cannon Vec3 into Babylon Vector3, and then doing a subtraction in line 125… to ATTEMPT to get a direction vector. So, it is my theory… that diff is a direction… possibly useful to smarter people than I. :slight_smile: diff is being displayed at-console… un-normalized… constantly.

The OTHER line of continuous console-barf… is joint1.physicsJoint.equationY.jacobianElementB.rotational

It was a value I saw changing… while the motor was running (powering an X-axis hinge). So, I thought I would puke it to console… show you guys. You can change to equationX or equationZ… they produce output, too… just slightly different. You can also switch to jacobianElementA, too, but that is boring. :slight_smile:

Does ANYONE have any ideas how I could get angle-in-degrees from these numbers? (Or from ANY OTHER “live-updated” hinge-sniffed properties)

There is another way, using leg1.rotationQuaternion (non-physics) or leg1.physicsImpostor.physicsBody.quaternion (physics)… but that is a bit of a work-around, because we would be using the leg-mesh instead of the hinge joint. But, I WILL GLADLY accept/love any ideas… using those solutions, too. Gladly! tutorial? Another recent asker?

And yeah, I’d love precision to at least 2 decimal spots (if possible). HELP! (thx). All hand-holding… quite welcome. Directions, and Quaternions, and me… have never gotten along well. thx agn!

Adding @Cedric for the physics :slight_smile:

First thing first :slight_smile:
You have to be very clear on what you want to do. Getting an angle (in radians or degrees) is easy:

  • compute the dot product of the 2 axis you want to measure the angle. call acos on that value (make checks on ranges before or you might get a NaN).

And that’s it! Convert to degrees because acos returns an angle in radians (range -pi, +pi if I recall correctly).
Hard part is to get the axis. I guess from the code that you want to get the angle between the leg and the green box. To do so, get the row of each transform matrix corresponding the the axis.
https://doc.babylonjs.com/api/classes/babylon.matrix#getrow
I suggest you to add a debug line to be sure that the axis you are retrieving is the one you want.
Then, normalize each vector and do the dot product, acos and so on.
I usually do that way because it’s easy to do it step by step and validate each step. It might be more difficult with quaternion.
Don’t forget that the transform matrix is the concatenation of 3 axis direction (multiplied by the scaling, so normalize before use) and 1 origin position.
Also, don’t forget that angles, and measures in general are relative.

WHAT did he just say? Is that English? Holy cow!

I’m looking for the angle of rotation of the hinge joint.

I don’t want to use the mesh/impostors, because when all 4 legs are added, they will each have different pivot axes, because they are all 90-degree difference from one another. Yet all the hinges themselves… are x-axis pivot. (so one hinge-angle calc works for all legs, IF the gathered values are from the joint-data itself).

But, I’m going to need a LOT more math hand-holding than decipering your words… sorry. I’m just not that math-worthy. I’ll try, though. erf. Thx for the reply.

Sorry for not being clear with my explanation.
What I wanted to say is that computing the angle between the leg length axis and the greenbox up axis is easy with a dot product and an acos.
It will work with any physic engine and you won’t have to deal with quaternion.
Maybe that’s not exactly what you want?

No, you were clear, and as far as knowing what I want… I’m not so sure about that. I’ll take anything, at this point… and your method is probably as-good-as others that might arrive in this thread. I’m gathering them all… weighing everything. Thx!

1 Like

Here’s a more Fisher-Price-level attempt…

https://playground.babylonjs.com/#7YV8E0#26

That is using data directly from joint.physicsJoint.equationY.jacobianElementB.rotational.x Watch console and see oddly named func at line 103, as wanted. kludgy, but… it gets some values at console that are NEAR degrees… though still un-usable for me (I need 0-359.99). :slight_smile:

This uses a maxForce of 9+ million, due-to slow motorSpeed of .15 (I actually want it even slower but…). Via watching console, notice the slowing of the motor speeds near -90 degrees… when motor has max lift task. Any slower speeds, and I would not have enough maxForce to get the job done. Yet… speed of .15 is still too fast, compared to the speed of… say… the opening of the shuttle cargo-bay doors. The coolest space craft… fold/unfold (retract/deploy) their stuff REAL SLOW. :slight_smile:

For general info… I learned that a motor just CANNOT out-power a spring that is trying to keep the leg aimed a certain way… no matter the maxForce. Setting spring restLength does little to help… but… IF you drop spring .stiffness and .damping to 0… before running the motor… the motor runs fine, no matter the spring’s restLength or push/pull axis. Exciting news, eh? (snore) Cannon springs have no enable/disable.

Ok, a little baby update. https://playground.babylonjs.com/#7YV8E0#33

(please pardon the massive amounts of experiment debris, in there)

Briefly, I am using the blue motorized-leg’s .rotationQuaternion.toEulerAngles()… to set .rotation on white test-rod. Looking good. So, at least I have the angle in Euler-form. Now for an attempt at what Cedric told me.

[ Wingy hugs quat.toEulerAngles() ]

Report seen on console… comes from code in lines 157-167, and was borrowed from THIS web-post. Not sure about the approach, yet. Need to study what Cedric said, carefully, now.

HELP WELCOME. Math hates me. (I failed Algebra 1… three years in a row… in HS. erf. But I did nearly as bad in History.) :slight_smile:

Ok, one more time.

https://playground.babylonjs.com/#7YV8E0#86

Getting the hinge angle (by using leg1 mesh) turned-out to be VERY VERY easy. i am SO stupid, sometimes (actually, often). Yes, I originally wanted to calc hinge angle DIRECTLY-from motorRotationalEquation-data on the Cannon hinge itself… maybe more precise and “closer to source”… but I gave up on that. I still seek it, though… ideally.

Getting the angle-in-degrees for the landing gear leg1 was embarrassingly easy.

angle = BABYLON.Tools.ToDegrees(leg1.rotationQuaternion.toEulerAngles().x);

SO simple. Watch console, there it is. (Wingy hugs it rambunctiously)

Soooo… now I can eliminate my little yellow intersectsMesh sensors… and use if (angle > foo) polling, instead of micro-switches. :slight_smile: Thanks yellow sensors… you were good workers, but I have to lay you off. Good luck “out there”… scrambling for your lives. :open_mouth:

I wanna thank @Cedric for teaching me things and giving me good search terms and math things to read about… even though I didn’t need/use much of it. I still got a little smarter… and I MAY work on that “direct-from-the-hinge-equation” electronic protractor… someday soon. It peaked my curiosity.

https://schteppe.github.io/cannon.js/docs/classes/HingeConstraint.html#property_motorEquation

Actually, I’m not using the motor… I’m using a constantly-set angularVelocity… so probably rotationalEquation1 or rotationalEquation2 would be the data to use for “protraction” (angle-reading).

A better person than I… could maybe pull it off. Extra credit for making the same code work… with hinges from all three p-engines. (The other two p-engines probably already have hinge.getAngle() built-in, though.) (Wingy kicks Cannon for having a poor toolbox) :slight_smile:

I think I’m going to mark this thread as self-solved, as self-centered as that may be. I think I now have a “workable” Cannon hinge “protractor”. YAY!

Wanna see the no-sensors, angle-polling, AV motor… trying to get 45 degrees on the deploy, and -90 on the retract? I knew ya did. https://playground.babylonjs.com/#7YV8E0#88 Lines 202-208 are the angle testers.

Lookin’ pretty good, but I got a little jiggle at deploy onEnd. Probably caused by evil line 124… the deployed-latch lockjoint connectedPivot (latch2 attachment point on the leg1). I HATE that line. :slight_smile:

1 Like

Ok, I marked this as solved, blah blah blah, but I have run into another issue.

When using the mesh (leg1) attached to the hinge joint… as the quat/angle to determine the hinge angle (as opposed to using values directly-from CannonJS hinge equations)… problems arise when deploying/retracting the landing gear… when orbiter is not flat/level/ortho-to-gravity-axis.

In short, when the orbiter is tilted, and pilot deploys landing gear… leg1 mesh quat is at 0 degrees… hanging-“down” towards gravity axis. BUT… the ACTUAL hinge angle… will be <> 0 degrees. To properly run my gear retract/deploy motor, I need ACTUAL hinge angle, and cannot count-on leg1 quat angle. I need the gear to properly retract/deploy, even if the orbiter is sideways or inverted, and for this… I need actual hinge angle, and not simply leg1 quat angle.

So, I’m here again, begging for help, preferably at 3-year-old level. :slight_smile: Really, I need hand-hold level, here, cuz I am old, barely able to hit my mouth with a shaking spoonful of pea porridge cold. :slight_smile:

Ok, let me show you what I’ve got.

https://playground.babylonjs.com/#7YV8E0#140

Yeah, I know, it’s a big fat pig playground, but we are working only in one small section…

…lines 230 - 264, an on-the-joint “hingeWatcher”

(A nod of thx to @gijs for Observable.add(() => joint1.updateAngle())

I got “live” values coming from the native joint equations… arriving in lines 239/240. Those values… are the ONLY values “swinging” with a swinging leg1. All other native hinge values were investigated/peeked during a swinging leg1. These are the only 2 “live” values seen changing… on the entire Cannon hinge “system” and sub-components.

jacY and jacZ… my new best friends. jacX was tested, too… but it remains == 0 all the time, so it’s not value-able for us.

NEXT, using a contorted chunk of code in lines 242-245, I am able to derive which “quadrant” the angle is within…

1-90 degrees == quadrant 1,
91-180 deg == q2,
181-270 == q3
271-360 == q4

So, now, using ONLY this gathered data… I STILL need degrees of rotation. hinge.getAngleInDegrees()

HELP! If you know how, SHOW US in this playground. Please don’t simply barf-out a bunch of mathematical terminology that will surely give me the 5th tumor I’ve gotten over this issue, so far. :smiley:

Watch console. jacY and jacZ appear to be good, delicious Euler values with shifted decimal points… but they are NOT so. Their values are 8.5 and 12 as they cross poles and equators (as they change quadrants)… and Mister Wingnut just cannot seem to fig… how to calc/derive 0-360 degree values… FROM these gathered values. HELP! heh.

Thx! (sigh) Does anyone need continuous rotation? Change ‘135’ in line 290… to something like 25000. The 135 degree stop-point IS working… but it is a leg1.rotQuat-derived angle, and works like crap when orbiter is un-level. I must say goodbye to that method.

For folks who think they have found a solution… may I add a caution. I have seen times/places… while studying these things… that the “rate of change” of jacY and jacZ… might vary (differently/beyond the understood mass-caused motor speed-changes). Possibly, the rate-of-change is slower near poles and equators. That would mean… what? The jacY and jacZ values are logarithmic, and not linear? (sigh) (Wingy’s dog starts whining pathetically) (Wingy digs in his closet to see if a flatbed plotter is stored there). :slight_smile:

Hi @Wingnut

From what I understand, you want to measure angle Alpha. Is that right?

Yeah. And later, when the leg becomes 3-4 total sections, even more angle calculations. (human leg-like). As long as greenbox and all bodyA’s for all bone-joint hinges… allow sideways, inverted, etc.

I’d prefer to use data from the joint itself, though. (no bodyA/bodyB quats)

BUT, if the hinge rotation-angle cannot be gotten with the values mentioned above, then I suppose I HAVE TO look at bodyA local up-vectors and bodyB impostor quaternion. Subtract one from other to get difference? I dunno. I’m scared.

gballanger is counting on me, too. :slight_smile: I’d love to simply install our own getAngle() on all Cannon hinges. :slight_smile: That’s one of the reasons I prefer NOT to use impostors/quats to attain the angle. I’d prefer to get it from hinge equations… making it nice and portable.

But I guess every hinge needs a bodyA and bodyB… they will ALWAYS be there. Hopefully, they will ALWAYS have a Cannon body quaternion on both… so I guess we can count-on those ALWAYS being there, BJS or other webGL lib.

IF/WHEN we/I need to use mesh.rotationQuaternion or mesh.physicsImpostor to derive hinge angle, we have made it BJS-only, right? To stay universal (all-native), we need to use mesh.physicsImpostor.physicsBody or below.

I guess leg1.rotationQuaternion is an exact copy/clone of joint1.physicsJoint.bodyB.quaternion. (see console).

So, I guess it’s just semantics. A quat is a quat. For those who might use this new CannonHinge.getAngle() with non-BJS frameworks, mesh.rotationQuaternion likely doesn’t exist.

Conversely, physicsJoint.bodyB.quaternion will exist for ANY webGL lib. shrug.

ANYWAY… https://playground.babylonjs.com/#7YV8E0#142

I tilted the orbiter, as we can see… and I cleaned-up the console reports.

At console… I’m reporting the x component of the toEuler() for both bodyA and bodyB .quaternions (working in native land)… and they look fine… likely identical to x-component of BJS .toEulerAngles() for greenbox and leg1 .rotationQuaternion. Last line at console… subtracting one from the other.

All looks good. I have EulerAngles.x for both bodies… gotten natively… so it will still work with non-BJS webGL frameworks.

Now what do I do with those values… to get them into degrees?

Cedric gave me the answer somewhere in there, didn’t he? For me, it’s like trying to read Klingon. :smiley:

I think I have SOME of the legwork done, already. We’re not stuck in Quat land anymore, and maybe we don’t need to deal-with matrix crap. Aww heck, let’s output a toDegrees(difference) to console… see what happens:

Looks off by about 10-15 degrees, and we go into negative values after it spins beyond the 180 (after passing north pole). shrug. I have NO IDEA what I am doing. :slight_smile: I think I AM sort-of working with greenbox down-vector, though. When leg1 is straight-down from orbiter body (NOT straight-down gravity vector), angle degrees should be 0. All easily adjustable later, I suspect… so switch at-will. Zero degrees being straight-up from orbiter body… is fine, too.

“ohh, I got them Schteppe left me without a hinge.getAngle()… blues.” (sing along, now) :slight_smile:

Maybe just blatantly STEAL AmmoJS hinge.getAngle() code… wedge it into cannon with a jack hammer and some 40-weight mesh lube? hmm.

This is like trying to solve a crossword puzzle that’s been printed on a torus knot. heh.