Saturday, 26 February 2011

UDK Motorsport: Torque curves and engine sound

I have my gear plot. I need to find some way to combine that with the engine's torque curve in order to get the kind of curve Unreal requires. The obvious solution is to use the output of the gear plot as the input of the torque curve.

This is a basic mathematical tool called function composition. The problem is that while the gear plot is a set of linear functions, the torque curve isn't a function at all. So we need to find a function that has roughly the shape of the torque curve we are interested in.

After hours of Googling, I stumbled upon that post which gave me the beginning of the solution: the idea is to use the engine's power curve, which has (partly) the shape of a cubic function.

In order to get a curve resembling our power curve, we will need to do something called curve fitting. I won't extend on how to do the fitting, it's quite trivial with gnuplot. However, keep in mind that you need a few sample points for the fitting to work. Just grab half a dozen points' coordinates along the curve, especially on the upward and downward slopes and at the extremum. Also, if you're using gnuplot to do the fitting, just remember to set the correct range before doing the fitting, or you'll end up with an incorrect curve.

Using some random data inaccurately measured from the 2004 Boxster curve I had on the first post about gears,  I get the following fitted curve (I've made some scaling to get readable power values):

Looks about right. Now, it's easy to retrieve the torque, as the power equals the revs (in rad/s) times the torque. So we just have to divide the power by the revs and we'll get the torque curve:
Let's compare with the original curves:
We're a bit off, but it does look okay (note that the ranges are slightly different on the two graphs). You can also see that the torque curve is getting funky near 0, which is normal, since we're dividing by a value that tends to 0. The post I mentioned earlier does state that this method is unreliable for rotational speeds under 1000 RPM, but in the case of cars, the engine spends very little time under that threshold, so it should be okay.

Now that I have my torque curve as a function I can put stuff into, it becomes easy to get the torque based on the linear speed for each gear:
Note that since the speed is in UU/s, the torque is in NUU rather than in Nm.
And there we finally are! Implementing those curves in Unreal is quite easy. We'll just take 4 points:

  • The origin.
  • The maximum torque.
  • The speed at which the torque reaches 0.
  • The speed at which the torque reaches -100. (No, you can't see that point on the graph above.)
The origin seems to be the same for all gears. For the other points, the OutValue is obviously the same for all gears as well, only the speed changes.  With the curve above, I get the following points:

Gears(1)=(TorqueCurve=(Points=((InVal=0.0,OutVal=7.0,InterpMode=CIM_CurveAuto),(InVal=360.0,OutVal=13.0,InterpMode=CIM_CurveAuto),(InVal=870.0,OutVal=0.0,InterpMode=CIM_CurveAuto),(InVal=961.0,OutVal=-100.0,InterpMode=CIM_CurveAuto))))
Gears(2)=(TorqueCurve=(Points=((InVal=0.0,OutVal=7.0,InterpMode=CIM_CurveAuto),(InVal=580.0,OutVal=13.0,InterpMode=CIM_CurveAuto),(InVal=1400.0,OutVal=0.0,InterpMode=CIM_CurveAuto),(InVal=1538.0,OutVal=-100.0,InterpMode=CIM_CurveAuto))))
Gears(3)=(TorqueCurve=(Points=((InVal=0.0,OutVal=7.0,InterpMode=CIM_CurveAuto),(InVal=835.0,OutVal=13.0,InterpMode=CIM_CurveAuto),(InVal=2000.0,OutVal=0.0,InterpMode=CIM_CurveAuto),(InVal=2200.0,OutVal=-100.0,InterpMode=CIM_CurveAuto))))
Gears(4)=(TorqueCurve=(Points=((InVal=0.0,OutVal=7.0,InterpMode=CIM_CurveAuto),(InVal=1278.0,OutVal=13.0,InterpMode=CIM_CurveAuto),(InVal=3040.0,OutVal=0.0,InterpMode=CIM_CurveAuto),(InVal=3347.0,OutVal=-100.0,InterpMode=CIM_CurveAuto))))
Gears(5)=(TorqueCurve=(Points=((InVal=0.0,OutVal=7.0,InterpMode=CIM_CurveAuto),(InVal=1810.0,OutVal=13.0,InterpMode=CIM_CurveAuto),(InVal=4370.0,OutVal=0.0,InterpMode=CIM_CurveAuto),(InVal=4812.0,OutVal=-100.0,InterpMode=CIM_CurveAuto))))

Note that I've scaled the outvals down as it seemed to provide too much torque as it were. But that is a matter of tweaking I didn't take the time to completely figure out.

This yields the following results:


"Hey, the engine makes some noise!"

Yep, let's quickly talk about that. SVehicle has an AudioComponent property called EngineSound. It's set as follows:

begin object class=AudioComponent Name=CarEngineSound
 SoundCue=SoundCue'A_Vehicle_Scorpion.SoundCues.A_Vehicle_Scorpion_EngineLoop'
end object
EngineSound=CarEngineSound
Components.Add(CarEngineSound);

Then, UDKVehicleSimCar uses its EngineRPMCurve property to change the pitch of the car's engine according to the simulated RPM. As for the torque curve, I'm using one curve per gear (on the video, it's the small graph).
It's very easy to implement since we already have those curves in the gear plot. Being linear, only two points are needed for the curve: one for the origin, one for the max RPM. Note that at the origin, I set OutVal to 1000 rather than 0 as even when the car is stopped, the egine should make some noise.

8 comments:

  1. Nice tutorials, thanks! Any UDK Motorsport posts soon?

    ReplyDelete
  2. They aren't really tutorials, but thanks :)

    I have a post about Pacejka curves in the works, but it's not ready yet.

    ReplyDelete
  3. Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.

    ReplyDelete
  4. Man u saved my life :) Thanks a lot

    ReplyDelete
  5. I noticed just a thing: with this trick, it seems that every gers applies the same amount of acceleration to the car, instead that making the first gear a lot more "powerful". Probably it just need to vertical scale the speed/torque graph...what do you think?
    (sorry for bad explanation, but i'm not english... :( )

    ReplyDelete
    Replies
    1. Err, I'm not sure I get what you mean. The first gear of a car is supposed to be a lot more "powerful" than the others. Plus, the maximum amount or *torque* an engine can provide has nothing to do with the gear you're in. Vertical scaling would just make it wrong.

      Delete
    2. Let's suppose we have a gearbox with this ratios: 3.3, 2.5, 1.8, 1.3, 1.0 and a final ratio of 3.0 and an engine with a max torque of 300NM. (random numbers!)
      If you're running in 1st gear, to the wheels,you're not going to provide 300NM, but 300NM * 3.3 * 3.0 = 2970NM, otherwise, when in 5th gear you're providing to the wheel only 900NM. This means that you have a greater acceleration in 1st gear, rather than in 5th. Looking at your video, it seems that in 1st gear and in 5th gear, the "delta speed/delta time" is quite costant, but with the 5th gear "longer", the engine stays in the range of "high torque" longer, providing a sort of innatural acceleration. This is why i thought (well..think) that it could be useful a vertical scaling. Doing so, in 5th gear you stay longer in the range of high torque, but this torque is lower, providing an higer speed, but a lower acceleration. Or i miss a part and can't figure out where...

      ps: thank you for your reply!

      Delete
    3. I think you are correct, actually. Unfortunately, I'm not sure I still have the code and the data for this, so I can't quickly test that. If I ever get my hands on that stuff, I'll let you know.

      Delete