How to project force into certain axis

am working on a suspension script for a car, and after following a tutorial i ran into a problem, i need to check the velocity of the car along the car’s y axis so i can limit the suspension’s force.

i want to use the velocity in order to calculate a counter force to stop the suspension from wobbling, but i dont know how to get that velocity only in the car’s local y axis, and if use the velocity as it is i’ll also create a counter force if the car is going forwards or sliding

What you’re trying to achieve is: the car’s local velocity from its known global velocity. Achieving this is simple.

Solution

Rotating the vector by your node’s basis (i.e. rotation matrix) will give you the vector in a different space. If your vector is defined in local space (i.e. relative to another object), rotating by the basis of your node will yield the same vector in global space. If your vector is defined in global space (as your velocity is), and you want it in local space, you must do the opposite of what was just described. This means rotating the vector by the inverse basis of your node.

Below is the transformation code for the global-to-local, and local-to-global transformation for a vector.
Global-to-local vector transformation

    var global_velocity: Vector3
    var local_velocity = global_basis.inverse() * global_velocity

Local-to-global vector transformation

    var local_velocity: Vector3
    var global_velocity = global_basis * local_velocity

Sidenote

Given that you intend to implement a spring system to simulate the suspension of a car, I would suggest that you do not confuse the car’s velocity for the spring’s velocity. A car simulation will, just like a real car, produce varying angular velocities for the car body; each corner (where the springs are attached) will differ in velocity. Failing to account for this will likely produce undesirable damping behaviour for the springs in question.

However, I think you should try out your current approach first and see what happens. If it feels off, you have this note to fall back on.


I hope this helped your issue.

1 Like

thank you, i got what i wanted using what you sent me, using global_basis.y however

as for the sidenote, i am accounting to that (i think) by getting the car’s velocity in the springs points instead of just one point being the car’s point, assuming this is what you meant, i didnt mention this since the post already looked confusing enough

I found out that the solution doesn’t actually work properly, and it only worked specifically in the tests I’ve conducted with the suspension, which were on a flat surface, I have found a different solution a few days ago but didn’t provide an update, but since it’s possible that people might stumble on this post for the same problem I changed my mind

after digging in godot tutorials for a solution, i couldn’t find one, so instead i looked for a pure math video, and found this:

so from that video i wrote the following function:

func project_vector(from: Vector3, to: Vector3)->Vector3:
	return (((from.x * to.x)+(from.y * to.y)+(from.z * to.z))/(sqrt(to.x**2+to.y**2+to.z**2)**2))*to

this function works very nicely, but again it might be only for the tests i conducted

Given that “people might stumble on this post” I am inclined to argue against what you have marked as the solution.

Not only does Vector3 already have a project() method, but your approach to computing the car’s local y-velocity is very backwards – at least if my assumption of how you solved your problem is correct. Sure, you can project the velocity-vector onto the basis-vector for the y-axis, and then take the magnitude of that to get the y-velocity, but that is not at all the optimal way to acquire the value you are seeking to compute: the local y-velocity.

I already gave you a solid, clear, and optimal solution to your problem. However, instead of using that solution (maybe because you didn’t understand how to utilize it), you decided to go a different way. That is fine.

What is not fine is voicing your concern of the post’s ability to communicate the proper solution, and then not providing an adequate description of such a solution. Even if you have solved your own issue, you can’t possibly expect anyone else to understand your approach with what you’ve described here.

I strongly suggest that you either:

  • Describe, in detail, what you have done to solve your issue in your context.
    • Code examples
    • Node setup
    • Visual vector example
  • Look at the solution I provided and ask questions about how you may utilize it.

huh, it seems i didn’t properly explain my issue

the thing i was looking for was infact the project() method that you just mentioned, which for some reason didn’t show up when i looked for it (in google, not the docs), and what i just posted was an alternative based on the assumption that the method doesn’t exist

the reason i need to project the current car’s velocity into the y basis is simply so that the forces i calculate for the spring only go in the spring’s axis, which is up and down, otherwise the car might slide or slow down when moving, i don’t know what you thought my issue was with your previous suggestion but it was infact not the solution

should i mark what you just said as the solution ?

1 Like

After further reading, it seems like what you are trying to compute is different from what you initially described. The approach you would use to compute an object’s local velocity on one axis is different from what you would do to compute the direction of that axis. In general, it’s really hard to help someone who can’t exactly describe what they need help with.

I’ve provided an example below of what a simple spring system might look like. Hopefully it will help avoid any further confusion or misunderstandings.

A standard spring system

The standard way to conceptualize a force is through the two attributes of a vector: direction, and magnitude. As such, you would usually use a normalized vector for the direction, and then multiply the direction by an amount to arrive at the desired force vector.

For a spring, the direction is dependent on what the spring force should affect. That said, it’s force only operates on one axis: along the spring. Computing the force for the spring is simply done with Hooke’s Law.

Here is how it looks for an ordinary spring system (the spring is parented to the car):

    var body: RigidBody3D # Your car

    # Spring characteristics
    var stiffness: float
    var damping: float

    # Spring state
    # NOTE: The spring only operates on one axis, so a single number is all that is needed
    var compression: float # How much the spring is compressed in percentages.
    var velocity: float    # I guess this is where you want your car's y-velocity
    # Example: (body.global_basis.inverse() * body.linear_velocity).Y
    # OR your approach: body.linear_velocity.project(body.global_basis.Y).length() 

    var force_direction = global_basis.Y
    var spring_force = force_direction * (compression * stiffness - vcelocity * damping);
    # The force calculation above makes use of Hooke's Law.

    # Apply the force at where the spring is located (relative to the body)
    var force_position = body.global_basis * position
    body.apply_force(spring_force, force_position)
    # Note that apply_force() needs the delta position (i.e. the position difference) in global space for where the force should be applied.

If you have any further questions about this topic, I’m happy to help. I’ve got a lot of personal experience with building vehicle simulations.


Regardless of whether you need more help, I hope you understand the importance of communicating your problems clearly. There are quite a few people willing to help you. Please respect that willingness by giving those people a clear picture of your situation – anything else is just … frustrating.

I don’t recall mentioning my need to rotate the direction of a force, perhaps my explanation wasn’t up to standards, might be a result of the language barrier

as for your approach, it seems that it rotates the velocity of the car to how it’d look if the car’s rotation was 0,0,0
that approach is pretty nice now that i understand it, the reason it doesn’t work for me is because am using the velocity raw to calculate the spring force, instead of getting it’s length and multiplying by the basis.y, so again, your solution simply wasn’t what i was looking for with my original question, here’s my code:

            var Ray = Suspensions[i]
			var Target = Ray.get_node("Target")
			Ray.force_raycast_update()
			if Ray.is_colliding():
				var Dist = Target.global_position - Ray.get_collision_point()
				#Suspension
				var CurrentSusForce = (-Dist * SuspensionStrength) - (project_vector(get_point_velocity(Ray.global_position), global_basis.y) * SuspensionDamping)
				apply_force(CurrentSusForce, Ray.global_position - global_position)

i am very thankful for your willingness to spend your time to answer my questions, you have given me insight on my original question (project method) and on a different approach to do this, which will certainly be useful while making other things, my lack of ability to communicate my problems clearly isn’t something under my control sadly

Fair enough. The use of Hooke’s Law in your code is similar to how I would do it; it just differs with how the vectors are computed. As long it works.

I disagree. Most things pertaining to one’s own abilities is mostly under your control. However, I understand that learning a different language can be hard.
I recently started learning a third language and it’s very hard right now.

It seems like we figured it out in the end though – that’s all that matters.


Good luck with your vehicle simulation!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.