Clutch Modelling Help

Started by
17 comments, last by Vu Chi Thien 6 years, 2 months ago
Quote

if this clutchTorque is used to drive the wheels, then there will be torque only if there is different in engineSpeed and wheelSpeed, ie torque is highest if clutch is slipping like crazy, which is not correct. And since this torque is fed back to the engine, then the engine speed would going up and down in a unrealistic manner. 

Using that linear model you are simulating something closer to a torque converter (fluid coupling used in automatic transmissions) rather than a clutch.  So that's why there's lots of slipping. 

This can be ok, maybe you just need "stiffer" constants:


clutchTorque = 50.0f * (engineRPM - drivelineRPM)...
//or
clutchTorque = (engineRPM - drivelineRPM)^2 ...
//etc

Or if you just do:


if(engineSpeed > drivelineSpeed)
  clutchTorque = blah;
else
  clutchTorque = -blah;

Then you will have lots of torque as soon as you have 0.00001 slip.  You might need a combination of the two to get enough clutch "grab" but not have an unstable simulation.

 

Quote

Another thing is that the engine torque does not go to the wheels but only the reaction torque does, which is

On 1/27/2018 at 4:37 PM, CombatWombat said:

clutchTorque = frictionConstant * clutchFactor;

which is a very small amount of torque.

Why is it a small amount?  You get to choose the frictionConstant to be whatever you desire. 

Maybe I confused you with using frictionConstant as the name.  I did not mean to suggest using something like 0.5 mu friction coefficient.  A real clutch has friction coefficient (0.5ish), heavy springs (~5000N+ normal force), and a mean radius (~0.125m) = ~312Nm.  Using something like 500-1000 for frictionConstant is not unreasonable.

 

Quote

Looking at the diagram (which is the best by the way), the way I understand it is that the engineNetTorque drives the flywheel, which is sideA. A fraction (0 - 100%) of that torque must affect/output to sideB, and how much of engineNetTorque is going to sideB depends on the amount of space in between sideA and sideB.

engineNetTorque drives the whole engine blob of mass.  Full stop.  Period.  Do not confuse  yourself with fractions of anything.  SideB of the clutch doesn't know what engine is doing.  It has no idea if there is an engine there at all.  Maybe its a hamster in a wheel.  Doesn't matter. SideB only knows that SideA is rubbing against it with some normal force and coefficient of friction.

 

Quote

I'm using (Unity3D), there is no way to extract roadReactionTorque at the wheel to feed back on the engine,

You don't have to.

You have some torque acting on SideB of the clutch (again, because SideA is rubbing against it, nothing to do with engine).  That gets multiplied by the gearbox.  You give this to your UnityWheelThing, it performs integration and has a new speed.  Next frame, you read that speed, multiply it by gearbox ratio, and that becomes the new speed for clutch-side-B.

 

 

 

Advertisement
8 hours ago, CombatWombat said:

Maybe I confused you with using frictionConstant as the name.  I did not mean to suggest using something like 0.5 mu friction coefficient.  A real clutch has friction coefficient (0.5ish), heavy springs (~5000N+ normal force), and a mean radius (~0.125m) = ~312Nm.  Using something like 500-1000 for frictionConstant is not unreasonable.

Oh! This, right here, is the source of my confusion about your implementation. I get it now. However I still have question. I other models I've looked at, they also use this torque to drive the wheels. In my understanding, this torque is the Capacity of the clutch, which means how much torque it can endure before it slips. Because of that I don't think of it as a torque to drive the wheel side. This leads to my other question: 

Say the engine is capable of outputting 400 Nm, and the clutchTorque is 500 Nm. If we use this 500 Nm clutchTorque to drive the wheels, then when the clutch is fully engaged, engineSpeed == wheelSpeed, 500 Nm will go to the wheel side instead of the maximum 400 Nm that the engine can output?

I put something together that may help.  Hope .xls can be attached here.  If not PM and I will email it.

Looking at the chart:

First ~50ms or so, clutch is disengaged.  You see engine accelerates freely, and gearbox coasts.  When clutch engages, engine speed dives down, and gearbox speed increases until they match.

In this, I used the linear/proportional model:


clutchTorque = SomeConstant*(EngineSpeed-DrivelineSpeed)

This works, but there is significant slippage as drivelineSpeed constantly lags behind engineSpeed.

So I added an integral term.  So the above becomes something like:


speedError = EngineSpeed-drivelineSpeed;
integralError += speedError;
// Make sure not to add to integralError when the clutch is disengaged!

clutchTorque = proportionalConstant*speedError + integralConstant*integralError;

