From e39e4b9a610ccfda1986002e0bbdae2372a79466 Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:47:18 -0800 Subject: [PATCH 01/26] [bot] Update Python packages (#34761) Update Python packages Co-authored-by: Vehicle Researcher --- msgq_repo | 2 +- opendbc_repo | 2 +- panda | 2 +- uv.lock | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/msgq_repo b/msgq_repo index 095f1e2361..ad9020c430 160000 --- a/msgq_repo +++ b/msgq_repo @@ -1 +1 @@ -Subproject commit 095f1e23613d47031a9b23e3f9ed5dd3fe01a06e +Subproject commit ad9020c430362d17c0edf97747d344389234be4d diff --git a/opendbc_repo b/opendbc_repo index bc839875bd..ca4f77b010 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit bc839875bd0ca476be71dea2cbebc92a4544c40c +Subproject commit ca4f77b0101d85a5e8d292e2e61f7a8c7492b9e2 diff --git a/panda b/panda index 2c802449fd..154b66782d 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 2c802449fd51d9904ca265d06b7a5f9969057ae3 +Subproject commit 154b66782ddf4b9293c4594bb5ee8bd9cd88f332 diff --git a/uv.lock b/uv.lock index fa933d5491..022e30508d 100644 --- a/uv.lock +++ b/uv.lock @@ -4279,7 +4279,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.3.4" +version = "8.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -4287,9 +4287,9 @@ dependencies = [ { name = "packaging" }, { name = "pluggy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, ] [[package]] @@ -4703,11 +4703,11 @@ wheels = [ [[package]] name = "scons" -version = "4.8.1" +version = "4.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b9/76/a2c1293642f9a448f2d012cabf525be69ca5abf4af289bc0935ac1554ee8/scons-4.8.1.tar.gz", hash = "sha256:5b641357904d2f56f7bfdbb37e165ab996b6143c948b9df0efc7305f54949daa", size = 3244174 } +sdist = { url = "https://files.pythonhosted.org/packages/61/7e/79e07dc2eb8874580934cd0c834a8a78f15d5b0d6155a424f6c7b35441c3/scons-4.9.0.tar.gz", hash = "sha256:f1a5e161bf3d1411d780d65d7919654b9405555994621d3d68e42d62114b592a", size = 3251763 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/a7/823091100c88d7d992c8c608d82a88ed59e227d13f8ccb33ea7a96d43d51/SCons-4.8.1-py3-none-any.whl", hash = "sha256:a4c3b434330e2d7d975002fd6783284ba348bf394db94c8f83fdc5bf69cdb8d7", size = 4123564 }, + { url = "https://files.pythonhosted.org/packages/18/f5/77635f6c68ed742a23e1f52977267e191ea7c2aec89b9604a86487405da1/scons-4.9.0-py3-none-any.whl", hash = "sha256:c8cc309db0f91cffdc27c1374fa3d31e9421bcb31d210de071b0b11adc84739b", size = 4130637 }, ] [[package]] From 159b1c9eb48551e6ac1d5f9281ac2218f320f499 Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Mon, 3 Mar 2025 15:15:36 -0800 Subject: [PATCH 02/26] Filet o Fish model (#34637) * 690b01c3 seems ok * correct temporal * push * inplace * bs * what thw * is this wrong * frames are skipped * new models * simplify decimation * clean up * clean up modelframe * need attr * lint * 0 --------- Co-authored-by: Comma Device --- selfdrive/modeld/constants.py | 8 +++++- selfdrive/modeld/modeld.py | 31 ++++++++++++++------- selfdrive/modeld/models/commonmodel.cc | 9 +++--- selfdrive/modeld/models/commonmodel.h | 5 ++-- selfdrive/modeld/models/commonmodel.pxd | 2 +- selfdrive/modeld/models/commonmodel_pyx.pyx | 4 +-- selfdrive/modeld/models/driving_policy.onnx | 4 +-- selfdrive/modeld/models/driving_vision.onnx | 2 +- 8 files changed, 42 insertions(+), 23 deletions(-) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index 2bb7b8100c..5ca0a86bc8 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -14,8 +14,14 @@ class ModelConstants: # model inputs constants MODEL_FREQ = 20 + HISTORY_FREQ = 5 + HISTORY_LEN_SECONDS = 5 + TEMPORAL_SKIP = MODEL_FREQ // HISTORY_FREQ + FULL_HISTORY_BUFFER_LEN = MODEL_FREQ * HISTORY_LEN_SECONDS + INPUT_HISTORY_BUFFER_LEN = HISTORY_FREQ * HISTORY_LEN_SECONDS + FEATURE_LEN = 512 - FULL_HISTORY_BUFFER_LEN = 100 + DESIRE_LEN = 8 TRAFFIC_CONVENTION_LEN = 2 LAT_PLANNER_STATE_LEN = 4 diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index ee825d158f..ae1e75e3e9 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -56,16 +56,24 @@ class ModelState: prev_desire: np.ndarray # for tracking the rising edge of the pulse def __init__(self, context: CLContext): - self.frames = {'input_imgs': DrivingModelFrame(context), 'big_input_imgs': DrivingModelFrame(context)} + self.frames = { + 'input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP), + 'big_input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) + } self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) + self.full_features_buffer = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) + self.full_desire = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32) + self.full_prev_desired_curv = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32) + self.temporal_idxs = slice(-1-(ModelConstants.TEMPORAL_SKIP*(ModelConstants.INPUT_HISTORY_BUFFER_LEN-1)), None, ModelConstants.TEMPORAL_SKIP) + # policy inputs self.numpy_inputs = { - 'desire': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), 'lateral_control_params': np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32), - 'prev_desired_curv': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), + 'prev_desired_curv': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), + 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } with open(VISION_METADATA_PATH, 'rb') as f: @@ -104,8 +112,9 @@ class ModelState: new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) self.prev_desire[:] = inputs['desire'] - self.numpy_inputs['desire'][0,:-1] = self.numpy_inputs['desire'][0,1:] - self.numpy_inputs['desire'][0,-1] = new_desire + self.full_desire[0,:-1] = self.full_desire[0,1:] + self.full_desire[0,-1] = new_desire + self.numpy_inputs['desire'][:] = self.full_desire[0, self.temporal_idxs] self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params'] @@ -128,15 +137,17 @@ class ModelState: self.vision_output = self.vision_run(**self.vision_inputs).numpy().flatten() vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) - self.numpy_inputs['features_buffer'][0,:-1] = self.numpy_inputs['features_buffer'][0,1:] - self.numpy_inputs['features_buffer'][0,-1] = vision_outputs_dict['hidden_state'][0, :] + self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:] + self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :] + self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs] self.policy_output = self.policy_run(**self.policy_inputs).numpy().flatten() policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) # TODO model only uses last value now - self.numpy_inputs['prev_desired_curv'][0,:-1] = self.numpy_inputs['prev_desired_curv'][0,1:] - self.numpy_inputs['prev_desired_curv'][0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] + self.full_prev_desired_curv[0,:-1] = self.full_prev_desired_curv[0,1:] + self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] + self.numpy_inputs['prev_desired_curv'][:] = self.full_prev_desired_curv[0, self.temporal_idxs] combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} if SEND_RAW_PRED: diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc index 9973d18588..99155d9f1e 100644 --- a/selfdrive/modeld/models/commonmodel.cc +++ b/selfdrive/modeld/models/commonmodel.cc @@ -5,11 +5,12 @@ #include "common/clutil.h" -DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { +DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip) : ModelFrame(device_id, context) { input_frames = std::make_unique(buf_size); + temporal_skip = _temporal_skip; input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); - img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 2*frame_size_bytes, NULL, &err)); - region.origin = 1 * frame_size_bytes; + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (temporal_skip+1)*frame_size_bytes, NULL, &err)); + region.origin = temporal_skip * frame_size_bytes; region.size = frame_size_bytes; last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); @@ -20,7 +21,7 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); - for (int i = 0; i < 1; i++) { + for (int i = 0; i < temporal_skip; i++) { CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); } loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); diff --git a/selfdrive/modeld/models/commonmodel.h b/selfdrive/modeld/models/commonmodel.h index 14409943e4..176d7eb6dc 100644 --- a/selfdrive/modeld/models/commonmodel.h +++ b/selfdrive/modeld/models/commonmodel.h @@ -64,20 +64,21 @@ protected: class DrivingModelFrame : public ModelFrame { public: - DrivingModelFrame(cl_device_id device_id, cl_context context); + DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip); ~DrivingModelFrame(); cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); const int MODEL_WIDTH = 512; const int MODEL_HEIGHT = 256; const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT * 3 / 2; - const int buf_size = MODEL_FRAME_SIZE * 2; + const int buf_size = MODEL_FRAME_SIZE * 2; // 2 frames are temporal_skip frames apart const size_t frame_size_bytes = MODEL_FRAME_SIZE * sizeof(uint8_t); private: LoadYUVState loadyuv; cl_mem img_buffer_20hz_cl, last_img_cl, input_frames_cl; cl_buffer_region region; + int temporal_skip; }; class MonitoringModelFrame : public ModelFrame { diff --git a/selfdrive/modeld/models/commonmodel.pxd b/selfdrive/modeld/models/commonmodel.pxd index b4f08b12aa..4ac64d9172 100644 --- a/selfdrive/modeld/models/commonmodel.pxd +++ b/selfdrive/modeld/models/commonmodel.pxd @@ -20,7 +20,7 @@ cdef extern from "selfdrive/modeld/models/commonmodel.h": cppclass DrivingModelFrame: int buf_size - DrivingModelFrame(cl_device_id, cl_context) + DrivingModelFrame(cl_device_id, cl_context, int) cppclass MonitoringModelFrame: int buf_size diff --git a/selfdrive/modeld/models/commonmodel_pyx.pyx b/selfdrive/modeld/models/commonmodel_pyx.pyx index 7b3a5bb342..5b7d11bc71 100644 --- a/selfdrive/modeld/models/commonmodel_pyx.pyx +++ b/selfdrive/modeld/models/commonmodel_pyx.pyx @@ -59,8 +59,8 @@ cdef class ModelFrame: cdef class DrivingModelFrame(ModelFrame): cdef cppDrivingModelFrame * _frame - def __cinit__(self, CLContext context): - self._frame = new cppDrivingModelFrame(context.device_id, context.context) + def __cinit__(self, CLContext context, int temporal_skip): + self._frame = new cppDrivingModelFrame(context.device_id, context.context, temporal_skip) self.frame = (self._frame) self.buf_size = self._frame.buf_size diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index f804b4ec31..cc2148c74b 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cae3285c876804e649b14adadcfb8be79a9bd5a1b928113e37f1f08e25e9688 -size 16581121 +oid sha256:5fd38c3b4d465d14a8ed128f8b1b265bff1589d42f398faa678b93f25b3385dc +size 15966721 diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx index 06c87d8755..aee6d8f1bf 100644 --- a/selfdrive/modeld/models/driving_vision.onnx +++ b/selfdrive/modeld/models/driving_vision.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29bbf79f9dfd7048c0013bb81e86d9b2979275b95ea1ed8a86d1a86a88695240 +oid sha256:897f80d0388250f99bba69b6a8434560cc0fd83157cbeb0bc134c67fe4e64624 size 34882971 From 68d22b960b85871bf61dfdb0e2d955c28fde647b Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 3 Mar 2025 18:28:49 -0600 Subject: [PATCH 03/26] rename steer_limited (#34763) rename --- selfdrive/controls/controlsd.py | 10 +++++----- selfdrive/controls/lib/latcontrol.py | 6 +++--- selfdrive/controls/lib/latcontrol_angle.py | 2 +- selfdrive/controls/lib/latcontrol_pid.py | 4 ++-- selfdrive/controls/lib/latcontrol_torque.py | 6 +++--- tools/tuning/measure_steering_accuracy.py | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index fb7dd3944c..14fd37040e 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -40,7 +40,7 @@ class Controls: 'driverMonitoringState', 'onroadEvents', 'driverAssistance'], poll='selfdriveState') self.pm = messaging.PubMaster(['carControl', 'controlsState']) - self.steer_limited = False + self.steer_limited_by_controls = False self.desired_curvature = 0.0 self.pose_calibrator = PoseCalibrator() @@ -112,7 +112,7 @@ class Controls: self.desired_curvature = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature) actuators.curvature = float(self.desired_curvature) steer, steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp, - self.steer_limited, self.desired_curvature, + self.steer_limited_by_controls, self.desired_curvature, self.calibrated_pose) # TODO what if not available actuators.torque = float(steer) actuators.steeringAngleDeg = float(steeringAngleDeg) @@ -161,10 +161,10 @@ class Controls: if self.sm['selfdriveState'].active: CO = self.sm['carOutput'] if self.CP.steerControlType == car.CarParams.SteerControlType.angle: - self.steer_limited = abs(CC.actuators.steeringAngleDeg - CO.actuatorsOutput.steeringAngleDeg) > \ - STEER_ANGLE_SATURATION_THRESHOLD + self.steer_limited_by_controls = abs(CC.actuators.steeringAngleDeg - CO.actuatorsOutput.steeringAngleDeg) > \ + STEER_ANGLE_SATURATION_THRESHOLD else: - self.steer_limited = abs(CC.actuators.torque - CO.actuatorsOutput.torque) > 1e-2 + self.steer_limited_by_controls = abs(CC.actuators.torque - CO.actuatorsOutput.torque) > 1e-2 # TODO: both controlsState and carControl valids should be set by # sm.all_checks(), but this creates a circular dependency diff --git a/selfdrive/controls/lib/latcontrol.py b/selfdrive/controls/lib/latcontrol.py index f84f70be4f..f0121f73bc 100644 --- a/selfdrive/controls/lib/latcontrol.py +++ b/selfdrive/controls/lib/latcontrol.py @@ -17,14 +17,14 @@ class LatControl(ABC): self.steer_max = 1.0 @abstractmethod - def update(self, active, CS, VM, params, steer_limited, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): pass def reset(self): self.sat_count = 0. - def _check_saturation(self, saturated, CS, steer_limited): - if saturated and CS.vEgo > self.sat_check_min_speed and not steer_limited and not CS.steeringPressed: + def _check_saturation(self, saturated, CS, steer_limited_by_controls): + if saturated and CS.vEgo > self.sat_check_min_speed and not steer_limited_by_controls and not CS.steeringPressed: self.sat_count += self.sat_count_rate else: self.sat_count -= self.sat_count_rate diff --git a/selfdrive/controls/lib/latcontrol_angle.py b/selfdrive/controls/lib/latcontrol_angle.py index 4162bd62dc..de07423fd4 100644 --- a/selfdrive/controls/lib/latcontrol_angle.py +++ b/selfdrive/controls/lib/latcontrol_angle.py @@ -11,7 +11,7 @@ class LatControlAngle(LatControl): super().__init__(CP, CI) self.sat_check_min_speed = 5. - def update(self, active, CS, VM, params, steer_limited, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): angle_log = log.ControlsState.LateralAngleState.new_message() if not active: diff --git a/selfdrive/controls/lib/latcontrol_pid.py b/selfdrive/controls/lib/latcontrol_pid.py index dedc97a964..cf54125a77 100644 --- a/selfdrive/controls/lib/latcontrol_pid.py +++ b/selfdrive/controls/lib/latcontrol_pid.py @@ -17,7 +17,7 @@ class LatControlPID(LatControl): super().reset() self.pid.reset() - def update(self, active, CS, VM, params, steer_limited, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): pid_log = log.ControlsState.LateralPIDState.new_message() pid_log.steeringAngleDeg = float(CS.steeringAngleDeg) pid_log.steeringRateDeg = float(CS.steeringRateDeg) @@ -43,6 +43,6 @@ class LatControlPID(LatControl): pid_log.i = float(self.pid.i) pid_log.f = float(self.pid.f) pid_log.output = float(output_steer) - pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited)) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited_by_controls)) return output_steer, angle_steers_des, pid_log diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index f677b7f897..7b00cce56b 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -37,7 +37,7 @@ class LatControlTorque(LatControl): self.torque_params.latAccelOffset = latAccelOffset self.torque_params.friction = friction - def update(self, active, CS, VM, params, steer_limited, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): pid_log = log.ControlsState.LateralTorqueState.new_message() if not active: output_torque = 0.0 @@ -73,7 +73,7 @@ class LatControlTorque(LatControl): desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, friction_compensation=True, gravity_adjusted=True) - freeze_integrator = steer_limited or CS.steeringPressed or CS.vEgo < 5 + freeze_integrator = steer_limited_by_controls or CS.steeringPressed or CS.vEgo < 5 output_torque = self.pid.update(pid_log.error, feedforward=ff, speed=CS.vEgo, @@ -87,7 +87,7 @@ class LatControlTorque(LatControl): pid_log.output = float(-output_torque) pid_log.actualLateralAccel = float(actual_lateral_accel) pid_log.desiredLateralAccel = float(desired_lateral_accel) - pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited)) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_controls)) # TODO left is positive in this convention return -output_torque, 0.0, pid_log diff --git a/tools/tuning/measure_steering_accuracy.py b/tools/tuning/measure_steering_accuracy.py index 5294ffcc49..a2f437819f 100755 --- a/tools/tuning/measure_steering_accuracy.py +++ b/tools/tuning/measure_steering_accuracy.py @@ -49,7 +49,7 @@ class SteeringAccuracyTool: active = sm['controlsState'].active steer = sm['carOutput'].actuatorsOutput.torque standstill = sm['carState'].standstill - steer_limited = abs(sm['carControl'].actuators.torque - sm['carControl'].actuatorsOutput.torque) > 1e-2 + steer_limited_by_controls = abs(sm['carControl'].actuators.torque - sm['carControl'].actuatorsOutput.torque) > 1e-2 overriding = sm['carState'].steeringPressed changing_lanes = sm['modelV2'].meta.laneChangeState != 0 model_points = sm['modelV2'].position.y @@ -77,7 +77,7 @@ class SteeringAccuracyTool: self.speed_group_stats[group][angle_abs]["steer"] += abs(steer) if len(model_points): self.speed_group_stats[group][angle_abs]["dpp"] += abs(model_points[0]) - if steer_limited: + if steer_limited_by_controls: self.speed_group_stats[group][angle_abs]["limited"] += 1 if control_state.saturated: self.speed_group_stats[group][angle_abs]["saturated"] += 1 From 41346b2cc72f6a699b4497b07363f78df7c3786d Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 3 Mar 2025 16:40:35 -0800 Subject: [PATCH 04/26] agnos 11.10 (#34764) --- launch_env.sh | 2 +- system/hardware/tici/agnos.json | 12 ++++---- system/hardware/tici/all-partitions.json | 36 ++++++++++++------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/launch_env.sh b/launch_env.sh index 88c6550443..049b9da279 100755 --- a/launch_env.sh +++ b/launch_env.sh @@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1 export VECLIB_MAXIMUM_THREADS=1 if [ -z "$AGNOS_VERSION" ]; then - export AGNOS_VERSION="11.9" + export AGNOS_VERSION="11.10" fi export STAGING_ROOT="/data/safe_staging" diff --git a/system/hardware/tici/agnos.json b/system/hardware/tici/agnos.json index 6538560363..d42c8151ab 100644 --- a/system/hardware/tici/agnos.json +++ b/system/hardware/tici/agnos.json @@ -67,17 +67,17 @@ }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75.img.xz", - "hash": "affcc08700026f1726ef16337e031fffc5556435b2b0facea81c7ffb0b66560c", - "hash_raw": "061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75", + "url": "https://commadist.azureedge.net/agnosupdate/system-5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9.img.xz", + "hash": "e4872f4132111b7b28586d978dd01bb48ffa031e103d029ebede7613c1bc2aa6", + "hash_raw": "5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9", "size": 4404019200, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "cc86836c6fc1c54f24dd0395e57e0b1ac6efe44d3ece833ab3ed456fe46a55cf", + "ondevice_hash": "4e5e680b4ac387ddc974b32dd3d5ec1d76282511eab974866b3b72399034985e", "alt": { - "hash": "061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75", - "url": "https://commadist.azureedge.net/agnosupdate/system-061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75.img", + "hash": "5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9", + "url": "https://commadist.azureedge.net/agnosupdate/system-5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9.img", "size": 4404019200 } } diff --git a/system/hardware/tici/all-partitions.json b/system/hardware/tici/all-partitions.json index 5b3478f746..e90e8c2ec4 100644 --- a/system/hardware/tici/all-partitions.json +++ b/system/hardware/tici/all-partitions.json @@ -350,51 +350,51 @@ }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75.img.xz", - "hash": "affcc08700026f1726ef16337e031fffc5556435b2b0facea81c7ffb0b66560c", - "hash_raw": "061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75", + "url": "https://commadist.azureedge.net/agnosupdate/system-5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9.img.xz", + "hash": "e4872f4132111b7b28586d978dd01bb48ffa031e103d029ebede7613c1bc2aa6", + "hash_raw": "5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9", "size": 4404019200, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "cc86836c6fc1c54f24dd0395e57e0b1ac6efe44d3ece833ab3ed456fe46a55cf", + "ondevice_hash": "4e5e680b4ac387ddc974b32dd3d5ec1d76282511eab974866b3b72399034985e", "alt": { - "hash": "061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75", - "url": "https://commadist.azureedge.net/agnosupdate/system-061783c4826369c7aa711266e8e1d9eecfd0a6d6c8afc6042e4045617512be75.img", + "hash": "5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9", + "url": "https://commadist.azureedge.net/agnosupdate/system-5612484e7f255659c0845de620e7c733afd2e1b939f9464f5ef039721bb7cba9.img", "size": 4404019200 } }, { "name": "userdata_90", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-fd9d27a3ef5c1f63b85721798ba4ea10f2a4c71d0c8d9b59362a99f24dfff54a.img.xz", - "hash": "b77b66ae8178519dbd72443ff7bdd21b97d0d4d76425472bedc7d369958de37b", - "hash_raw": "fd9d27a3ef5c1f63b85721798ba4ea10f2a4c71d0c8d9b59362a99f24dfff54a", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-16c037fa42ee99bc6ec92909efc8a8075a0e8a0232a7d90e39e7d40a7bd0ee8e.img.xz", + "hash": "c6fb215f2b297f7ff5b8f133bc5d687772b37f2fee42a44aa730e37a84a14e52", + "hash_raw": "16c037fa42ee99bc6ec92909efc8a8075a0e8a0232a7d90e39e7d40a7bd0ee8e", "size": 96636764160, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "52d2b8e2486e7fa0cdeb2a6512a8058db43544c905367a2e1b81a5ad4636d4b7" + "ondevice_hash": "7199262f209abbb07be5eece505ac4d4c7ba8957f2d9ff7b1ac1ef2063461665" }, { "name": "userdata_89", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-1042711c5f69146ff7680f09eab1b2eb6fe9da0411318e9ff913c27168cb0307.img.xz", - "hash": "cc24b1c78234f92cd8ef66541f3fb8924719fc4b7f42c26e26eb71ec21cd2e93", - "hash_raw": "1042711c5f69146ff7680f09eab1b2eb6fe9da0411318e9ff913c27168cb0307", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-62c2c41470282b581ec1bbbe0375fb3b6c66df2f4bc3dc6c6fdf796f1797f136.img.xz", + "hash": "d66f894436fa11d4ff00f8a84e54d9e23a6492b0087f69bb958d2ab0bdc6dfba", + "hash_raw": "62c2c41470282b581ec1bbbe0375fb3b6c66df2f4bc3dc6c6fdf796f1797f136", "size": 95563022336, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "80bf38b8b60ea1ef1fc0849af4e18bf114761f98f5371476e2f762d0f8463204" + "ondevice_hash": "f1d3685618f6d1bde24ce6109284c5d30ece2f4fd015be67e8b52ef7e06067a4" }, { "name": "userdata_30", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-6d429550c42616e3f252034305f238ce0e90926762992ff3f92322f226caa5b6.img.xz", - "hash": "657b052cf6434ef19ff73bdeaf5b2511e5c42f64594ae37bac467a12b4cd673f", - "hash_raw": "6d429550c42616e3f252034305f238ce0e90926762992ff3f92322f226caa5b6", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-3e71d8804c90a6dff5048edb976149f9ea177efa139dea47cb585cef76b26f6e.img.xz", + "hash": "1b201ecbd0e1573777811bf18fa90cb080bfbccb34a6dcfd39b412632e7ca699", + "hash_raw": "3e71d8804c90a6dff5048edb976149f9ea177efa139dea47cb585cef76b26f6e", "size": 32212254720, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "6437e5a5b7144103952950f2f59f8e70b98cd26ee5bfb06cbd0a13b2e2f343b7" + "ondevice_hash": "47c28e63209556442cd9d2fd06a6c0e7fcf35c8a4e4fbcc550b9c089429ad0e0" } ] \ No newline at end of file From 701868d5cddb1fa2a4e84289b0e45c4232322c72 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 3 Mar 2025 18:21:02 -0800 Subject: [PATCH 05/26] firehose auto start + stats (#34747) * don't need that * stats * lil more * lil more * cleanup * tweaks --------- Co-authored-by: Comma Device --- common/params_keys.h | 2 +- selfdrive/ui/qt/offroad/firehose.cc | 99 +++++++++++++++-------------- selfdrive/ui/qt/offroad/firehose.h | 19 +++--- system/athena/athenad.py | 4 -- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index 40a69ebd88..2b540b744c 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -8,6 +8,7 @@ inline static std::unordered_map keys = { {"AdbEnabled", PERSISTENT}, {"AlwaysOnDM", PERSISTENT}, {"ApiCache_Device", PERSISTENT}, + {"ApiCache_FirehoseStats", PERSISTENT}, {"AssistNowToken", PERSISTENT}, {"AthenadPid", PERSISTENT}, {"AthenadUploadQueue", PERSISTENT}, @@ -36,7 +37,6 @@ inline static std::unordered_map keys = { {"ExperimentalLongitudinalEnabled", PERSISTENT | DEVELOPMENT_ONLY}, {"ExperimentalMode", PERSISTENT}, {"ExperimentalModeConfirmed", PERSISTENT}, - {"FirehoseMode", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION}, {"FirmwareQueryDone", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION}, {"ForcePowerDown", PERSISTENT}, {"GitBranch", PERSISTENT}, diff --git a/selfdrive/ui/qt/offroad/firehose.cc b/selfdrive/ui/qt/offroad/firehose.cc index 7b48b0fd9a..77474d00c2 100644 --- a/selfdrive/ui/qt/offroad/firehose.cc +++ b/selfdrive/ui/qt/offroad/firehose.cc @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) { layout = new QVBoxLayout(this); @@ -28,7 +31,7 @@ FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) content_layout->setSpacing(20); // Top description - QLabel *description = new QLabel(tr("openpilot learns to drive by watching humans, like you, drive.\n\nFirehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode.")); + QLabel *description = new QLabel(tr("openpilot learns to drive by watching humans, like you, drive.\n\nFirehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode.")); description->setStyleSheet("font-size: 45px; padding-bottom: 20px;"); description->setWordWrap(true); content_layout->addWidget(description); @@ -40,41 +43,16 @@ FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) line->setStyleSheet("background-color: #444444; margin-top: 5px; margin-bottom: 5px;"); content_layout->addWidget(line); - enable_firehose = new ParamControl("FirehoseMode", tr("Enable Firehose Mode"), "", ""); + toggle_label = new QLabel(tr("Firehose Mode: ACTIVE")); + toggle_label->setStyleSheet("font-size: 60px; font-weight: bold; color: white;"); + content_layout->addWidget(toggle_label); - content_layout->addWidget(enable_firehose); - - // Create progress bar container - progress_container = new QFrame(); - progress_container->hide(); - QHBoxLayout *progress_layout = new QHBoxLayout(progress_container); - progress_layout->setContentsMargins(10, 0, 10, 10); - progress_layout->setSpacing(20); - - progress_bar = new QProgressBar(); - progress_bar->setRange(0, 100); - progress_bar->setValue(0); - progress_bar->setTextVisible(false); - progress_bar->setStyleSheet(R"( - QProgressBar { - background-color: #444444; - border-radius: 10px; - height: 20px; - } - QProgressBar::chunk { - background-color: #3498db; - border-radius: 10px; - } - )"); - progress_bar->setFixedHeight(40); - - // Progress text - progress_text = new QLabel(tr("0%")); - progress_text->setStyleSheet("font-size: 40px; font-weight: bold; color: white;"); - - progress_layout->addWidget(progress_text); - - content_layout->addWidget(progress_container); + // Add contribution label + contribution_label = new QLabel("0 minutes"); + contribution_label->setStyleSheet("font-size: 52px; margin-top: 10px; margin-bottom: 10px;"); + contribution_label->setWordWrap(true); + contribution_label->hide(); + content_layout->addWidget(contribution_label); // Add a separator before detailed instructions QFrame *line2 = new QFrame(); @@ -85,22 +63,49 @@ FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) // Detailed instructions at the bottom detailed_instructions = new QLabel(tr( - "Follow these steps to get your device ready:
" - "\t1. Bring your device inside and connect to a good USB-C adapter
" - "\t2. Connect to Wi-Fi
" - "\t3. Enable the toggle
" - "\t4. Leave it connected for at least 30 minutes
" + "For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.
" "
" - "The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness." - "

FAQ
" - "Does it matter how or where I drive? Nope, just drive as you normally would.
" - "What's a good USB-C adapter? Any fast phone or laptop charger should be fine.
" - "Do I need to be on Wi-Fi? Yes.
" - "Do I need to bring the device inside? No, you can enable once you're parked, however your uploads will be limited by your car's battery.
" + "Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.
" + "

" + "Frequently Asked Questions

" + "Does it matter how or where I drive? Nope, just drive as you normally would.

" + "What's a good USB-C adapter? Any fast phone or laptop charger should be fine.

" + "Does it matter which software I run? Yes, only upstream openpilot (and particular forks) are able to be used for training." )); - detailed_instructions->setStyleSheet("font-size: 40px; padding: 20px; color: #E4E4E4;"); + detailed_instructions->setStyleSheet("font-size: 40px; color: #E4E4E4;"); detailed_instructions->setWordWrap(true); content_layout->addWidget(detailed_instructions); layout->addWidget(content, 1); + + // Set up the API request for firehose stats + const QString dongle_id = QString::fromStdString(Params().get("DongleId")); + firehose_stats = new RequestRepeater(this, CommaApi::BASE_URL + "/v1/devices/" + dongle_id + "/firehose_stats", + "ApiCache_FirehoseStats", 30, true); + QObject::connect(firehose_stats, &RequestRepeater::requestDone, [=](const QString &response, bool success) { + if (success) { + QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); + QJsonObject json = doc.object(); + int count = json["firehose"].toInt(); + contribution_label->setText(tr("%1 %2 of your driving are in the training dataset so far.").arg(count).arg(count == 1 ? "segment" : "segments")); + contribution_label->show(); + } + }); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &FirehosePanel::refresh); +} + +void FirehosePanel::refresh() { + auto deviceState = (*uiState()->sm)["deviceState"].getDeviceState(); + auto networkType = deviceState.getNetworkType(); + bool networkMetered = deviceState.getNetworkMetered(); + + bool is_active = !networkMetered && (networkType != cereal::DeviceState::NetworkType::NONE); + if (is_active) { + toggle_label->setText(tr("ACTIVE")); + toggle_label->setStyleSheet("font-size: 60px; font-weight: bold; color: #2ecc71;"); + } else { + toggle_label->setText(tr("INACTIVE: connect to unmetered network")); + toggle_label->setStyleSheet("font-size: 60px;"); + } } diff --git a/selfdrive/ui/qt/offroad/firehose.h b/selfdrive/ui/qt/offroad/firehose.h index 7f5899f9f0..9082cb0f99 100644 --- a/selfdrive/ui/qt/offroad/firehose.h +++ b/selfdrive/ui/qt/offroad/firehose.h @@ -2,10 +2,8 @@ #include #include -#include #include -#include "selfdrive/ui/qt/widgets/controls.h" -#include "common/params.h" +#include "selfdrive/ui/qt/request_repeater.h" // Forward declarations class SettingsWindow; @@ -17,12 +15,13 @@ public: private: QVBoxLayout *layout; - - ParamControl *enable_firehose; - QFrame *progress_container; - QProgressBar *progress_bar; - QLabel *progress_text; + QLabel *detailed_instructions; - - void updateFirehoseState(bool enabled); + QLabel *contribution_label; + QLabel *toggle_label; + + RequestRepeater *firehose_stats; + +private slots: + void refresh(); }; diff --git a/system/athena/athenad.py b/system/athena/athenad.py index 27440e84a6..b36bdb103d 100755 --- a/system/athena/athenad.py +++ b/system/athena/athenad.py @@ -508,10 +508,6 @@ def getSshAuthorizedKeys() -> str: def getGithubUsername() -> str: return Params().get("GithubUsername", encoding='utf8') or '' -@dispatcher.add_method -def getFirehoseMode() -> bool: - return Params().get_bool("FirehoseMode") or False - @dispatcher.add_method def getSimInfo(): return HARDWARE.get_sim_info() From 34a072890cc3c963ea6cb2cdaa23c96f3d802a93 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 3 Mar 2025 18:39:12 -0800 Subject: [PATCH 06/26] fix translations --- selfdrive/ui/qt/offroad/firehose.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/ui/qt/offroad/firehose.cc b/selfdrive/ui/qt/offroad/firehose.cc index 77474d00c2..ab1d0198c7 100644 --- a/selfdrive/ui/qt/offroad/firehose.cc +++ b/selfdrive/ui/qt/offroad/firehose.cc @@ -48,7 +48,7 @@ FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) content_layout->addWidget(toggle_label); // Add contribution label - contribution_label = new QLabel("0 minutes"); + contribution_label = new QLabel(); contribution_label->setStyleSheet("font-size: 52px; margin-top: 10px; margin-bottom: 10px;"); contribution_label->setWordWrap(true); contribution_label->hide(); From 338b7c915fd37345fe925088c7444ddfdbab9e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20R=C4=85czy?= Date: Mon, 3 Mar 2025 22:10:48 -0500 Subject: [PATCH 07/26] regen: use ci bucket for files (#34766) * Remove route meta mode * use get_url * Remove useless import --- selfdrive/test/process_replay/regen.py | 52 +++++++--------------- selfdrive/test/process_replay/regen_all.py | 2 +- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py index e87b8347e1..4d00613f0a 100755 --- a/selfdrive/test/process_replay/regen.py +++ b/selfdrive/test/process_replay/regen.py @@ -12,10 +12,9 @@ from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKE check_openpilot_enabled, check_most_messages_valid, get_custom_params_from_lr from openpilot.selfdrive.test.process_replay.vision_meta import DRIVER_CAMERA_FRAME_SIZES from openpilot.selfdrive.test.update_ci_routes import upload_route -from openpilot.tools.lib.route import Route from openpilot.tools.lib.framereader import FrameReader, BaseFrameReader, FrameType from openpilot.tools.lib.logreader import LogReader, LogIterable, save_log - +from openpilot.tools.lib.openpilotci import get_url class DummyFrameReader(BaseFrameReader): def __init__(self, w: int, h: int, frame_count: int, pix_val: int): @@ -55,45 +54,28 @@ def regen_segment( def setup_data_readers( - route: str, sidx: int, use_route_meta: bool, - needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False + route: str, sidx: int, needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False ) -> tuple[LogReader, dict[str, Any]]: - if use_route_meta: - r = Route(route) - lr = LogReader(r.log_paths()[sidx]) - frs = {} - if needs_road_cam and len(r.camera_paths()) > sidx and r.camera_paths()[sidx] is not None: - frs['roadCameraState'] = FrameReader(r.camera_paths()[sidx]) - if needs_road_cam and len(r.ecamera_paths()) > sidx and r.ecamera_paths()[sidx] is not None: - frs['wideRoadCameraState'] = FrameReader(r.ecamera_paths()[sidx]) - if needs_driver_cam: - if dummy_driver_cam: - frs['driverCameraState'] = DummyFrameReader.zero_dcamera() - elif len(r.dcamera_paths()) > sidx and r.dcamera_paths()[sidx] is not None: - device_type = next(str(msg.initData.deviceType) for msg in lr if msg.which() == "initData") - assert device_type != "neo", "Driver camera not supported on neo segments. Use dummy dcamera." - frs['driverCameraState'] = FrameReader(r.dcamera_paths()[sidx]) - else: - lr = LogReader(f"{route}/{sidx}/r") - frs = {} - if needs_road_cam: - frs['roadCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/fcamera.hevc") - if next((True for m in lr if m.which() == "wideRoadCameraState"), False): - frs['wideRoadCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/ecamera.hevc") - if needs_driver_cam: - if dummy_driver_cam: - frs['driverCameraState'] = DummyFrameReader.zero_dcamera() - else: - device_type = next(str(msg.initData.deviceType) for msg in lr if msg.which() == "initData") - assert device_type != "neo", "Driver camera not supported on neo segments. Use dummy dcamera." - frs['driverCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/dcamera.hevc") + lr = LogReader(f"{route}/{sidx}/r") + frs = {} + if needs_road_cam: + frs['roadCameraState'] = FrameReader(get_url(route, str(sidx), "fcamera.hevc")) + if next((True for m in lr if m.which() == "wideRoadCameraState"), False): + frs['wideRoadCameraState'] = FrameReader(get_url(route, str(sidx), "ecamera.hevc")) + if needs_driver_cam: + if dummy_driver_cam: + frs['driverCameraState'] = DummyFrameReader.zero_dcamera() + else: + device_type = next(str(msg.initData.deviceType) for msg in lr if msg.which() == "initData") + assert device_type != "neo", "Driver camera not supported on neo segments. Use dummy dcamera." + frs['driverCameraState'] = FrameReader(get_url(route, str(sidx), "dcamera.hevc")) return lr, frs def regen_and_save( route: str, sidx: int, processes: str | Iterable[str] = "all", outdir: str = FAKEDATA, - upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False + upload: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False ) -> str: if not isinstance(processes, str) and not hasattr(processes, "__iter__"): raise ValueError("whitelist_proc must be a string or iterable") @@ -110,7 +92,7 @@ def regen_and_save( replayed_processes = CONFIGS all_vision_pubs = {pub for cfg in replayed_processes for pub in cfg.vision_pubs} - lr, frs = setup_data_readers(route, sidx, use_route_meta, + lr, frs = setup_data_readers(route, sidx, needs_driver_cam="driverCameraState" in all_vision_pubs, needs_road_cam="roadCameraState" in all_vision_pubs or "wideRoadCameraState" in all_vision_pubs, dummy_driver_cam=dummy_driver_cam) diff --git a/selfdrive/test/process_replay/regen_all.py b/selfdrive/test/process_replay/regen_all.py index 656a5b89e1..78a90b420c 100755 --- a/selfdrive/test/process_replay/regen_all.py +++ b/selfdrive/test/process_replay/regen_all.py @@ -17,7 +17,7 @@ def regen_job(segment, upload, disable_tqdm): sn = SegmentName(segment[1]) fake_dongle_id = 'regen' + ''.join(random.choice('0123456789ABCDEF') for _ in range(11)) try: - relr = regen_and_save(sn.route_name.canonical_name, sn.segment_num, upload=upload, use_route_meta=False, + relr = regen_and_save(sn.route_name.canonical_name, sn.segment_num, upload=upload, outdir=os.path.join(FAKEDATA, fake_dongle_id), disable_tqdm=disable_tqdm, dummy_driver_cam=True) relr = '|'.join(relr.split('/')[-2:]) return f' ("{segment[0]}", "{relr}"), ' From 9c9a060365582eed91548a6c3d1fb368f73bc56e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 3 Mar 2025 19:11:53 -0800 Subject: [PATCH 08/26] saturated warning: remove redundant speed check --- selfdrive/selfdrived/selfdrived.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 784925c966..68716c1f64 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -331,8 +331,8 @@ class SelfdriveD: desired_lateral_accel = controlstate.desiredCurvature * (clipped_speed**2) undershooting = abs(desired_lateral_accel) / abs(1e-3 + actual_lateral_accel) > 1.2 turning = abs(desired_lateral_accel) > 1.0 - good_speed = CS.vEgo > 5 - if undershooting and turning and good_speed and lac.saturated: + # TODO: lac.saturated includes speed and other checks, should be pulled out + if undershooting and turning and lac.saturated: self.events.add(EventName.steerSaturated) # Check for FCW From 949aaaba2c6ddc57c54bbd7ca938b476d7b15545 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 3 Mar 2025 19:34:33 -0800 Subject: [PATCH 09/26] regenerate problem segments --- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/test/process_replay/test_processes.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 3c63f00300..d0f0d671d7 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -d343af55506b14a4011bfe43b2a49c7e3c387d75 \ No newline at end of file +a9487c6a5c2f0bb83c9d629ff64c8f64a4e4ca13 \ No newline at end of file diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 0fff34917f..927f54c0c3 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -42,22 +42,22 @@ source_segments = [ segments = [ ("BODY", "regenA67A128BCD8|2024-08-30--02-36-22--0"), - ("HYUNDAI", "regen9CBD921E93E|2024-08-30--02-38-51--0"), + ("HYUNDAI", "regenCCD47FEBC0C|2025-03-04--03-21-48--0"), ("HYUNDAI2", "regen306779F6870|2024-10-03--04-03-23--0"), - ("TOYOTA", "regen1CA7A48E6F7|2024-08-30--02-45-08--0"), + ("TOYOTA", "regen4A5115B248D|2025-03-04--03-21-43--0"), ("TOYOTA2", "regen6E484EDAB96|2024-08-30--02-47-37--0"), ("TOYOTA3", "regen4CE950B0267|2024-08-30--02-51-30--0"), - ("HONDA", "regenC8F0D6ADC5C|2024-08-30--02-54-01--0"), + ("HONDA", "regenB8CABEC09CC|2025-03-04--03-32-55--0"), ("HONDA2", "regen4B38A7428CD|2024-08-30--02-56-31--0"), ("CHRYSLER", "regenF3DBBA9E8DF|2024-08-30--02-59-03--0"), ("RAM", "regenDB02684E00A|2024-08-30--03-02-54--0"), - ("SUBARU", "regenAA1FF48CF1F|2024-08-30--03-06-45--0"), + ("SUBARU", "regen5E3347D0A0F|2025-03-04--03-23-55--0"), ("GM", "regen720F2BA4CF6|2024-08-30--03-09-15--0"), ("GM2", "regen9ADBECBCD1C|2024-08-30--03-13-04--0"), ("NISSAN", "regen58464878D07|2024-08-30--03-15-31--0"), ("VOLKSWAGEN", "regenED976DEB757|2024-08-30--03-18-02--0"), ("MAZDA", "regenACF84CCF482|2024-08-30--03-21-55--0"), - ("FORD", "regen756F8230C21|2024-11-07--00-08-24--0"), + ("FORD", "regenA75209BD115|2025-03-04--03-23-53--0"), ("RIVIAN", "bc095dc92e101734|000000db--ee9fe46e57--1"), ] From 6891b795c49070a8916946454a85fae0fddb84a6 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 3 Mar 2025 21:47:52 -0600 Subject: [PATCH 10/26] controls: limit max curvature from lateral acceleration (#34651) * limit max curvature with lateral accel too * not a guideline * roll compensation in curv clip * improve clipping and alerting * typo * clean up * no float * get ready * good idea * good * redundant * TODO * test * do max curvature clip last * flip --------- Co-authored-by: Bruce Wayne --- selfdrive/controls/controlsd.py | 8 ++-- selfdrive/controls/lib/drive_helpers.py | 38 +++++++++++++------ selfdrive/controls/lib/latcontrol.py | 7 ++-- selfdrive/controls/lib/latcontrol_angle.py | 4 +- selfdrive/controls/lib/latcontrol_pid.py | 4 +- selfdrive/controls/lib/latcontrol_torque.py | 4 +- .../controls/lib/tests/test_latcontrol.py | 10 ++++- selfdrive/selfdrived/selfdrived.py | 2 +- 8 files changed, 50 insertions(+), 27 deletions(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 14fd37040e..dcc1c74794 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -109,11 +109,11 @@ class Controls: actuators.accel = float(self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits)) # Steering PID loop and lateral MPC - self.desired_curvature = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature) - actuators.curvature = float(self.desired_curvature) + self.desired_curvature, curvature_limited = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature, lp.roll) + actuators.curvature = self.desired_curvature steer, steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp, self.steer_limited_by_controls, self.desired_curvature, - self.calibrated_pose) # TODO what if not available + self.calibrated_pose, curvature_limited) # TODO what if not available actuators.torque = float(steer) actuators.steeringAngleDeg = float(steeringAngleDeg) # Ensure no NaNs/Infs @@ -180,7 +180,7 @@ class Controls: cs.longitudinalPlanMonoTime = self.sm.logMonoTime['longitudinalPlan'] cs.lateralPlanMonoTime = self.sm.logMonoTime['modelV2'] - cs.desiredCurvature = float(self.desired_curvature) + cs.desiredCurvature = self.desired_curvature cs.longControlState = self.LoC.long_control_state cs.upAccelCmd = float(self.LoC.pid.p) cs.uiAccelCmd = float(self.LoC.pid.i) diff --git a/selfdrive/controls/lib/drive_helpers.py b/selfdrive/controls/lib/drive_helpers.py index dcb0093a18..41384abae8 100644 --- a/selfdrive/controls/lib/drive_helpers.py +++ b/selfdrive/controls/lib/drive_helpers.py @@ -1,5 +1,6 @@ import numpy as np from cereal import log +from opendbc.car.vehicle_model import ACCELERATION_DUE_TO_GRAVITY from openpilot.common.realtime import DT_CTRL MIN_SPEED = 1.0 @@ -7,20 +8,33 @@ CONTROL_N = 17 CAR_ROTATION_RADIUS = 0.0 # This is a turn radius smaller than most cars can achieve MAX_CURVATURE = 0.2 +MAX_VEL_ERR = 5.0 # m/s # EU guidelines -MAX_LATERAL_JERK = 5.0 -MAX_VEL_ERR = 5.0 - -def clip_curvature(v_ego, prev_curvature, new_curvature): - new_curvature = np.clip(new_curvature, -MAX_CURVATURE, MAX_CURVATURE) - v_ego = max(MIN_SPEED, v_ego) - max_curvature_rate = MAX_LATERAL_JERK / (v_ego**2) # inexact calculation, check https://github.com/commaai/openpilot/pull/24755 - safe_desired_curvature = np.clip(new_curvature, - prev_curvature - max_curvature_rate * DT_CTRL, - prev_curvature + max_curvature_rate * DT_CTRL) - - return safe_desired_curvature +MAX_LATERAL_JERK = 5.0 # m/s^3 +MAX_LATERAL_ACCEL_NO_ROLL = 3.0 # m/s^2 + + +def clamp(val, min_val, max_val): + clamped_val = float(np.clip(val, min_val, max_val)) + return clamped_val, clamped_val != val + + +def clip_curvature(v_ego, prev_curvature, new_curvature, roll): + # This function respects ISO lateral jerk and acceleration limits + a max curvature + v_ego = max(v_ego, MIN_SPEED) + max_curvature_rate = MAX_LATERAL_JERK / (v_ego ** 2) # inexact calculation, check https://github.com/commaai/openpilot/pull/24755 + new_curvature = np.clip(new_curvature, + prev_curvature - max_curvature_rate * DT_CTRL, + prev_curvature + max_curvature_rate * DT_CTRL) + + roll_compensation = roll * ACCELERATION_DUE_TO_GRAVITY + max_lat_accel = MAX_LATERAL_ACCEL_NO_ROLL + roll_compensation + min_lat_accel = -MAX_LATERAL_ACCEL_NO_ROLL + roll_compensation + new_curvature, limited_accel = clamp(new_curvature, min_lat_accel / v_ego ** 2, max_lat_accel / v_ego ** 2) + + new_curvature, limited_max_curv = clamp(new_curvature, -MAX_CURVATURE, MAX_CURVATURE) + return float(new_curvature), limited_accel or limited_max_curv def get_speed_error(modelV2: log.ModelDataV2, v_ego: float) -> float: diff --git a/selfdrive/controls/lib/latcontrol.py b/selfdrive/controls/lib/latcontrol.py index f0121f73bc..dcf0003430 100644 --- a/selfdrive/controls/lib/latcontrol.py +++ b/selfdrive/controls/lib/latcontrol.py @@ -17,14 +17,15 @@ class LatControl(ABC): self.steer_max = 1.0 @abstractmethod - def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited): pass def reset(self): self.sat_count = 0. - def _check_saturation(self, saturated, CS, steer_limited_by_controls): - if saturated and CS.vEgo > self.sat_check_min_speed and not steer_limited_by_controls and not CS.steeringPressed: + def _check_saturation(self, saturated, CS, steer_limited_by_controls, curvature_limited): + # Saturated only if control output is not being limited by car torque/angle rate limits + if (saturated or curvature_limited) and CS.vEgo > self.sat_check_min_speed and not steer_limited_by_controls and not CS.steeringPressed: self.sat_count += self.sat_count_rate else: self.sat_count -= self.sat_count_rate diff --git a/selfdrive/controls/lib/latcontrol_angle.py b/selfdrive/controls/lib/latcontrol_angle.py index de07423fd4..1b249a3d1a 100644 --- a/selfdrive/controls/lib/latcontrol_angle.py +++ b/selfdrive/controls/lib/latcontrol_angle.py @@ -11,7 +11,7 @@ class LatControlAngle(LatControl): super().__init__(CP, CI) self.sat_check_min_speed = 5. - def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited): angle_log = log.ControlsState.LateralAngleState.new_message() if not active: @@ -23,7 +23,7 @@ class LatControlAngle(LatControl): angle_steers_des += params.angleOffsetDeg angle_control_saturated = abs(angle_steers_des - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD - angle_log.saturated = bool(self._check_saturation(angle_control_saturated, CS, False)) + angle_log.saturated = bool(self._check_saturation(angle_control_saturated, CS, False, curvature_limited)) angle_log.steeringAngleDeg = float(CS.steeringAngleDeg) angle_log.steeringAngleDesiredDeg = angle_steers_des return 0, float(angle_steers_des), angle_log diff --git a/selfdrive/controls/lib/latcontrol_pid.py b/selfdrive/controls/lib/latcontrol_pid.py index cf54125a77..1f1199565e 100644 --- a/selfdrive/controls/lib/latcontrol_pid.py +++ b/selfdrive/controls/lib/latcontrol_pid.py @@ -17,7 +17,7 @@ class LatControlPID(LatControl): super().reset() self.pid.reset() - def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited): pid_log = log.ControlsState.LateralPIDState.new_message() pid_log.steeringAngleDeg = float(CS.steeringAngleDeg) pid_log.steeringRateDeg = float(CS.steeringRateDeg) @@ -43,6 +43,6 @@ class LatControlPID(LatControl): pid_log.i = float(self.pid.i) pid_log.f = float(self.pid.f) pid_log.output = float(output_steer) - pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited_by_controls)) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_steer) < 1e-3, CS, steer_limited_by_controls, curvature_limited)) return output_steer, angle_steers_des, pid_log diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 7b00cce56b..3aef57baca 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -37,7 +37,7 @@ class LatControlTorque(LatControl): self.torque_params.latAccelOffset = latAccelOffset self.torque_params.friction = friction - def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose): + def update(self, active, CS, VM, params, steer_limited_by_controls, desired_curvature, calibrated_pose, curvature_limited): pid_log = log.ControlsState.LateralTorqueState.new_message() if not active: output_torque = 0.0 @@ -87,7 +87,7 @@ class LatControlTorque(LatControl): pid_log.output = float(-output_torque) pid_log.actualLateralAccel = float(actual_lateral_accel) pid_log.desiredLateralAccel = float(desired_lateral_accel) - pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_controls)) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_controls, curvature_limited)) # TODO left is positive in this convention return -output_torque, 0.0, pid_log diff --git a/selfdrive/controls/lib/tests/test_latcontrol.py b/selfdrive/controls/lib/tests/test_latcontrol.py index c7038dd581..564c93be0d 100644 --- a/selfdrive/controls/lib/tests/test_latcontrol.py +++ b/selfdrive/controls/lib/tests/test_latcontrol.py @@ -33,7 +33,15 @@ class TestLatControl: lp = generate_livePose() pose = Pose.from_live_pose(lp.livePose) + # Saturate for curvature limited and controller limited for _ in range(1000): - _, _, lac_log = controller.update(True, CS, VM, params, False, 1, pose) + _, _, lac_log = controller.update(True, CS, VM, params, False, 0, pose, True) + assert lac_log.saturated + + for _ in range(1000): + _, _, lac_log = controller.update(True, CS, VM, params, False, 0, pose, False) + assert not lac_log.saturated + for _ in range(1000): + _, _, lac_log = controller.update(True, CS, VM, params, False, 1, pose, False) assert lac_log.saturated diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 68716c1f64..8b7db19c9a 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -328,7 +328,7 @@ class SelfdriveD: if lac.active and not recent_steer_pressed and not self.CP.notCar: clipped_speed = max(CS.vEgo, MIN_LATERAL_CONTROL_SPEED) actual_lateral_accel = controlstate.curvature * (clipped_speed**2) - desired_lateral_accel = controlstate.desiredCurvature * (clipped_speed**2) + desired_lateral_accel = self.sm['modelV2'].action.desiredCurvature * (clipped_speed**2) undershooting = abs(desired_lateral_accel) / abs(1e-3 + actual_lateral_accel) > 1.2 turning = abs(desired_lateral_accel) > 1.0 # TODO: lac.saturated includes speed and other checks, should be pulled out From f818c5528f808351e5350e26c88bce4f84a786b5 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 3 Mar 2025 22:24:16 -0600 Subject: [PATCH 11/26] bump opendbc (#34768) bump --- opendbc_repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendbc_repo b/opendbc_repo index ca4f77b010..34a109cc79 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit ca4f77b0101d85a5e8d292e2e61f7a8c7492b9e2 +Subproject commit 34a109cc7956dbf022f57b6bca2207f2719e25a7 From e5ba737db0f1991a02896480387dadca6ac46bf4 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 3 Mar 2025 22:56:59 -0800 Subject: [PATCH 12/26] Revert "Filet o Fish model (#34637)" This reverts commit 159b1c9eb48551e6ac1d5f9281ac2218f320f499. --- selfdrive/modeld/constants.py | 8 +----- selfdrive/modeld/modeld.py | 31 +++++++-------------- selfdrive/modeld/models/commonmodel.cc | 9 +++--- selfdrive/modeld/models/commonmodel.h | 5 ++-- selfdrive/modeld/models/commonmodel.pxd | 2 +- selfdrive/modeld/models/commonmodel_pyx.pyx | 4 +-- selfdrive/modeld/models/driving_policy.onnx | 4 +-- selfdrive/modeld/models/driving_vision.onnx | 2 +- 8 files changed, 23 insertions(+), 42 deletions(-) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index 5ca0a86bc8..2bb7b8100c 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -14,14 +14,8 @@ class ModelConstants: # model inputs constants MODEL_FREQ = 20 - HISTORY_FREQ = 5 - HISTORY_LEN_SECONDS = 5 - TEMPORAL_SKIP = MODEL_FREQ // HISTORY_FREQ - FULL_HISTORY_BUFFER_LEN = MODEL_FREQ * HISTORY_LEN_SECONDS - INPUT_HISTORY_BUFFER_LEN = HISTORY_FREQ * HISTORY_LEN_SECONDS - FEATURE_LEN = 512 - + FULL_HISTORY_BUFFER_LEN = 100 DESIRE_LEN = 8 TRAFFIC_CONVENTION_LEN = 2 LAT_PLANNER_STATE_LEN = 4 diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index ae1e75e3e9..ee825d158f 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -56,24 +56,16 @@ class ModelState: prev_desire: np.ndarray # for tracking the rising edge of the pulse def __init__(self, context: CLContext): - self.frames = { - 'input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP), - 'big_input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) - } + self.frames = {'input_imgs': DrivingModelFrame(context), 'big_input_imgs': DrivingModelFrame(context)} self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) - self.full_features_buffer = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) - self.full_desire = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32) - self.full_prev_desired_curv = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32) - self.temporal_idxs = slice(-1-(ModelConstants.TEMPORAL_SKIP*(ModelConstants.INPUT_HISTORY_BUFFER_LEN-1)), None, ModelConstants.TEMPORAL_SKIP) - # policy inputs self.numpy_inputs = { - 'desire': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), 'lateral_control_params': np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32), - 'prev_desired_curv': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), + 'prev_desired_curv': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), + 'features_buffer': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } with open(VISION_METADATA_PATH, 'rb') as f: @@ -112,9 +104,8 @@ class ModelState: new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) self.prev_desire[:] = inputs['desire'] - self.full_desire[0,:-1] = self.full_desire[0,1:] - self.full_desire[0,-1] = new_desire - self.numpy_inputs['desire'][:] = self.full_desire[0, self.temporal_idxs] + self.numpy_inputs['desire'][0,:-1] = self.numpy_inputs['desire'][0,1:] + self.numpy_inputs['desire'][0,-1] = new_desire self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params'] @@ -137,17 +128,15 @@ class ModelState: self.vision_output = self.vision_run(**self.vision_inputs).numpy().flatten() vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) - self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:] - self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :] - self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs] + self.numpy_inputs['features_buffer'][0,:-1] = self.numpy_inputs['features_buffer'][0,1:] + self.numpy_inputs['features_buffer'][0,-1] = vision_outputs_dict['hidden_state'][0, :] self.policy_output = self.policy_run(**self.policy_inputs).numpy().flatten() policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) # TODO model only uses last value now - self.full_prev_desired_curv[0,:-1] = self.full_prev_desired_curv[0,1:] - self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] - self.numpy_inputs['prev_desired_curv'][:] = self.full_prev_desired_curv[0, self.temporal_idxs] + self.numpy_inputs['prev_desired_curv'][0,:-1] = self.numpy_inputs['prev_desired_curv'][0,1:] + self.numpy_inputs['prev_desired_curv'][0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} if SEND_RAW_PRED: diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc index 99155d9f1e..9973d18588 100644 --- a/selfdrive/modeld/models/commonmodel.cc +++ b/selfdrive/modeld/models/commonmodel.cc @@ -5,12 +5,11 @@ #include "common/clutil.h" -DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip) : ModelFrame(device_id, context) { +DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { input_frames = std::make_unique(buf_size); - temporal_skip = _temporal_skip; input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); - img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (temporal_skip+1)*frame_size_bytes, NULL, &err)); - region.origin = temporal_skip * frame_size_bytes; + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 2*frame_size_bytes, NULL, &err)); + region.origin = 1 * frame_size_bytes; region.size = frame_size_bytes; last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); @@ -21,7 +20,7 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); - for (int i = 0; i < temporal_skip; i++) { + for (int i = 0; i < 1; i++) { CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); } loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); diff --git a/selfdrive/modeld/models/commonmodel.h b/selfdrive/modeld/models/commonmodel.h index 176d7eb6dc..14409943e4 100644 --- a/selfdrive/modeld/models/commonmodel.h +++ b/selfdrive/modeld/models/commonmodel.h @@ -64,21 +64,20 @@ protected: class DrivingModelFrame : public ModelFrame { public: - DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip); + DrivingModelFrame(cl_device_id device_id, cl_context context); ~DrivingModelFrame(); cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); const int MODEL_WIDTH = 512; const int MODEL_HEIGHT = 256; const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT * 3 / 2; - const int buf_size = MODEL_FRAME_SIZE * 2; // 2 frames are temporal_skip frames apart + const int buf_size = MODEL_FRAME_SIZE * 2; const size_t frame_size_bytes = MODEL_FRAME_SIZE * sizeof(uint8_t); private: LoadYUVState loadyuv; cl_mem img_buffer_20hz_cl, last_img_cl, input_frames_cl; cl_buffer_region region; - int temporal_skip; }; class MonitoringModelFrame : public ModelFrame { diff --git a/selfdrive/modeld/models/commonmodel.pxd b/selfdrive/modeld/models/commonmodel.pxd index 4ac64d9172..b4f08b12aa 100644 --- a/selfdrive/modeld/models/commonmodel.pxd +++ b/selfdrive/modeld/models/commonmodel.pxd @@ -20,7 +20,7 @@ cdef extern from "selfdrive/modeld/models/commonmodel.h": cppclass DrivingModelFrame: int buf_size - DrivingModelFrame(cl_device_id, cl_context, int) + DrivingModelFrame(cl_device_id, cl_context) cppclass MonitoringModelFrame: int buf_size diff --git a/selfdrive/modeld/models/commonmodel_pyx.pyx b/selfdrive/modeld/models/commonmodel_pyx.pyx index 5b7d11bc71..7b3a5bb342 100644 --- a/selfdrive/modeld/models/commonmodel_pyx.pyx +++ b/selfdrive/modeld/models/commonmodel_pyx.pyx @@ -59,8 +59,8 @@ cdef class ModelFrame: cdef class DrivingModelFrame(ModelFrame): cdef cppDrivingModelFrame * _frame - def __cinit__(self, CLContext context, int temporal_skip): - self._frame = new cppDrivingModelFrame(context.device_id, context.context, temporal_skip) + def __cinit__(self, CLContext context): + self._frame = new cppDrivingModelFrame(context.device_id, context.context) self.frame = (self._frame) self.buf_size = self._frame.buf_size diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index cc2148c74b..f804b4ec31 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fd38c3b4d465d14a8ed128f8b1b265bff1589d42f398faa678b93f25b3385dc -size 15966721 +oid sha256:5cae3285c876804e649b14adadcfb8be79a9bd5a1b928113e37f1f08e25e9688 +size 16581121 diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx index aee6d8f1bf..06c87d8755 100644 --- a/selfdrive/modeld/models/driving_vision.onnx +++ b/selfdrive/modeld/models/driving_vision.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:897f80d0388250f99bba69b6a8434560cc0fd83157cbeb0bc134c67fe4e64624 +oid sha256:29bbf79f9dfd7048c0013bb81e86d9b2979275b95ea1ed8a86d1a86a88695240 size 34882971 From fe4585ee884a9e694671a194a9382a1c5cef5736 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Tue, 4 Mar 2025 16:27:25 -0500 Subject: [PATCH 13/26] tools: notebook to search commaCarSegments for a CAN ID (#34771) --- .../examples/find_segments_with_message.ipynb | 279 ++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 tools/car_porting/examples/find_segments_with_message.ipynb diff --git a/tools/car_porting/examples/find_segments_with_message.ipynb b/tools/car_porting/examples/find_segments_with_message.ipynb new file mode 100644 index 0000000000..82b06c1f31 --- /dev/null +++ b/tools/car_porting/examples/find_segments_with_message.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 30, + "id": "228a6736-de31-4255-9d72-a6ff391b968d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 221 qualifying vehicles:\n" + ] + } + ], + "source": [ + "from opendbc.car import structs\n", + "from opendbc.car.values import PLATFORMS\n", + "\n", + "print(f\"Found {len(PLATFORMS)} qualifying vehicles:\")\n", + "# for platform in PLATFORMS:\n", + "# print(f\" {platform}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "ed1c8aec-c274-4c61-b83d-711ea194bf86", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting segments from commaCarSegments dataset:\n", + "No segments available for for DODGE_DURANGO\n", + "No segments available for for FORD_RANGER_MK2\n", + "No segments available for for HOLDEN_ASTRA\n", + "No segments available for for CADILLAC_ATS\n", + "No segments available for for CHEVROLET_MALIBU\n", + "No segments available for for CADILLAC_XT4\n", + "No segments available for for CHEVROLET_VOLT_2019\n", + "No segments available for for CHEVROLET_TRAVERSE\n", + "No segments available for for GMC_YUKON\n", + "No segments available for for HONDA_ODYSSEY_CHN\n", + "No segments available for for HYUNDAI_KONA_2022\n", + "No segments available for for HYUNDAI_NEXO_1ST_GEN\n", + "No segments available for for GENESIS_GV70_ELECTRIFIED_1ST_GEN\n", + "No segments available for for GENESIS_G80_2ND_GEN_FL\n", + "No segments available for for RIVIAN_R1_GEN1\n", + "No segments available for for SUBARU_FORESTER_HYBRID\n", + "No segments available for for TESLA_MODEL_3\n", + "No segments available for for TESLA_MODEL_Y\n", + "No segments available for for TOYOTA_RAV4_PRIME\n", + "No segments available for for TOYOTA_SIENNA_4TH_GEN\n", + "No segments available for for LEXUS_LC_TSS2\n", + "No segments available for for VOLKSWAGEN_CADDY_MK3\n", + "No segments available for for VOLKSWAGEN_CRAFTER_MK2\n", + "No segments available for for VOLKSWAGEN_JETTA_MK6\n", + "Collected 577 segments for analysis\n" + ] + } + ], + "source": [ + "import random\n", + "\n", + "from openpilot.tools.lib.logreader import LogReader\n", + "from openpilot.tools.lib.comma_car_segments import get_comma_car_segments_database\n", + "\n", + "database = get_comma_car_segments_database()\n", + "TEST_SEGMENTS = []\n", + "\n", + "MAX_SEGS_PER_PLATFORM = 3 # Increase this to search more segments\n", + "\n", + "print(\"Collecting segments from commaCarSegments dataset:\")\n", + "for platform in TEST_PLATFORMS:\n", + " if platform not in database:\n", + " print(f\"No segments available for for {platform}\")\n", + " continue\n", + " \n", + " all_segments = database[platform]\n", + "\n", + " NUM_SEGMENTS = min(len(all_segments), MAX_SEGS_PER_PLATFORM)\n", + "\n", + " # print(f\"Got {len(all_segments)} segments for platform {platform}, sampling {NUM_SEGMENTS} segments\")\n", + " TEST_SEGMENTS.extend(random.sample(all_segments, NUM_SEGMENTS))\n", + "\n", + "print(f\"Collected {len(TEST_SEGMENTS)} segments for analysis\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "0c75e8f2-4f5f-4f89-b8db-5223a6534a9f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Match found in d753e5427226080e/2023-12-30--10-14-03/9/s for CHRYSLER PACIFICA HYBRID 2018\n", + "Match found in 810855dc1450c716/2023-12-26--10-03-20/3/s for CHRYSLER PACIFICA HYBRID 2018\n", + "Match found in 7f268b92fc672c4d/2023-11-02--20-54-34/103/s for CHRYSLER PACIFICA HYBRID 2018\n", + "Match found in 1a10807c60c127fd/2023-12-09--19-21-30/49/s for CHRYSLER PACIFICA HYBRID 2019\n", + "Match found in b70b56b76a6217f2/2023-12-26--12-29-24/4/s for CHRYSLER PACIFICA HYBRID 2019\n", + "Match found in 86deeb65f10c3129/2023-12-29--07-38-12/179/s for CHRYSLER PACIFICA HYBRID 2019\n", + "Match found in 0a3e89f78b1d0071/2023-11-30--10-33-13/13/s for CHRYSLER PACIFICA 2018\n", + "Match found in 8fc6a1b72c8b1357/2023-11-30--17-35-04/10/s for CHRYSLER PACIFICA 2018\n", + "Match found in d5de6f3e9371e89e/2023-11-16--17-19-54/48/s for CHRYSLER PACIFICA 2018\n", + "Match found in 5fc1717be83fc0da/2024-01-03--13-16-03/27/s for CHRYSLER PACIFICA 2020\n", + "Match found in c1feb10d20626c65/2023-12-16--17-46-24/9/s for CHRYSLER PACIFICA 2020\n", + "Match found in c1feb10d20626c65/2023-11-21--17-40-18/25/s for CHRYSLER PACIFICA 2020\n", + "Match found in a63a23c3e628f288/2023-11-05--18-36-20/22/s for JEEP GRAND CHEROKEE V6 2018\n", + "Match found in 46b21f1c5f7aa885/2023-11-14--15-22-04/21/s for JEEP GRAND CHEROKEE V6 2018\n", + "Match found in a63a23c3e628f288/2023-12-13--09-15-47/27/s for JEEP GRAND CHEROKEE V6 2018\n", + "Match found in 4ffe7a3fb831a625/2024-01-04--09-15-33/22/s for JEEP GRAND CHEROKEE 2019\n", + "Match found in c5b49919572d2c5a/2023-12-17--15-54-06/73/s for JEEP GRAND CHEROKEE 2019\n", + "Match found in 9c2b832d06f93621/2024-01-25--13-52-19/8/s for JEEP GRAND CHEROKEE 2019\n", + "Match found in 1618132d68afc876/2023-11-24--10-21-12/4/s for HYUNDAI KONA ELECTRIC 2ND GEN\n", + "Match found in 1618132d68afc876/2023-08-27--09-32-14/13/s for HYUNDAI KONA 2ND GEN\n", + "Match found in 1618132d68afc876/2023-11-24--10-21-12/3/s for HYUNDAI KONA ELECTRIC 2ND GEN\n", + "Match found in df7fdd56970d90fe/2023-12-29--07-48-56/53/s for HYUNDAI IONIQ 6 2023\n", + "Match found in 0ad7facc77922c3e/2023-12-29--17-12-45/14/s for HYUNDAI IONIQ 6 2023\n", + "Match found in 0ad7facc77922c3e/2023-12-16--08-49-13/39/s for HYUNDAI IONIQ 6 2023\n", + "Match found in 78ad5150de133637/2023-09-13--16-15-57/0/s for KIA K8 HYBRID 1ST GEN\n", + "Match found in 78ad5150de133637/2023-09-13--16-15-57/2/s for KIA K8 HYBRID 1ST GEN\n", + "Match found in 78ad5150de133637/2023-09-13--16-15-57/1/s for KIA K8 HYBRID 1ST GEN\n", + "Match found in b153671049a867b3/2023-12-15--20-40-16/0/s for KIA NIRO EV 2ND GEN\n", + "Match found in b153671049a867b3/2024-01-12--17-43-31/2/s for KIA NIRO EV 2ND GEN\n", + "Match found in b153671049a867b3/2023-12-03--21-08-30/3/s for KIA NIRO EV 2ND GEN\n", + "Match found in 7387ab2a564c6d9f/2023-12-02--07-10-34/52/s for KIA NIRO HYBRID 2ND GEN\n", + "Match found in 7387ab2a564c6d9f/2024-01-06--16-24-36/1/s for KIA NIRO HYBRID 2ND GEN\n", + "Match found in 7387ab2a564c6d9f/2024-01-06--16-24-36/9/s for KIA NIRO HYBRID 2ND GEN\n", + "Match found in 2efdac7dc41207f1/2023-12-27--07-24-22/89/s for KIA EV6 2022\n", + "Match found in 5ac586afbb236b5d/2023-12-05--18-23-10/7/s for VOLKSWAGEN ARTEON 1ST GEN\n", + "Match found in c34ef43981b6d888/2024-01-18--16-00-06/9/s for VOLKSWAGEN ARTEON 1ST GEN\n", + "Match found in 5ac586afbb236b5d/2024-01-04--20-01-19/4/s for VOLKSWAGEN ARTEON 1ST GEN\n", + "Match found in 16758e226aa2f747/2023-12-16--10-24-39/13/s for VOLKSWAGEN ATLAS 1ST GEN\n", + "Match found in 3174d252cec3bf6f/2023-12-12--18-39-06/6/s for VOLKSWAGEN ATLAS 1ST GEN\n", + "Match found in e80066d826c705a9/2024-01-06--17-28-45/211/s for VOLKSWAGEN ATLAS 1ST GEN\n", + "Match found in 2cdded3a5da75b6a/2024-01-06--13-37-16/2/s for VOLKSWAGEN GOLF 7TH GEN\n", + "Match found in abe0b7fe730c51a9/2023-10-30--14-24-49/4/s for VOLKSWAGEN GOLF 7TH GEN\n", + "Match found in 8fe9ced03c94e256/2023-12-14--16-31-55/8/s for VOLKSWAGEN GOLF 7TH GEN\n", + "Match found in a97d27ce2a78958a/2024-01-09--06-57-35/9/s for VOLKSWAGEN JETTA 7TH GEN\n", + "Match found in 0649d406184b7131/2024-01-20--14-43-41/3/s for VOLKSWAGEN JETTA 7TH GEN\n", + "Match found in 0649d406184b7131/2023-11-07--16-30-10/17/s for VOLKSWAGEN JETTA 7TH GEN\n", + "Match found in 5405cac0c9d58c3d/2023-11-05--17-13-17/6/s for VOLKSWAGEN PASSAT 8TH GEN\n", + "Match found in 2d7d87433a67c925/2024-01-05--16-31-16/38/s for VOLKSWAGEN PASSAT 8TH GEN\n", + "Match found in 2d7d87433a67c925/2023-12-26--08-44-17/2/s for VOLKSWAGEN PASSAT 8TH GEN\n", + "Match found in 0cd0b7f7e31a3853/2021-11-03--19-30-22/0/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 0bbe367c98fa1538/2023-07-01--19-42-26/7/s for VOLKSWAGEN POLO 6TH GEN\n", + "Match found in 0cd0b7f7e31a3853/2021-11-03--19-30-22/2/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/1/s for VOLKSWAGEN TAOS 1ST GEN\n", + "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/0/s for VOLKSWAGEN TAOS 1ST GEN\n", + "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/2/s for VOLKSWAGEN TAOS 1ST GEN\n", + "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/0/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/2/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/1/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 4e144f64a2535890/2023-12-05--12-22-10/5/s for VOLKSWAGEN TIGUAN 2ND GEN\n", + "Match found in 1b5cf3b409037cc4/2023-12-11--10-23-35/5/s for VOLKSWAGEN TIGUAN 2ND GEN\n", + "Match found in 1b41980e9972d348/2023-10-29--15-13-08/3/s for VOLKSWAGEN TIGUAN 2ND GEN\n", + "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/0/s for VOLKSWAGEN TOURAN 2ND GEN\n", + "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/2/s for VOLKSWAGEN TOURAN 2ND GEN\n", + "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/1/s for VOLKSWAGEN TOURAN 2ND GEN\n", + "Match found in 207b9d7ee3fb513a/2023-12-19--14-59-25/14/s for VOLKSWAGEN TRANSPORTER T6.1\n", + "Match found in a459f4556782eba1/2023-11-05--17-16-20/22/s for VOLKSWAGEN TRANSPORTER T6.1\n", + "Match found in a459f4556782eba1/2023-11-27--12-27-58/47/s for VOLKSWAGEN TRANSPORTER T6.1\n", + "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/0/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/1/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/2/s for SKODA KODIAQ 1ST GEN\n", + "Match found in a973e9182bc96a2c/2024-01-14--15-14-33/54/s for AUDI A3 3RD GEN\n", + "Match found in 23daff6c438612d2/2023-12-21--15-37-32/22/s for AUDI A3 3RD GEN\n", + "Match found in 23daff6c438612d2/2024-01-17--09-31-14/20/s for AUDI A3 3RD GEN\n", + "Match found in 6c6b466346192818/2021-06-06--14-17-47/0/s for AUDI Q2 1ST GEN\n", + "Match found in 6c6b466346192818/2021-06-06--14-17-47/1/s for AUDI Q2 1ST GEN\n", + "Match found in 6c6b466346192818/2021-06-06--14-17-47/2/s for AUDI Q2 1ST GEN\n", + "Match found in 839125529d3c3cdf/2023-11-29--15-49-50/56/s for AUDI Q3 2ND GEN\n", + "Match found in d7bfab70d5011e1d/2023-11-24--00-49-14/24/s for AUDI Q3 2ND GEN\n", + "Match found in 98a3015c4f16846d/2023-11-04--12-32-32/76/s for AUDI Q3 2ND GEN\n", + "Match found in fc6b6c9a3471c846/2021-05-27--13-39-56/2/s for SEAT LEON 3RD GEN\n", + "Match found in fc6b6c9a3471c846/2021-05-27--13-39-56/1/s for SEAT LEON 3RD GEN\n", + "Match found in aef9c04d6ec5cd57/2023-07-15--16-49-38/12/s for SEAT LEON 3RD GEN\n", + "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/2/s for VOLKSWAGEN POLO 6TH GEN\n", + "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/1/s for VOLKSWAGEN POLO 6TH GEN\n", + "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/0/s for VOLKSWAGEN POLO 6TH GEN\n", + "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/0/s for SKODA SCALA 1ST GEN\n", + "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/1/s for SKODA SCALA 1ST GEN\n", + "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/2/s for SKODA SCALA 1ST GEN\n", + "Match found in 12d6ae3057c04b0d/2021-09-04--21-21-21/1/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 12d6ae3057c04b0d/2021-09-04--21-21-21/0/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 7d76baac7cf42e15/2024-01-13--03-42-46/2/s for SKODA KAROQ 1ST GEN\n", + "Match found in 8a5da7c1d1783730/2024-01-17--06-32-18/4/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 8a5da7c1d1783730/2023-12-23--16-48-07/42/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 2ca49a03c8084514/2023-12-27--08-54-31/4/s for SKODA KODIAQ 1ST GEN\n", + "Match found in 66e5edc3a16459c5/2021-05-25--19-00-29/1/s for SKODA OCTAVIA 3RD GEN\n", + "Match found in f5392228324cda8d/2023-10-29--14-05-24/120/s for SKODA OCTAVIA 3RD GEN\n", + "Match found in 3fa7570f2fcace3d/2023-11-11--07-57-34/1/s for SKODA OCTAVIA 3RD GEN\n", + "Match found in 54ada937747ef8ca/2023-11-09--16-13-28/12/s for SKODA SUPERB 3RD GEN\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Match found in 54ada937747ef8ca/2023-12-14--08-14-41/8/s for SKODA SUPERB 3RD GEN\n", + "Match found in 54ada937747ef8ca/2023-11-16--06-01-05/7/s for SKODA SUPERB 3RD GEN\n", + "Analysis finished\n" + ] + } + ], + "source": [ + "from openpilot.selfdrive.pandad import can_capnp_to_list\n", + "from openpilot.tools.lib.logreader import LogReader\n", + "\n", + "message_to_check = 0x3c0 # Volkswagen CAN ignition message\n", + "\n", + "segment_count = len(TEST_SEGMENTS)\n", + "for idx, segment in enumerate(TEST_SEGMENTS):\n", + " lr = LogReader(segment)\n", + " CP = lr.first(\"carParams\")\n", + " if CP is None:\n", + " continue\n", + "\n", + " can_packets = [msg for msg in lr if msg.which() == \"can\"]\n", + "\n", + " # print(f\"Evaluating segment {idx} of {segment_count} for {CP.carFingerprint}\")\n", + "\n", + " matched_segments = {}\n", + " for packet in can_packets:\n", + " for msg in packet.can:\n", + " if msg.address == message_to_check:\n", + " matched_segments.update({segment: CP.carFingerprint})\n", + "\n", + " if segment in matched_segments:\n", + " print(f\"Match found in {segment} for {CP.carFingerprint}\")\n", + "\n", + "print(f\"Analysis finished\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7724dd97-f62e-4fd3-9f64-63d49be669d2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f393e00-8efd-40fb-a41e-d312531a83e8", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "openpilot", + "language": "python", + "name": "openpilot" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From bc422a07384afed95b4c2037022c3517ef277cba Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 4 Mar 2025 15:54:43 -0600 Subject: [PATCH 14/26] juggle: use DBC dict generator (#34772) * juggle: support tesla DBC * better * fix * sort --- tools/cabana/dbc/generate_dbc_json.py | 6 +++--- tools/plotjuggler/juggle.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/cabana/dbc/generate_dbc_json.py b/tools/cabana/dbc/generate_dbc_json.py index 5e928e6054..d002a50ef8 100755 --- a/tools/cabana/dbc/generate_dbc_json.py +++ b/tools/cabana/dbc/generate_dbc_json.py @@ -7,7 +7,7 @@ from opendbc.car.fingerprints import MIGRATION from opendbc.car.values import PLATFORMS -def generate_dbc_json() -> str: +def generate_dbc_dict() -> dict[str, str]: dbc_map = {} for platform in PLATFORMS.values(): if platform != "MOCK": @@ -24,7 +24,7 @@ def generate_dbc_json() -> str: if MIGRATION[m] in dbc_map: dbc_map[m] = dbc_map[MIGRATION[m]] - return json.dumps(dict(sorted(dbc_map.items())), indent=2) + return dbc_map if __name__ == "__main__": @@ -35,5 +35,5 @@ if __name__ == "__main__": args = parser.parse_args() with open(args.out, 'w') as f: - f.write(generate_dbc_json()) + f.write(json.dumps(dict(sorted(generate_dbc_dict().items())), indent=2)) print(f"Generated and written to {args.out}") diff --git a/tools/plotjuggler/juggle.py b/tools/plotjuggler/juggle.py index 5b6bd0a418..f66782d6f3 100755 --- a/tools/plotjuggler/juggle.py +++ b/tools/plotjuggler/juggle.py @@ -13,6 +13,7 @@ from functools import partial from opendbc.car.fingerprints import MIGRATION from openpilot.common.basedir import BASEDIR from openpilot.common.swaglog import cloudlog +from openpilot.tools.cabana.dbc.generate_dbc_json import generate_dbc_dict from openpilot.tools.lib.logreader import LogReader, ReadMode, save_log from openpilot.selfdrive.test.process_replay.migration import migrate_all @@ -90,11 +91,10 @@ def juggle_route(route_or_segment_name, can, layout, dbc, should_migrate): if dbc is None: try: CP = lr.first('carParams') - platform = CP.carFingerprint - DBC = __import__(f"opendbc.car.{CP.brand}.values", fromlist=['DBC']).DBC - dbc = DBC[MIGRATION.get(CP.carFingerprint, CP.carFingerprint)]['pt'] + platform = MIGRATION.get(CP.carFingerprint, CP.carFingerprint) + dbc = generate_dbc_dict()[platform] except Exception: - cloudlog.error("Failed to get DBC name from logs!") + cloudlog.exception("Failed to get DBC name from logs!") with tempfile.NamedTemporaryFile(suffix='.rlog', dir=juggle_dir) as tmp: save_log(tmp.name, all_data, compress=False) From b8362fd7250d323fb4e200822d772a4735385b5c Mon Sep 17 00:00:00 2001 From: Alexandre Nobuharu Sato <66435071+AlexandreSato@users.noreply.github.com> Date: Tue, 4 Mar 2025 20:25:01 -0300 Subject: [PATCH 15/26] Multilang: update pt-BR translations (#34773) update pt-BR translations --- selfdrive/ui/translations/main_pt-BR.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index f2aa00d322..06b2ef7b35 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -309,25 +309,27 @@ FirehosePanel 🔥 Firehose Mode 🔥 - + 🔥 Mode Firehose 🔥 Enable Firehose Mode - + Habilitar Modo Firehose openpilot learns to drive by watching humans, like you, drive. Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - + O openpilot aprende a dirigir observando humanos, como você, dirigirem. + +O Modo Firehose permite maximizar o envio de seus dados de treinamento para melhorar os modelos de direção do openpilot. Mais dados significam modelos maiores e um Modo Experimental melhor. 0% - 5G {0%?} + 5G {0%?} Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - + Siga estes passos para preparar seu dispositivo:<br> 1. Leve o dispositivo para dentro e conecte-o a um bom adaptador USB-C<br> 2. Conecte-se ao Wi-Fi<br> 3. Ative a opção<br> 4. Deixe-o conectado por pelo menos 30 minutos<br><br>A opção será desativada quando você reiniciar o dispositivo. Repita esse processo pelo menos uma vez por semana para obter a máxima eficácia.<br><br><b>FAQ</b><br><i>Importa como ou onde eu dirijo?</i> Não, basta dirigir normalmente.<br><i>O que é um bom adaptador USB-C?</i> Qualquer carregador rápido de celular ou laptop deve servir..<br><i>Preciso estar conectado ao Wi-Fi?</i> Sim.<br><i>Preciso levar o dispositivo para dentro de casa?</i> Não, você pode ativar a opção enquanto estiver estacionado, mas seus envios serão limitados pela bateria do carro.<br> @@ -668,7 +670,7 @@ Isso pode levar até um minuto. Firehose - + Firehose @@ -1146,15 +1148,15 @@ Isso pode levar até um minuto. WiFiPromptWidget Open - + Abrir Maximize your training data uploads to improve openpilot's driving models. - + Maximize seus envios de dados de treinamento para melhorar os modelos de direção do openpilot. <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> - + <span style='font-family: "Noto Color Emoji";'>🔥</span> Mode Firehose <span style='font-family: Noto Color Emoji;'>🔥</span> From 7dfbf0b1e1860540a083a3511db98414733d15bb Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Tue, 4 Mar 2025 18:28:44 -0800 Subject: [PATCH 16/26] process_replay: set sensor in cameraState migration (#34776) set sensor in cameraState migration --- selfdrive/test/process_replay/migration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/test/process_replay/migration.py b/selfdrive/test/process_replay/migration.py index 061da31de3..2d42d31619 100644 --- a/selfdrive/test/process_replay/migration.py +++ b/selfdrive/test/process_replay/migration.py @@ -358,6 +358,7 @@ def migrate_cameraStates(msgs): new_msg = messaging.new_message(msg.which()) new_camera_state = getattr(new_msg, new_msg.which()) + new_camera_state.sensor = camera_state.sensor new_camera_state.frameId = encode_id new_camera_state.encodeId = encode_id # timestampSof was added later so it might be missing on some old segments From 3e8e7e8e6df51d00e0008bc09c2a47acab7e3fc5 Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Tue, 4 Mar 2025 18:36:30 -0800 Subject: [PATCH 17/26] update model_replay route (#34774) * update route * Update selfdrive/test/process_replay/model_replay.py Co-authored-by: Maxime Desroches --------- Co-authored-by: Maxime Desroches --- selfdrive/test/process_replay/model_replay.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py index 50027574ba..8cd8222ddc 100755 --- a/selfdrive/test/process_replay/model_replay.py +++ b/selfdrive/test/process_replay/model_replay.py @@ -19,8 +19,8 @@ from openpilot.tools.lib.framereader import FrameReader, NumpyFrameReader from openpilot.tools.lib.logreader import LogReader, save_log from openpilot.tools.lib.github_utils import GithubUtils -TEST_ROUTE = "2f4452b03ccb98f0|2022-12-03--13-45-30" -SEGMENT = 6 +TEST_ROUTE = "8494c69d3c710e81|000001d4--2648a9a404" +SEGMENT = 4 MAX_FRAMES = 100 if PC else 400 NO_MODEL = "NO_MODEL" in os.environ From 3f9437e249d6822eb6590a2f4a0fe276e6a33842 Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Tue, 4 Mar 2025 20:24:17 -0800 Subject: [PATCH 18/26] process_replay: support lane changes in model_replay (#34777) * lane changes need to see these * newline * add lc probs --- selfdrive/test/process_replay/model_replay.py | 5 ++++- selfdrive/test/process_replay/process_replay.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py index 8cd8222ddc..36398af8ca 100755 --- a/selfdrive/test/process_replay/model_replay.py +++ b/selfdrive/test/process_replay/model_replay.py @@ -66,6 +66,8 @@ def generate_report(proposed, master, tmp, commit): (lambda x: get_idx_if_non_empty(x.action.desiredCurvature), "desiredCurvature"), (lambda x: get_idx_if_non_empty(x.leadsV3[0].x, 0), "leadsV3.x"), (lambda x: get_idx_if_non_empty(x.laneLines[1].y, 0), "laneLines.y"), + (lambda x: get_idx_if_non_empty(x.meta.desireState, 3), "desireState.laneChangeLeft"), + (lambda x: get_idx_if_non_empty(x.meta.desireState, 4), "desireState.laneChangeRight"), (lambda x: get_idx_if_non_empty(x.meta.disengagePredictions.gasPressProbs, 1), "gasPressProbs") ], "modelV2") DriverStateV2_Plots = zl([ @@ -143,7 +145,8 @@ def trim_logs_to_max_frames(logs, max_frames, frs_types, include_all_types): def model_replay(lr, frs): # modeld is using frame pairs - modeld_logs = trim_logs_to_max_frames(lr, MAX_FRAMES, {"roadCameraState", "wideRoadCameraState"}, {"roadEncodeIdx", "wideRoadEncodeIdx", "carParams"}) + modeld_logs = trim_logs_to_max_frames(lr, MAX_FRAMES, {"roadCameraState", "wideRoadCameraState"}, + {"roadEncodeIdx", "wideRoadEncodeIdx", "carParams", "carState", "carControl"}) dmodeld_logs = trim_logs_to_max_frames(lr, MAX_FRAMES, {"driverCameraState"}, {"driverEncodeIdx", "carParams"}) if not SEND_EXTRA_INPUTS: diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 1135aeb874..34ca98fdc2 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -568,7 +568,7 @@ CONFIGS = [ ), ProcessConfig( proc_name="modeld", - pubs=["deviceState", "roadCameraState", "wideRoadCameraState", "liveCalibration", "driverMonitoringState", "carState"], + pubs=["deviceState", "roadCameraState", "wideRoadCameraState", "liveCalibration", "driverMonitoringState", "carState", "carControl"], subs=["modelV2", "drivingModelData", "cameraOdometry"], ignore=["logMonoTime", "modelV2.frameDropPerc", "modelV2.modelExecutionTime", "drivingModelData.frameDropPerc", "drivingModelData.modelExecutionTime"], should_recv_callback=ModeldCameraSyncRcvCallback(), From 31076b818df68ea171447ccafa07039311a11136 Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Tue, 4 Mar 2025 20:35:57 -0800 Subject: [PATCH 19/26] Filet o Fish model (#34775) * 690b01c3 seems ok * correct temporal * push * inplace * bs * what thw * is this wrong * frames are skipped * new models * simplify decimation * clean up * clean up modelframe * need attr * lint * 0 * use all samples * this should break - Revert "use all samples" This reverts commit 6c0d7943ac5fbb7ae60af1a1201e2423e4c3c105. * add lc probs * Revert "this should break - Revert "use all samples"" This reverts commit ca38c54333555266a0d2c885c28af28941841431. * Reapply "this should break - Revert "use all samples"" This reverts commit a3f0246f209f85f06b9090d9492bfba32ed8cfed. * Revert "Reapply "this should break - Revert "use all samples""" This reverts commit 7fd3d2a191b688e5ef7b4dcc8f5379e900af10f8. --------- Co-authored-by: Comma Device --- selfdrive/modeld/constants.py | 8 +++++- selfdrive/modeld/modeld.py | 31 ++++++++++++++------- selfdrive/modeld/models/commonmodel.cc | 9 +++--- selfdrive/modeld/models/commonmodel.h | 5 ++-- selfdrive/modeld/models/commonmodel.pxd | 2 +- selfdrive/modeld/models/commonmodel_pyx.pyx | 4 +-- selfdrive/modeld/models/driving_policy.onnx | 4 +-- selfdrive/modeld/models/driving_vision.onnx | 2 +- 8 files changed, 42 insertions(+), 23 deletions(-) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index 2bb7b8100c..5ca0a86bc8 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -14,8 +14,14 @@ class ModelConstants: # model inputs constants MODEL_FREQ = 20 + HISTORY_FREQ = 5 + HISTORY_LEN_SECONDS = 5 + TEMPORAL_SKIP = MODEL_FREQ // HISTORY_FREQ + FULL_HISTORY_BUFFER_LEN = MODEL_FREQ * HISTORY_LEN_SECONDS + INPUT_HISTORY_BUFFER_LEN = HISTORY_FREQ * HISTORY_LEN_SECONDS + FEATURE_LEN = 512 - FULL_HISTORY_BUFFER_LEN = 100 + DESIRE_LEN = 8 TRAFFIC_CONVENTION_LEN = 2 LAT_PLANNER_STATE_LEN = 4 diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index ee825d158f..1e557942fe 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -56,16 +56,24 @@ class ModelState: prev_desire: np.ndarray # for tracking the rising edge of the pulse def __init__(self, context: CLContext): - self.frames = {'input_imgs': DrivingModelFrame(context), 'big_input_imgs': DrivingModelFrame(context)} + self.frames = { + 'input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP), + 'big_input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) + } self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) + self.full_features_buffer = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) + self.full_desire = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32) + self.full_prev_desired_curv = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32) + self.temporal_idxs = slice(-1-(ModelConstants.TEMPORAL_SKIP*(ModelConstants.INPUT_HISTORY_BUFFER_LEN-1)), None, ModelConstants.TEMPORAL_SKIP) + # policy inputs self.numpy_inputs = { - 'desire': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), 'lateral_control_params': np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32), - 'prev_desired_curv': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), + 'prev_desired_curv': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), + 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } with open(VISION_METADATA_PATH, 'rb') as f: @@ -104,8 +112,9 @@ class ModelState: new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) self.prev_desire[:] = inputs['desire'] - self.numpy_inputs['desire'][0,:-1] = self.numpy_inputs['desire'][0,1:] - self.numpy_inputs['desire'][0,-1] = new_desire + self.full_desire[0,:-1] = self.full_desire[0,1:] + self.full_desire[0,-1] = new_desire + self.numpy_inputs['desire'][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2) self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params'] @@ -128,15 +137,17 @@ class ModelState: self.vision_output = self.vision_run(**self.vision_inputs).numpy().flatten() vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) - self.numpy_inputs['features_buffer'][0,:-1] = self.numpy_inputs['features_buffer'][0,1:] - self.numpy_inputs['features_buffer'][0,-1] = vision_outputs_dict['hidden_state'][0, :] + self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:] + self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :] + self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs] self.policy_output = self.policy_run(**self.policy_inputs).numpy().flatten() policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) # TODO model only uses last value now - self.numpy_inputs['prev_desired_curv'][0,:-1] = self.numpy_inputs['prev_desired_curv'][0,1:] - self.numpy_inputs['prev_desired_curv'][0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] + self.full_prev_desired_curv[0,:-1] = self.full_prev_desired_curv[0,1:] + self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] + self.numpy_inputs['prev_desired_curv'][:] = self.full_prev_desired_curv[0, self.temporal_idxs] combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} if SEND_RAW_PRED: diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc index 9973d18588..99155d9f1e 100644 --- a/selfdrive/modeld/models/commonmodel.cc +++ b/selfdrive/modeld/models/commonmodel.cc @@ -5,11 +5,12 @@ #include "common/clutil.h" -DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { +DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip) : ModelFrame(device_id, context) { input_frames = std::make_unique(buf_size); + temporal_skip = _temporal_skip; input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); - img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 2*frame_size_bytes, NULL, &err)); - region.origin = 1 * frame_size_bytes; + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (temporal_skip+1)*frame_size_bytes, NULL, &err)); + region.origin = temporal_skip * frame_size_bytes; region.size = frame_size_bytes; last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); @@ -20,7 +21,7 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); - for (int i = 0; i < 1; i++) { + for (int i = 0; i < temporal_skip; i++) { CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); } loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); diff --git a/selfdrive/modeld/models/commonmodel.h b/selfdrive/modeld/models/commonmodel.h index 14409943e4..176d7eb6dc 100644 --- a/selfdrive/modeld/models/commonmodel.h +++ b/selfdrive/modeld/models/commonmodel.h @@ -64,20 +64,21 @@ protected: class DrivingModelFrame : public ModelFrame { public: - DrivingModelFrame(cl_device_id device_id, cl_context context); + DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip); ~DrivingModelFrame(); cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); const int MODEL_WIDTH = 512; const int MODEL_HEIGHT = 256; const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT * 3 / 2; - const int buf_size = MODEL_FRAME_SIZE * 2; + const int buf_size = MODEL_FRAME_SIZE * 2; // 2 frames are temporal_skip frames apart const size_t frame_size_bytes = MODEL_FRAME_SIZE * sizeof(uint8_t); private: LoadYUVState loadyuv; cl_mem img_buffer_20hz_cl, last_img_cl, input_frames_cl; cl_buffer_region region; + int temporal_skip; }; class MonitoringModelFrame : public ModelFrame { diff --git a/selfdrive/modeld/models/commonmodel.pxd b/selfdrive/modeld/models/commonmodel.pxd index b4f08b12aa..4ac64d9172 100644 --- a/selfdrive/modeld/models/commonmodel.pxd +++ b/selfdrive/modeld/models/commonmodel.pxd @@ -20,7 +20,7 @@ cdef extern from "selfdrive/modeld/models/commonmodel.h": cppclass DrivingModelFrame: int buf_size - DrivingModelFrame(cl_device_id, cl_context) + DrivingModelFrame(cl_device_id, cl_context, int) cppclass MonitoringModelFrame: int buf_size diff --git a/selfdrive/modeld/models/commonmodel_pyx.pyx b/selfdrive/modeld/models/commonmodel_pyx.pyx index 7b3a5bb342..5b7d11bc71 100644 --- a/selfdrive/modeld/models/commonmodel_pyx.pyx +++ b/selfdrive/modeld/models/commonmodel_pyx.pyx @@ -59,8 +59,8 @@ cdef class ModelFrame: cdef class DrivingModelFrame(ModelFrame): cdef cppDrivingModelFrame * _frame - def __cinit__(self, CLContext context): - self._frame = new cppDrivingModelFrame(context.device_id, context.context) + def __cinit__(self, CLContext context, int temporal_skip): + self._frame = new cppDrivingModelFrame(context.device_id, context.context, temporal_skip) self.frame = (self._frame) self.buf_size = self._frame.buf_size diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index f804b4ec31..cc2148c74b 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cae3285c876804e649b14adadcfb8be79a9bd5a1b928113e37f1f08e25e9688 -size 16581121 +oid sha256:5fd38c3b4d465d14a8ed128f8b1b265bff1589d42f398faa678b93f25b3385dc +size 15966721 diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx index 06c87d8755..aee6d8f1bf 100644 --- a/selfdrive/modeld/models/driving_vision.onnx +++ b/selfdrive/modeld/models/driving_vision.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29bbf79f9dfd7048c0013bb81e86d9b2979275b95ea1ed8a86d1a86a88695240 +oid sha256:897f80d0388250f99bba69b6a8434560cc0fd83157cbeb0bc134c67fe4e64624 size 34882971 From 54f845c3699cd622689a3d8a596c9739710bfcba Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:54:05 -0800 Subject: [PATCH 20/26] [bot] Update Python packages (#34779) Update Python packages Co-authored-by: Vehicle Researcher --- opendbc_repo | 2 +- panda | 2 +- uv.lock | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/opendbc_repo b/opendbc_repo index 34a109cc79..e7d08ac479 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 34a109cc7956dbf022f57b6bca2207f2719e25a7 +Subproject commit e7d08ac4794c859e604d260da010d4685c164e5b diff --git a/panda b/panda index 154b66782d..3bf1f8e871 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 154b66782ddf4b9293c4594bb5ee8bd9cd88f332 +Subproject commit 3bf1f8e871f3c577fccba07f57958f30508a2187 diff --git a/uv.lock b/uv.lock index 022e30508d..fe3ee05e77 100644 --- a/uv.lock +++ b/uv.lock @@ -12,11 +12,11 @@ resolution-markers = [ [[package]] name = "aiohappyeyeballs" -version = "2.4.6" +version = "2.4.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/07/508f9ebba367fc3370162e53a3cfd12f5652ad79f0e0bfdf9f9847c6f159/aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0", size = 21726 } +sdist = { url = "https://files.pythonhosted.org/packages/de/7c/79a15272e88d2563c9d63599fa59f05778975f35b255bf8f90c8b12b4ada/aiohappyeyeballs-2.4.8.tar.gz", hash = "sha256:19728772cb12263077982d2f55453babd8bec6a052a926cd5c0c42796da8bf62", size = 22337 } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/4c/03fb05f56551828ec67ceb3665e5dc51638042d204983a03b0a1541475b6/aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", size = 14543 }, + { url = "https://files.pythonhosted.org/packages/52/0e/b187e2bb3eeb2644515109657c4474d65a84e7123de249bf1e8467d04a65/aiohappyeyeballs-2.4.8-py3-none-any.whl", hash = "sha256:6cac4f5dd6e34a9644e69cf9021ef679e4394f54e58a183056d12009e42ea9e3", size = 15005 }, ] [[package]] @@ -760,13 +760,13 @@ wheels = [ [[package]] name = "libusb1" -version = "3.2.0" +version = "3.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d9/b7/9e833af6cb52fa2aece1c6a1378667ca0172bead14f63ffccc3cb9862df3/libusb1-3.2.0.tar.gz", hash = "sha256:a11a6095e718cd49418a96329314da271cca6be7b4317a142724523371ac8961", size = 105601 } +sdist = { url = "https://files.pythonhosted.org/packages/69/c7/3c441fb0628b5afdfe68768f90f8d6ce74dc08e72691fb78d0875db06c48/libusb1-3.3.0.tar.gz", hash = "sha256:b642aa518689f8e053f61955cba274e72bc8d0794c65d7990745aaae90dfc8a1", size = 107253 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/35/d5bde9434fc734709960a94cc489d487184d0ab08e5867311d5a4c64fcea/libusb1-3.2.0-py3-none-any.whl", hash = "sha256:048d4fb79021ec05af667a32e51a911578fc63ab3ed48a4f4fe0f67da797f416", size = 65829 }, - { url = "https://files.pythonhosted.org/packages/a3/cd/ef05b2c67fff2d704aa0325993187ce6a6d04f40ba4be953766b47f5f949/libusb1-3.2.0-py3-none-win32.whl", hash = "sha256:5dc48d6f5207e184cb53278527e7d8e5f4051d8bc419bd15b564c37dc5cca268", size = 127781 }, - { url = "https://files.pythonhosted.org/packages/f9/82/8bcadf2794fa2d39ec100a4f3945db58c316d55c1a0e79ac2cf81c754282/libusb1-3.2.0-py3-none-win_amd64.whl", hash = "sha256:b13acc618263348c91bc4476fadada47be98b7924d6f60e79e3f1da67ac39ddc", size = 139410 }, + { url = "https://files.pythonhosted.org/packages/c7/48/b24b810b14595bd4680030f73a31119120069a8857f41554f00e00b57229/libusb1-3.3.0-py3-none-any.whl", hash = "sha256:7923ff2bbe43878e1c7cf733fde49cca844ecada29dbc436033bca6171cda41f", size = 67044 }, + { url = "https://files.pythonhosted.org/packages/3f/45/52980eedf3fb78711960a558465b3d998beed327fcd2b8483119527adc44/libusb1-3.3.0-py3-none-win32.whl", hash = "sha256:270f35b3a8faddd63d78de9b2341e49f6aed6083dceb4b04f47b95fd944e8d00", size = 128992 }, + { url = "https://files.pythonhosted.org/packages/af/d3/992bfd5bcd9d7a978563d3dabb11d0fce5cf7ceea73d9633fbadba93df4e/libusb1-3.3.0-py3-none-win_amd64.whl", hash = "sha256:61e2b4efdbacdd689bf4eab6b9afa2d6ee8a4bae20ffbf7c5785024d25fa3258", size = 140624 }, ] [[package]] @@ -1578,16 +1578,16 @@ wheels = [ [[package]] name = "protobuf" -version = "5.29.3" +version = "6.30.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f7/d1/e0a911544ca9993e0f17ce6d3cc0932752356c1b0a834397f28e63479344/protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620", size = 424945 } +sdist = { url = "https://files.pythonhosted.org/packages/53/6a/2629bb3529e5bdfbd6c4608ff5c7d942cd4beae85793f84ba543aab2548a/protobuf-6.30.0.tar.gz", hash = "sha256:852b675d276a7d028f660da075af1841c768618f76b90af771a8e2c29e6f5965", size = 429239 } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/7a/1e38f3cafa022f477ca0f57a1f49962f21ad25850c3ca0acd3b9d0091518/protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888", size = 422708 }, - { url = "https://files.pythonhosted.org/packages/61/fa/aae8e10512b83de633f2646506a6d835b151edf4b30d18d73afd01447253/protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a", size = 434508 }, - { url = "https://files.pythonhosted.org/packages/dd/04/3eaedc2ba17a088961d0e3bd396eac764450f431621b58a04ce898acd126/protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e", size = 417825 }, - { url = "https://files.pythonhosted.org/packages/4f/06/7c467744d23c3979ce250397e26d8ad8eeb2bea7b18ca12ad58313c1b8d5/protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84", size = 319573 }, - { url = "https://files.pythonhosted.org/packages/a8/45/2ebbde52ad2be18d3675b6bee50e68cd73c9e0654de77d595540b5129df8/protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f", size = 319672 }, - { url = "https://files.pythonhosted.org/packages/fd/b2/ab07b09e0f6d143dfb839693aa05765257bceaa13d03bf1a696b78323e7a/protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f", size = 172550 }, + { url = "https://files.pythonhosted.org/packages/aa/76/8b1cbf762d98b09fcb29bbc6eca97dc6e1cd865b97a49c443aa23f1a9f82/protobuf-6.30.0-cp310-abi3-win32.whl", hash = "sha256:7337d76d8efe65ee09ee566b47b5914c517190196f414e5418fa236dfd1aed3e", size = 419141 }, + { url = "https://files.pythonhosted.org/packages/57/50/2ea2fb4533321438f5106723c70c303529ba184540e619ebe75e790d402e/protobuf-6.30.0-cp310-abi3-win_amd64.whl", hash = "sha256:9b33d51cc95a7ec4f407004c8b744330b6911a37a782e2629c67e1e8ac41318f", size = 430995 }, + { url = "https://files.pythonhosted.org/packages/a1/7d/a7dfa7aa3deda114920b1ed57c0026e85a976e74658db2784a0443510252/protobuf-6.30.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:52d4bb6fe76005860e1d0b8bfa126f5c97c19cc82704961f60718f50be16942d", size = 417570 }, + { url = "https://files.pythonhosted.org/packages/11/87/a9c7b020c4072dc34e3a2a3cde69366ffc623afff0e7f10f4e5275aaec01/protobuf-6.30.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:7940ab4dfd60d514b2e1d3161549ea7aed5be37d53bafde16001ac470a3e202b", size = 317310 }, + { url = "https://files.pythonhosted.org/packages/95/66/424db2262723781dc94208ff9ce201df2f44f18a46fbff3c067812c6b5b9/protobuf-6.30.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:d79bf6a202a536b192b7e8d295d7eece0c86fbd9b583d147faf8cfeff46bf598", size = 316203 }, + { url = "https://files.pythonhosted.org/packages/51/6f/21c2b7de96c3051f847a4a88a12fdf015ed6b7d50fc131fb101a739bd7a5/protobuf-6.30.0-py3-none-any.whl", hash = "sha256:e5ef216ea061b262b8994cb6b7d6637a4fb27b3fb4d8e216a6040c0b93bd10d7", size = 167054 }, ] [[package]] From 50d059f96b38a07fba1ea2f6e17db5c28edb49c7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:54:21 -0800 Subject: [PATCH 21/26] [bot] Update translations (#34778) Update translations Co-authored-by: Vehicle Researcher --- selfdrive/ui/translations/main_ar.ts | 22 +++++++++++------ selfdrive/ui/translations/main_de.ts | 22 +++++++++++------ selfdrive/ui/translations/main_es.ts | 22 +++++++++++------ selfdrive/ui/translations/main_fr.ts | 22 +++++++++++------ selfdrive/ui/translations/main_ja.ts | 30 ++++++++++++++---------- selfdrive/ui/translations/main_ko.ts | 30 ++++++++++++++---------- selfdrive/ui/translations/main_pt-BR.ts | 30 ++++++++++++++---------- selfdrive/ui/translations/main_th.ts | 22 +++++++++++------ selfdrive/ui/translations/main_tr.ts | 22 +++++++++++------ selfdrive/ui/translations/main_zh-CHS.ts | 30 ++++++++++++++---------- selfdrive/ui/translations/main_zh-CHT.ts | 30 ++++++++++++++---------- 11 files changed, 180 insertions(+), 102 deletions(-) diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index 00a98f70c3..8c667e246c 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 831e589b03..e7160fc903 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_es.ts b/selfdrive/ui/translations/main_es.ts index ed6d946214..afbe7424be 100644 --- a/selfdrive/ui/translations/main_es.ts +++ b/selfdrive/ui/translations/main_es.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts index f2eba9860a..8be7842ddf 100644 --- a/selfdrive/ui/translations/main_fr.ts +++ b/selfdrive/ui/translations/main_fr.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index a5c21d29a6..d8c75ecf1c 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -311,25 +311,31 @@ 🔥 Firehose Mode 🔥 🔥 Firehoseモード 🔥 - - Enable Firehose Mode - Firehoseを有効にする - openpilot learns to drive by watching humans, like you, drive. -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - openpilotは人間であるあなたの運転から学び、AI学習します。 - -Firehoseモードを有効にすると、学習データを最大限アップロードし、openpilotの運転モデルを向上させることができます。より多くのデータはより大きなモデルを生み出し、Experimentalモードの精度向上につながります。 +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + - 0% - 5G {0%?} + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - 以下の手順に従ってデバイスを準備してください:<br> 1. デバイスを室内に持ち込み、高速なUSB-C電源に接続してください<br> 2. Wi-Fiに接続してください<br> 3. 機能を有効にしてください<br> 4. 少なくとも30分間接続したままにしてください<br><br>デバイスを再起動すると、この機能はオフになります。最大の効果を得るために、少なくとも週に1回は繰り返してください。<br><br><b>FAQ</b><br><i>どのように運転するか、どこで運転するかは重要ですか?</i> いいえ、普段通りに運転してください。<br><i>高速なUSB-C電源とは何ですか?</i> スマフォやノートPC用のワット数の大きい充電器を使って下さい。<br><i>Wi-Fiに接続する必要がありますか?</i> その通りです。<br><i>デバイスを屋内に持ち込む必要がありますか?</i> いいえ、駐車後に有効にすることができますが、アップロードは車のバッテリーによって制限されます。<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network + diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index b497e39f21..9a1da3c396 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -311,25 +311,31 @@ 🔥 Firehose Mode 🔥 🔥 파이어호스 모드 🔥 - - Enable Firehose Mode - 파이어호스 모드 활성화 - openpilot learns to drive by watching humans, like you, drive. -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - 오픈파일럿은 여러분과 같은 사람이 운전하는 모습을 보면서 운전하는 법을 배웁니다. - -파이어호스 모드를 사용하면 훈련 데이터 업로드를 최대화하여 오픈파일럿의 주행 모델을 개선할 수 있습니다. 더 많은 데이터는 더 나은 실험 모드를 갖춘 더 큰 모델을 의미합니다. +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + - 0% - 0% + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - 다음 단계에 따라 장치를 준비하세요.:<br> 1. 장치를 내부로 가져와 올바른 USB-C 어댑터에 연결하세요.<br> 2. Wi-Fi에 연결하세요.<br> 3. 토글을 활성화하세요.<br> 4. 최소 30분 동안 연결 상태로 두세요.<br><br> 장치를 다시 시작하면 토글이 꺼집니다. 효과를 극대화하려면 적어도 일주일에 한 번씩 반복하세요.<br><br><b>자주 묻는 질문</b><br><i>운전 방법이나 장소가 중요한가요?</i> 아니요, 평소처럼 운전하세요.<br><i>올바른 USB-C 어댑터란 무엇인가요?</i> 휴대폰이나 노트북 고속 충전기라면 어떤 것이든 괜찮습니다.<br><i>Wi-Fi에 연결되어 있어야 하나요?</i> 예.<br><i>장치를 차 안으로 가져와야 하나요?</i> 아니요, 주차한 후에는 활성화할 수 있지만 차량의 배터리에 따라 업로드가 제한됩니다.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network + diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 06b2ef7b35..0b224fa940 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -311,25 +311,31 @@ 🔥 Firehose Mode 🔥 🔥 Mode Firehose 🔥 - - Enable Firehose Mode - Habilitar Modo Firehose - openpilot learns to drive by watching humans, like you, drive. -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - O openpilot aprende a dirigir observando humanos, como você, dirigirem. - -O Modo Firehose permite maximizar o envio de seus dados de treinamento para melhorar os modelos de direção do openpilot. Mais dados significam modelos maiores e um Modo Experimental melhor. +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + - 0% - 5G {0%?} + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - Siga estes passos para preparar seu dispositivo:<br> 1. Leve o dispositivo para dentro e conecte-o a um bom adaptador USB-C<br> 2. Conecte-se ao Wi-Fi<br> 3. Ative a opção<br> 4. Deixe-o conectado por pelo menos 30 minutos<br><br>A opção será desativada quando você reiniciar o dispositivo. Repita esse processo pelo menos uma vez por semana para obter a máxima eficácia.<br><br><b>FAQ</b><br><i>Importa como ou onde eu dirijo?</i> Não, basta dirigir normalmente.<br><i>O que é um bom adaptador USB-C?</i> Qualquer carregador rápido de celular ou laptop deve servir..<br><i>Preciso estar conectado ao Wi-Fi?</i> Sim.<br><i>Preciso levar o dispositivo para dentro de casa?</i> Não, você pode ativar a opção enquanto estiver estacionado, mas seus envios serão limitados pela bateria do carro.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network + diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index 41dc3cad56..07c3892958 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts index 421a92b950..dda3cdec22 100644 --- a/selfdrive/ui/translations/main_tr.ts +++ b/selfdrive/ui/translations/main_tr.ts @@ -312,21 +312,29 @@ - Enable Firehose Mode + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. - openpilot learns to drive by watching humans, like you, drive. - -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. + Firehose Mode: ACTIVE - 0% - 5G {0%?} + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + + + + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index e6c8734b15..01ac85a8ce 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -311,25 +311,31 @@ 🔥 Firehose Mode 🔥 🔥 训练数据上传模式 🔥 - - Enable Firehose Mode - 启用训练数据上传模式 - openpilot learns to drive by watching humans, like you, drive. -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - openpilot 通过观察人类(像你一样的驾驶)来学习驾驶。 - -训练数据上传模式可让你最大化上传训练数据,以改进 openpilot 的驾驶模型。更多数据意味着更大的模型,并带来更优秀的实验模式。 +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + - 0% - 0% + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - 按照以下步骤准备您的设备:<br> 1. 将设备带到室内并连接到良好的 USB-C 充电器<br> 2. 连接 Wi-Fi<br> 3. 启用开关<br> 4. 保持连接至少 30 分钟<br><br>开关会在设备重新启动后自动关闭。请至少每周重复一次,以获得最佳效果。<br><br><b>常见问题</b><br><i>驾驶方式或地点重要吗?</i> 不,按照平常的方式驾驶即可。<br><i>什么是良好的 USB-C 充电器?</i> 任何快速手机或笔记本电脑充电器都可以。<br><i>我需要连接 Wi-Fi 吗?</i> 是的。<br><i>我需要把设备带到室内吗?</i> 不,您可以在停车后启用,但您的上传速度将受限于车辆的电池。<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network + diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index d750e9c46a..02d3593e60 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -311,25 +311,31 @@ 🔥 Firehose Mode 🔥 🔥 訓練資料上傳模式 🔥 - - Enable Firehose Mode - 啟用訓練資料上傳模式 - openpilot learns to drive by watching humans, like you, drive. -Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models with better Experimental Mode. - openpilot 透過觀察人類(像你一樣的駕駛)來學習駕駛。 - -訓練資料上傳模式可讓你最大化上傳訓練數據,以改進 openpilot 的駕駛模型。更多數據意味著更大的模型,並帶來更優秀的實驗模式。 +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%1 %2</b> of your driving are in the training dataset so far. + - 0% - 0% + ACTIVE + - Follow these steps to get your device ready:<br> 1. Bring your device inside and connect to a good USB-C adapter<br> 2. Connect to Wi-Fi<br> 3. Enable the toggle<br> 4. Leave it connected for at least 30 minutes<br><br>The toggle turns off once you restart your device. Repeat at least once a week for maximum effectiveness.<br><br><b>FAQ</b><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><i>Do I need to be on Wi-Fi?</i> Yes.<br><i>Do I need to bring the device inside?</i> No, you can enable once you're parked, however your uploads will be limited by your car's battery.<br> - 按照以下步驟準備您的裝置:<br> 1. 將裝置帶到室內並連接到良好的 USB-C 充電器<br> 2. 連接 Wi-Fi<br> 3. 啟用開關<br> 4. 保持連接至少 30 分鐘<br><br>開關會在裝置重新啟動後自動關閉。請至少每週重複一次,以獲得最佳效果。<br><br><b>常見問題</b><br><i>駕駛方式或地點重要嗎?</i> 不,按照平常的方式駕駛即可。<br><i>什麼是良好的 USB-C 充電器?</i> 任何快速手機或筆記本電腦充電器都可以。<br><i>我需要連接 Wi-Fi 嗎?</i> 是的。<br><i>我需要把裝置帶到室內嗎?</i> 不,您可以在停車後啟用,但您的上傳速度將受限於車輛的電池。<br> + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to unmetered network + From a82db2d331384fade0a4b1062d58921afa56a1a9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 5 Mar 2025 03:41:16 -0600 Subject: [PATCH 22/26] Revert "Filet o Fish model" (#34780) Revert "Filet o Fish model (#34775)" This reverts commit 31076b818df68ea171447ccafa07039311a11136. --- selfdrive/modeld/constants.py | 8 +----- selfdrive/modeld/modeld.py | 31 +++++++-------------- selfdrive/modeld/models/commonmodel.cc | 9 +++--- selfdrive/modeld/models/commonmodel.h | 5 ++-- selfdrive/modeld/models/commonmodel.pxd | 2 +- selfdrive/modeld/models/commonmodel_pyx.pyx | 4 +-- selfdrive/modeld/models/driving_policy.onnx | 4 +-- selfdrive/modeld/models/driving_vision.onnx | 2 +- 8 files changed, 23 insertions(+), 42 deletions(-) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index 5ca0a86bc8..2bb7b8100c 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -14,14 +14,8 @@ class ModelConstants: # model inputs constants MODEL_FREQ = 20 - HISTORY_FREQ = 5 - HISTORY_LEN_SECONDS = 5 - TEMPORAL_SKIP = MODEL_FREQ // HISTORY_FREQ - FULL_HISTORY_BUFFER_LEN = MODEL_FREQ * HISTORY_LEN_SECONDS - INPUT_HISTORY_BUFFER_LEN = HISTORY_FREQ * HISTORY_LEN_SECONDS - FEATURE_LEN = 512 - + FULL_HISTORY_BUFFER_LEN = 100 DESIRE_LEN = 8 TRAFFIC_CONVENTION_LEN = 2 LAT_PLANNER_STATE_LEN = 4 diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index 1e557942fe..ee825d158f 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -56,24 +56,16 @@ class ModelState: prev_desire: np.ndarray # for tracking the rising edge of the pulse def __init__(self, context: CLContext): - self.frames = { - 'input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP), - 'big_input_imgs': DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) - } + self.frames = {'input_imgs': DrivingModelFrame(context), 'big_input_imgs': DrivingModelFrame(context)} self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) - self.full_features_buffer = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) - self.full_desire = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32) - self.full_prev_desired_curv = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32) - self.temporal_idxs = slice(-1-(ModelConstants.TEMPORAL_SKIP*(ModelConstants.INPUT_HISTORY_BUFFER_LEN-1)), None, ModelConstants.TEMPORAL_SKIP) - # policy inputs self.numpy_inputs = { - 'desire': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), 'lateral_control_params': np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32), - 'prev_desired_curv': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), + 'prev_desired_curv': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), + 'features_buffer': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } with open(VISION_METADATA_PATH, 'rb') as f: @@ -112,9 +104,8 @@ class ModelState: new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) self.prev_desire[:] = inputs['desire'] - self.full_desire[0,:-1] = self.full_desire[0,1:] - self.full_desire[0,-1] = new_desire - self.numpy_inputs['desire'][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2) + self.numpy_inputs['desire'][0,:-1] = self.numpy_inputs['desire'][0,1:] + self.numpy_inputs['desire'][0,-1] = new_desire self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params'] @@ -137,17 +128,15 @@ class ModelState: self.vision_output = self.vision_run(**self.vision_inputs).numpy().flatten() vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) - self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:] - self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :] - self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs] + self.numpy_inputs['features_buffer'][0,:-1] = self.numpy_inputs['features_buffer'][0,1:] + self.numpy_inputs['features_buffer'][0,-1] = vision_outputs_dict['hidden_state'][0, :] self.policy_output = self.policy_run(**self.policy_inputs).numpy().flatten() policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) # TODO model only uses last value now - self.full_prev_desired_curv[0,:-1] = self.full_prev_desired_curv[0,1:] - self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] - self.numpy_inputs['prev_desired_curv'][:] = self.full_prev_desired_curv[0, self.temporal_idxs] + self.numpy_inputs['prev_desired_curv'][0,:-1] = self.numpy_inputs['prev_desired_curv'][0,1:] + self.numpy_inputs['prev_desired_curv'][0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} if SEND_RAW_PRED: diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc index 99155d9f1e..9973d18588 100644 --- a/selfdrive/modeld/models/commonmodel.cc +++ b/selfdrive/modeld/models/commonmodel.cc @@ -5,12 +5,11 @@ #include "common/clutil.h" -DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip) : ModelFrame(device_id, context) { +DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { input_frames = std::make_unique(buf_size); - temporal_skip = _temporal_skip; input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); - img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (temporal_skip+1)*frame_size_bytes, NULL, &err)); - region.origin = temporal_skip * frame_size_bytes; + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 2*frame_size_bytes, NULL, &err)); + region.origin = 1 * frame_size_bytes; region.size = frame_size_bytes; last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); @@ -21,7 +20,7 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); - for (int i = 0; i < temporal_skip; i++) { + for (int i = 0; i < 1; i++) { CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); } loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); diff --git a/selfdrive/modeld/models/commonmodel.h b/selfdrive/modeld/models/commonmodel.h index 176d7eb6dc..14409943e4 100644 --- a/selfdrive/modeld/models/commonmodel.h +++ b/selfdrive/modeld/models/commonmodel.h @@ -64,21 +64,20 @@ protected: class DrivingModelFrame : public ModelFrame { public: - DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip); + DrivingModelFrame(cl_device_id device_id, cl_context context); ~DrivingModelFrame(); cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); const int MODEL_WIDTH = 512; const int MODEL_HEIGHT = 256; const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT * 3 / 2; - const int buf_size = MODEL_FRAME_SIZE * 2; // 2 frames are temporal_skip frames apart + const int buf_size = MODEL_FRAME_SIZE * 2; const size_t frame_size_bytes = MODEL_FRAME_SIZE * sizeof(uint8_t); private: LoadYUVState loadyuv; cl_mem img_buffer_20hz_cl, last_img_cl, input_frames_cl; cl_buffer_region region; - int temporal_skip; }; class MonitoringModelFrame : public ModelFrame { diff --git a/selfdrive/modeld/models/commonmodel.pxd b/selfdrive/modeld/models/commonmodel.pxd index 4ac64d9172..b4f08b12aa 100644 --- a/selfdrive/modeld/models/commonmodel.pxd +++ b/selfdrive/modeld/models/commonmodel.pxd @@ -20,7 +20,7 @@ cdef extern from "selfdrive/modeld/models/commonmodel.h": cppclass DrivingModelFrame: int buf_size - DrivingModelFrame(cl_device_id, cl_context, int) + DrivingModelFrame(cl_device_id, cl_context) cppclass MonitoringModelFrame: int buf_size diff --git a/selfdrive/modeld/models/commonmodel_pyx.pyx b/selfdrive/modeld/models/commonmodel_pyx.pyx index 5b7d11bc71..7b3a5bb342 100644 --- a/selfdrive/modeld/models/commonmodel_pyx.pyx +++ b/selfdrive/modeld/models/commonmodel_pyx.pyx @@ -59,8 +59,8 @@ cdef class ModelFrame: cdef class DrivingModelFrame(ModelFrame): cdef cppDrivingModelFrame * _frame - def __cinit__(self, CLContext context, int temporal_skip): - self._frame = new cppDrivingModelFrame(context.device_id, context.context, temporal_skip) + def __cinit__(self, CLContext context): + self._frame = new cppDrivingModelFrame(context.device_id, context.context) self.frame = (self._frame) self.buf_size = self._frame.buf_size diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index cc2148c74b..f804b4ec31 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fd38c3b4d465d14a8ed128f8b1b265bff1589d42f398faa678b93f25b3385dc -size 15966721 +oid sha256:5cae3285c876804e649b14adadcfb8be79a9bd5a1b928113e37f1f08e25e9688 +size 16581121 diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx index aee6d8f1bf..06c87d8755 100644 --- a/selfdrive/modeld/models/driving_vision.onnx +++ b/selfdrive/modeld/models/driving_vision.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:897f80d0388250f99bba69b6a8434560cc0fd83157cbeb0bc134c67fe4e64624 +oid sha256:29bbf79f9dfd7048c0013bb81e86d9b2979275b95ea1ed8a86d1a86a88695240 size 34882971 From e394569eaeaa3eb56dc28c4fd1c921be53078d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Wed, 5 Mar 2025 13:33:45 -0800 Subject: [PATCH 23/26] Pre leak TinyGrad unbump (#34781) --- tinygrad_repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tinygrad_repo b/tinygrad_repo index 6f39c4d653..70266e9f94 160000 --- a/tinygrad_repo +++ b/tinygrad_repo @@ -1 +1 @@ -Subproject commit 6f39c4d653737c056540194605dc18a7273df280 +Subproject commit 70266e9f94d5a247ccbb2f3a46e72a2fbdaf7a8e From d15599a30bd92e5e02b3ad932ec78a59ba33766d Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:40:51 -0500 Subject: [PATCH 24/26] tools: updates to find_segments_with_message notebook (#34782) * cleanup, refactor, progress bar * more cleanup, add EXTRA_SEGMENTS * not everyone can see that route * add to README * update README * red panda support --- tools/car_porting/README.md | 39 ++- .../examples/find_segments_with_message.ipynb | 291 ++++++++---------- 2 files changed, 158 insertions(+), 172 deletions(-) diff --git a/tools/car_porting/README.md b/tools/car_porting/README.md index 68b0a57fb3..77492035ca 100644 --- a/tools/car_porting/README.md +++ b/tools/car_porting/README.md @@ -57,7 +57,21 @@ Traceback (most recent call last): AssertionError: 1 is not false : panda safety doesn't agree with openpilot: {'gasPressed': 116} ``` -### [tools/car_porting/examples/subaru_steer_temp_fault.ipynb](/tools/car_porting/examples/subaru_steer_temp_fault.ipynb) +## Jupyter notebooks + +To use these notebooks, install Jupyter within your [openpilot virtual environment](/tools/README.md). + +```bash +uv pip install jupyter ipykernel +``` + +Launching: + +```bash +jupyter notebook +``` + +### [examples/subaru_steer_temp_fault.ipynb](/tools/car_porting/examples/subaru_steer_temp_fault.ipynb) An example of searching through a database of segments for a specific condition, and plotting the results. @@ -65,7 +79,7 @@ An example of searching through a database of segments for a specific condition, *a plot of the steer_warning vs steering angle, where we can see it is clearly caused by a large steering angle change* -### [tools/car_porting/examples/subaru_long_accel.ipynb](/tools/car_porting/examples/subaru_long_accel.ipynb) +### [examples/subaru_long_accel.ipynb](/tools/car_porting/examples/subaru_long_accel.ipynb) An example of plotting the response of an actuator when it is active. @@ -73,7 +87,7 @@ An example of plotting the response of an actuator when it is active. *a plot of the brake_pressure vs acceleration, where we can see it is a fairly linear response.* -### [tools/car_porting/examples/ford_vin_fingerprint.ipynb](/tools/car_porting/examples/ford_vin_fingerprint.ipynb) +### [examples/ford_vin_fingerprint.ipynb](/tools/car_porting/examples/ford_vin_fingerprint.ipynb) In this example, we use the public comma car segments database to check if vin fingerprinting is feasible for ford. @@ -94,3 +108,22 @@ vin: 5LM5J7XC8MGXXXXXX real platform: FORD EXPLORER 6TH GEN determi vin: 3FTTW8E31PRXXXXXX real platform: FORD MAVERICK 1ST GEN determined platform: mock correct: False vin: 3FTTW8E99NRXXXXXX real platform: FORD MAVERICK 1ST GEN determined platform: mock correct: False ``` + +### [examples/find_segments_with_message.ipynb](/tools/car_porting/examples/find_segments_with_message.ipynb) + +Searches for segments where a set of given CAN message IDs are present. In the example, we search for all messages +used for CAN-based ignition detection. + +``` +Match found: 46b21f1c5f7aa885/2024-01-23--15-19-34/20/s JEEP GRAND CHEROKEE V6 2018 ['VW CAN Ign'] +Match found: a63a23c3e628f288/2023-11-05--18-36-20/8/s JEEP GRAND CHEROKEE V6 2018 ['VW CAN Ign'] +Match found: ce31b7a998781ba8/2024-01-19--07-05-29/23/s JEEP GRAND CHEROKEE 2019 ['VW CAN Ign'] +Match found: e1dfba62a4e33f7b/2023-12-25--19-31-00/4/s JEEP GRAND CHEROKEE 2019 ['VW CAN Ign'] +Match found: e1dfba62a4e33f7b/2024-01-10--14-33-57/2/s JEEP GRAND CHEROKEE 2019 ['VW CAN Ign'] +Match found: ae679616266f4096/2023-12-05--15-43-46/4/s RAM HD 5TH GEN ['Tesla 3/Y CAN Ign'] +Match found: ae679616266f4096/2023-11-18--17-49-42/3/s RAM HD 5TH GEN ['Tesla 3/Y CAN Ign'] +Match found: ae679616266f4096/2024-01-03--21-57-09/25/s RAM HD 5TH GEN ['Tesla 3/Y CAN Ign'] +Match found: 6dae2984cc53cd7f/2023-12-10--11-53-15/17/s FORD BRONCO SPORT 1ST GEN ['Rivian CAN Ign'] +Match found: 6dae2984cc53cd7f/2023-12-03--17-31-17/29/s FORD BRONCO SPORT 1ST GEN ['Rivian CAN Ign'] +Match found: 6dae2984cc53cd7f/2023-11-27--23-29-07/1/s FORD BRONCO SPORT 1ST GEN ['Rivian CAN Ign'] +``` diff --git a/tools/car_porting/examples/find_segments_with_message.ipynb b/tools/car_porting/examples/find_segments_with_message.ipynb index 82b06c1f31..4e688cc65b 100644 --- a/tools/car_porting/examples/find_segments_with_message.ipynb +++ b/tools/car_porting/examples/find_segments_with_message.ipynb @@ -2,30 +2,26 @@ "cells": [ { "cell_type": "code", - "execution_count": 30, - "id": "228a6736-de31-4255-9d72-a6ff391b968d", + "execution_count": 85, + "id": "facb8edc-9924-491a-a4dd-fe6135b0c6c4", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found 221 qualifying vehicles:\n" - ] - } - ], + "outputs": [], "source": [ + "# Import all cars from opendbc\n", + "\n", "from opendbc.car import structs\n", - "from opendbc.car.values import PLATFORMS\n", + "from opendbc.car.values import PLATFORMS as TEST_PLATFORMS\n", + "\n", + "# Example: add additional platforms/segments to test outside of commaCarSegments\n", "\n", - "print(f\"Found {len(PLATFORMS)} qualifying vehicles:\")\n", - "# for platform in PLATFORMS:\n", - "# print(f\" {platform}\")" + "EXTRA_SEGMENTS = {\n", + " # \"81dd9e9fe256c397/0000001f--97c42cf98d\", # Volkswagen ID.4 test route, new car port, not in public dataset\n", + "}" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 86, "id": "ed1c8aec-c274-4c61-b83d-711ea194bf86", "metadata": {}, "outputs": [ @@ -33,32 +29,32 @@ "name": "stdout", "output_type": "stream", "text": [ - "Collecting segments from commaCarSegments dataset:\n", - "No segments available for for DODGE_DURANGO\n", - "No segments available for for FORD_RANGER_MK2\n", - "No segments available for for HOLDEN_ASTRA\n", - "No segments available for for CADILLAC_ATS\n", - "No segments available for for CHEVROLET_MALIBU\n", - "No segments available for for CADILLAC_XT4\n", - "No segments available for for CHEVROLET_VOLT_2019\n", - "No segments available for for CHEVROLET_TRAVERSE\n", - "No segments available for for GMC_YUKON\n", - "No segments available for for HONDA_ODYSSEY_CHN\n", - "No segments available for for HYUNDAI_KONA_2022\n", - "No segments available for for HYUNDAI_NEXO_1ST_GEN\n", - "No segments available for for GENESIS_GV70_ELECTRIFIED_1ST_GEN\n", - "No segments available for for GENESIS_G80_2ND_GEN_FL\n", - "No segments available for for RIVIAN_R1_GEN1\n", - "No segments available for for SUBARU_FORESTER_HYBRID\n", - "No segments available for for TESLA_MODEL_3\n", - "No segments available for for TESLA_MODEL_Y\n", - "No segments available for for TOYOTA_RAV4_PRIME\n", - "No segments available for for TOYOTA_SIENNA_4TH_GEN\n", - "No segments available for for LEXUS_LC_TSS2\n", - "No segments available for for VOLKSWAGEN_CADDY_MK3\n", - "No segments available for for VOLKSWAGEN_CRAFTER_MK2\n", - "No segments available for for VOLKSWAGEN_JETTA_MK6\n", - "Collected 577 segments for analysis\n" + "Searching 221 platforms\n", + "No segments available for DODGE_DURANGO\n", + "No segments available for FORD_RANGER_MK2\n", + "No segments available for HOLDEN_ASTRA\n", + "No segments available for CADILLAC_ATS\n", + "No segments available for CHEVROLET_MALIBU\n", + "No segments available for CADILLAC_XT4\n", + "No segments available for CHEVROLET_VOLT_2019\n", + "No segments available for CHEVROLET_TRAVERSE\n", + "No segments available for GMC_YUKON\n", + "No segments available for HONDA_ODYSSEY_CHN\n", + "No segments available for HYUNDAI_KONA_2022\n", + "No segments available for HYUNDAI_NEXO_1ST_GEN\n", + "No segments available for GENESIS_GV70_ELECTRIFIED_1ST_GEN\n", + "No segments available for GENESIS_G80_2ND_GEN_FL\n", + "No segments available for RIVIAN_R1_GEN1\n", + "No segments available for SUBARU_FORESTER_HYBRID\n", + "No segments available for TESLA_MODEL_3\n", + "No segments available for TESLA_MODEL_Y\n", + "No segments available for TOYOTA_RAV4_PRIME\n", + "No segments available for TOYOTA_SIENNA_4TH_GEN\n", + "No segments available for LEXUS_LC_TSS2\n", + "No segments available for VOLKSWAGEN_CADDY_MK3\n", + "No segments available for VOLKSWAGEN_CRAFTER_MK2\n", + "No segments available for VOLKSWAGEN_JETTA_MK6\n", + "Searching 577 segments\n" ] } ], @@ -68,174 +64,131 @@ "from openpilot.tools.lib.logreader import LogReader\n", "from openpilot.tools.lib.comma_car_segments import get_comma_car_segments_database\n", "\n", + "\n", + "MAX_SEGS_PER_PLATFORM = 3 # Increase this to search more segments\n", + "\n", "database = get_comma_car_segments_database()\n", "TEST_SEGMENTS = []\n", "\n", - "MAX_SEGS_PER_PLATFORM = 3 # Increase this to search more segments\n", + "print(f\"Searching {len(TEST_PLATFORMS)} platforms\")\n", "\n", - "print(\"Collecting segments from commaCarSegments dataset:\")\n", "for platform in TEST_PLATFORMS:\n", " if platform not in database:\n", - " print(f\"No segments available for for {platform}\")\n", + " print(f\"No segments available for {platform}\")\n", " continue\n", " \n", " all_segments = database[platform]\n", - "\n", " NUM_SEGMENTS = min(len(all_segments), MAX_SEGS_PER_PLATFORM)\n", - "\n", - " # print(f\"Got {len(all_segments)} segments for platform {platform}, sampling {NUM_SEGMENTS} segments\")\n", " TEST_SEGMENTS.extend(random.sample(all_segments, NUM_SEGMENTS))\n", "\n", - "print(f\"Collected {len(TEST_SEGMENTS)} segments for analysis\")\n" + "TEST_SEGMENTS.extend(EXTRA_SEGMENTS)\n", + "\n", + "print(f\"Searching {len(TEST_SEGMENTS)} segments\")" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "id": "0c75e8f2-4f5f-4f89-b8db-5223a6534a9f", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Match found in d753e5427226080e/2023-12-30--10-14-03/9/s for CHRYSLER PACIFICA HYBRID 2018\n", - "Match found in 810855dc1450c716/2023-12-26--10-03-20/3/s for CHRYSLER PACIFICA HYBRID 2018\n", - "Match found in 7f268b92fc672c4d/2023-11-02--20-54-34/103/s for CHRYSLER PACIFICA HYBRID 2018\n", - "Match found in 1a10807c60c127fd/2023-12-09--19-21-30/49/s for CHRYSLER PACIFICA HYBRID 2019\n", - "Match found in b70b56b76a6217f2/2023-12-26--12-29-24/4/s for CHRYSLER PACIFICA HYBRID 2019\n", - "Match found in 86deeb65f10c3129/2023-12-29--07-38-12/179/s for CHRYSLER PACIFICA HYBRID 2019\n", - "Match found in 0a3e89f78b1d0071/2023-11-30--10-33-13/13/s for CHRYSLER PACIFICA 2018\n", - "Match found in 8fc6a1b72c8b1357/2023-11-30--17-35-04/10/s for CHRYSLER PACIFICA 2018\n", - "Match found in d5de6f3e9371e89e/2023-11-16--17-19-54/48/s for CHRYSLER PACIFICA 2018\n", - "Match found in 5fc1717be83fc0da/2024-01-03--13-16-03/27/s for CHRYSLER PACIFICA 2020\n", - "Match found in c1feb10d20626c65/2023-12-16--17-46-24/9/s for CHRYSLER PACIFICA 2020\n", - "Match found in c1feb10d20626c65/2023-11-21--17-40-18/25/s for CHRYSLER PACIFICA 2020\n", - "Match found in a63a23c3e628f288/2023-11-05--18-36-20/22/s for JEEP GRAND CHEROKEE V6 2018\n", - "Match found in 46b21f1c5f7aa885/2023-11-14--15-22-04/21/s for JEEP GRAND CHEROKEE V6 2018\n", - "Match found in a63a23c3e628f288/2023-12-13--09-15-47/27/s for JEEP GRAND CHEROKEE V6 2018\n", - "Match found in 4ffe7a3fb831a625/2024-01-04--09-15-33/22/s for JEEP GRAND CHEROKEE 2019\n", - "Match found in c5b49919572d2c5a/2023-12-17--15-54-06/73/s for JEEP GRAND CHEROKEE 2019\n", - "Match found in 9c2b832d06f93621/2024-01-25--13-52-19/8/s for JEEP GRAND CHEROKEE 2019\n", - "Match found in 1618132d68afc876/2023-11-24--10-21-12/4/s for HYUNDAI KONA ELECTRIC 2ND GEN\n", - "Match found in 1618132d68afc876/2023-08-27--09-32-14/13/s for HYUNDAI KONA 2ND GEN\n", - "Match found in 1618132d68afc876/2023-11-24--10-21-12/3/s for HYUNDAI KONA ELECTRIC 2ND GEN\n", - "Match found in df7fdd56970d90fe/2023-12-29--07-48-56/53/s for HYUNDAI IONIQ 6 2023\n", - "Match found in 0ad7facc77922c3e/2023-12-29--17-12-45/14/s for HYUNDAI IONIQ 6 2023\n", - "Match found in 0ad7facc77922c3e/2023-12-16--08-49-13/39/s for HYUNDAI IONIQ 6 2023\n", - "Match found in 78ad5150de133637/2023-09-13--16-15-57/0/s for KIA K8 HYBRID 1ST GEN\n", - "Match found in 78ad5150de133637/2023-09-13--16-15-57/2/s for KIA K8 HYBRID 1ST GEN\n", - "Match found in 78ad5150de133637/2023-09-13--16-15-57/1/s for KIA K8 HYBRID 1ST GEN\n", - "Match found in b153671049a867b3/2023-12-15--20-40-16/0/s for KIA NIRO EV 2ND GEN\n", - "Match found in b153671049a867b3/2024-01-12--17-43-31/2/s for KIA NIRO EV 2ND GEN\n", - "Match found in b153671049a867b3/2023-12-03--21-08-30/3/s for KIA NIRO EV 2ND GEN\n", - "Match found in 7387ab2a564c6d9f/2023-12-02--07-10-34/52/s for KIA NIRO HYBRID 2ND GEN\n", - "Match found in 7387ab2a564c6d9f/2024-01-06--16-24-36/1/s for KIA NIRO HYBRID 2ND GEN\n", - "Match found in 7387ab2a564c6d9f/2024-01-06--16-24-36/9/s for KIA NIRO HYBRID 2ND GEN\n", - "Match found in 2efdac7dc41207f1/2023-12-27--07-24-22/89/s for KIA EV6 2022\n", - "Match found in 5ac586afbb236b5d/2023-12-05--18-23-10/7/s for VOLKSWAGEN ARTEON 1ST GEN\n", - "Match found in c34ef43981b6d888/2024-01-18--16-00-06/9/s for VOLKSWAGEN ARTEON 1ST GEN\n", - "Match found in 5ac586afbb236b5d/2024-01-04--20-01-19/4/s for VOLKSWAGEN ARTEON 1ST GEN\n", - "Match found in 16758e226aa2f747/2023-12-16--10-24-39/13/s for VOLKSWAGEN ATLAS 1ST GEN\n", - "Match found in 3174d252cec3bf6f/2023-12-12--18-39-06/6/s for VOLKSWAGEN ATLAS 1ST GEN\n", - "Match found in e80066d826c705a9/2024-01-06--17-28-45/211/s for VOLKSWAGEN ATLAS 1ST GEN\n", - "Match found in 2cdded3a5da75b6a/2024-01-06--13-37-16/2/s for VOLKSWAGEN GOLF 7TH GEN\n", - "Match found in abe0b7fe730c51a9/2023-10-30--14-24-49/4/s for VOLKSWAGEN GOLF 7TH GEN\n", - "Match found in 8fe9ced03c94e256/2023-12-14--16-31-55/8/s for VOLKSWAGEN GOLF 7TH GEN\n", - "Match found in a97d27ce2a78958a/2024-01-09--06-57-35/9/s for VOLKSWAGEN JETTA 7TH GEN\n", - "Match found in 0649d406184b7131/2024-01-20--14-43-41/3/s for VOLKSWAGEN JETTA 7TH GEN\n", - "Match found in 0649d406184b7131/2023-11-07--16-30-10/17/s for VOLKSWAGEN JETTA 7TH GEN\n", - "Match found in 5405cac0c9d58c3d/2023-11-05--17-13-17/6/s for VOLKSWAGEN PASSAT 8TH GEN\n", - "Match found in 2d7d87433a67c925/2024-01-05--16-31-16/38/s for VOLKSWAGEN PASSAT 8TH GEN\n", - "Match found in 2d7d87433a67c925/2023-12-26--08-44-17/2/s for VOLKSWAGEN PASSAT 8TH GEN\n", - "Match found in 0cd0b7f7e31a3853/2021-11-03--19-30-22/0/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 0bbe367c98fa1538/2023-07-01--19-42-26/7/s for VOLKSWAGEN POLO 6TH GEN\n", - "Match found in 0cd0b7f7e31a3853/2021-11-03--19-30-22/2/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/1/s for VOLKSWAGEN TAOS 1ST GEN\n", - "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/0/s for VOLKSWAGEN TAOS 1ST GEN\n", - "Match found in 7d82b2f3a9115f1f/2021-10-21--15-39-42/2/s for VOLKSWAGEN TAOS 1ST GEN\n", - "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/0/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/2/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 2744c89a8dda9a51/2021-07-24--21-28-06/1/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 4e144f64a2535890/2023-12-05--12-22-10/5/s for VOLKSWAGEN TIGUAN 2ND GEN\n", - "Match found in 1b5cf3b409037cc4/2023-12-11--10-23-35/5/s for VOLKSWAGEN TIGUAN 2ND GEN\n", - "Match found in 1b41980e9972d348/2023-10-29--15-13-08/3/s for VOLKSWAGEN TIGUAN 2ND GEN\n", - "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/0/s for VOLKSWAGEN TOURAN 2ND GEN\n", - "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/2/s for VOLKSWAGEN TOURAN 2ND GEN\n", - "Match found in a589dcc642fdb10a/2021-06-14--20-54-26/1/s for VOLKSWAGEN TOURAN 2ND GEN\n", - "Match found in 207b9d7ee3fb513a/2023-12-19--14-59-25/14/s for VOLKSWAGEN TRANSPORTER T6.1\n", - "Match found in a459f4556782eba1/2023-11-05--17-16-20/22/s for VOLKSWAGEN TRANSPORTER T6.1\n", - "Match found in a459f4556782eba1/2023-11-27--12-27-58/47/s for VOLKSWAGEN TRANSPORTER T6.1\n", - "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/0/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/1/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 0cd0b7f7e31a3853/2021-11-18--00-38-32/2/s for SKODA KODIAQ 1ST GEN\n", - "Match found in a973e9182bc96a2c/2024-01-14--15-14-33/54/s for AUDI A3 3RD GEN\n", - "Match found in 23daff6c438612d2/2023-12-21--15-37-32/22/s for AUDI A3 3RD GEN\n", - "Match found in 23daff6c438612d2/2024-01-17--09-31-14/20/s for AUDI A3 3RD GEN\n", - "Match found in 6c6b466346192818/2021-06-06--14-17-47/0/s for AUDI Q2 1ST GEN\n", - "Match found in 6c6b466346192818/2021-06-06--14-17-47/1/s for AUDI Q2 1ST GEN\n", - "Match found in 6c6b466346192818/2021-06-06--14-17-47/2/s for AUDI Q2 1ST GEN\n", - "Match found in 839125529d3c3cdf/2023-11-29--15-49-50/56/s for AUDI Q3 2ND GEN\n", - "Match found in d7bfab70d5011e1d/2023-11-24--00-49-14/24/s for AUDI Q3 2ND GEN\n", - "Match found in 98a3015c4f16846d/2023-11-04--12-32-32/76/s for AUDI Q3 2ND GEN\n", - "Match found in fc6b6c9a3471c846/2021-05-27--13-39-56/2/s for SEAT LEON 3RD GEN\n", - "Match found in fc6b6c9a3471c846/2021-05-27--13-39-56/1/s for SEAT LEON 3RD GEN\n", - "Match found in aef9c04d6ec5cd57/2023-07-15--16-49-38/12/s for SEAT LEON 3RD GEN\n", - "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/2/s for VOLKSWAGEN POLO 6TH GEN\n", - "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/1/s for VOLKSWAGEN POLO 6TH GEN\n", - "Match found in 0bbe367c98fa1538/2023-03-04--17-46-11/0/s for VOLKSWAGEN POLO 6TH GEN\n", - "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/0/s for SKODA SCALA 1ST GEN\n", - "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/1/s for SKODA SCALA 1ST GEN\n", - "Match found in 026b6d18fba6417f/2021-03-26--09-17-04/2/s for SKODA SCALA 1ST GEN\n", - "Match found in 12d6ae3057c04b0d/2021-09-04--21-21-21/1/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 12d6ae3057c04b0d/2021-09-04--21-21-21/0/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 7d76baac7cf42e15/2024-01-13--03-42-46/2/s for SKODA KAROQ 1ST GEN\n", - "Match found in 8a5da7c1d1783730/2024-01-17--06-32-18/4/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 8a5da7c1d1783730/2023-12-23--16-48-07/42/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 2ca49a03c8084514/2023-12-27--08-54-31/4/s for SKODA KODIAQ 1ST GEN\n", - "Match found in 66e5edc3a16459c5/2021-05-25--19-00-29/1/s for SKODA OCTAVIA 3RD GEN\n", - "Match found in f5392228324cda8d/2023-10-29--14-05-24/120/s for SKODA OCTAVIA 3RD GEN\n", - "Match found in 3fa7570f2fcace3d/2023-11-11--07-57-34/1/s for SKODA OCTAVIA 3RD GEN\n", - "Match found in 54ada937747ef8ca/2023-11-09--16-13-28/12/s for SKODA SUPERB 3RD GEN\n" - ] + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "27a243c33de44498b2b946190df44b23", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "segments searched: 0%| | 0/577 [00:00 0:\n", + " message_names = [MESSAGES_TO_FIND[message] for message in matched_messages]\n", + " print(f\"Match found: {segment:<45} {CP.carFingerprint:<38} {message_names}\")\n", "\n", - "print(f\"Analysis finished\")\n" + " progress_bar.update()\n" ] }, { @@ -257,9 +210,9 @@ ], "metadata": { "kernelspec": { - "display_name": "openpilot", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "openpilot" + "name": "python3" }, "language_info": { "codemirror_mode": { From 821148150b73c1ad7b7d192b64c684c09687f4b8 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 5 Mar 2025 15:42:22 -0800 Subject: [PATCH 25/26] Revert "make test_onroad faster (#34704) (#34783) * Revert "make test_onroad faster (#34704)" This reverts commit 470ec468300c3caa4881098f3b0b9e0954f286e1. * try this * add there * cleanup * try this * lil more * list * classic * don't skip test --- conftest.py | 4 +- pyproject.toml | 3 +- selfdrive/test/test_onroad.py | 85 +++++++++++++---------------------- 3 files changed, 36 insertions(+), 56 deletions(-) diff --git a/conftest.py b/conftest.py index a14a33c37d..9eda5d612a 100644 --- a/conftest.py +++ b/conftest.py @@ -77,8 +77,10 @@ def openpilot_class_fixture(): @pytest.fixture(scope="function") -def tici_setup_fixture(openpilot_function_fixture): +def tici_setup_fixture(request, openpilot_function_fixture): """Ensure a consistent state for tests on-device. Needs the openpilot function fixture to run first.""" + if 'skip_tici_setup' in request.keywords: + return HARDWARE.initialize_hardware() HARDWARE.set_power_save(False) os.system("pkill -9 -f athena") diff --git a/pyproject.toml b/pyproject.toml index e554a2f29d..58e714e3a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -143,6 +143,7 @@ asyncio_default_fixture_loop_scope = "function" markers = [ "slow: tests that take awhile to run and can be skipped with -m 'not slow'", "tici: tests that are only meant to run on the C3/C3X", + "skip_tici_setup: mark test to skip tici setup fixture" ] testpaths = [ "common", @@ -215,7 +216,7 @@ lint.select = [ "E", "F", "W", "PIE", "C4", "ISC", "A", "B", "NPY", # numpy "UP", # pyupgrade - "TRY302", "TRY400", "TRY401", # try/excepts + "TRY203", "TRY400", "TRY401", # try/excepts "RUF008", "RUF100", "TID251", "PLR1704", diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 23d1687770..7435239e5c 100644 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -1,8 +1,6 @@ import math import json import os -import pathlib -import psutil import pytest import shutil import subprocess @@ -12,7 +10,7 @@ from collections import Counter, defaultdict from pathlib import Path from tabulate import tabulate -from cereal import car, log +from cereal import log import cereal.messaging as messaging from cereal.services import SERVICE_LIST from openpilot.common.basedir import BASEDIR @@ -23,6 +21,7 @@ from openpilot.selfdrive.test.helpers import set_params_enabled, release_only from openpilot.system.hardware import HARDWARE from openpilot.system.hardware.hw import Paths from openpilot.tools.lib.logreader import LogReader +from openpilot.tools.lib.log_time_series import msgs_to_time_series """ CPU usage budget @@ -112,6 +111,7 @@ def cputime_total(ct): @pytest.mark.tici +@pytest.mark.skip_tici_setup class TestOnroad: @classmethod @@ -119,7 +119,8 @@ class TestOnroad: if "DEBUG" in os.environ: segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog.zst")), Path(Paths.log_root()).iterdir()) segs = sorted(segs, key=lambda x: x.stat().st_mtime) - cls.lr = list(LogReader(os.path.join(segs[-3], "rlog.zst"))) + cls.lr = list(LogReader(os.path.join(segs[-1], "rlog.zst"))) + cls.ts = msgs_to_time_series(cls.lr) return # setup env @@ -140,44 +141,31 @@ class TestOnroad: proc = subprocess.Popen(["python", manager_path]) sm = messaging.SubMaster(['carState']) - with Timeout(150, "controls didn't start"): - while sm.recv_frame['carState'] < 0: + with Timeout(30, "controls didn't start"): + while not sm.seen['carState']: sm.update(1000) - route = None - cls.segments = [] - with Timeout(300, "timed out waiting for logs"): - while route is None: - route = params.get("CurrentRoute", encoding="utf-8") - time.sleep(0.01) + route = params.get("CurrentRoute", encoding="utf-8") + assert route is not None - # test car params caching - params.put("CarParamsCache", car.CarParams().to_bytes()) - - while len(cls.segments) < 1: - segs = set() - if Path(Paths.log_root()).exists(): - segs = set(Path(Paths.log_root()).glob(f"{route}--*")) - cls.segments = sorted(segs, key=lambda s: int(str(s).rsplit('--')[-1])) - time.sleep(0.01) + segs = list(Path(Paths.log_root()).glob(f"{route}--*")) + assert len(segs) == 1 time.sleep(TEST_DURATION) - finally: - cls.gpu_procs = {psutil.Process(int(f.name)).name() for f in pathlib.Path('/sys/devices/virtual/kgsl/kgsl/proc/').iterdir() if f.is_dir()} - if proc is not None: proc.terminate() if proc.wait(60) is None: proc.kill() - cls.lrs = [list(LogReader(os.path.join(str(s), "rlog.zst"))) for s in cls.segments] - - cls.lr = list(LogReader(os.path.join(str(cls.segments[0]), "rlog.zst"))) - cls.log_path = cls.segments[0] + cls.lr = list(LogReader(os.path.join(str(segs[0]), "rlog.zst"))) + st = time.monotonic() + cls.ts = msgs_to_time_series(cls.lr) + print("msgs to time series", time.monotonic() - st) + log_path = segs[0] cls.log_sizes = {} - for f in cls.log_path.iterdir(): + for f in log_path.iterdir(): assert f.is_file() cls.log_sizes[f] = f.stat().st_size / 1e6 @@ -198,7 +186,7 @@ class TestOnroad: assert len(msgs) >= math.floor(SERVICE_LIST[s].frequency*int(TEST_DURATION*0.8)) def test_manager_starting_time(self): - st = self.msgs['managerState'][0].logMonoTime / 1e9 + st = self.ts['managerState']['t'][0] assert (st - self.manager_st) < 10, f"manager.py took {st - self.manager_st}s to publish the first 'managerState' msg" def test_cloudlog_size(self): @@ -226,7 +214,7 @@ class TestOnroad: result += "-------------- UI Draw Timing ------------------\n" result += "------------------------------------------------\n" - ts = [m.uiDebug.drawTimeMillis for m in self.msgs['uiDebug']] + ts = self.ts['uiDebug']['drawTimeMillis'] result += f"min {min(ts):.2f}ms\n" result += f"max {max(ts):.2f}ms\n" result += f"std {np.std(ts):.2f}ms\n" @@ -309,9 +297,6 @@ class TestOnroad: assert np.max(np.diff(mems)) <= 4, "Max memory increase too high" assert np.average(np.diff(mems)) <= 1, "Average memory increase too high" - def test_gpu_usage(self): - assert self.gpu_procs == {"weston", "ui", "camerad", "selfdrive.modeld.modeld", "selfdrive.modeld.dmonitoringmodeld"} - def test_camera_frame_timings(self, subtests): # test timing within a single camera result = "\n" @@ -319,7 +304,7 @@ class TestOnroad: result += "----------------- SOF Timing ------------------\n" result += "------------------------------------------------\n" for name in ['roadCameraState', 'wideRoadCameraState', 'driverCameraState']: - ts = [getattr(m, m.which()).timestampSof for m in self.lr if name in m.which()] + ts = self.ts[name]['timestampSof'] d_ms = np.diff(ts) / 1e6 d50 = np.abs(d_ms-50) result += f"{name} sof delta vs 50ms: min {min(d50):.2f}ms\n" @@ -338,33 +323,30 @@ class TestOnroad: # sanity checks within a single cam for cam in cams: with subtests.test(test="frame_skips", camera=cam): - cam_log = [getattr(x, x.which()) for x in self.msgs[cam]] - assert set(np.diff([x.frameId for x in cam_log])) == {1, }, "Frame ID skips" + assert set(np.diff(self.ts[cam]['frameId'])) == {1, }, "Frame ID skips" # EOF > SOF - eof_sof_diff = np.array([x.timestampEof - x.timestampSof for x in cam_log]) + eof_sof_diff = self.ts[cam]['timestampEof'] - self.ts[cam]['timestampSof'] assert np.all(eof_sof_diff > 0) assert np.all(eof_sof_diff < 50*1e6) - fid = {c: [getattr(m, m.which()).frameId for m in self.msgs[c]] for c in cams} - first_fid = [min(x) for x in fid.values()] + first_fid = {c: min(self.ts[c]['frameId']) for c in cams} if cam.endswith('CameraState'): # camerad guarantees that all cams start on frame ID 0 # (note loggerd also needs to start up fast enough to catch it) - assert set(first_fid) == {0, }, "Cameras don't start on frame ID 0" + assert set(first_fid.values()) == {0, }, "Cameras don't start on frame ID 0" else: # encoder guarantees all cams start on the same frame ID - assert len(set(first_fid)) == 1, "Cameras don't start on same frame ID" + assert len(set(first_fid.values())) == 1, "Cameras don't start on same frame ID" # we don't do a full segment rotation, so these might not match exactly - last_fid = [max(x) for x in fid.values()] - assert max(last_fid) - min(last_fid) < 10 + last_fid = {c: max(self.ts[c]['frameId']) for c in cams} + assert max(last_fid.values()) - min(last_fid.values()) < 10 - start, end = min(first_fid), min(last_fid) - all_ts = [[getattr(m, m.which()).timestampSof for m in self.msgs[c]] for c in cams] + start, end = min(first_fid.values()), min(last_fid.values()) for i in range(end-start): - ts = [round(x[i]/1e6, 1) for x in all_ts] - diff = max(ts) - min(ts) + ts = {c: round(self.ts[c]['timestampSof'][i]/1e6, 1) for c in cams} + diff = (max(ts.values()) - min(ts.values())) assert diff < 2, f"Cameras not synced properly: frame_id={start+i}, {diff=:.1f}ms, {ts=}" def test_mpc_execution_timings(self): @@ -438,12 +420,7 @@ class TestOnroad: @release_only def test_startup(self): - startup_alert = None - for msg in self.lrs[0]: - # can't use onroadEvents because the first msg can be dropped while loggerd is starting up - if msg.which() == "selfdriveState": - startup_alert = msg.selfdriveState.alertText1 - break + startup_alert = self.ts['selfdriveState']['alertText1'][0] expected = EVENTS[log.OnroadEvent.EventName.startup][ET.PERMANENT].alert_text_1 assert startup_alert == expected, "wrong startup alert" From 65bf2ec0ea5c2598d3e66340ecc6177f51dc112a Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 5 Mar 2025 15:58:03 -0800 Subject: [PATCH 26/26] test_onroad: add sanity check on ecode outputs (#34784) * test_onroad: add sanity check on ecode outputs * exact --- selfdrive/test/test_onroad.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 7435239e5c..9756010614 100644 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -349,6 +349,25 @@ class TestOnroad: diff = (max(ts.values()) - min(ts.values())) assert diff < 2, f"Cameras not synced properly: frame_id={start+i}, {diff=:.1f}ms, {ts=}" + def test_camera_encoder_matches(self, subtests): + # sanity check that the frame metadata is consistent with the encoded frames + pairs = [('roadCameraState', 'roadEncodeIdx'), + ('wideRoadCameraState', 'wideRoadEncodeIdx'), + ('driverCameraState', 'driverEncodeIdx')] + for cam, enc in pairs: + with subtests.test(camera=cam, encoder=enc): + cam_frames = {fid: (sof, eof) for fid, sof, eof in zip( + self.ts[cam]['frameId'], + self.ts[cam]['timestampSof'], + self.ts[cam]['timestampEof'], + strict=True, + )} + for i, fid in enumerate(self.ts[enc]['frameId']): + cam_sof, cam_eof = cam_frames[fid] + enc_sof, enc_eof = self.ts[enc]['timestampSof'][i], self.ts[enc]['timestampEof'][i] + assert enc_sof == cam_sof, f"SOF mismatch: frameId={fid}, enc_sof={enc_sof}, cam_sof={cam_sof}" + assert enc_eof == cam_eof, f"EOF mismatch: frameId={fid}, enc_eof={enc_eof}, cam_eof={cam_eof}" + def test_mpc_execution_timings(self): result = "\n" result += "------------------------------------------------\n"