• Race hard. Race fair.

# ABS Script, it works, but how to make it better?

Discussion in 'Racer' started by Mr Whippy, Oct 29, 2012.

1. ### Mr Whippy

Messages:
2,977
Ratings:
+456
Hi everyone,

Just been tinkering with an ABS script this afternoon but wanted to make it better.

Here is the code so far

Code:
```//Focus on the car used by the script owner
rcar \$car=get scriptowner car

shared float \$slipratio0
shared float \$slipratio1
shared float \$slipratio2
shared float \$slipratio3
shared float \$brake0stat = 4040
shared float \$brake1stat = 4040
shared float \$brake2stat = 1920
shared float \$brake3stat = 1920
shared float \$brake0 = 4040
shared float \$brake1 = 4040
shared float \$brake2 = 1920
shared float \$brake3 = 1920
shared float \$wheel0optimum = -0.3
shared float \$wheel1optimum = -0.3
shared float \$wheel2optimum = -0.2
shared float \$wheel3optimum = -0.2

//Base frequency at speed for an 'off' cycle (total on/off cycle would be double this value in ms)
shared float \$abs_base = 40
//At what speed (m/s) to start to reduce the frequency of the ABS
shared float \$abs_slow = 10
//Factor that slows the ABS down linearly from the start of speed reduction to 0 (bigger = slower)
shared float \$abs_slow_factor = 14

shared float \$brake
shared float \$speed

shared float \$abs_speed

while 1
{
\$brake = get \$car brake

\$speed = get \$car tachovelocity

if \$speed < \$abs_slow
{
\$abs_speed = \$abs_base + ((\$abs_slow - \$speed) * \$abs_slow_factor)
}

\$slipratio0 = get \$car wheel 0 slipratio
\$slipratio1 = get \$car wheel 1 slipratio
\$slipratio2 = get \$car wheel 2 slipratio
\$slipratio3 = get \$car wheel 3 slipratio

//WHEEL0
if \$slipratio0 < \$wheel0optimum
{
if \$brake0 > 0
{
\$brake0 -= (\$brake0stat / \$abs_speed)
}
else
{
\$brake0 = 0
}
}
else
{
if \$brake0 < \$brake0stat
{
\$brake0 += (\$brake0stat / \$abs_speed)
}
else
{
\$brake0 = \$brake0stat
}
}

//WHEEL1
if \$slipratio1 < \$wheel1optimum
{
if \$brake1 > 0
{
\$brake1 -= (\$brake1stat / \$abs_speed)
}
else
{
\$brake1 = 0
}
}
else
{
if \$brake1 < \$brake1stat
{
\$brake1 += (\$brake1stat / \$abs_speed)
}
else
{
\$brake1 = \$brake1stat
}
}

//WHEEL2
if \$slipratio2 < \$wheel2optimum
{
if \$brake2 > 0
{
\$brake2 -= (\$brake2stat / \$abs_speed)
}
else
{
\$brake2 = 0
}
}
else
{
if \$brake2 < \$brake2stat
{
\$brake2 += (\$brake2stat / \$abs_speed)
}
else
{
\$brake2 = \$brake2stat
}
}

//WHEEL3
if \$slipratio3 < \$wheel3optimum
{
if \$brake3 > 0
{
\$brake3 -= (\$brake3stat / \$abs_speed)
}
else
{
\$brake3 = 0
}
}
else
{
if \$brake3 < \$brake3stat
{
\$brake3 += (\$brake3stat / \$abs_speed)
}
else
{
\$brake3 = \$brake3stat
}
}

set system "car0.wheel0.max_braking" to \$brake0;
set system "car0.wheel1.max_braking" to \$brake1;
set system "car0.wheel2.max_braking" to \$brake2;
set system "car0.wheel3.max_braking" to \$brake3;

interrupt
}```

So basically we define the starting braking values we want (same as car.ini values) for each wheel. That sets a target to get back to when the ABS is active.

Then we set the same value again just to get things going, but that value will change during operation, it just needs a starting value.

Then we define some variables, the ABS pulse speed, the start of slowing speed, and the rate it slows down by.

Then we define the optimum slip ratio for each wheel, this is based on preference but ideally you want a bit less at the rear to make it stable. Every car and it's tyres might need different values here.