There is a somewhat narrow range of values for proportionalConstant and integralConstant where this works and is stable.  Mostly because I'm using simple Euler integration here at only 100hz.  You can experiment with adding derivative term, using better integrators, or upping the refresh rate to get better stability.  Or switch to a locked model once the speeds get close.

 

 

 

ClutchModel.xls

12 hours ago, CombatWombat said:

I put something together that may help.  Hope .xls can be attached here.  If not PM and I will email it.

Looking at the chart:

First ~50ms or so, clutch is disengaged.  You see engine accelerates freely, and gearbox coasts.  When clutch engages, engine speed dives down, and gearbox speed increases until they match.

In this, I used the linear/proportional model:



clutchTorque = SomeConstant*(EngineSpeed-DrivelineSpeed)

This works, but there is significant slippage as drivelineSpeed constantly lags behind engineSpeed.

So I added an integral term.  So the above becomes something like:



speedError = EngineSpeed-drivelineSpeed;
integralError += speedError;
// Make sure not to add to integralError when the clutch is disengaged!

clutchTorque = proportionalConstant*speedError + integralConstant*integralError;

There is a somewhat narrow range of values for proportionalConstant and integralConstant where this works and is stable.  Mostly because I'm using simple Euler integration here at only 100hz.  You can experiment with adding derivative term, using better integrators, or upping the refresh rate to get better stability.  Or switch to a locked model once the speeds get close.

 

ClutchModel.xls

The xls is you sent shines a lot of light on me. Thanks so much for that. I'm also using Euler at 100Hz. 

Still I have a lot of jittering at low speed delta (engineSpeed - wheelSpeed). Decreasing proportionalStrength and integralStrength helps somewhat, but that would let  the speed delta increasingly large which led to power loss and the car cannot reach max speed at current gear. So this acts more like a torque converter like my first implementation. 

Say if I want to implement a model that uses constant clutchTorque like you gave earlier:

On 1/28/2018 at 4:37 AM, CombatWombat said:

clutchTorque = frictionConstant * clutchFactor;

then I can replace proportionalStrength * speedError with the frictionConstant, and keep integralStrength * integralError right? Since the integral part acts like sort of a "damping" that scale with speed delta, so when the delta is small the damping gets smaller. To me I would prefer this model you first shown since it acts more like a real clutch, which is what I'm going after. 

Also if I were to implement the locked model, then what would be the condition for lock-up? Since it's really hard to get speed delta to be exactly 0, using speed delta as the condition is not very good. Second is comparing torque of 2 sides with the clutch capacity, but at low engine or wheel torque, the torque will of course be lower than the capacity, which means the clutch would locked immediately. Also this is not very possible since I cannot extract reaction torque from the wheel side. Have you ever implement this and do you have any suggestion for this implementation?

If you don't mind, I would like to ask what model did you use in your project, the clutch converter like type, the constant clutch torque type, or the locked clutch type? And what engine or language did you use?

 

Again, thank you so so much for everything you have done until now. You were a big help to me.

Quote

Since the integral part acts like sort of a "damping" that scale with speed delta

It does not.  Look again at the implementation.  Integral is integral of a PID controller.  Essentially proportional gets you close, and then integral compensates for the long term error. 

 

Quote

To me I would prefer this model you first shown since it acts more like a real clutch, which is what I'm going after.

Real clutch only applies that 500Nm (or whatever) until the nanosecond it's speed has equalized.  In discrete time you are stuck applying it for the full 10 ms.  This makes it jittery.  The proportional model is smoother in this respect.

 

Quote

Also if I were to implement the locked model, then what would be the condition for lock-up?

As bmarci said in a previous post, and good plan is to lockup when the sign changes (zero crossing).


lastSpeedError = speedError;
speedError = engineSpeed - drivelineSpeed;

if(sign(lastSpeedError) != sign(speedError))
	// Zero crossing, lockup.

 

Quote

If you don't mind, I would like to ask what model did you use in your project, the clutch converter like type, the constant clutch torque type, or the locked clutch type? And what engine or language did you use?

Used the constant type, but with a lockup method that summed the inertia of the entire driveline and treated it as one part, so the jitteryness wasn't apparent.

C++.  Engine wasn't mine, but was rolled from scratch for the game.

 

Thanks so much again. 

I'm still studying and testing around with the model you gave me in the xls. It will take a while for me to get good result and come up with a good combination of values. Still I have some confusion I would like to ask:

On 2/1/2018 at 8:42 PM, CombatWombat said:

It does not.  Look again at the implementation.  Integral is integral of a PID controller.  Essentially proportional gets you close, and then integral compensates for the long term error. 

So after trying different values, to me increasing the proportional and integral would result in getting to the desired value faster, but gives more oscillation at high time step. Lower values would result in a smother jump. So from here I think with high torque value using lower proportional and integral would be better, and higher values for lower torque.

 

