Skip to content

Commit 1bc12f1

Browse files
authored
Reapply "LagdToggle: refactor and only instantiate once" (commaai#1137) (commaai#1138)
* Reapply "`LagdToggle`: refactor and only instantiate once" (commaai#1137) This reverts commit b4f19d4. * infinite woo gone * use them hz
1 parent b4f19d4 commit 1bc12f1

12 files changed

Lines changed: 97 additions & 77 deletions

File tree

common/params_keys.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
192192

193193
// model panel params
194194
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
195-
{"LagdToggleDesc", {PERSISTENT, STRING}},
196195
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
196+
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
197197

198198
// mapd
199199
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},

selfdrive/controls/controlsd.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from openpilot.selfdrive.controls.lib.longcontrol import LongControl
2222
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose
2323

24+
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
25+
from openpilot.sunnypilot.modeld.modeld_base import ModelStateBase
2426
from openpilot.sunnypilot.selfdrive.controls.controlsd_ext import ControlsExt
2527

2628
State = log.SelfdriveState.OpenpilotState
@@ -30,15 +32,16 @@
3032
ACTUATOR_FIELDS = tuple(car.CarControl.Actuators.schema.fields.keys())
3133

3234

33-
class Controls(ControlsExt):
35+
class Controls(ControlsExt, ModelStateBase):
3436
def __init__(self) -> None:
3537
self.params = Params()
3638
cloudlog.info("controlsd is waiting for CarParams")
3739
self.CP = messaging.log_from_bytes(self.params.get("CarParams", block=True), car.CarParams)
3840
cloudlog.info("controlsd got CarParams")
3941

40-
# Initialize sunnypilot controlsd extension
42+
# Initialize sunnypilot controlsd extension and base model state
4143
ControlsExt.__init__(self, self.CP, self.params)
44+
ModelStateBase.__init__(self)
4245

4346
self.CI = interfaces[self.CP.carFingerprint](self.CP, self.CP_SP)
4447

@@ -93,8 +96,9 @@ def state_control(self):
9396
torque_params.frictionCoefficientFiltered)
9497

9598
self.LaC.extension.update_model_v2(self.sm['modelV2'])
96-
calculated_lag = self.LaC.extension.lagd_torqued_main(self.CP, self.sm['liveDelay'])
97-
self.LaC.extension.update_lateral_lag(calculated_lag)
99+
100+
self.lat_delay = get_lat_delay(self.params, self.sm["liveDelay"].lateralDelay)
101+
self.LaC.extension.update_lateral_lag(self.lat_delay)
98102

99103
long_plan = self.sm['longitudinalPlan']
100104
model_v2 = self.sm['modelV2']

selfdrive/locationd/lagd.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from openpilot.common.realtime import config_realtime_process
1313
from openpilot.common.swaglog import cloudlog
1414
from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose, fft_next_good_size, parabolic_peak_interp
15+
from openpilot.sunnypilot.livedelay.lagd_toggle import LagdToggle
1516

1617
BLOCK_SIZE = 100
1718
BLOCK_NUM = 50
@@ -374,6 +375,8 @@ def main():
374375
lag, valid_blocks = initial_lag_params
375376
lag_learner.reset(lag, valid_blocks)
376377

378+
lagd_toggle = LagdToggle(CP)
379+
377380
while True:
378381
sm.update()
379382
if sm.all_checks():
@@ -392,3 +395,6 @@ def main():
392395

393396
if sm.frame % 1200 == 0: # cache every 60 seconds
394397
params.put_nonblocking("LiveDelay", lag_msg_dat)
398+
399+
if sm.frame % 60 == 0: # read from and write to params every 3 seconds
400+
lagd_toggle.update(lag_msg)

selfdrive/locationd/torqued.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
from openpilot.common.filter_simple import FirstOrderFilter
1111
from openpilot.common.swaglog import cloudlog
1212
from openpilot.selfdrive.locationd.helpers import PointBuckets, ParameterEstimator, PoseCalibrator, Pose
13-
14-
from openpilot.sunnypilot.livedelay.lagd_toggle import LagdToggle
13+
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
1514

1615
HISTORY = 5 # secs
1716
POINTS_PER_BUCKET = 1500
@@ -51,7 +50,7 @@ def add_point(self, x, y):
5150
break
5251

