def state_control(self, CS): """Given the state, this function returns an actuators packet""" # Update VehicleModel params = self.sm['liveParameters'] x = max(params.stiffnessFactor, 0.1) sr = max(params.steerRatio, 0.1) self.VM.update_params(x, sr) lat_plan = self.sm['lateralPlan'] long_plan = self.sm['longitudinalPlan'] actuators = car.CarControl.Actuators.new_message() actuators.longControlState = self.LoC.long_control_state if CS.leftBlinker or CS.rightBlinker: self.last_blinker_frame = self.sm.frame # State specific actions if not self.active: self.LaC.reset() self.LoC.reset(v_pid=CS.vEgo) if not self.joystick_mode: # accel PID loop pid_accel_limits = self.CI.get_pid_accel_limits( self.CP, CS.vEgo, self.v_cruise_kph * CV.KPH_TO_MS) actuators.accel = self.LoC.update(self.active, CS, self.CP, long_plan, pid_accel_limits) # Steering PID loop and lateral MPC desired_curvature, desired_curvature_rate = get_lag_adjusted_curvature( self.CP, CS.vEgo, lat_plan.psis, lat_plan.curvatures, lat_plan.curvatureRates) actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update( self.active, CS, self.CP, self.VM, params, desired_curvature, desired_curvature_rate) else: lac_log = log.ControlsState.LateralDebugState.new_message() if self.sm.rcv_frame['testJoystick'] > 0 and self.active: actuators.accel = 4.0 * clip(self.sm['testJoystick'].axes[0], -1, 1) steer = clip(self.sm['testJoystick'].axes[1], -1, 1) # max angle is 45 for angle-based cars actuators.steer, actuators.steeringAngleDeg = steer, steer * 45. lac_log.active = True lac_log.steeringAngleDeg = CS.steeringAngleDeg lac_log.output = steer lac_log.saturated = abs(steer) >= 0.9 # Check for difference between desired angle and angle for angle based control angle_control_saturated = self.CP.steerControlType == car.CarParams.SteerControlType.angle and \ abs(actuators.steeringAngleDeg - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD if angle_control_saturated and not CS.steeringPressed and self.active: self.saturated_count += 1 else: self.saturated_count = 0 # Send a "steering required alert" if saturation count has reached the limit if (lac_log.saturated and not CS.steeringPressed) or \ (self.saturated_count > STEER_ANGLE_SATURATION_TIMEOUT): if len(lat_plan.dPathPoints): # Check if we deviated from the path left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[ 0] < -0.1 right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[ 0] > 0.1 if left_deviation or right_deviation: self.events.add(EventName.steerSaturated) # Ensure no NaNs/Infs for p in ACTUATOR_FIELDS: attr = getattr(actuators, p) if not isinstance(attr, Number): continue if not math.isfinite(attr): cloudlog.error( f"actuators.{p} not finite {actuators.to_dict()}") setattr(actuators, p, 0.0) return actuators, lac_log
def state_control(self, CS): """Given the state, this function returns an actuators packet""" # Update VehicleModel params = self.sm['liveParameters'] x = max(params.stiffnessFactor, 0.1) sr = max(params.steerRatio, 0.1) if not self.sm['dragonConf'].dpSrLearner: if self.sm['dragonConf'].dpSrCustom >= 10: sr = self.sm['dragonConf'].dpSrCustom else: sr = self.CP.steerRatio self.VM.update_params(x, sr) lat_plan = self.sm['lateralPlan'] long_plan = self.sm['longitudinalPlan'] actuators = car.CarControl.Actuators.new_message() if CS.leftBlinker or CS.rightBlinker: self.last_blinker_frame = self.sm.frame # State specific actions if not self.active: self.LaC.reset() self.LoC.reset(v_pid=CS.vEgo) if not self.joystick_mode: # Gas/Brake PID loop actuators.gas, actuators.brake, self.v_target, self.a_target = self.LoC.update( self.active, CS, self.CP, long_plan) # Steering PID loop and lateral MPC desired_curvature, desired_curvature_rate = get_lag_adjusted_curvature( self.CP, CS.vEgo, lat_plan.psis, lat_plan.curvatures, lat_plan.curvatureRates) actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update( self.active, CS, self.CP, self.VM, params, desired_curvature, desired_curvature_rate) else: lac_log = log.ControlsState.LateralDebugState.new_message() if self.sm.rcv_frame['testJoystick'] > 0 and self.active: gb = clip(self.sm['testJoystick'].axes[0], -1, 1) actuators.gas, actuators.brake = max(gb, 0), max(-gb, 0) steer = clip(self.sm['testJoystick'].axes[1], -1, 1) # max angle is 45 for angle-based cars actuators.steer, actuators.steeringAngleDeg = steer, steer * 45. lac_log.active = True lac_log.steeringAngleDeg = CS.steeringAngleDeg lac_log.output = steer lac_log.saturated = abs(steer) >= 0.9 # Check for difference between desired angle and angle for angle based control angle_control_saturated = self.CP.steerControlType == car.CarParams.SteerControlType.angle and \ abs(actuators.steeringAngleDeg - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD if angle_control_saturated and not CS.steeringPressed and self.active: self.saturated_count += 1 else: self.saturated_count = 0 # Send a "steering required alert" if saturation count has reached the limit if (lac_log.saturated and not CS.steeringPressed) or \ (self.saturated_count > STEER_ANGLE_SATURATION_TIMEOUT): if len(lat_plan.dPathPoints): # Check if we deviated from the path left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[ 0] < -0.1 right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[ 0] > 0.1 if left_deviation or right_deviation: self.events.add(EventName.steerSaturated) return actuators, lac_log
def state_control(self, CS): """Given the state, this function returns a CarControl packet""" # Update VehicleModel params = self.sm['liveParameters'] x = max(params.stiffnessFactor, 0.1) sr = max(params.steerRatio, 0.1) self.VM.update_params(x, sr) lat_plan = self.sm['lateralPlan'] long_plan = self.sm['longitudinalPlan'] CC = car.CarControl.new_message() CC.enabled = self.enabled # Check which actuators can be enabled CC.latActive = self.active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ CS.vEgo > self.CP.minSteerSpeed and not CS.standstill CC.longActive = self.active and not self.events.any(ET.OVERRIDE) and self.CP.openpilotLongitudinalControl actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state if CS.leftBlinker or CS.rightBlinker: self.last_blinker_frame = self.sm.frame # State specific actions if not CC.latActive: self.LaC.reset() if not CC.longActive: self.LoC.reset(v_pid=CS.vEgo) if not self.joystick_mode: # accel PID loop pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, self.v_cruise_kph * CV.KPH_TO_MS) t_since_plan = (self.sm.frame - self.sm.rcv_frame['longitudinalPlan']) * DT_CTRL actuators.accel = self.LoC.update(CC.longActive, CS, long_plan, pid_accel_limits, t_since_plan) # Steering PID loop and lateral MPC self.desired_curvature, self.desired_curvature_rate = get_lag_adjusted_curvature(self.CP, CS.vEgo, lat_plan.psis, lat_plan.curvatures, lat_plan.curvatureRates) actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, params, self.last_actuators, self.desired_curvature, self.desired_curvature_rate, self.sm['liveLocationKalman']) else: lac_log = log.ControlsState.LateralDebugState.new_message() if self.sm.rcv_frame['testJoystick'] > 0: if CC.longActive: actuators.accel = 4.0*clip(self.sm['testJoystick'].axes[0], -1, 1) if CC.latActive: steer = clip(self.sm['testJoystick'].axes[1], -1, 1) # max angle is 45 for angle-based cars actuators.steer, actuators.steeringAngleDeg = steer, steer * 45. lac_log.active = self.active lac_log.steeringAngleDeg = CS.steeringAngleDeg lac_log.output = actuators.steer lac_log.saturated = abs(actuators.steer) >= 0.9 # Send a "steering required alert" if saturation count has reached the limit if lac_log.active and lac_log.saturated and not CS.steeringPressed: dpath_points = lat_plan.dPathPoints if len(dpath_points): # Check if we deviated from the path # TODO use desired vs actual curvature left_deviation = actuators.steer > 0 and dpath_points[0] < -0.20 right_deviation = actuators.steer < 0 and dpath_points[0] > 0.20 if left_deviation or right_deviation: self.events.add(EventName.steerSaturated) # Ensure no NaNs/Infs for p in ACTUATOR_FIELDS: attr = getattr(actuators, p) if not isinstance(attr, SupportsFloat): continue if not math.isfinite(attr): cloudlog.error(f"actuators.{p} not finite {actuators.to_dict()}") setattr(actuators, p, 0.0) return CC, lac_log
def state_control(self, CS): """Given the state, this function returns an actuators packet""" # Update VehicleModel params = self.sm['liveParameters'] x = max(params.stiffnessFactor, 0.1) #sr = max(params.steerRatio, 0.1) if ntune_common_enabled('useLiveSteerRatio'): sr = max(params.steerRatio, 0.1) else: sr = max(ntune_common_get('steerRatio'), 0.1) self.VM.update_params(x, sr) lat_plan = self.sm['lateralPlan'] long_plan = self.sm['longitudinalPlan'] actuators = car.CarControl.Actuators.new_message() actuators.longControlState = self.LoC.long_control_state if CS.leftBlinker or CS.rightBlinker: self.last_blinker_frame = self.sm.frame # State specific actions if not self.active: self.LaC.reset() self.LoC.reset(v_pid=CS.vEgo) if not CS.cruiseState.enabledAcc: self.LoC.reset(v_pid=CS.vEgo) if not self.joystick_mode: # accel PID loop pid_accel_limits = self.CI.get_pid_accel_limits( self.CP, CS.vEgo, self.v_cruise_kph * CV.KPH_TO_MS) t_since_plan = (self.sm.frame - self.sm.rcv_frame['longitudinalPlan']) * DT_CTRL actuators.accel = self.LoC.update( self.active and CS.cruiseState.enabledAcc, CS, self.CP, long_plan, pid_accel_limits, t_since_plan, self.sm['radarState']) # Steering PID loop and lateral MPC lat_active = self.active and not CS.steerWarning and not CS.steerError and CS.vEgo > self.CP.minSteerSpeed t_since_plan = (self.sm.frame - self.sm.rcv_frame['lateralPlan']) * DT_CTRL desired_curvature, desired_curvature_rate = get_lag_adjusted_curvature( self.CP, CS.vEgo, lat_plan.psis, lat_plan.curvatures, lat_plan.curvatureRates, t_since_plan) actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update( lat_active, CS, self.CP, self.VM, params, self.last_actuators, desired_curvature, desired_curvature_rate) else: lac_log = log.ControlsState.LateralDebugState.new_message() if self.sm.rcv_frame['testJoystick'] > 0 and self.active: actuators.accel = 4.0 * clip(self.sm['testJoystick'].axes[0], -1, 1) steer = clip(self.sm['testJoystick'].axes[1], -1, 1) # max angle is 45 for angle-based cars actuators.steer, actuators.steeringAngleDeg = steer, steer * 45. lac_log.active = True lac_log.steeringAngleDeg = CS.steeringAngleDeg lac_log.output = steer lac_log.saturated = abs(steer) >= 0.9 # Send a "steering required alert" if saturation count has reached the limit if lac_log.active and lac_log.saturated and not CS.steeringPressed: dpath_points = lat_plan.dPathPoints if len(dpath_points): # Check if we deviated from the path # TODO use desired vs actual curvature left_deviation = actuators.steer > 0 and dpath_points[0] < -0.20 right_deviation = actuators.steer < 0 and dpath_points[0] > 0.20 if left_deviation or right_deviation: self.events.add(EventName.steerSaturated) # Ensure no NaNs/Infs for p in ACTUATOR_FIELDS: attr = getattr(actuators, p) if not isinstance(attr, Number): continue if not math.isfinite(attr): cloudlog.error( f"actuators.{p} not finite {actuators.to_dict()}") setattr(actuators, p, 0.0) return actuators, lac_log