On 2/1/2018 at 8:42 PM, CombatWombat said:

Real clutch only applies that 500Nm (or whatever) until the nanosecond it's speed has equalized.  In discrete time you are stuck applying it for the full 10 ms.  This makes it jittery.  The proportional model is smoother in this respect.

 

Because in the model discussing here in the topic, clutchTorque, which is frictionConstant * clutchInput, is used to drive the wheels. So say I have an example: 

The engine produce 400Nm maximum torque.

The torque capacity of the clutch is 500Nm.

So when the clutch is fully closed, would the full 500Nm of clutchTorque go to the wheels despite the engine cannot produce that much torque (max 400Nm)? This is the biggest confusion for me right now.

Quote

So after trying different values, to me increasing the proportional and integral would result in getting to the desired value faster, but gives more oscillation at high time step.

Yes pretty much.

 

Quote

So from here I think with high torque value using lower proportional and integral would be better, and higher values for lower torque.

Maybe.  It's also highly effected by the masses/inertia, tire "stiffness", etc.

 

Quote

So when the clutch is fully closed, would the full 500Nm of clutchTorque go to the wheels despite the engine cannot produce that much torque (max 400Nm)? This is the biggest confusion for me right now.

Yes, but only for one frame.  The next frame it might be -500.  It might do +500, +500, -500, as it oscillates around the target set point.  It should average out very close to 400Nm over enough frames.  The linear model I sent in the xls definitely averages out where the transmitted torque is nearly equal to the engine's torque produced (it will not be exact as some of the torque is required to accelerate the engine's own inertia.)  It should work similar with the more "digital" model, but you'd need to experiment.

Does your model now work properly, but exhibit some other strange quirks?  Or does it still completely run-away?

 

So, this is a bit above my pay grade, but in general I'd say this problem could be described as trying to solve a 1D velocity constraint.  So I'd wonder if some of the techniques used in collision response (sequential impulse, etc) might be applicable here.  Anyone?

On 2/5/2018 at 9:58 PM, CombatWombat said:

Yes, but only for one frame.  The next frame it might be -500.  It might do +500, +500, -500, as it oscillates around the target set point.  It should average out very close to 400Nm over enough frames. 

OK, so with non-locking model, there will always be a little bit of oscillation when delta velocity gets smaller, but eventually gets averaged after enough timestep, and the output at the frame update is smoothed. And with high torque cases (super cars, race cars, high power trucks ...) we need small timesteps/high frequency.

Quote

Used the constant type, but with a lockup method that summed the inertia of the entire driveline and treated it as one part, so the jitteryness wasn't apparent.

So basically like:


if (clutchLocked)
{
  engineSpeed = wheelSpeed * Gear;
  torqueAtWheel = (engineTorque * Gear) * diffBias; 
}
else
{
  engineSpeed += (engineTorque - clutchTorque)/engineInertia;
  torqueAtWheel = clutchTorque * Gear * diffBias;
}

 

 

On 2/5/2018 at 9:58 PM, CombatWombat said:

Does your model now work properly, but exhibit some other strange quirks?  Or does it still completely run-away?

I'm still experimenting with different values and having fairly good result at high speed, high engine RPM, but still lots of jittering at low speed low gear and high torque. One reason for the jittering is actually because of the built-in physic engine, so I also have to play around a lot with the timestep and substep config of the engine itself, which is going to take a long time. This problem occurs with everyone I asked in the official forum and no one has the solid solution yet.

On 2/5/2018 at 9:58 PM, CombatWombat said:

So I'd wonder if some of the techniques used in collision response (sequential impulse, etc) might be applicable here.  Anyone

Talks about impulse, I bumped into this forum post of an open-source racing sim, with used impulse for clutch modeling, and based on the engine - wheel speed difference. Basically this model calculate engine torque impulse and clutch resistance impulse, and the net torque drives the engine inertia:


engineVelocity += (engineTorqueImpulse - clutchDragImpulse) / engineInertia;

And here's the clutch impulse calculation:


public float GetDragImpulse(float engine_speed, float drive_speed, float engineInertia, float drivetrainInertia, float ratio, float engineTorquedt){
    
    float drivetrainInertiaR=drivetrainInertia/ratio;
    impulseLimit=clutch_position*torqueCapacity*Time.deltaTime;

    float lambda=(engineInertia*drivetrainInertiaR*(drive_speed - engine_speed) - drivetrainInertiaR*engineTorquedt)/(engineInertia + drivetrainInertiaR);
    lambda = Mathf.Clamp(lambda, -impulseLimit, impulseLimit);
    
    return lambda;
}

Here the topic:

http://vdrift.net/Forum/showthread.php?tid=1617&page=2

This topic is closed to new replies.

Advertisement