Everything is linearly changed.

Then we check each wheel, if it's slipping over the optimum then we start to tweak the brake force down. We tweak the brake force down for slipping wheels again and again until they reach 0 brake force or stop slipping over the optimum slip ratio... at that point they start having their brake force increased again.

Then finally we set the braking forces to the car at the end of each physics step.

It seems to work nicely. I've factored plenty of variables, but it'd be nice to offer up a few modes to choose from, pairing both front wheels rather than each one, for both slip detection and for brake force adjustment.

I guess a function could be written that takes the main variables and applies it to each wheel, pairs of wheels, or all four wheels for example.

Then maybe it can make it into Onyx or Racer properly...

I know I've cheated by using slip ratio rather than wheel accelerations to detect slip, BUT, in the end the real ECU's will err towards this kind of response any way, that is the ideal response and thus they program towards it!

Anyone care to share ideas or improve the script further?

I'd really like to see basic 'car' features like this scripted by us guys and then we can maintain and improve them with time.
If Ruud then finds the time he can improve and/or implement them better or into Racer properly using our scripts as a guide!

Thanks

Dave

2. ### Stereo

Messages:
2,277
Ratings:
+1,240
The main thing I see to question is the input frequency - updating wheel speeds in the real world would depend on the wheel rotation sensors, so it won't necessarily happen at 1000Hz. Wikipedia suggests there won't be more than 100 pulses per revolution. Probably assume lower, say, 50 pulses per revolution (number of teeth on the sensor wheel). Anyway, if you then assume the wheel's about 0.65m in diameter, the wheel rotates once every 2m while not slipping, so at 10m/s it's 5 revolutions, or at best 250 pulses per second - one every 40mm. I think I would preferentially use this type of calculation to determine how often to pulse at low speeds. When you're talking a slip ratio of -0.3, then the wheel's already turning 30% slower than that, so only 175 pulses. (wheel speed = vehicle speed*(1+slip ratio) should be how it's defined)

If it takes a few pulses to determine the current speed then it's easy to see why it would take a bit to update.

I'd probably implement it something like (noting this isn't necessarily valid code)
Code:
```// before the while loop
float \$pulsetime0
float \$pulsetime1 // also wheels 2 and 3
float \$pulsedist = 120 // distance (in mm) wheel travels per speed update.  In this case 40mm per pulse * 3 to give it time to figure it out.

// in the while loop
\$pulsetime0 += \$interval
\$pulsetime1 += \$interval // etc.

if (\$pulsetime0 > \$pulsedist/(abs(\$speed)+0.01)) {
\$slipratio0 = get \$car wheel 0 slipratio
\$pulsetime0 = 0
} // and likewise for the other wheels
```
This would then replace the low speed pulsing changes, since at 10m/s this is already limiting it to 120/10 = 12ms delay to updates on wheel speed. The pulsing on and off should happen at a steady rate corresponding to opening/closing the ABS brake reservoirs imo.

It would be more accurate to update the distance traveled by each wheel, using something like
Code:
```\$pulsedist0 += \$speed*(1+\$actualslipratio0)*\$interval
...
if (\$pulsedist0 > \$pulsedist) {
\$slipratio0 = \$actualslipratio0
\$pulsedist0 = 0
}```
But that requires the current slip ratio, so then there'd have to be two slipratio variables - a real world one and a sensor one. Don't know if the extra effort is worth it. It does make the if statement simpler.

3. ### Mr Whippy

Messages:
2,977
Ratings:
+456
From what I've read the systems are set to pulse slower at low speeds primarily to improve effectiveness on snow and gravel type surfaces where the wedge build-up is a better solution to slowing down.

But clearly as you say, the resolution of the wheel speed sensor is important to determining the effective maximum frequency the system could feasibly run it, irrespective of what speed the ABS unit itself can apply and relax the braking pressures!

I suppose what you raise enforces realism, but having a user input with 'sensible' values would be just as effective but remove maths and allow flexibility. I guess it's also lighter on the processing to do less maths

What would be ideal is to create an excel sheet I guess that could contain the wheel speed sensor specifications and wheel/tyre dimensions, and a plot of maximum reliable frequency of speed updates vs actual tyre road speed...

