Trying to replicate target_angle implementation for PinJoint2D

Godot Version

4.2

Question

I am trying to implement 2D articulated physics (an example pretty close to what i am trying to achieve would be good old Ski Stunt Simulator. Essentially directly controlling the limbs relative rotations with the mouse). I had done some testing ages ago with XNA and am trying to start on that again. What i am basically missing is a “target angle” for the PinJoint2D.

In my original implementation i used Farseer Physics which allowed combining a Revolute Joint with an Angle Joint, the latter simply enforcing a certain angle between the two bodies.

So i went to the source code of FarSeer, looked at the implementation of the AngleJoint and tried to add this implementation to PinJoint2D as a script.

The original implementation can be found here for reference: Farseer-Physics/SourceFiles/Dynamics/Joints/AngleJoint.cs at master · tinco/Farseer-Physics (github.com)

It basically applies velocities to both bodies to compensate for the difference between the actual angle between the bodies and the target angle.

Important parts are in InitVelocityConstraints and SolveVelocityConstraints

Here is my current implementation in GDScript.

GDScript on Pastebin.com

The result SOMEWHAT works, but it is both way too bouncy and also way too instable. Any pointers what i might have to look into or fix would be greatly appreciated!

This is just a question before looking at the code. Is there a reason you extended a pin joint 2d over just a joint2d?

These will run a physics constraint simulation underneath your code, I assume your implementation is meant to solve all the physics?

And are you using the _integrated_physics function to work directly with your physics joint object inside the physics server?

Update I looked at it. I have a suspicion that you may want to take a node2d, mimic joint options, and work outside the joint physics node, otherwise I think you need to manage the joint constraint solver already taking effect by Godot’s pinjoint node.

1 Like

Thanks for the reply. I was basically trying to mimic what Farseer does. Which is having two types of Joints at once, one being the RevoluteJoint (=PinJoint2D) and the other only enforcing the angle.

As for the last paragraph i am not sure i really understand. Do you mean i should try the very same approach just with the script not being on the PinJoint node?

Yeah, but if your confident about applying manual forces and Godot joint applying forces together then i guess that isn’t necessary?

1 Like

K, the only thing I see that could be doing more is using the apply_torque_impulse function. I don’t recall exactly but it probably applies mass inside the function. So you may have inverse mass squared? Godot calls rotation mass inertia, but I have a feeling mass is used to much potential here. I need to look at the source code.

Maybe could modify angular damping on the bodies

1 Like

Good point. Will check for that. Farseer actually also uses inertia, but i am having a bit of trouble finding my way around the docs and code (for the docs my main issue is that it can be tricky to understand on which class a property is and having to go up and down the inheritance chain, and in code i found it confusing that there are separate files for the joints but the actual calculation seems to be in the server sources.

Thanks a lot for the input and pointers! I am getting somewhere slowly.

I found multiple issues:

  • There was a mismatch in units (degrees vs. radians)
  • The way i calculated inertia was flawed. Thanks to your pointer i used the physics server’s state method to directly get inverse inertia
  • There was an issue with parameters being named the same as parameters on the base classes.

Here is my current state:

YouTube

The angle between the two bodies is controlled with mouse y. As you can see it basically works. But it still tends to “explode” and i also have to add an unexpected modifier to the applied torque impulse. So i still need to look into that some more. I am also not sure what causes the instability. I wonder if the lack of sync between the input processing and the physics processing can be an issue?

Haha That’s awesome :sunglasses:. A little worm I suppose?

At least for apply force vs apply impulse, it usually seems impulse is trying to directly adjust an acceleration/velocity based on force and mass. Where ‘apply force’ will add it to some accumulation vectors to be processed later. It says in the docs it is better for applying physics over time. Not sure what constraints physics should use.

Supposedly there are physics procedures that run multiple times per physics frames. 8 is the default. Although I haven’t understood where in the code it is doing so.

Since Godot removed bullet physics for version 4, there has been a lack of attention on the quality of Godot physics. Many people have jumped ship to use Jult plugin. I have had some trouble with a joint rope myself but have found work arounds I can live with.

So i seemed to be okayish on track. I re-worked the implementation quite a lot to expose a bunch of parameters (like which mouse axis to use, being able to invert, define min/max angles and the likes). That all worked okayish. But as soon as i started creating a more complex setup it is pretty much exploding immediately :confused:

Back to troubleshooting and the drawing board.

Slowly starting to wonder if i should try adding farseer via GDExtension :
:upside_down_face: