|  |  | @ -28,6 +28,7 @@ from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle, S | 
			
		
	
		
		
			
				
					
					|  |  |  | from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque |  |  |  | from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque | 
			
		
	
		
		
			
				
					
					|  |  |  | from openpilot.selfdrive.controls.lib.longcontrol import LongControl |  |  |  | from openpilot.selfdrive.controls.lib.longcontrol import LongControl | 
			
		
	
		
		
			
				
					
					|  |  |  | from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel |  |  |  | from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | from openpilot.system.hardware import HARDWARE |  |  |  | from openpilot.system.hardware import HARDWARE | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -78,6 +79,11 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |     # Setup sockets |  |  |  |     # Setup sockets | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.pm = messaging.PubMaster(['controlsState', 'carControl', 'onroadEvents']) |  |  |  |     self.pm = messaging.PubMaster(['controlsState', 'carControl', 'onroadEvents']) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if self.params.get_bool("UbloxAvailable"): | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       self.gps_location_service = "gpsLocationExternal" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     else: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       self.gps_location_service = "gpsLocation" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     self.gps_packets = [self.gps_location_service] | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.sensor_packets = ["accelerometer", "gyroscope"] |  |  |  |     self.sensor_packets = ["accelerometer", "gyroscope"] | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.camera_packets = ["roadCameraState", "driverCameraState", "wideRoadCameraState"] |  |  |  |     self.camera_packets = ["roadCameraState", "driverCameraState", "wideRoadCameraState"] | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -86,16 +92,16 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |     # TODO: de-couple controlsd with card/conflate on carState without introducing controls mismatches |  |  |  |     # TODO: de-couple controlsd with card/conflate on carState without introducing controls mismatches | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.car_state_sock = messaging.sub_sock('carState', timeout=20) |  |  |  |     self.car_state_sock = messaging.sub_sock('carState', timeout=20) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     ignore = self.sensor_packets + ['testJoystick'] |  |  |  |     ignore = self.sensor_packets + self.gps_packets + ['testJoystick'] | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if SIMULATION: |  |  |  |     if SIMULATION: | 
			
		
	
		
		
			
				
					
					|  |  |  |       ignore += ['driverCameraState', 'managerState'] |  |  |  |       ignore += ['driverCameraState', 'managerState'] | 
			
		
	
		
		
			
				
					
					|  |  |  |     if REPLAY: |  |  |  |     if REPLAY: | 
			
		
	
		
		
			
				
					
					|  |  |  |       # no vipc in replay will make them ignored anyways |  |  |  |       # no vipc in replay will make them ignored anyways | 
			
		
	
		
		
			
				
					
					|  |  |  |       ignore += ['roadCameraState', 'wideRoadCameraState'] |  |  |  |       ignore += ['roadCameraState', 'wideRoadCameraState'] | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', |  |  |  |     self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', | 
			
		
	
		
		
			
				
					
					|  |  |  |                                    'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'liveLocationKalman', |  |  |  |                                    'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'livePose', | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                                    'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', |  |  |  |                                    'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', | 
			
		
	
		
		
			
				
					
					|  |  |  |                                    'testJoystick'] + self.camera_packets + self.sensor_packets, |  |  |  |                                    'testJoystick'] + self.camera_packets + self.sensor_packets + self.gps_packets, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                                   ignore_alive=ignore, ignore_avg_freq=ignore+['radarState', 'testJoystick'], ignore_valid=['testJoystick', ], |  |  |  |                                   ignore_alive=ignore, ignore_avg_freq=ignore+['radarState', 'testJoystick'], ignore_valid=['testJoystick', ], | 
			
		
	
		
		
			
				
					
					|  |  |  |                                   frequency=int(1/DT_CTRL)) |  |  |  |                                   frequency=int(1/DT_CTRL)) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -120,6 +126,9 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.AM = AlertManager() |  |  |  |     self.AM = AlertManager() | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.events = Events() |  |  |  |     self.events = Events() | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     self.pose_calibrator = PoseCalibrator() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     self.calibrated_pose: Pose|None = None | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.LoC = LongControl(self.CP) |  |  |  |     self.LoC = LongControl(self.CP) | 
			
		
	
		
		
			
				
					
					|  |  |  |     self.VM = VehicleModel(self.CP) |  |  |  |     self.VM = VehicleModel(self.CP) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -335,11 +344,9 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |       self.logged_comm_issue = None |  |  |  |       self.logged_comm_issue = None | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if not (self.CP.notCar and self.joystick_mode): |  |  |  |     if not (self.CP.notCar and self.joystick_mode): | 
			
		
	
		
		
			
				
					
					|  |  |  |       if not self.sm['liveLocationKalman'].posenetOK: |  |  |  |       if not self.sm['livePose'].posenetOK: | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         self.events.add(EventName.posenetInvalid) |  |  |  |         self.events.add(EventName.posenetInvalid) | 
			
		
	
		
		
			
				
					
					|  |  |  |       if not self.sm['liveLocationKalman'].deviceStable: |  |  |  |       if not self.sm['livePose'].inputsOK: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         self.events.add(EventName.deviceFalling) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       if not self.sm['liveLocationKalman'].inputsOK: |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         self.events.add(EventName.locationdTemporaryError) |  |  |  |         self.events.add(EventName.locationdTemporaryError) | 
			
		
	
		
		
			
				
					
					|  |  |  |       if not self.sm['liveParameters'].valid and not TESTING_CLOSET and (not SIMULATION or REPLAY): |  |  |  |       if not self.sm['liveParameters'].valid and not TESTING_CLOSET and (not SIMULATION or REPLAY): | 
			
		
	
		
		
			
				
					
					|  |  |  |         self.events.add(EventName.paramsdTemporaryError) |  |  |  |         self.events.add(EventName.paramsdTemporaryError) | 
			
		
	
	
		
		
			
				
					|  |  | @ -375,10 +382,10 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     # TODO: fix simulator |  |  |  |     # TODO: fix simulator | 
			
		
	
		
		
			
				
					
					|  |  |  |     if not SIMULATION or REPLAY: |  |  |  |     if not SIMULATION or REPLAY: | 
			
		
	
		
		
			
				
					
					|  |  |  |       # Not show in first 1 km to allow for driving out of garage. This event shows after 5 minutes |  |  |  |       gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_CTRL < 2.0 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if not self.sm['liveLocationKalman'].gpsOK and self.sm['liveLocationKalman'].inputsOK and (self.distance_traveled > 1500): |  |  |  |       if not gps_ok and self.sm['livePose'].inputsOK and (self.distance_traveled > 1500): | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         self.events.add(EventName.noGps) |  |  |  |         self.events.add(EventName.noGps) | 
			
		
	
		
		
			
				
					
					|  |  |  |       if self.sm['liveLocationKalman'].gpsOK: |  |  |  |       if gps_ok: | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         self.distance_traveled = 0 |  |  |  |         self.distance_traveled = 0 | 
			
		
	
		
		
			
				
					
					|  |  |  |       self.distance_traveled += CS.vEgo * DT_CTRL |  |  |  |       self.distance_traveled += CS.vEgo * DT_CTRL | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -429,6 +436,13 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |            if ps.safetyModel not in IGNORED_SAFETY_MODES): |  |  |  |            if ps.safetyModel not in IGNORED_SAFETY_MODES): | 
			
		
	
		
		
			
				
					
					|  |  |  |       self.mismatch_counter += 1 |  |  |  |       self.mismatch_counter += 1 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # calibrate the live pose and save it for later use | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if self.sm.updated["liveCalibration"]: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       self.pose_calibrator.feed_live_calib(self.sm['liveCalibration']) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if self.sm.updated["livePose"]: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       device_pose = Pose.from_live_pose(self.sm['livePose']) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       self.calibrated_pose = self.pose_calibrator.build_calibrated_pose(device_pose) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     return CS |  |  |  |     return CS | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   def state_transition(self, CS): |  |  |  |   def state_transition(self, CS): | 
			
		
	
	
		
		
			
				
					|  |  | @ -573,7 +587,7 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  |       actuators.curvature = self.desired_curvature |  |  |  |       actuators.curvature = self.desired_curvature | 
			
		
	
		
		
			
				
					
					|  |  |  |       actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp, |  |  |  |       actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                                                              self.steer_limited, self.desired_curvature, |  |  |  |                                                                              self.steer_limited, self.desired_curvature, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                                                              self.sm['liveLocationKalman']) |  |  |  |                                                                              self.calibrated_pose) # TODO what if not available | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     else: |  |  |  |     else: | 
			
		
	
		
		
			
				
					
					|  |  |  |       lac_log = log.ControlsState.LateralDebugState.new_message() |  |  |  |       lac_log = log.ControlsState.LateralDebugState.new_message() | 
			
		
	
		
		
			
				
					
					|  |  |  |       if self.sm.recv_frame['testJoystick'] > 0: |  |  |  |       if self.sm.recv_frame['testJoystick'] > 0: | 
			
		
	
	
		
		
			
				
					|  |  | @ -650,12 +664,9 @@ class Controls: | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     # Orientation and angle rates can be useful for carcontroller |  |  |  |     # Orientation and angle rates can be useful for carcontroller | 
			
		
	
		
		
			
				
					
					|  |  |  |     # Only calibrated (car) frame is relevant for the carcontroller |  |  |  |     # Only calibrated (car) frame is relevant for the carcontroller | 
			
		
	
		
		
			
				
					
					|  |  |  |     orientation_value = list(self.sm['liveLocationKalman'].calibratedOrientationNED.value) |  |  |  |     if self.calibrated_pose is not None: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if len(orientation_value) > 2: |  |  |  |       CC.orientationNED = self.calibrated_pose.orientation.xyz.tolist() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       CC.orientationNED = orientation_value |  |  |  |       CC.angularVelocity = self.calibrated_pose.angular_velocity.xyz.tolist() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     angular_rate_value = list(self.sm['liveLocationKalman'].angularVelocityCalibrated.value) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if len(angular_rate_value) > 2: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       CC.angularVelocity = angular_rate_value |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     CC.cruiseControl.override = self.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl |  |  |  |     CC.cruiseControl.override = self.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl | 
			
		
	
		
		
			
				
					
					|  |  |  |     CC.cruiseControl.cancel = CS.cruiseState.enabled and (not self.enabled or not self.CP.pcmCruise) |  |  |  |     CC.cruiseControl.cancel = CS.cruiseState.enabled and (not self.enabled or not self.CP.pcmCruise) | 
			
		
	
	
		
		
			
				
					|  |  | 
 |