Getting Tangential speed for a wheel in the rotation direction?

Hey, I’m trying to get the tangential velocity of a spinning wheel, in order to calculate skidding and stuff like that…
But no matter what I try it always leads to a dead end… I tried just using BasePart.RotVelocity, as well as the new AssemblyAngularVelocity - no luck… And now my custom approach has the same issue as they did…

My current approach…

local LastRotValue = {};
runServ.Heartbeat:Connect(function(dt)
	for i, wheel in pairs(Wheels:GetChildren()) do
		if LastRotValue[wheel.Name] ~= nil then
			local prev = LastRotValue[wheel.Name]
			local new = wheel.CFrame.upVector
			local radius = wheel.Size.Z/2
			
			local angle = math.acos(prev:Dot(new))
			
			wheel:SetAttribute("TangentialVelocity", -UsefulFunctions.Round((angle/dt) * radius, 2))
			LastRotValue[wheel.Name] = new
		else
			LastRotValue[wheel.Name] = wheel.CFrame.upVector
		end
	end
end)

Basically I want the rotation to be relative to the wheel itself, not global… if that makes sense…
Because you can’t accurately tell the RPM’s of a wheel if it appears to speed up and slow down (even go into negatives)… And the same issue was with RorVelocity, too… (issue is the velocity shifts from positive to negative when steering the vehicle towards and away from -Z)

I assume I explained it quite poorly, however I’ll try helping as much as possible, providing someone actually responds. I’m guessing the issue is I’ve forgotten to account for wheels turning rotation or something…

How are you causing the wheel to rotate in the first place? Is it just a VehicleSeat?

Hinge constraint, setting torque and changing speed to move forawrd/reverse

Edit: I would use the RotVelocity.Magnitude. but I only want the axial rotation of the wheel… that would also apply rotation caused by drifting…

Edit #2: RotVelocity is global, I’m looking for a local solution, whether that is the wheels own space or at least relative to vehicle main part… I really just need the delta angle / second… It appears to be harder than I originally thought.

You could look at the HingeConstraint’s CurrentAngle every frame instead of calculating the angle between the UpVector if you want to go the “calculate velocity by hand” route.

Or you could try to project the BodyAngularVelocity onto the axis of rotation. Not sure if this is quite right but give it a shot:

local function AngularVelocityOnAxis(part, worldAxisUnit)
	local angVel = part.AssemblyAngularVelocity
	local projectedOnAxis = angVel.Unit * angVel:Dot(worldAxisUnit)

	return projectedOnAxis.Magnitude
end

Multiply that result by the radius and boom.

For example

local wheel = ...
local angvel = AngularVelocityOnAxis(wheel, wheel.CFrame.RightVector) -- assuming its rotating around X axis
local radius = wheel.Size.Z / 2 -- assuming that's the radius
local tanVel = radius * angvel
1 Like

Actually you might just be able to do

local function AngularVelocityLocal(part)
	return part.CFrame:VectorToObjectSpace(part.AssemblyAngularVelocity)
end

local tangentVel = radius * AngularVelocityLocal(wheel).X

Kinda sorta. It doesn’t really make sense to get a local velocity like this though, I like the first solution better.

1 Like

Hey, thank you for your help, still not 100% what I wanted, even if it’s very close.
Couple issues. first and most obvious is that the new AssemblyAngularVelocity takes into account the movement of entire vehicle, I’m looking for a specific wheel rotation velocity. And, while RotVelocity can be used, it’s deprecated, and there comes a risk, no matter the magnitude, that future roblox updates could break the functionality of it, so I’m looking for a custom approach…
But the Hinge current angle seems the most promising! Although, my current approach by storing the previous angle, and subtract from the new angle works more like acceleration/deceleration. There’s also the issue of the rotation being clamped to 360, which causes a few issues for me… I could maybe check when the new rotation is less than the old one, to get an idea of when the angle refreshed, but that would still not save me from skipping an entire turn or whatever… However I’m using Heartbeat, so not even sure if I can actually skip a full lap…

Edit: Yeah, sooo… the “current angle” is in range from 0-180, and then it goes to -180-0… It made things a bit more annoying, but I think it’s still doable…

Stealing from this q:

    -- Shortest distance (angular) between two angles.
    -- It will be in range [0, 180].
    function DistanceDegrees(alpha, beta) {
        local phi = math.abs(beta - alpha) % 360; -- This is either the distance or 360 - distance
        local distance = phi > 180 and 360 - phi or phi;
        return distance;
    }
1 Like