I am trying to implement a spring with the node Generic6DOFJoint. Generic6DOFJoint has a Spring property, but I can't seem to get it to work and from my research I haven't found any tutorial, example implementation or other support on the Generic6DOFJoint node. Can someone help me. Thanks.
Generic6DOFJoint (Spring)
- Edited
I will outline what I do in a couple posts, starting here:
(recommended) You connect two RigidBodies to a Joint. Because these elements are under the control of Bullet, they should not be the children of any scene subtree subject to a transform change. In short none of these elements should be node children of each other.
I use an assembly Spatial (for 3d work) to organize an assembly of bodies and their joint (s), like so: AssemblyNode Body1 Body2 Joint
The reason to place the joint after the bodies is to prevent godot spamming warnings that a joint lost the bodies it was bound to if this scene subtree is deleted. Being the last child, it is deleted first, removing the complaint. If the bodies are deleted first, you'll get a warning spam storm.
Using an assembly makes it easy to place the collection when added to a scene. Just be sure not to casually (read not after setup) change AssemblyNode's transforms after. The consequence can be that the objects behave a bit erratically because you have changed the position of these elements and Bullet is not aware. This messes with its simulation for a few frames.
(next setup)
- Edited
The first thing you'll want to do in your scene is to get the node_a and node_b of the Joint to reference Body1 and Body2 respectively.
Here I will use RigidBody for both body1 and body2 to keep things as simple as possible. This example will model body2 being effected by a y-axis spring (Y axis only)
Give them spherical collision shapes (again for simplicity here). Set their sizes as you see fit and give them some visual aspect with MeshInstance or CSGShape and maybe a shader.
As a development step, set Body1 mode to STATIC, Body2 (RIGID). Place Body1 over Body2 and so they are separate and Body2 has room to fall. This setup makes Body1 like a fixed hanger (because of the STATiC mode) and body2 the moving body (RIGID body mode).
Now, configuring the 6DOF part:
Joints represent a 'pivot' or reference frame around for its constraints and degrees of freedom. All the movement configured for 6dof is relative to this reference frame.
I usually think of placing it with respect to node_b. Here, placing it in the middle of the space between body1 and 2 is fine.
This joint by default is set up as 'rigid', that is like the two bodies pinned together by an invisible beam (the joint constraints), and you configure the joint's degrees-of-freedom fields to allow motion you want.
In this example, disable linear_limit_y. This will allow body2 to move freely along the joints y-axis. (later you can experiment with linear_limit_y to 'box-in' the spring motion if you want, but later)
(note that I think bullet configures the joint axis internally and "up" is defined as going from body1 to body2.)
Now go to linear_spring_y and enable it. You will notice 3 other properties in the spring_y inspector fold-out.. or whatever it is called.
The three values determine the overall characteristics for the spring.
So if you know the basics of spring physics, there is the notion of the rest-point (equilibrium) and this is the point where the spring exerts no forces. Stiffness refers to what is known as the 'restoring' force applied when there is deviation from this rest position.
The force applied is proportional to the amount of displacements from the equilibrium point.
Damping is a 'viscosity' factor that works against motion in the spring's axis. You can use it to prevent the bodies from gaining too much velocity for your purposes.
So with this in mind, play with the set up (run it), maybe label all the bodies and the joint as 'tool' since i think then you can modify in the editor and see what happens.
Since body2 is under the influence of 1 g of gravity, it will sink down a bit and maybe bobble and slowly come to rest (because damping).
If you play with the equilibrium point, body2 will 'sink' or 'rise' accordingly. If you play with stiffness, body2 will sink less and will move more sharply when equilibrium changes (or if body2 is pulled up or down). If you play with damping body2's max velocity from stiffness/applied force will be effected.
Next steps:
Put floor under this assembly and make body1 a rigid body and play with the behavior.
Enable linear_limit_y and set up the upper and lower limits (think upside down). Godot's editor feed back is a bit wonky in my opinion but play with upper and lower separately a little to get an idea of how they work.
Lastly you can set body1 to kinematic-mode and add some scripting to move that body around to explore the spring physics.
Hi!
I would like to bump this post because dotted has been really helpful, and I found very clear instructions on how to set up joints which I haven’t found elsewhere. For instance, after a couple of days of googling and playing around with joints I still hadn’t figured out that the positive direction is from body a to body b, I was just looking at the joint’s origin… duh!
I have a related question hence the post hijacking: where are the joint forces applied? Is it for example at the node’s origin or at the center of mass? Is it possible to manually define the point where forces are applied in each body?
My intended application is that of a car axle and its suspension. It would have two springs, between the same nodes a and b (chassis and axle, one joint on the right and one on the left hand side). Would having two springs essentially generate two identical joints acting on the objects at the same points (I.e. not on the left and right hand sides, but twice at the origin or center of mass)? I could emulate a two spring behavior by having a single 6DOFJoint and allowing some additional “springiness” in another direction (ex: around the Z axis) but I’d like to try the two springs approach if there is a way to make it work.
And extra question: when the joint is instantiated, it spawns at the scene’s origin. Should I leave it there, or should I physically translate it to where the joint would be in my assembly? I know that some Godot nodes should be left at the origin and not messed with.
Thank you!
The joint's position has be be at the same point as one of the node's (I used node a) prior to setting the node a/b or adding the joint to the scene.
Thank you for the reply cybereality, I’d like a clarification: is it in response to the extra question about general best practices for instantiating joints, or is it for the earlier question about setting the point of application for the joints?
- Edited
I'm not sure. But the joint position does matter. In my case it had to be positioned on the "stationary" node. My node was moving, but this was the one that was user controlled. For example, if you had a chain attached on the wall, then the joint should be at the point the chain connects with the wall.
Thank you, I will keep experimenting with joints then. In my case the joint’s attachment point matters, so I will try to:
- place joints at various locations to see the effects (in the case of my car, I’d try front left, front right, etc.)
- manually code some logic to add torque and forces. Springs are simple systems, maybe I’ll get away with that. I just tried some simple code with a constant force applied to manually-defined points on the car’s chassis and it is straightforward enough. I’ll add the spring logic and see if I can wrap my head around having several coordinate systems to compute forces on (one for the spring, one for the chassis)
If it's the axis of a car, then I guess center between the two wheels would make sense. It's hard to say, this caused me a lot of problems, because it is not properly documented.