Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How to convert angular velocity to linear velocity?

Asked by
y3_th 176
4 years ago

I have a BasePart with zero friction that I want to inherit the velocity of the BaseParts beneath it. When it comes to linear velocity, all I have to do is add the velocities of the BaseParts, then add whatever additional velocity I want on top of it in order to achieve my goal.

function FixedUpdate(_, deltaTime) --connected to RunService.Stepped
    local baseVelocity = Vector3.new()
    for _, part in pairs(GroundedParts) do 
        if part.CanCollide then 
            baseVelocity = baseVelocity + part.Velocity --there could be a better way to handle velocity by getting the average of all of the velocities but i'm too lazy to do that right now
        end
    end

    local additionalVelocity = Vector3.new(10, 0, 0)

    FinalVelocity = additionalVelocity + baseVelocity
    Movement.Velocity = FinalVelocity --Movement is a BodyVelocity parented to the Part
end

I can also do the same thing with angular velocity and rotations, although I use a BodyGyro instead of a BodyAngularVelocity to lock the X and Z axes of rotation and make it easier to make the part face at an angle.

function FixedUpdate(_, deltaTime) --same function as before except I removed all of the unnecessary parts so this is easier on the eyes I guess
    local baseRotVelocity = Vector3.new()
    for _, part in pairs(GroundedParts) do 
        if part.CanCollide then 
            baseRotVelocity  = baseRotVelocity + part.RotVelocity
        end
    end

    FinalRotation = FinalRotation * cfa(0, baseRotVelocity.Y * deltaTime, 0)
    Rotation.CFrame = FinalRotation
end

However, I face an issue when trying to convert the angular velocity into linear velocity. No matter what I try, the rotation always seems slower or faster than the linear velocity, destroying the effect. The only thing I've seem to have gotten correct is how to calculate the direction of the linear velocity, which is perpendicular to the vector between the part that inherits the angular velocity and the part that has the angular velocity.

local function perpendicular(v)
    return Vector3.new(v.Z, 0, -v.X) --roblox apparently has a "right-handed" cartesian coordinate system so i have to do this which is just a negated form of Vector3.new(-v.Z, 0, v.X)
end

local radius     = ((Character.Position - part.Position) * Vector3.new(1, 0, 1)).Unit
local tangent    = perpendicular(radius).Unit --there could be a better way to do this using the cross product between the y axis and the radius but i'm just going to leave it like this for now

How am I supposed to calculate the magnitude to multiply the direction by? I know that it somehow involves the angular velocity itself (which is why nothing spins when a part has an angular velocity of 0, 0, 0), but what else should I throw in there, and why?

NOTE: sorry for the bad grammar it's almost 8 pm

0
use a camshaft Fifkee 2017 — 4y
0
that's an oddly specific problem, what exactly are you trying to achieve with this Elyzzia 1294 — 4y
0
just thought of something to answer this problem y3_th 176 — 4y

1 answer

Log in to vote
0
Answered by
y3_th 176
4 years ago
Edited 4 years ago

Preface

It seems that I was over-complicating this question for anyone to understand, so I've figured out a solution and posted it here. Converting angular velocity to linear velocity was actually easier than I thought.

Prerequisites

  • An understanding of the formula for the length of an arc (length = angle * radius)
  • A way to get a perpendicular vector in two-dimensional space

Explanation

In order to convert angular velocity into linear velocity, we must first get the direction of the linear velocity, which is perpendicular to the distance between the part we want to apply the angular velocity to and the part with the angular velocity.

--just imagine that part2 is the part we want to apply the velocity to and part1 is the part that has the velocity
local function perpendicular(v)
    return Vector3.new(v.Z, 0, -v.X)
end

local radius     = (part2.Position - part1.Position) * Vector3.new(1, 0, 1)
local tangent    = perpendicular(radius).Unit --this is the direction that we want the linear velocity to go in

Now that we have the direction of the linear velocity, we need to find the magnitude to multiply it by. Fortunately, the formula for the length of an arc is helpful here. We can treat the linear velocity as a line tangent to a circle that has a magnitude equivalent to the length of an arc with a central angle equivalent to the angular velocity on the Y axis.

local radius     = (part2.Position - part1.Position) * Vector3.new(1, 0, 1)
local tangent    = perpendicular(radius).Unit --this is the direction that we want the linear velocity to go in
local magnitude  = radius.Magnitude * part.RotVelocity.Y --this is the length of the arc, multiplying the radius by theta, which is the part's rotational velocity on the y axis

All we have to do now is to multiply the magnitude by the direction, which gives us what I think is a nice and clean solution.

baseVelocity = baseVelocity + magnitude * tangent

Result

Here's how it turned out.

!embedding broke

It's funny how I spent a week trying to figure this out before going to ScriptingHelpers and then thought of a solution just a few hours after waking up the next day.

0
Oddly enough I sometimes go to bed thinking of a problem and literally wake up with the answer the next day. Sometimes the best thing to do is to take a break from it for a while, otherwise you could end up causing more harm than good to your code. SteelMettle1 394 — 4y
Ad

Answer this question