# Physics of tracked vehicles

This topic is 1277 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have a hobby project in Unreal Engine 4, where I try to build some sort of template for simulation of tracked vehicles. It was going rather well until a point where I've tried to investigate why it's so difficult to steer tracked vehicles. If you want to see how it work right now you can grab executable from the first post:

if you have experience with blueprints in UE4, the link to the git repo is in the same post.

I don't think it's possible to describe all implementation details as post will be rather long and difficult to follow, but I'll try my best to squeeze in the description of how friction specific sub-system works and which part is a source of major headache.

There is a simple simulation of the engine connected to gearbox, axle and then steering differential. Angular velocity of axle is integrated and used as input into calculating torque output of the engine and angular velocity of the sprockets which pull tracks.

The traction of the vehicle is based on friction and comes in two parts:

1) Torque coming from the engine, which creates an opposing force at point of contact

2) Relative velocity of the track at point of contact

The way it's processed is rather simple:

- the assumption is that we run calculation only at points of track directly under the road-wheels and only if road-wheels are in "contact" with the ground

- at each contact point we calculate relative velocity of the vehicle (linear velocity of root + linear velocity as a result of vehicle rotation)

- linear velocity of the track itself is calculated from angular velocity of the sprocket which pulls it

- from relative velocity of the vehicle we subtract linear velocity of the track and project it on the surface of the ground, which gives us a final relative velocity of the track in relation to the ground surface

- from final relative velocity we calculate a total force necessary to completely stop the vehicle (taking into account multiple contact point), by multiplying velocity by mass of the vehicle and dividing by delta time to turn "impulse" into force, let's call this velocity induced force

- the other part of friction is calculated as force opposing torque from engine, let's call it torque induced force

- velocity and torque induced forces are summed up and let's call their sum "total stopping force", we can't apply it yet as we need to take into account normal force and friction coefficient
- normal force at contact point is calculated using suspension of the road-wheel
- using normal force and friction coefficient we get an upper bound of friction force

- "total stopping force" is capped in magnitude by upper bound of friction force and resulting force is applied to chassis of vehicle
Now I need to apply some of this friction force to the track itself, so for example tracks can roll in neutral on the slope. This is where it get hairy. My reasoning was that I can take friction force which was applied to vehicle and calculate which portion of it would be applied to track. For this I just

divide final friction force by the mass of the vehicle and then multiply by the mass of the track. Resulting force is turned into torque and applied to the axle after calculating angular acceleration. Does this make sense?

There were couple of problems with my variables, first the moment of inertia of track and sprocket (rest of transmission was ignored) were not calculated properly and total mass of the tracks was 3 times lower than it was supposed to be. I've recalculated moment of inertia into more realistic range but main problem arrived when I changed mass of the tracks. As mass of the track went up, the friction force effecting track became larger as well, at this point of time it's so large that tanks can barely do a neutral turn.

I'm not sure where the bug is, perhaps my engine torque is just too weak (maybe I forgot to take into account gearbox) or my logic of applying friction to the track itself is completely off. In latest compiled version of the project I had to make downsize force effecting track to about 6 times.

Maybe someone has an idea of what I'm doing wrong. Most likely I have some heresy in the physics model that I'm trying to apply or perhaps only "velocity induced force" should be applicable to the track and not "torque induced force" as it already adds velocity to the track (realized this when I was writing this post).

##### Share on other sites
No clue, but i remember a very realistic tracked vehicle in Newton physics engine.
It was made as a stress test for a new algorithm to eliminate joint error (every piece of the track is aunique body connected by joints),
so most of the things you try to model happen automatically, but it's surely worth a look.

There was also an older demo with a simpler modeled tracked vehicle like you do, but it seems broken at the actual version,
maybe check the older stable releases on github.

newtondynamics.com -> github -> build demosSanbox in release mode, select 'Articulated robotic actuators' demo

##### Share on other sites
I've seen couple of examples based on simulating track. They do look really good and you get all nice effects of track sway, correct obstacle climbing, braking of the track is very easy to do as well. Unfortunate part is a performance hit, stability at high velocity and LOD. This is the main reason why I went in direction of raycast/cylinder collider type of simulation.

I think the main issue is the logic of how friction force is transferred to chassis. If one would aim for idealistic simulation of a single wheel then there would be several cases which need to be resolved. One, where wheel is not powered and not breaking. Ignoring mechanical losses, all friction force, except part aligned with rotational axis of the wheel, would be applied to chassis. The part aligned with rotation axis would be transformed into torque on the wheel. The other case is when wheel is powered. In this case to get the force acting on chassis we need to find overlap between torque coming from engine and torque from aligned part of friction force. If torques are opposing each other the we get an overlap which is transformed into force on chassis at point of suspension. If torques are alligned then we sum them up.
(To be continued)

##### Share on other sites

(continue)

What I mean by overlap of torque is let's say engine provides 100Nm on pivot of the wheel in clockwise direction. Opposing friction force provides 60Nm of torque in clockwise direction. The resulting torque left on the wheel is 40Nm and 60Nm is transferred into force pushing chassis forward. Does this make sense?

##### Share on other sites

Got a bit of a pseudo-code for a wheel simulation, if this works I'll extend it to tracks:

chassisVelocityAtPoint = getVelocityAtPoint(Chassis, contactPoint) //root linear velocity + linear velocity from chassis rotation
relativeVelocity = projectOnPlane(chassisVelocityAtPoint - wheelLinearVelocity, surfaceNormal)
velocityInducedForce = relativeVelocity * vehicleMass / deltaTime
maxFrictionForce = length(mu * NormalForce)
wheelTorque = GetWheelTorqueFromEngineAndGearBox()
fullFrictionForce = capVectorLength(velocityInducedForce + torqueInducedForce, maxFrictionForce)

frictionForceOnWheel = projectOnVector(fullFrictionForce, wheelForwardVector)
frictionForceToChassis = fullFrictionForce - frictionForceOnWheel //reject part of the force which contributes to wheel roll
AddForceAtLocation(Chassis, frictionForceToChassis, contactPoint) //force on chassis from wheel slip

transmissionFactor = clamp(breakRatio + wheelAxleInefficiency, 0.0, 1.0) //wheelAxleInefficiency is a small variable representing some rotational friction of axle
frictionForceToChassis = frictionForceOnWheel * transmissionFactor
AddForceAtLocation(Chassis, frictionForceToChassis, contactPoint) //force on chassis from wheel rotation

frictionTorqueOnWheel = frictionForceOnWheel * wheelRadius * (1 - transmissionFactor)
wheelTorque = wheelTorque - frictionTorqueOnWheel
RecalculateWheelAngularVelocity()


• 17
• 12
• 11
• 21
• 16