That way we could then draw a .crv file and simply look it up to choose appropriate wheel speeds as a base point, and then tweak that (generally upwards (slower)) to suit our exact needs in testing.

I was already thinking about that a bit and so fired off an email to Ruud to ask if he can share any info/technique or best practice for Onyx/qscript/rsx stuff for loading in a CRV file and using it... if we could just draw a curve for the above considerations we kill a lot of complex maths by 'baking' the solution into a curve file (probably what some of the 2d/3d 'maps' are on cars in this case)

I keep thinking it'd be a great to have access to the wheel speed variable. We could then do what real ABS does and look at wheel rate of change of accelerations and look for 'unreal' acceleration rates.
We could do as you say above and input a factor for the 'resolution' of the wheels speed sensing and then get degrading intervals at lower speed via that method, along with any further slowing of ABS action we may want.
We could program ABS a little bit more realistically that way.

BUT, there is some mega maths in the ABS functions I've seen to do things like release all brakes if all four wheels are stopped to see if one starts spinning so the car can see if indeed the car is still sliding or is in-fact stopped.
Deriving the friction coefficient of the surface to adapt the real/unreal accelerations to the surface, etc.

I'm mainly thinking how can the script be made more streamlined from a function POV.

Ie, can we write a function for this that just runs the nested operations with wildcards, and then run the function on any number or pair of wheels, from 4 wheel cars with 2 channel, to 3 channel, to 4 channel, to 8 wheeled trucks etc.

In the end this is hard coded to 4 channel 4 wheel, but in practice the sensing and application of the function could be set to pairs, or detected on singles and applied to pairs, or any other combo you define I suppose.

The function itself can then be stored elsewhere (even in another script) and updated, while end users can just set the ABS settings they specifically require?!

Hmmmmm

Dave

4. ### Mr Whippy

Messages:
2,977
Ratings:
+456
Been tinkering with values a bit, the above ones are ok for some cars, but these seem more realistic for a modern sports car:

float \$wheel0optimum = -0.16
float \$wheel1optimum = -0.16
float \$wheel2optimum = -0.15
float \$wheel3optimum = -0.15

float \$abs_base = 50
float \$abs_slow = 12
float \$abs_slow_factor = 22

Obviously that higher reduction in low speed pulse rate looks more appropriate to real values when you watch the car come to a stop.

The optimum values were probably too high, with the above you get good steering control when stopping and still very good overall deceleration.

Brmmmmm!

Dave

5. ### Stereo

Messages:
2,277
Ratings:
+1,240
Yeah, I suppose the math is more important to just be sure the system that's set up is flexible enough to simulate all modes decently - and a starting point is to explore how they work in reality, so we can figure out what behaviour can be expected. Since slip rates aren't generally measurable (maybe with GPS they could be?) the system isn't going to know that all 4 wheels are slipping optimally, just that certain wheels are experiencing sudden deceleration. Or in something like a Skyline, the accelerometer of the car will say the wheels should be slowing at rate X, so if they exceed that, something's up. I imagine that would change the behaviour under all 4 wheels sliding, too - the car's decelerating but wheels aren't moving means all brakes should be cut temporarily.

Haven't given the script a try in Racer yet, will do soon.

In terms of splitting up behaviour and general logic, I suppose you could do a function that returns the abs application of four wheels, on a range from 0 to 1 each - input would be the current sensor info of the four wheels (slip ratios), brake input, and whatever other information the car can give it. The function would keep track of timing, thus being in charge of which if any wheels got synchronized ABS pulsing.

I guess I only mentioned briefly in the other post, but wheel speed should be derivable from vehicle speed and slip ratios - a ratio of 0 means they're equal, -1 means the wheel's stopped, according to the reference, so wheel speed = vehicle speed*(1+slip ratio).
Of course, if you can derive a formula using the wheel speed, you can substitute vehicle speed and slip ratios into it - for example, if the car and wheels are matching deceleration then slip ratio is constant, if the slip ratio changes then the wheel's accelerating at a different rate from the car. So one variation on this would be to instead of define optimum slip ratios, define a max change per unit time, and turn off the brake when the slip ratio jumps suddenly.

It would probably help visualize to plot slip ratios, here I turned on logging and did a 0-150km/h-0 run.