5352

54-
class TorqueEstimator(ParameterEstimator, LagdToggle):
53+
class TorqueEstimator(ParameterEstimator):
5554
def __init__(self, CP, decimated=False, track_all_points=False):
5655
super().__init__()
5756
self.CP = CP
@@ -99,6 +98,7 @@ def __init__(self, CP, decimated=False, track_all_points=False):
9998

10099
# try to restore cached params
101100
params = Params()
101+
self.params = params
102102
params_cache = params.get("CarParamsPrevRoute")
103103
torque_cache = params.get("LiveTorqueParameters")
104104
if params_cache is not None and torque_cache is not None:
@@ -180,7 +180,7 @@ def handle_log(self, t, which, msg):
180180
elif which == "liveCalibration":
181181
self.calibrator.feed_live_calib(msg)
182182
elif which == "liveDelay":
183-
self.lag = self.lagd_torqued_main(self.CP, msg)
183+
self.lag = get_lat_delay(self.params, msg.lateralDelay)
184184
# calculate lateral accel from past steering torque
185185
elif which == "livePose":
186186
if len(self.raw_points['steer_torque']) == self.hist_len:

selfdrive/modeld/modeld.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
from openpilot.selfdrive.modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext
3232
from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address
3333

34-
from openpilot.sunnypilot.livedelay.lagd_toggle import LagdToggle
34+
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
35+
from openpilot.sunnypilot.modeld.modeld_base import ModelStateBase
3536

3637

3738
PROCESS_NAME = "selfdrive.modeld.modeld"
@@ -79,13 +80,14 @@ def __init__(self, vipc=None):
7980
if vipc is not None:
8081
self.frame_id, self.timestamp_sof, self.timestamp_eof = vipc.frame_id, vipc.timestamp_sof, vipc.timestamp_eof
8182

82-
class ModelState:
83+
class ModelState(ModelStateBase):
8384
frames: dict[str, DrivingModelFrame]
8485
inputs: dict[str, np.ndarray]
8586
output: np.ndarray
8687
prev_desire: np.ndarray # for tracking the rising edge of the pulse
8788

8889
def __init__(self, context: CLContext):
90+
ModelStateBase.__init__(self)
8991
self.LAT_SMOOTH_SECONDS = LAT_SMOOTH_SECONDS
9092
with open(VISION_METADATA_PATH, 'rb') as f:
9193
vision_metadata = pickle.load(f)
@@ -249,8 +251,6 @@ def main(demo=False):
249251
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
250252
cloudlog.info("modeld got CarParams: %s", CP.brand)
251253

252-
modeld_lagd = LagdToggle()
253-
254254
# TODO this needs more thought, use .2s extra for now to estimate other delays
255255
# TODO Move smooth seconds to action function
256256
long_delay = CP.longitudinalActuatorDelay + LONG_SMOOTH_SECONDS
@@ -296,7 +296,9 @@ def main(demo=False):
296296
is_rhd = sm["driverMonitoringState"].isRHD
297297
frame_id = sm["roadCameraState"].frameId
298298
v_ego = max(sm["carState"].vEgo, 0.)
299-
lat_delay = modeld_lagd.lagd_main(CP, sm, model)
299+
if sm.frame % 60 == 0:
300+
model.lat_delay = get_lat_delay(params, sm["liveDelay"].lateralDelay)
301+
lat_delay = model.lat_delay + LAT_SMOOTH_SECONDS
300302
lateral_control_params = np.array([v_ego, lat_delay], dtype=np.float32)
301303
if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']:
302304
device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32)

selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,6 @@ void ModelsPanel::updateLabels() {
361361
QString desc = tr("Enable this for the car to learn and adapt its steering response time. "
362362
"Disable to use a fixed steering response time. Keeping this on provides the stock openpilot experience. "
363363
"The Current value is updated automatically when the vehicle is Onroad.");
364-
QString current = QString::fromStdString(params.get("LagdToggleDesc", false));
365-
if (!current.isEmpty()) {
366-
desc += "<br><br><b><span style=\"color:#e0e0e0\">" + tr("Current:") + "</span></b> <span style=\"color:#e0e0e0\">" + current + "</span>";
367-
}
368364
lagd_toggle_control->setDescription(desc);
369365

370366
delay_control->setVisible(!params.getBool("LagdToggle"));

sunnypilot/livedelay/helpers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
3+
4+
This file is part of sunnypilot and is licensed under the MIT License.
5+
See the LICENSE.md file in the root directory for more details.
6+
"""
7+
from openpilot.common.params import Params
8+
9+
10+
def get_lat_delay(params: Params, stock_lat_delay: float) -> float:
11+
if params.get_bool("LagdToggle"):
12+
return float(params.get("LagdValueCache", return_default=True))
13+
14+
return stock_lat_delay

sunnypilot/livedelay/lagd_toggle.py

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,35 @@
44
This file is part of sunnypilot and is licensed under the MIT License.
55
See the LICENSE.md file in the root directory for more details.
66
"""
7+
from cereal import log
8+
9+
from opendbc.car import structs
710
from openpilot.common.params import Params
8-
from openpilot.common.swaglog import cloudlog
911

1012

1113
class LagdToggle:
12-
def __init__(self):
14+
def __init__(self, CP: structs.CarParams):
15+
self.CP = CP
1316
self.params = Params()
1417
self.lag = 0.0
15-
self._last_desc = None
16-
17-
@property
18-
def software_delay(self):
19-
return self.params.get("LagdToggleDelay")
20-
21-
def _maybe_update_desc(self, desc):
22-
if desc != self._last_desc:
23-
self.params.put_nonblocking("LagdToggleDesc", desc)
24-
self._last_desc = desc
25-
26-
def lagd_main(self, CP, sm, model):
27-
if self.params.get_bool("LagdToggle"):
28-
lateral_delay = sm["liveDelay"].lateralDelay
29-
lat_smooth = model.LAT_SMOOTH_SECONDS
30-
result = lateral_delay + lat_smooth
31-
desc = f"live steer delay learner ({lateral_delay:.3f}s) + model smoothing filter ({lat_smooth:.3f}s) = total delay ({result:.3f}s)"
32-
self._maybe_update_desc(desc)
33-
return result
34-
35-
steer_actuator_delay = CP.steerActuatorDelay
36-
lat_smooth = model.LAT_SMOOTH_SECONDS
37-
delay = self.software_delay
38-
result = (steer_actuator_delay + delay) + lat_smooth
39-
desc = (f"Vehicle steering delay ({steer_actuator_delay:.3f}s) + software delay ({delay:.3f}s) + " +
40-
f"model smoothing filter ({lat_smooth:.3f}s) = total delay ({result:.3f}s)")
41-
self._maybe_update_desc(desc)
42-
return result
43-
44-
def lagd_torqued_main(self, CP, msg):
45-
if self.params.get_bool("LagdToggle"):
46-
self.lag = msg.lateralDelay
47-
cloudlog.debug(f"TORQUED USING LIVE DELAY: {self.lag:.3f}")
48-
else:
49-
self.lag = CP.steerActuatorDelay + self.software_delay
50-
cloudlog.debug(f"TORQUED USING STEER ACTUATOR: {self.lag:.3f}")
51-
return self.lag
18+
19+
self.lagd_toggle = self.params.get_bool("LagdToggle")
20+
self.software_delay = self.params.get("LagdToggleDelay", return_default=True)
21+
22+
def read_params(self) -> None:
23+
self.lagd_toggle = self.params.get_bool("LagdToggle")
24+
self.software_delay = self.params.get("LagdToggleDelay", return_default=True)
25+
26+
def update(self, lag_msg: log.LiveDelayData) -> None:
27+
self.read_params()
28+
29+
if not self.lagd_toggle:
30+
steer_actuator_delay = self.CP.steerActuatorDelay
31+
delay = self.software_delay
32+
self.lag = (steer_actuator_delay + delay)
33+
self.params.put_nonblocking("LagdValueCache", self.lag)
34+
return
35+
36+
lateral_delay = lag_msg.liveDelay.lateralDelay
37+
self.lag = lateral_delay
38+
self.params.put_nonblocking("LagdValueCache", self.lag)

sunnypilot/modeld/modeld.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@
2020
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
2121
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value
2222

23+
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
2324
from openpilot.sunnypilot.modeld.runners import ModelRunner, Runtime
2425
from openpilot.sunnypilot.modeld.parse_model_outputs import Parser
2526
from openpilot.sunnypilot.modeld.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState
2627
from openpilot.sunnypilot.modeld.constants import ModelConstants, Plan
2728
from openpilot.sunnypilot.models.helpers import get_active_bundle, get_model_path, load_metadata, prepare_inputs, load_meta_constants
28-
from openpilot.sunnypilot.livedelay.lagd_toggle import LagdToggle
2929
from openpilot.sunnypilot.modeld.models.commonmodel_pyx import ModelFrame, CLContext
30+
from openpilot.sunnypilot.modeld.modeld_base import ModelStateBase
3031

3132

3233
PROCESS_NAME = "selfdrive.modeld.modeld_snpe"
@@ -48,7 +49,7 @@ def __init__(self, vipc=None):
4849
if vipc is not None:
4950
self.frame_id, self.timestamp_sof, self.timestamp_eof = vipc.frame_id, vipc.timestamp_sof, vipc.timestamp_eof
5051

51-
class ModelState:
52+
class ModelState(ModelStateBase):
5253
frame: ModelFrame
5354
wide_frame: ModelFrame
5455
inputs: dict[str, np.ndarray]
@@ -57,6 +58,7 @@ class ModelState:
5758
model: ModelRunner
5859

5960
def __init__(self, context: CLContext):
61+
ModelStateBase.__init__(self)
6062
self.frame = ModelFrame(context)
6163
self.wide_frame = ModelFrame(context)
6264
self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32)
@@ -202,8 +204,6 @@ def main(demo=False):
202204

