openpilot
openpilot copied to clipboard
GM: dynamic regen acceleration threshold
Description
GM Chevy Volt has bad longitudinal oscillations when stopping behind a lead. This is partially caused the the threshold value of desired acceleration necessary to actuate friction brakes.
The value of -1m/s^2 reflects the amount of regen braking force available at city and highway speeds. At lower speeds, however, this value is too high, so when openpilot requests -0.9m/s^2 of acceleration at low speeds, it will not actuate the friction brakes, only lowering the gas command which does not yield the necessary regen at those speeds, causing the long controller integral gain to wind up and correct, delivering harsh, sudden braking, quickly overshooting the desired acceleration and letting off the brakes. This repeats, creating uncomfortable oscillations visible in the image in the verification section below (left side, red path "aEgo").
Some additional context: this was previously found to be an issue for GM ICE cars, which generate far less engine braking force compared to EV regen braking. The solution was to use a threshold gas/brake acceleration value closer to 0m/s^2, implemented by @sshane and myself.
The solution here is to use a speed-based, dynamic gas/brake acceleration threshold based on measurements of the Chevy Volt regen braking force on a flat, smooth road. I performed tests to determine this profile and derived a lookup table used to control the threshold gas/brake acceleration value while on-road.
Gathering data
To understand how much regen is accessible at different speeds, I drove at 2am to conduct some tests where I drive at highway speeds (with openpilot disengaged) and then let off the gas and allow regen to slow me down as much as it will, to a "stop".
Here are plots of data collected from two runs on the same stretch of fairly flat, smooth freeway, once in each direction.
Here are the two runs overlaid. The pitch-adjusted acceleration is slightly different, but very close. I suspect this is due to an internal controller in the car that is targeting it's own regen braking profile.
Gas/brake threshold profile
Based on values of vEgo and aEgo at the characteristic points in the aEgo vs time plot indicated above, I derived the following profile, where the middle line is the average between the two runs:
While this clearly changes with vehicle pitch, that will be accounted for by GM longitudinal pitch-compensation.
The positive portion of the plot corresponds to creep acceleration, which necessitates some amount of non-zero brake command in order to maintain velocities below ~1.2m/s. This was determined by, on a flat smooth surface, releasing the brake when stopped in gear and allowing the car to creep forward. The positive acceleration threshold at low speed creates a small delay when resuming from a stop on an incline, but this is only slightly slower to start than before. I've also confirmed this is alleviated by longitudinal pitch-compensation.
Here are the values of the average profile:
speed [mph] regen brake "force" [m/s^2]
1.12 0.68
1.34 0.67
1.57 0.63
1.79 0.56
2.02 0.49
2.24 0.38
2.46 0.30
2.69 0.13
2.89 0.00
3.40 -0.14
3.47 -0.16
3.58 -0.18
3.81 -0.21
4.03 -0.26
4.48 -0.32
4.93 -0.41
5.60 -0.50
12.36 -0.72
21.50 -0.90
45.92 -1.12
52.64 -1.15
78.40 -1.16
Sidenote
Moving forward, this could easily be implemented as an auto-learned profile. If the minimum gas command is being sent with a zero brake command, then the resulting acceleration (pitch-, and perhaps drag-adjusted) can be attributed to engine/regen braking under the current conditions (speed, engine RPM, transmission gear, high voltage battery temperature and state of charge, depending on how thorough you wanted to be). This could also be easily extracted from rlogs.
I expect this type of change could have a significant impact on long control for all makes and models, especially if auto-learned. Learned gas/brake threshold profiles, or those determined server-side from rlogs, could be consolidated and added as the default for a particular car when openpilot is first run, and then auto-learned on each individual car to account for weather, tire pressure/size, differences in suspension, etc.
Verification
Preliminary results show a complete elimination of oscillations in aEgo. Here the right set of plots are with the dynamic lookup table and an adjusted tune, compared to stock on the left. See the complete elimination of acceleration oscillations (red path, 4th plot down), and much better execution of the desired acceleration (green path, 4th plot down).
I was lucky enough to get rather comparable stops on master vs this branch.
Route Route: c11fcb510a549332|2022-08-23--07-36-40--1
~~converting to draft until new profile derived from better test data~~
Updated with new test data.
~~TODO: these results are from the earlier implementation using a similar, but not the same gas/brake threshold profile. Need to record new test route.~~
~~TODO: this enables the use of much lower ki and kp values for the gm long tunes, and I wanted to include a new Volt long tune with this PR.~~ ~~Tune made too. Waiting on a test route.~~
Made a function to compute_gb
like we do for Honda and simplified the breakpoints, but it splits up the X and Y of the breakpoints, let me know which you found clearer (updating the breakpoints or this).
I think your version is cleaner and more readable (as usual...), and that will capture 95% of what's going on (though I still plan on doing a NN for long control FF that includes this component of controls). And being framed in the context of desired accel as you've done makes it easier to understand how the gas/brake lookups work conceptually 🤓.
@twilsonco @nworb-cire can you guys test this?
I have tested this change on my 2018 GMC Acadia df51b2195de66a9b|2023-07-11--17-18-07--0 In the 12 mile test, I experienced several different types of stops behind leads and all were smooth and comfortable and I never felt as if I needed to intervene. The resume acceleration is still very poor and requires intervention every time.
threshold works as expected! just need one Volt to test the new low-speed tuning now
I can provide test routes this week with a comparison against stock as above.
I'll merge a temporary fix to the issue ASAP then, and then revert with this PR
Finally got around to testing. Recorded two routes, one on master and one on this branch.
- master: c11fcb510a549332|2023-07-15--18-28-15--0
- gm-volt-long-tune: c11fcb510a549332|2023-07-15--19-39-52--1
Here are some plots comparing the stopping behavior (which is the primary situation this PR addresses) between master and the PR branch currently.
- The subjective experience didn't improve a whole lot for the drives I did compared to the comparison I originally did above.
- I figure this is because the Volt long tune was done in the context of inaccurate long feedforward due to the shifting gas/brake threshold this PR tries to address. The resulting current Volt long tune has too high kp, which was necessary to stop in time and correct for the inaccurate feedforward.
- With this change in place, the error—that kp needed to be high to correct—is lessened, and so too can kp be decreased in order to get the (graphically and subjectively) smoother stops as in the original PR.
- So, a followup adjustment to the Volt tune is recommended.
I also think one more breakpoint would be worth adding to split the error between the current super-simple profile and the one I derived earlier. Here's my proposed revision for the ev profile;
bp=[2, 5, 20]
v=[0, -0.75, -1.1]
The corresponding ICE car profile would be
bp=[2, 5, 20]
v=[0, -0.03, -0.1]
...or something.
I also think it may be worth it to use a smoothed profile using quadratic b-splines, given the dramatic shift in slope that still seems to be making the stops less smooth than they could be.
Despite the subtle change in subjective driver experience, the plots make it clear where and how this is helping. Recall this change is to make it so that, at lower speeds, the brakes come on sooner (in response to a lower magnitude negative desired accel).
- The right column (with dynamic gas/brake compensation) shows the brake command coming on when actuators.accel is still at -0.28, while in the left column brakes come on at accel = -1.0.
- The result is that with master, there's a pause in deceleration while actuators.accel has to get from 0 to -1.0 before brakes actuate, during which time error begins to grow, and finally as the friction brakes come on, it's in combination with the P corrective response and results in harsh braking, which overshoots and then releases.
- By the time the brake command comes on with master, you can see error has been growing between aEgo and actuators.accel for 2s.
- Rather than engaging the brakes sooner, you can see it slowly ramping down the gas command (even though at those speeds it's not getting the regen brake force it expects).
- With the dynamic gas/brake threshold, there is no such lapse in brake force, and less error occurs.
Master | PR branch |
---|---|
Here's more plots
Master | PR branch |
---|---|
stop behind stopped lead |
stop behind stopped lead |
stop behind stopping lead |
stop for red light |
... |
@sshane
Is this ready for merge?
I checked your routes and we went from undershooting deceleration to overshooting, you can see integral switching sides. Left is master, right is this branch:
True, but there's consistent error on the left plot that's vanishingly small on the right plot (space between desired and actual speed, also see the magnitude on the p response. It stays at 0.2 on the right and 0.5 on the left).
However, nworby is making great progress on a better approach to data-based long controls. Might be better to let this sit for a bit until his he ready for comparison.
If we don't currently expect to merge this PR, let's close. You can re-open if we do end up wanting this version of it.
Closed this in favor of https://github.com/commaai/openpilot/pull/29659 which is now closed. Please reopen @adeebshihadeh
This PR has had no activity for 30 days. It will be automatically closed in 7 days if there is no activity.
I'll update this shortly Routes using a simplified EV lookup table, slightly adjusted to account for the overshoot you pointed out above.
This PR has had no activity for 30 days. It will be automatically closed in 7 days if there is no activity.
This PR has had no activity for 30 days. It will be automatically closed in 7 days if there is no activity.
This PR has been automatically closed due to inactivity. Feel free to re-open once activity resumes.