Lots of rear wheelspin at the start, then a deceleration during the shift into second, then into third, and then hard on the brakes. Peak acceleration may be a little misleading because drag was certainly helping at first. This is 100% on the brakes so I can't say why the rear wheels stopped slipping.

Focusing in on the braking section,

It definitely looks like at about the 19.25 second mark the front wheels diverge strongly from the rears (wheel 0 more than wheel 1) and gets optimal braking around 19.4 seconds. Which matches up with how ABS is described - one (or in this case two) wheels with unusually fast deceleration.

Using the script from your first post, with changed constants as per second.

(again, just from starting braking until it stabilized)

What's concerning me is that this is a slower deceleration and a longer stopping time. I don't know if I have the script tuned wrong or what.

The RX-7's brakes have
max_braking=2650
braking_factor=0.7
and same max_braking on the rear, but factor 0.3, whereas yours seem to have higher max_braking front than rear? Because of that I figured the script is using final values (2650*0.7, 2650*0.3) rather than max_braking all around.

If I set the brakes all to 2650 in script, then the abs performs like this.

This time at least it performs equally to the original, stopping in 4.3 seconds (and, I believe, a shorter distance). The fronts spend a fair amount of time near locked up though.

Seems like the ABS is most active around 23 seconds, pulsing on and off about 6 times. And again, braking is best when the fronts are completely locked up. Maybe the RX7's pacejka is faulty.

EDIT: OH. Small bug in the script that meant the pulse speed didn't initialize until I was under 12m/s. Doy.
Code:
```\$abs_speed = \$abs_base
if \$speed < \$abs_slow
{
\$abs_speed += (\$abs_slow - \$speed) * \$abs_slow_factor
}```
\$abs_speed only changed when braking below \$abs_slow, this properly sets it.

And pulsed braking is achieved, with all 4 wheels entering that ~-0.16 slip ratio range and staying there, aside from one glitch, and low speed skidding. Again, similar stopping time of 4.4 seconds, but now the wheels are rolling the entire time so control should be improved.