203205
cloudlog.info("modeld got CarParams: %s", CP.brand)
204206

205-
modeld_lagd = LagdToggle()
206-
207207
# Enable lagd support for sunnypilot modeld
208208
long_delay = CP.longitudinalActuatorDelay + model.LONG_SMOOTH_SECONDS
209209
prev_action = log.ModelDataV2.Action()
@@ -248,8 +248,9 @@ def main(demo=False):
248248
v_ego = sm["carState"].vEgo
249249
is_rhd = sm["driverMonitoringState"].isRHD
250250
frame_id = sm["roadCameraState"].frameId
251-
steer_delay = modeld_lagd.lagd_main(CP, sm, model)
252-
251+
if sm.frame % 60 == 0:
252+
model.lat_delay = get_lat_delay(params, sm["liveDelay"].lateralDelay)
253+
lat_delay = model.lat_delay + model.LAT_SMOOTH_SECONDS
253254
if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']:
254255
device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32)
255256
dc = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))]
@@ -283,7 +284,7 @@ def main(demo=False):
283284
}
284285

285286
if "lateral_control_params" in model.inputs.keys():
286-
inputs['lateral_control_params'] = np.array([max(v_ego, 0.), steer_delay], dtype=np.float32)
287+
inputs['lateral_control_params'] = np.array([max(v_ego, 0.), lat_delay], dtype=np.float32)
287288

288289
if "driving_style" in model.inputs.keys():
289290
inputs['driving_style'] = np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], dtype=np.float32)
@@ -306,7 +307,7 @@ def main(demo=False):
306307
action = model.get_action_from_model(model_output, prev_action, long_delay + DT_MDL)
307308
fill_model_msg(drivingdata_send, modelv2_send, model_output, action, publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id,
308309
frame_drop_ratio, meta_main.timestamp_eof, model_execution_time, live_calib_seen,
309-
v_ego, steer_delay, model.meta)
310+
v_ego, lat_delay, model.meta)
310311

311312
desire_state = modelv2_send.modelV2.meta.desireState
312313
l_lane_change_prob = desire_state[log.Desire.laneChangeLeft]

sunnypilot/modeld/modeld_base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
3+
4+
This file is part of sunnypilot and is licensed under the MIT License.
5+
See the LICENSE.md file in the root directory for more details.
6+
"""
7+
from openpilot.common.params import Params
8+
9+
10+
class ModelStateBase:
11+
def __init__(self):
12+
self.lat_delay = Params().get("LagdValueCache", return_default=True)

0 commit comments

Comments
 (0)