Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 931cc12

Browse files
committed
Adopted latest torqued
1 parent 6c7b7f6 commit 931cc12

File tree

5 files changed

+92
-72
lines changed

5 files changed

+92
-72
lines changed

common/params.cc

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ std::unordered_map<std::string, uint32_t> keys = {
9898
{"CarParams", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
9999
{"CarParamsCache", CLEAR_ON_MANAGER_START},
100100
{"CarParamsPersistent", PERSISTENT},
101+
{"CarParamsPrevRoute", PERSISTENT},
101102
{"CarVin", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
102103
{"CompletedTrainingVersion", PERSISTENT},
103104
{"ControlsReady", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},

selfdrive/controls/controlsd.py

+5
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ def __init__(self, sm=None, pm=None, can_sock=None, CI=None):
127127
safety_config.safetyModel = car.CarParams.SafetyModel.noOutput
128128
self.CP.safetyConfigs = [safety_config]
129129

130+
# Write previous route's CarParams
131+
prev_cp = self.params.get("CarParamsPersistent")
132+
if prev_cp is not None:
133+
self.params.put("CarParamsPrevRoute", prev_cp)
134+
130135
# Write CarParams for radard
131136
cp_bytes = self.CP.to_bytes()
132137
self.params.put("CarParams", cp_bytes)

selfdrive/locationd/helpers.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import numpy as np
2+
from typing import List, Optional, Tuple, Any
3+
4+
from cereal import log
5+
6+
7+
class NPQueue:
8+
def __init__(self, maxlen: int, rowsize: int) -> None:
9+
self.maxlen = maxlen
10+
self.arr = np.empty((0, rowsize))
11+
12+
def __len__(self) -> int:
13+
return len(self.arr)
14+
15+
def append(self, pt: List[float]) -> None:
16+
if len(self.arr) < self.maxlen:
17+
self.arr = np.append(self.arr, [pt], axis=0)
18+
else:
19+
self.arr[:-1] = self.arr[1:]
20+
self.arr[-1] = pt
21+
22+
23+
class PointBuckets:
24+
def __init__(self, x_bounds: List[Tuple[float, float]], min_points: List[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None:
25+
self.x_bounds = x_bounds
26+
self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds}
27+
self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True))
28+
self.min_points_total = min_points_total
29+
30+
def bucket_lengths(self) -> List[int]:
31+
return [len(v) for v in self.buckets.values()]
32+
33+
def __len__(self) -> int:
34+
return sum(self.bucket_lengths())
35+
36+
def is_valid(self) -> bool:
37+
individual_buckets_valid = all(len(v) >= min_pts for v, min_pts in zip(self.buckets.values(), self.buckets_min_points.values(), strict=True))
38+
total_points_valid = self.__len__() >= self.min_points_total
39+
return individual_buckets_valid and total_points_valid
40+
41+
def add_point(self, x: float, y: float, bucket_val: float) -> None:
42+
raise NotImplementedError
43+
44+
def get_points(self, num_points: Optional[int] = None) -> Any:
45+
points = np.vstack([x.arr for x in self.buckets.values()])
46+
if num_points is None:
47+
return points
48+
return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
49+
50+
def load_points(self, points: List[List[float]]) -> None:
51+
for point in points:
52+
self.add_point(*point)
53+
54+
55+
class ParameterEstimator:
56+
""" Base class for parameter estimators """
57+
def reset(self) -> None:
58+
raise NotImplementedError
59+
60+
def handle_log(self, t: int, which: str, msg: log.Event) -> None:
61+
raise NotImplementedError
62+
63+
def get_msg(self, valid: bool, with_points: bool) -> log.Event:
64+
raise NotImplementedError

selfdrive/locationd/torqued.py

+17-70
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
#!/usr/bin/env python3
2-
import os
3-
import sys
4-
import signal
52
import numpy as np
63
from collections import deque, defaultdict
74

@@ -12,6 +9,7 @@
129
from openpilot.common.filter_simple import FirstOrderFilter
1310
from openpilot.system.swaglog import cloudlog
1411
from openpilot.selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
12+
from openpilot.selfdrive.locationd.helpers import PointBuckets, ParameterEstimator
1513

1614
HISTORY = 5 # secs
1715
POINTS_PER_BUCKET = 1500
@@ -43,56 +41,15 @@ def slope2rot(slope):
4341
return np.array([[cos, -sin], [sin, cos]])
4442

4543

46-
class NPQueue:
47-
def __init__(self, maxlen, rowsize):
48-
self.maxlen = maxlen
49-
self.arr = np.empty((0, rowsize))
50-
51-
def __len__(self):
52-
return len(self.arr)
53-
54-
def append(self, pt):
55-
if len(self.arr) < self.maxlen:
56-
self.arr = np.append(self.arr, [pt], axis=0)
57-
else:
58-
self.arr[:-1] = self.arr[1:]
59-
self.arr[-1] = pt
60-
61-
62-
class PointBuckets:
63-
def __init__(self, x_bounds, min_points, min_points_total):
64-
self.x_bounds = x_bounds
65-
self.buckets = {bounds: NPQueue(maxlen=POINTS_PER_BUCKET, rowsize=3) for bounds in x_bounds}
66-
self.buckets_min_points = dict(zip(x_bounds, min_points))
67-
self.min_points_total = min_points_total
68-
69-
def bucket_lengths(self):
70-
return [len(v) for v in self.buckets.values()]
71-
72-
def __len__(self):
73-
return sum(self.bucket_lengths())
74-
75-
def is_valid(self):
76-
return all(len(v) >= min_pts for v, min_pts in zip(self.buckets.values(), self.buckets_min_points.values())) and (self.__len__() >= self.min_points_total)
77-
44+
class TorqueBuckets(PointBuckets):
7845
def add_point(self, x, y):
7946
for bound_min, bound_max in self.x_bounds:
8047
if (x >= bound_min) and (x < bound_max):
8148
self.buckets[(bound_min, bound_max)].append([x, 1.0, y])
8249
break
8350

84-
def get_points(self, num_points=None):
85-
points = np.vstack([x.arr for x in self.buckets.values()])
86-
if num_points is None:
87-
return points
88-
return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
8951

90-
def load_points(self, points):
91-
for x, y in points:
92-
self.add_point(x, y)
93-
94-
95-
class TorqueEstimator:
52+
class TorqueEstimator(ParameterEstimator):
9653
def __init__(self, CP, decimated=False):
9754
self.hist_len = int(HISTORY / DT_MDL)
9855
self.lag = CP.steerActuatorDelay + .2 # from controlsd
@@ -113,7 +70,7 @@ def __init__(self, CP, decimated=False):
11370
self.offline_friction = 0.0
11471
self.offline_latAccelFactor = 0.0
11572
self.resets = 0.0
116-
self.use_params = CP.carName in ALLOWED_CARS
73+
self.use_params = CP.carName in ALLOWED_CARS and CP.lateralTuning.which() == 'torque'
11774

11875
if CP.lateralTuning.which() == 'torque':
11976
self.offline_friction = CP.lateralTuning.torque.friction
@@ -135,7 +92,7 @@ def __init__(self, CP, decimated=False):
13592

13693
# try to restore cached params
13794
params = Params()
138-
params_cache = params.get("LiveTorqueCarParams")
95+
params_cache = params.get("CarParamsPrevRoute")
13996
torque_cache = params.get("LiveTorqueParameters")
14097
if params_cache is not None and torque_cache is not None:
14198
try:
@@ -158,7 +115,6 @@ def __init__(self, CP, decimated=False):
158115
cloudlog.info("restored torque params from cache")
159116
except Exception:
160117
cloudlog.exception("failed to restore cached torque params")
161-
params.remove("LiveTorqueCarParams")
162118
params.remove("LiveTorqueParameters")
163119

164120
self.filtered_params = {}
@@ -176,7 +132,11 @@ def reset(self):
176132
self.resets += 1.0
177133
self.decay = MIN_FILTER_DECAY
178134
self.raw_points = defaultdict(lambda: deque(maxlen=self.hist_len))
179-
self.filtered_points = PointBuckets(x_bounds=STEER_BUCKET_BOUNDS, min_points=self.min_bucket_points, min_points_total=self.min_points_total)
135+
self.filtered_points = TorqueBuckets(x_bounds=STEER_BUCKET_BOUNDS,
136+
min_points=self.min_bucket_points,
137+
min_points_total=self.min_points_total,
138+
points_per_bucket=POINTS_PER_BUCKET,
139+
rowsize=3)
180140

181141
def estimate_params(self):
182142
points = self.filtered_points.get_points(self.fit_points)
@@ -256,34 +216,17 @@ def get_msg(self, valid=True, with_points=False):
256216
return msg
257217

258218

259-
def main(sm=None, pm=None):
219+
def main():
260220
config_realtime_process([0, 1, 2, 3], 5)
261221

262-
if sm is None:
263-
sm = messaging.SubMaster(['carControl', 'carState', 'liveLocationKalman'], poll=['liveLocationKalman'])
264-
265-
if pm is None:
266-
pm = messaging.PubMaster(['liveTorqueParameters'])
222+
pm = messaging.PubMaster(['liveTorqueParameters'])
223+
sm = messaging.SubMaster(['carControl', 'carState', 'liveLocationKalman'], poll=['liveLocationKalman'])
267224

268225
params = Params()
269226
CP = car.CarParams.from_bytes(params.get("CarParams", block=True))
270227
# with car.CarParams.from_bytes(params.get("CarParams", block=True)) as CP:
271228
estimator = TorqueEstimator(CP)
272229

273-
def cache_params(sig, frame):
274-
signal.signal(sig, signal.SIG_DFL)
275-
cloudlog.warning("caching torque params")
276-
277-
params = Params()
278-
params.put("LiveTorqueCarParams", CP.as_builder().to_bytes())
279-
280-
msg = estimator.get_msg(with_points=True)
281-
params.put("LiveTorqueParameters", msg.to_bytes())
282-
283-
sys.exit(0)
284-
if "REPLAY" not in os.environ:
285-
signal.signal(signal.SIGINT, cache_params)
286-
287230
while True:
288231
sm.update()
289232
if sm.all_checks():
@@ -296,6 +239,10 @@ def cache_params(sig, frame):
296239
if sm.frame % 5 == 0:
297240
pm.send('liveTorqueParameters', estimator.get_msg(valid=sm.all_checks()))
298241

242+
# Cache points every 60 seconds while onroad
243+
if sm.frame % 240 == 0:
244+
msg = estimator.get_msg(valid=sm.all_checks(), with_points=True)
245+
params.put_nonblocking("LiveTorqueParameters", msg.to_bytes())
299246

300247
if __name__ == "__main__":
301248
main()

selfdrive/test/process_replay/process_replay.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -589,10 +589,13 @@ def get_custom_params_from_lr(lr: Union[LogReader, List[capnp._DynamicStructRead
589589
assert initial_state in ["first", "last"]
590590
msg_index = 0 if initial_state == "first" else -1
591591

592-
assert len(car_params) > 0, "carParams required for initial state of liveParameters and liveTorqueCarParams"
592+
assert len(car_params) > 0, "carParams required for initial state of liveParameters and CarParamsPrevRoute"
593593
CP = car_params[msg_index].carParams
594594

595-
custom_params = {}
595+
custom_params = {
596+
"CarParamsPrevRoute": CP.as_builder().to_bytes()
597+
}
598+
596599
if len(live_calibration) > 0:
597600
custom_params["CalibrationParams"] = live_calibration[msg_index].as_builder().to_bytes()
598601
if len(live_parameters) > 0:

0 commit comments

Comments
 (0)