Enabling velocity (not sure why I didn't earlier) shows the more complete story.

Nice smooth braking all the way down. Obviously here velocity's on a different scale, the peak's ~150km/h and -2 is 0km/h.

6. ### Mr Whippy

Messages:
2,977
Ratings:
+456
Interesting plots there, thank you for that!

Certainly something I should do because I can record real g's for deceleration under ABS with my G-tech Pro RR, so I can get a good idea of what the ABS active/inactive curves might look like for my car and work form there.

As per the function on wheel speed, I'm not sure it can be derived that nicely by using the car speed because any type of yaw or slide might impact the actual wheel speeds, so cornering at any significant rate will mean the outside wheels are going a fair bit faster than the insides.

Ideally we could just do with wheel speed readouts to do lots of other useful things with any way

But as said, I think we can do some excel jobs and work out what are realistic kinds of frequencies for polling the wheels and go from there perhaps?

Some interesting problems arise with wheel speed for the programming of ABS. They are removed IRL by integration with other sensors as you say, or just some heavy duty maths and calibration tables.

For instance, ABS up hills reduces braking performance because the component of gravity can help decelerate the car faster than expected, thus ABS can activate when the wheels are not really decelerating fast enough to cause them to slip.
An extreme case is braking while heading straight up. The ABS would assume the wheels are locked due to the 1g deceleration despite them free-wheeling!

Obviously then ABS may be acting too late heading down hill.

I believe certain functions try alleviate these limitations, as well as doing clever de-activation/re-activation to check if the vehicle is still moving assuming the stopped wheel is actually sliding still... possibly triggering ABS in phases around the car so all four wheels can't get the opportunity to lock and thus the ABS lose it's 'senses'... lots of little tricks and systems. And all probably set up to work by careful calibration and mapping to tables so they work properly! (not something I want to get in to hehe)

I think it's nicer to look at the results of real data when braking with ABS on wet roads, dry roads etc, and then make sure our system emulates it nicely.
Of course, a thorough look at how ABS really works and it's limitations, and then a look at the real results is totally valid and important... but I still think the system will get too bloated and not give us the results we expect if we try *copy* real life too much.

I'm just concerned that going down the wheel speed route will give a nice result in ideal conditions, but as soon as we need to consider X, Y or Z conditions then we need to have clauses, and cross-check logic, and then they might need calibrating with more coefficients, and so on...

Wheel slip ratio is elegant... ok it's possibly too elegant, but I believe the desired end result of ALL the work any manufacturer will do will err towards operation that slip ratio sensing would provide straight away.

Thus perhaps all we need to be concerned with is understanding the limitations of real systems and how to 'downgrade' our system to make it less ideal...
It seems more sensible than trying to limit our sensing to wheel speeds, and then fighting the same battles as manufacturers have for decades to get half-decent modern ABS systems in Racer!

Give the code a try for now any way, it's much more realistic.

Part of me finds it perhaps a bit too choppy still, I'm not sure if my linear cutting/releasing of brake pressure is ideal. It'd be nice to use a 'tween' type in-out-in motion perhaps, and force the ABS to do different cycles depending on spec.
Ie, if the slip is breached then the ABS has to trim all the way off before being allowed to re-allow braking pressure, rather than my current system which will probably tend to bounce around 25-75% range once activated making it feel less smooth ended.

All these things could be coded into a nice elegant function with a few flags to set behaviours.

Then we can just tinker with the function to make changes to the entire way it reacts, but hopefully the car specific settings can stay pretty much fixed once they are set up (ie, number of channels, wheels to operate on, etc)

Hmmm

Dave

7. ### Mr Whippy

Messages:
2,977
Ratings:
+456
Uh, I'm confused what you have done to the script here:

Code:
```\$abs_speed = \$abs_base
if \$speed < \$abs_slow
{
\$abs_speed += (\$abs_slow - \$speed) * \$abs_slow_factor
}```
It is incorrect as your rightly point out, if the abs is triggered at low speed then the abs speed becomes a function of car tachovelocity. The abs speed isn't reset.

But what has the 2nd amendment done?
Is that simply tidying up the code because entering that if statement, abs_speed = abs_base so you can write it as abs_speed += ??

It just makes it harder to read for now.

Basically the correct function should be that at higher speeds (over the abs_slow value) the abs will simply turn on and off at a fixed rate (based on the value set)

Then when you get down to these lower speeds the pulse rate will decrease (as per real life, and opposite to how Racer ABS works!). That decrease begins at abs_slow and increases in duration by the factor given on top of the abs_base rate...

It looks like that should work properly now with your tweak, but still as I expected it.

Your edited updated plot of slip ratios and speed looks correct and very nice! Exactly what I would expect from what I thought I had programmed

Optimal SR values should be around 1.15, but in practice ABS seems to cycle around 1 > 1.3... with 1.15 being the ideal average I suppose (for a modern sports tyre)

1.3 was simply too high and made steering not happen.

I think you can also probably get really close on the rear optimum SR to front, but obviously the car will become more unstable under braking the closer they get!

So is the only important change you have made to define

\$abs_speed = \$abs_base

Just before the if statement for low-speed adjustment? To stop \$abs_speed being permanently set at the last value before the if statement became false?

Many thanks

Dave

8. ### Mr Whippy

Messages:
2,977
Ratings:
+456
I'm not really a fan of the braking factor and max_braking stuff. It's mainly for making brake bias work nicely for race cars I assume.

I suppose if you wanted you can think of max_braking as the master cylinder pressure available for all brakes, set it equally all around, and then use braking_factor at each caliper to adjust the force at each caliper, even under ABS control.

It'd be a trivial change, and maybe a better way to think of things. That way you could see the input pressure and conserve it by making the total braking_factor values at all wheels only sum 1!

I'm happy to do whatever works best for both setting up cars, integrating with existing Racer systems/logic, and makes it intuitive for users to set their cars up!

All that matters in the end though is that with ABS off your values are realistic and would lock up the appropriate wheels at appropriate brake pedal inputs.
I usually test my brakes without ABS first to make sure the values make sense at a range of speeds and straight-line braking performance is really high...

I suppose we might have a load of cars out there with values tweaked so that cars stop accurately and need almost full pedal travel to engage ABS, while with a more realistic ABS/brake biasing perhaps we can start to not worry so much about that...
Right away I've felt that braking zone braking is more intuitive, I'm happy to feel around for the ABS point and still feel like I get solid braking if I enter it, wheras before I wanted to avoid triggering ABS as much as possible as usually it reduced braking performance noticeably!

Hmmmm

Dave

9. ### Mr Whippy

Messages:
2,977
Ratings:
+456
PS, are your plots in Matlab, or the old Racer telemetry analyser, or parsed into Excel or something?

Care to share if possible?

Racer should have a way to save the graphing it can display

Dave

10. ### Mr Whippy

Messages:
2,977
Ratings:
+456
OK, I'm getting the same results as you on the speed/g's vs slip ratio plots...

Almost constant g through the faster pulsing section, and then at lower speed the pulsing changes and slows down increasingly, the g-force subsiding a little and also having intermittent small spikes until stationary.

I suppose this is where tweaking coefficients will get the full-stop behaviour perfected with as solid a deceleration as possible to the very last moment... but also considering steering performance too

Cheers

Dave

11. ### Stereo

Messages:
2,277
Ratings:
+1,240
I used R with the ascii logs (so log.enable=1, log.type=0, log.period=10 in racer.ini)

Didn't really make the code the most readable it could be.
Code:
```# read file
# set up plot function with racer data names

plotlog <- function(table, range) {
# plot the accel divided by gravity
plot(table\$time[range],table\$az[range]/9.8,type='l',col='grey',ylim=c(-1.5,1.5),xlab="time(ms)",ylab="value");
lines(table\$time[range],table\$sr0[range],col='red')
lines(table\$time[range],table\$sr1[range],col='orange')
lines(table\$time[range],table\$sr2[range],col='blue')
lines(table\$time[range],table\$sr3[range],col='green')
# speed divided by 27.7778 to get 100km/h per unit from m/s
lines(table\$time[range],sqrt(table\$vx[range]^2+table\$vy[range]^2+table\$vz[range]^2)/27.7778,col='black')
# and a horizontal line at zero for reference
lines(c(0,30000),c(0,0),col='black')
legend(x="bottomleft",legend=c("acceleration (g)","slip ratio 0","slip ratio 1","slip ratio 2","slip ratio 3", "speed (*100 km/h)"),col=c("grey","red","orange","blue","green","black"),lty=c(1,1,1,1,1,1))
}

# ignore 5 seconds on start and 2 seconds on finish
l = length(rx7\$time)
range=1:l
plotlog(rx7,500:(l-200))

plotlog(rx7,1910:2350)
```
With R you just select the part of the file you want to run, so I was tweaking the range on the last line and then rerunning just the plotting code, to focus on the braking section.

The reason I skipped 5 seconds at the start and 2 at the end is waiting for the countdown, and the fade back to menus. I was just loading up Carlswood, moving to the pits, and accelerating away to make the logs simple.

This is a little cleaned up from what I was using last night.

1 and a bit laps at Carlswood with the ABS script on, it does make braking down for the first corner quite a bit easier.

12. ### Mr Whippy

Messages:
2,977
Ratings:
+456
This ABS does make braking much more stable.

A big problem with the old ABS was the increase in operating frequency at low speeds, opposite to what is ideal... and also if you had too high rear brake force and locked a rear first then the front ABS would not work, or you'd get a sudden engagement after you thought it was terminal.

Either way the old system did the job back in the old days but imo it needed to be improved and this is an improvement despite it's slight weaknesses.
I think it's better ABS than any other road-car sim we've seen anywhere even in it's current state!

I've been driving laps at a few tracks and just find this lovely and smooth and natural feeling. Outright braking performance is marginally improved with the same pacejka but I don't think it's a 'cheat' approach.
I just think the old system wasn't as good as current road-car ABS is, and so it was costing us time!

Obviously for some 80's or 90's ABS implement we would want to purposely hurt this system by having either 0/1 going over optimum slip engaging ABS on both 0+1, same for the rears... since they were 4 sensor 2 channel jobbies (fun in the snow when the two nearside wheels were on ice and the other two were on clear road haha!)

Dave

13. ### RuudRACER Developer

Messages:
592
Ratings:
+58
I've converted this to Onyx. In car.ini I added scripts.load=abs.oxs. This requires Racer v0.9.0 RC5 though, I will upload a new Racer before the end of Friday.

Some notes:
- The car velocity is calculated in a weird way; only vel_x and vel_z are available as separate values, and no sqrt() exists yet. I'll add a sqrt() function in Onyx.
- There's no for() statement in Onyx yet, hence a while() loop.
- There's a bug so that if you define 'float slipRatio[4],brakeStat[4];', a statement brakeStat[0]=... will not compile due a type error. This is a bug in Onyx though.
- GetSystemFloat() with "car0" really shouldn't be the way to do it, since it's car-index dependent. Still thinking of a nice way, perhaps GetCarSystemFloat("controls_brakes") for example. However, it's still kind of slow; caching a pointer to the system values might be a lot faster.
- I see that car speed is not correct with negative values. Need to add an abs() function.

It does give a pretty nice example of the difference of QScript and Onyx. It's more strict (Onyx is typesafe and uses curly braces and semicolons), but as you can see the step from QScript to Onyx isn't that bad.

Code:
```/*
* Scripted ABS
* BUGS:
* - Only works with a single car.
*/

#include "racer.oxs"

//void OnFrame()
void OnTick()
// At physics frequency (1000Hz)
{
float slipRatio[4];  // Avoid defining multiple arrays for now (Onyx bug)
float brakeStat[4];
float brake[4];
float wheelOptimum[4];
float brakes,speed,absSpeed;

// Constants
brakeStat[0]=4040;
brakeStat[1]=4040;
brakeStat[2]=1920;
brakeStat[3]=1920;
brake[0]=4040;
brake[1]=4040;
brake[2]=1920;
brake[3]=1920;
wheelOptimum[0]=-0.16;
wheelOptimum[1]=-0.16;
wheelOptimum[2]=-0.15;
wheelOptimum[3]=-0.15;

// Base frequency at speed for an 'off' cycle (total on/off cycle would be double this value in ms)
const float absBase=75;
// At what speed (m/s) to start to reduce the frequency of the ABS
const float absSlow=14;
// Factor that slows the ABS down linearly from the start of speed reduction to 0 (bigger = slower)
const float absSlowFactor=14;

// Inputs
brakes=GetSystemFloat("car0.controls_brakes");

// Big hack to get speed
float sx,sz;
sx=GetSystemFloat("car0.telemetry.vel_x");
sz=GetSystemFloat("car0.telemetry.vel_z");
speed=sx;
if(sz>speed)speed=sz;

absSpeed=absBase;
if(speed<absSlow)
absSpeed=absBase+(absSlow-speed)*absSlowFactor;

slipRatio[0]=GetSystemFloat("car0.wheel0.slipratio");
slipRatio[1]=GetSystemFloat("car0.wheel1.slipratio");
slipRatio[2]=GetSystemFloat("car0.wheel2.slipratio");
slipRatio[3]=GetSystemFloat("car0.wheel3.slipratio");

int i;
i=0; while(i<4)
{
if(slipRatio[i]<wheelOptimum[i])
{
if(brake[i]>0)
brake[i]=brake[i]-brakeStat[i]/absSpeed;
else
brake[i]=0;
} else
{
if(brake[i]<brakeStat[i])
brake[i]=brake[i]+brakeStat[i]/absSpeed;
else
brake[i]=brakeStat[i];
}
i=i+1;
}

SetSystemFloat("car0.wheel0.max_braking",brake[0]);
SetSystemFloat("car0.wheel1.max_braking",brake[1]);
SetSystemFloat("car0.wheel2.max_braking",brake[2]);
SetSystemFloat("car0.wheel3.max_braking",brake[3]);

//echo(brake[0]);
}```

• Like x 1
14. ### Mr Whippy

Messages:
2,977
Ratings:
+456
Ahhh, thanks Ruud!

That code for the actual function is much more streamlined now (ie, one location to maintain/tweak it)

I suppose you could also run the SetSystemFloat from 0...3 inside a while loop too...

Just trying to think how we can make the script easy to configure for vehicles with many different wheels, different sensing and different applications of ABS.

Certainly a great reference for us to now work from and try get even better behaviour!

I'm looking forward to Onyx becoming polished so we can really use it for all the scripting jobs we once did via console scripts or qscript etc...

How all I need is a way to make a noise play when the ABS event is triggered, so we can get a nice pulsing ABS noise hehe

Dave