Conditional Experimental Mode
Added toggles for "Conditional Experimental Mode". Conditions based on road curvature, turn signals, speed, lead speed, navigation instructions, and stop signs/stop lights are all individually toggleable. Co-Authored-By: eFini <16603033+efinilan@users.noreply.github.com> Co-Authored-By: Kumar <36933347+rav4kumar@users.noreply.github.com>
This commit is contained in:
parent
b70b3e030a
commit
6aa8906cae
|
@ -19,9 +19,11 @@ enum FrogPilotEvents @0xf35cc4560bbf6ec2 {
|
|||
}
|
||||
|
||||
struct FrogPilotNavigation @0xda96579883444c35 {
|
||||
navigationConditionMet @0 :Bool;
|
||||
}
|
||||
|
||||
struct FrogPilotPlan @0x80ae746ee2596b11 {
|
||||
conditionalExperimental @1 :Bool;
|
||||
laneWidthLeft @3 :Float32;
|
||||
laneWidthRight @4 :Float32;
|
||||
}
|
||||
|
|
|
@ -218,6 +218,20 @@ std::unordered_map<std::string, uint32_t> keys = {
|
|||
{"ApiCache_DriveStats", PERSISTENT},
|
||||
{"BlindSpotPath", PERSISTENT},
|
||||
{"CameraView", PERSISTENT},
|
||||
{"CECurves", PERSISTENT},
|
||||
{"CECurvesLead", PERSISTENT},
|
||||
{"CENavigation", PERSISTENT},
|
||||
{"CENavigationIntersections", PERSISTENT},
|
||||
{"CENavigationLead", PERSISTENT},
|
||||
{"CENavigationTurns", PERSISTENT},
|
||||
{"CESignal", PERSISTENT},
|
||||
{"CESlowerLead", PERSISTENT},
|
||||
{"CESpeed", PERSISTENT},
|
||||
{"CESpeedLead", PERSISTENT},
|
||||
{"CEStatus", PERSISTENT},
|
||||
{"CEStopLights", PERSISTENT},
|
||||
{"CEStopLightsLead", PERSISTENT},
|
||||
{"ConditionalExperimental", PERSISTENT},
|
||||
{"CustomAlerts", PERSISTENT},
|
||||
{"CustomUI", PERSISTENT},
|
||||
{"DisengageVolume", PERSISTENT},
|
||||
|
|
|
@ -558,5 +558,6 @@ tinygrad_repo/tinygrad/runtime/ops_gpu.py
|
|||
tinygrad_repo/tinygrad/shape/*
|
||||
tinygrad_repo/tinygrad/*.py
|
||||
|
||||
selfdrive/frogpilot/functions/conditional_experimental_mode.py
|
||||
selfdrive/frogpilot/functions/frogpilot_functions.py
|
||||
selfdrive/frogpilot/functions/frogpilot_planner.py
|
||||
|
|
|
@ -6,7 +6,7 @@ from openpilot.selfdrive.car.body.values import DBC
|
|||
STARTUP_TICKS = 100
|
||||
|
||||
class CarState(CarStateBase):
|
||||
def update(self, cp, frogpilot_variables):
|
||||
def update(self, cp, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
ret.wheelSpeeds.fl = cp.vl['MOTORS_DATA']['SPEED_L']
|
||||
|
|
|
@ -29,8 +29,8 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
# wait for everything to init first
|
||||
if self.frame > int(5. / DT_CTRL):
|
||||
|
|
|
@ -21,7 +21,7 @@ class CarState(CarStateBase):
|
|||
else:
|
||||
self.shifter_values = can_define.dv["GEAR"]["PRNDL"]
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
# events
|
||||
events = self.create_common_events(ret, frogpilot_variables, extra_gears=[car.CarState.GearShifter.low])
|
||||
|
|
|
@ -20,7 +20,7 @@ class CarState(CarStateBase):
|
|||
self.vehicle_sensors_valid = False
|
||||
self.unsupported_platform = False
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
# Ford Q3 hybrid variants experience a bug where a message from the PCM sends invalid checksums,
|
||||
|
|
|
@ -103,8 +103,8 @@ class CarInterface(CarInterfaceBase):
|
|||
ret.centerToFront = ret.wheelbase * 0.44
|
||||
return ret
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
events = self.create_common_events(ret, frogpilot_variables, extra_gears=[GearShifter.manumatic])
|
||||
if not self.CS.vehicle_sensors_valid:
|
||||
|
|
|
@ -28,7 +28,7 @@ class CarState(CarStateBase):
|
|||
|
||||
# FrogPilot variables
|
||||
|
||||
def update(self, pt_cp, cam_cp, loopback_cp, frogpilot_variables):
|
||||
def update(self, pt_cp, cam_cp, loopback_cp, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
self.prev_cruise_buttons = self.cruise_buttons
|
||||
|
|
|
@ -346,8 +346,8 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
# Don't add event if transitioning from INIT, unless it's to an actual button
|
||||
if self.CS.cruise_buttons != CruiseButtons.UNPRESS or self.CS.prev_cruise_buttons != CruiseButtons.INIT:
|
||||
|
|
|
@ -108,7 +108,7 @@ class CarState(CarStateBase):
|
|||
# However, on cars without a digital speedometer this is not always present (HRV, FIT, CRV 2016, ILX and RDX)
|
||||
self.dash_speed_seen = False
|
||||
|
||||
def update(self, cp, cp_cam, cp_body, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, cp_body, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
# car params
|
||||
|
|
|
@ -314,8 +314,8 @@ class CarInterface(CarInterfaceBase):
|
|||
disable_ecu(logcan, sendcan, bus=1, addr=0x18DAB0F1, com_cont_req=b'\x28\x83\x03')
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT),
|
||||
|
|
|
@ -55,9 +55,9 @@ class CarState(CarStateBase):
|
|||
# FrogPilot variables
|
||||
self.main_enabled = False
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
if self.CP.carFingerprint in CANFD_CAR:
|
||||
return self.update_canfd(cp, cp_cam, frogpilot_variables)
|
||||
return self.update_canfd(cp, cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret = car.CarState.new_message()
|
||||
cp_cruise = cp_cam if self.CP.carFingerprint in CAMERA_SCC_CAR else cp
|
||||
|
@ -172,7 +172,7 @@ class CarState(CarStateBase):
|
|||
|
||||
return ret
|
||||
|
||||
def update_canfd(self, cp, cp_cam, frogpilot_variables):
|
||||
def update_canfd(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
self.is_metric = cp.vl["CRUISE_BUTTONS_ALT"]["DISTANCE_UNIT"] != 1
|
||||
|
|
|
@ -344,8 +344,8 @@ class CarInterface(CarInterfaceBase):
|
|||
if CP.flags & HyundaiFlags.ENABLE_BLINKERS:
|
||||
disable_ecu(logcan, sendcan, bus=CanBus(CP).ECAN, addr=0x7B1, com_cont_req=b'\x28\x83\x01')
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
if self.CS.CP.openpilotLongitudinalControl:
|
||||
ret.buttonEvents = create_button_events(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT)
|
||||
|
|
|
@ -215,14 +215,14 @@ class CarInterfaceBase(ABC):
|
|||
def _update(self, c: car.CarControl) -> car.CarState:
|
||||
pass
|
||||
|
||||
def update(self, c: car.CarControl, can_strings: List[bytes], frogpilot_variables) -> car.CarState:
|
||||
def update(self, c: car.CarControl, can_strings: List[bytes], conditional_experimental_mode, frogpilot_variables) -> car.CarState:
|
||||
# parse can
|
||||
for cp in self.can_parsers:
|
||||
if cp is not None:
|
||||
cp.update_strings(can_strings)
|
||||
|
||||
# get CarState
|
||||
ret = self._update(c, frogpilot_variables)
|
||||
ret = self._update(c, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret.canValid = all(cp.can_valid for cp in self.can_parsers if cp is not None)
|
||||
ret.canTimeout = any(cp.bus_timeout for cp in self.can_parsers if cp is not None)
|
||||
|
|
|
@ -18,7 +18,7 @@ class CarState(CarStateBase):
|
|||
self.lkas_allowed_speed = False
|
||||
self.lkas_disabled = False
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
|
||||
ret = car.CarState.new_message()
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
|
|
|
@ -49,8 +49,8 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
# events
|
||||
events = self.create_common_events(ret, frogpilot_variables)
|
||||
|
|
|
@ -20,7 +20,7 @@ class CarInterface(CarInterfaceBase):
|
|||
ret.steerRatio = 13.
|
||||
return ret
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
self.sm.update(0)
|
||||
gps_sock = 'gpsLocationExternal' if self.sm.rcv_frame['gpsLocationExternal'] > 1 else 'gpsLocation'
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class CarState(CarStateBase):
|
|||
self.steeringTorqueSamples = deque(TORQUE_SAMPLES*[0], TORQUE_SAMPLES)
|
||||
self.shifter_values = can_define.dv["GEARBOX"]["GEAR_SHIFTER"]
|
||||
|
||||
def update(self, cp, cp_adas, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_adas, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
if self.CP.carFingerprint in (CAR.ROGUE, CAR.XTRAIL, CAR.ALTIMA):
|
||||
|
|
|
@ -39,8 +39,8 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
buttonEvents = []
|
||||
be = car.CarState.ButtonEvent.new_message()
|
||||
|
|
|
@ -16,7 +16,7 @@ class CarState(CarStateBase):
|
|||
|
||||
self.angle_rate_calulator = CanSignalRateCalculator(50)
|
||||
|
||||
def update(self, cp, cp_cam, cp_body, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, cp_body, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
throttle_msg = cp.vl["Throttle"] if self.car_fingerprint not in HYBRID_CARS else cp_body.vl["Throttle_Hybrid"]
|
||||
|
|
|
@ -136,9 +136,9 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body, frogpilot_variables)
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret.events = self.create_common_events(ret, frogpilot_variables).to_msg()
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class CarState(CarStateBase):
|
|||
self.acc_state = 0
|
||||
self.das_control_counters = deque(maxlen=32)
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
# Vehicle speed
|
||||
|
|
|
@ -51,8 +51,8 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret.events = self.create_common_events(ret, frogpilot_variables).to_msg()
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class CarState(CarStateBase):
|
|||
|
||||
# FrogPilot variables
|
||||
|
||||
def update(self, cp, cp_cam, frogpilot_variables):
|
||||
def update(self, cp, cp_cam, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
ret.doorOpen = any([cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_FL"], cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_FR"],
|
||||
|
|
|
@ -286,8 +286,8 @@ class CarInterface(CarInterfaceBase):
|
|||
disable_ecu(logcan, sendcan, bus=0, addr=0x750, sub_addr=0xf, com_cont_req=communication_control)
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
# events
|
||||
events = self.create_common_events(ret, frogpilot_variables)
|
||||
|
|
|
@ -30,9 +30,9 @@ class CarState(CarStateBase):
|
|||
|
||||
return button_events
|
||||
|
||||
def update(self, pt_cp, cam_cp, ext_cp, trans_type, frogpilot_variables):
|
||||
def update(self, pt_cp, cam_cp, ext_cp, trans_type, conditional_experimental_mode, frogpilot_variables):
|
||||
if self.CP.carFingerprint in PQ_CARS:
|
||||
return self.update_pq(pt_cp, cam_cp, ext_cp, trans_type, frogpilot_variables)
|
||||
return self.update_pq(pt_cp, cam_cp, ext_cp, trans_type, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
ret = car.CarState.new_message()
|
||||
# Update vehicle speed and acceleration from ABS wheel speeds.
|
||||
|
@ -153,7 +153,7 @@ class CarState(CarStateBase):
|
|||
|
||||
return ret
|
||||
|
||||
def update_pq(self, pt_cp, cam_cp, ext_cp, trans_type, frogpilot_variables):
|
||||
def update_pq(self, pt_cp, cam_cp, ext_cp, trans_type, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = car.CarState.new_message()
|
||||
# Update vehicle speed and acceleration from ABS wheel speeds.
|
||||
ret.wheelSpeeds = self.get_wheel_speeds(
|
||||
|
|
|
@ -225,8 +225,8 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def _update(self, c, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType, frogpilot_variables)
|
||||
def _update(self, c, conditional_experimental_mode, frogpilot_variables):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType, conditional_experimental_mode, frogpilot_variables)
|
||||
|
||||
events = self.create_common_events(ret, frogpilot_variables, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
|
||||
pcm_enable=not self.CS.CP.openpilotLongitudinalControl,
|
||||
|
|
|
@ -448,7 +448,7 @@ class Controls:
|
|||
|
||||
# Update carState from CAN
|
||||
can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True)
|
||||
CS = self.CI.update(self.CC, can_strs, self.frogpilot_variables)
|
||||
CS = self.CI.update(self.CC, can_strs, self.conditional_experimental_mode, self.frogpilot_variables)
|
||||
if len(can_strs) and REPLAY:
|
||||
self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime
|
||||
|
||||
|
@ -572,7 +572,7 @@ class Controls:
|
|||
else:
|
||||
self.state = State.enabled
|
||||
self.current_alert_types.append(ET.ENABLE)
|
||||
self.v_cruise_helper.initialize_v_cruise(CS, self.experimental_mode, self.frogpilot_variables)
|
||||
self.v_cruise_helper.initialize_v_cruise(CS, self.experimental_mode, self.conditional_experimental_mode, self.frogpilot_variables)
|
||||
|
||||
# Check if openpilot is engaged and actuators are enabled
|
||||
self.enabled = self.state in ENABLED_STATES
|
||||
|
@ -604,6 +604,10 @@ class Controls:
|
|||
CC = car.CarControl.new_message()
|
||||
CC.enabled = self.enabled
|
||||
|
||||
# Update Experimental Mode
|
||||
if self.conditional_experimental_mode:
|
||||
self.experimental_mode = frogpilot_plan.conditionalExperimental
|
||||
|
||||
# Gear Check
|
||||
self.driving_gear = CS.gearShifter not in (GearShifter.neutral, GearShifter.park, GearShifter.reverse, GearShifter.unknown)
|
||||
|
||||
|
@ -911,7 +915,11 @@ class Controls:
|
|||
def params_thread(self, evt):
|
||||
while not evt.is_set():
|
||||
self.is_metric = self.params.get_bool("IsMetric")
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if not self.conditional_experimental_mode:
|
||||
self.experimental_mode = self.params.get_bool("ExperimentalMode")
|
||||
else:
|
||||
self.experimental_mode = False
|
||||
if self.CP.notCar:
|
||||
self.joystick_mode = self.params.get_bool("JoystickDebugMode")
|
||||
time.sleep(0.1)
|
||||
|
@ -934,6 +942,8 @@ class Controls:
|
|||
t.join()
|
||||
|
||||
def update_frogpilot_params(self):
|
||||
self.conditional_experimental_mode = self.params.get_bool("ConditionalExperimental")
|
||||
|
||||
custom_alerts = self.params.get_bool("CustomAlerts")
|
||||
|
||||
lateral_tune = self.params.get_bool("LateralTune")
|
||||
|
|
|
@ -125,12 +125,15 @@ class VCruiseHelper:
|
|||
self.button_timers[b.type.raw] = 1 if b.pressed else 0
|
||||
self.button_change_states[b.type.raw] = {"standstill": CS.cruiseState.standstill, "enabled": enabled}
|
||||
|
||||
def initialize_v_cruise(self, CS, experimental_mode: bool, frogpilot_variables) -> None:
|
||||
def initialize_v_cruise(self, CS, experimental_mode: bool, conditional_experimental_mode, frogpilot_variables) -> None:
|
||||
# initializing is handled by the PCM
|
||||
if self.CP.pcmCruise:
|
||||
return
|
||||
|
||||
initial = V_CRUISE_INITIAL_EXPERIMENTAL_MODE if experimental_mode else V_CRUISE_INITIAL
|
||||
if conditional_experimental_mode:
|
||||
initial = V_CRUISE_INITIAL
|
||||
else:
|
||||
initial = V_CRUISE_INITIAL_EXPERIMENTAL_MODE if experimental_mode else V_CRUISE_INITIAL
|
||||
|
||||
# 250kph or above probably means we never had a set speed
|
||||
if any(b.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for b in CS.buttonEvents) and self.v_cruise_kph_last < 250:
|
||||
|
|
|
@ -337,6 +337,7 @@ class LongitudinalMpc:
|
|||
|
||||
def update(self, radarstate, v_cruise, x, v, a, j, frogpilot_planner, personality=log.LongitudinalPersonality.standard):
|
||||
t_follow = get_T_FOLLOW(personality)
|
||||
self.t_follow = t_follow
|
||||
v_ego = self.x0[1]
|
||||
self.status = radarstate.leadOne.status or radarstate.leadTwo.status
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,196 @@
|
|||
import numpy as np
|
||||
from cereal import car
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.numpy_fast import interp
|
||||
from openpilot.common.params import Params
|
||||
|
||||
# Constants
|
||||
PROBABILITY = 0.6 # 60% chance of condition being true
|
||||
THRESHOLD = 5 # Time threshold (0.25s)
|
||||
|
||||
SPEED_LIMIT = 25 # Speed limit for turn signal check
|
||||
|
||||
# Lookup table for stop sign / stop light detection
|
||||
SLOW_DOWN_BP = [0., 10., 20., 30., 40., 50., 55.]
|
||||
SLOW_DOWN_DISTANCE = [10, 30., 50., 70., 80., 90., 120.]
|
||||
TRAJECTORY_SIZE = 33
|
||||
|
||||
|
||||
class GenericMovingAverageCalculator:
|
||||
def __init__(self):
|
||||
self.data = []
|
||||
self.total = 0
|
||||
|
||||
def add_data(self, value):
|
||||
if len(self.data) == THRESHOLD:
|
||||
self.total -= self.data.pop(0)
|
||||
self.data.append(value)
|
||||
self.total += value
|
||||
|
||||
def get_moving_average(self):
|
||||
if len(self.data) == 0:
|
||||
return None
|
||||
return self.total / len(self.data)
|
||||
|
||||
def reset_data(self):
|
||||
self.data = []
|
||||
self.total = 0
|
||||
|
||||
|
||||
class ConditionalExperimentalMode:
|
||||
def __init__(self):
|
||||
self.params_memory = Params("/dev/shm/params")
|
||||
|
||||
self.curve_detected = False
|
||||
self.experimental_mode = False
|
||||
self.lead_detected = False
|
||||
self.lead_detected_previously = False
|
||||
self.lead_slowing_down = False
|
||||
self.red_light_detected = False
|
||||
self.slower_lead_detected = False
|
||||
self.slowing_down = False
|
||||
|
||||
self.previous_status_value = 0
|
||||
self.previous_v_ego = 0
|
||||
self.previous_v_lead = 0
|
||||
self.status_value = 0
|
||||
|
||||
self.curvature_gmac = GenericMovingAverageCalculator()
|
||||
self.lead_detection_gmac = GenericMovingAverageCalculator()
|
||||
self.lead_slowing_down_gmac = GenericMovingAverageCalculator()
|
||||
self.slow_down_gmac = GenericMovingAverageCalculator()
|
||||
self.slow_lead_gmac = GenericMovingAverageCalculator()
|
||||
self.slowing_down_gmac = GenericMovingAverageCalculator()
|
||||
|
||||
def update(self, carState, frogpilotNavigation, modelData, mpc, radarState, road_curvature, standstill, v_ego):
|
||||
# Update Experimental Mode based on the current driving conditions
|
||||
condition_met = self.check_conditions(carState, frogpilotNavigation, modelData, standstill, v_ego)
|
||||
if (not self.experimental_mode and condition_met):
|
||||
self.experimental_mode = True
|
||||
elif (self.experimental_mode and not condition_met):
|
||||
self.experimental_mode = False
|
||||
self.status_value = 0
|
||||
|
||||
# Update the onroad status bar
|
||||
if self.status_value != self.previous_status_value:
|
||||
self.params_memory.put_int("CEStatus", self.status_value)
|
||||
self.previous_status_value = self.status_value
|
||||
|
||||
self.update_conditions(modelData, mpc, radarState, road_curvature, v_ego)
|
||||
|
||||
# Check conditions for the appropriate state of Experimental Mode
|
||||
def check_conditions(self, carState, frogpilotNavigation, modelData, standstill, v_ego):
|
||||
if standstill:
|
||||
return self.experimental_mode
|
||||
|
||||
# Keep Experimental Mode active if slowing down for a red light
|
||||
if (self.stop_lights_lead or not self.lead_slowing_down) and self.slowing_down and self.status_value == 12:
|
||||
return True
|
||||
|
||||
# Navigation check
|
||||
if self.navigation and modelData.navEnabled and frogpilotNavigation.navigationConditionMet and (self.navigation_lead or not self.lead_detected):
|
||||
self.status_value = 5
|
||||
return True
|
||||
|
||||
# Speed check
|
||||
if (not self.lead_detected and v_ego < self.limit) or (self.lead_detected and v_ego < self.limit_lead):
|
||||
self.status_value = 7 if self.lead_detected else 8
|
||||
return True
|
||||
|
||||
# Slower lead check
|
||||
if self.slower_lead and self.slower_lead_detected:
|
||||
self.status_value = 9
|
||||
return True
|
||||
|
||||
# Turn signal check
|
||||
if self.signal and v_ego < SPEED_LIMIT and (carState.leftBlinker or carState.rightBlinker):
|
||||
self.status_value = 10
|
||||
return True
|
||||
|
||||
# Road curvature check
|
||||
if self.curves and self.curve_detected:
|
||||
self.status_value = 11
|
||||
return True
|
||||
|
||||
# Stop sign and light check
|
||||
if self.stop_lights and self.red_light_detected:
|
||||
self.status_value = 12
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update_conditions(self, modelData, mpc, radarState, road_curvature, v_ego):
|
||||
v_lead = radarState.leadOne.vLead
|
||||
|
||||
self.lead_detection(radarState)
|
||||
self.road_curvature(road_curvature)
|
||||
self.slow_lead(mpc, radarState, v_ego, v_lead)
|
||||
self.stop_sign_and_light(modelData, v_ego)
|
||||
self.v_ego_slowing_down(v_ego)
|
||||
self.v_lead_slowing_down(v_lead)
|
||||
|
||||
# Lead detection
|
||||
def lead_detection(self, radarState):
|
||||
self.lead_detection_gmac.add_data(radarState.leadOne.status)
|
||||
self.lead_detected = self.lead_detection_gmac.get_moving_average() >= PROBABILITY
|
||||
|
||||
def v_ego_slowing_down(self, v_ego):
|
||||
self.slowing_down_gmac.add_data(v_ego < self.previous_v_ego)
|
||||
self.slowing_down = self.slowing_down_gmac.get_moving_average() >= PROBABILITY
|
||||
self.previous_v_ego = v_ego
|
||||
|
||||
def v_lead_slowing_down(self, v_lead):
|
||||
if self.lead_detected:
|
||||
self.lead_slowing_down_gmac.add_data(v_lead < self.previous_v_lead or v_lead <= 0)
|
||||
self.lead_slowing_down = self.lead_slowing_down_gmac.get_moving_average() >= PROBABILITY
|
||||
self.previous_v_lead = v_lead
|
||||
else:
|
||||
self.lead_slowing_down_gmac.reset_data()
|
||||
self.lead_slowing_down = False
|
||||
self.previous_v_lead = 0
|
||||
|
||||
# Determine the road curvature - Credit goes to to Pfeiferj!
|
||||
def road_curvature(self, road_curvature):
|
||||
lead_check = self.curves_lead or not self.lead_detected
|
||||
|
||||
if lead_check and not self.red_light_detected:
|
||||
self.curvature_gmac.add_data(road_curvature > 1.6 or self.curve_detected and road_curvature > 1.1)
|
||||
self.curve_detected = self.curvature_gmac.get_moving_average() >= PROBABILITY
|
||||
else:
|
||||
self.curvature_gmac.reset_data()
|
||||
self.curve_detected = False
|
||||
|
||||
# Slower lead detection - Credit goes to the DragonPilot team!
|
||||
def slow_lead(self, mpc, radarState, v_ego, v_lead):
|
||||
if not self.lead_detected and self.lead_detected_previously:
|
||||
self.slow_lead_gmac.reset_data()
|
||||
self.slower_lead_detected = False
|
||||
|
||||
if self.lead_detected:
|
||||
self.slow_lead_gmac.add_data(radarState.leadOne.dRel < (v_ego - 1) * mpc.t_follow)
|
||||
self.slower_lead_detected = self.slow_lead_gmac.get_moving_average() >= PROBABILITY
|
||||
|
||||
self.lead_detected_previously = self.lead_detected
|
||||
|
||||
# Stop sign/stop light detection - Credit goes to the DragonPilot team!
|
||||
def stop_sign_and_light(self, modelData, v_ego):
|
||||
lead_check = self.stop_lights_lead or not self.lead_slowing_down
|
||||
|
||||
# Check if the model data is consistent and wants to stop
|
||||
model_check = len(modelData.orientation.x) == len(modelData.position.x) == TRAJECTORY_SIZE
|
||||
model_stopping = modelData.position.x[TRAJECTORY_SIZE - 1] < interp(v_ego * CV.MS_TO_KPH, SLOW_DOWN_BP, SLOW_DOWN_DISTANCE)
|
||||
|
||||
self.slow_down_gmac.add_data(lead_check and model_check and model_stopping and not self.curve_detected and not self.slower_lead_detected)
|
||||
self.red_light_detected = self.slow_down_gmac.get_moving_average() >= PROBABILITY
|
||||
|
||||
def update_frogpilot_params(self, is_metric, params):
|
||||
self.curves = params.get_bool("CECurves")
|
||||
self.curves_lead = params.get_bool("CECurvesLead")
|
||||
self.limit = params.get_int("CESpeed") * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS)
|
||||
self.limit_lead = params.get_int("CESpeedLead") * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS)
|
||||
self.navigation = params.get_bool("CENavigation")
|
||||
self.navigation_lead = params.get_bool("CENavigationLead")
|
||||
self.signal = params.get_bool("CESignal")
|
||||
self.slower_lead = params.get_bool("CESlowerLead")
|
||||
self.stop_lights = params.get_bool("CEStopLights")
|
||||
self.stop_lights_lead = params.get_bool("CEStopLightsLead")
|
|
@ -48,3 +48,9 @@ class FrogPilotFunctions:
|
|||
distance_to_road_edge = np.mean(np.abs(current_y - road_edge_y_interp))
|
||||
|
||||
return min(distance_to_lane, distance_to_road_edge)
|
||||
|
||||
@staticmethod
|
||||
def road_curvature(modelData, v_ego):
|
||||
predicted_velocities = np.array(modelData.velocity.x)
|
||||
curvature_ratios = np.abs(np.array(modelData.acceleration.y)) / (predicted_velocities**2)
|
||||
return np.amax(curvature_ratios * (v_ego**2))
|
||||
|
|
|
@ -6,10 +6,14 @@ from openpilot.selfdrive.controls.lib.longitudinal_planner import A_CRUISE_MIN,
|
|||
|
||||
from openpilot.selfdrive.frogpilot.functions.frogpilot_functions import FrogPilotFunctions
|
||||
|
||||
from openpilot.selfdrive.frogpilot.functions.conditional_experimental_mode import ConditionalExperimentalMode
|
||||
|
||||
class FrogPilotPlanner:
|
||||
def __init__(self, params, params_memory):
|
||||
self.cem = ConditionalExperimentalMode()
|
||||
self.fpf = FrogPilotFunctions()
|
||||
|
||||
self.road_curvature = 0
|
||||
self.v_cruise = 0
|
||||
|
||||
self.accel_limits = [A_CRUISE_MIN, get_max_accel(0)]
|
||||
|
@ -27,6 +31,10 @@ class FrogPilotPlanner:
|
|||
else:
|
||||
self.accel_limits = [A_CRUISE_MIN, get_max_accel(v_ego)]
|
||||
|
||||
# Conditional Experimental Mode
|
||||
if self.conditional_experimental_mode and enabled:
|
||||
self.cem.update(carState, sm['frogpilotNavigation'], modelData, mpc, sm['radarState'], self.road_curvature, carState.standstill, v_ego)
|
||||
|
||||
# Update the max allowed speed
|
||||
self.v_cruise = self.update_v_cruise(carState, controlsState, enabled, modelData, v_cruise, v_ego)
|
||||
|
||||
|
@ -39,6 +47,9 @@ class FrogPilotPlanner:
|
|||
self.lane_width_left = 0
|
||||
self.lane_width_right = 0
|
||||
|
||||
# Update the current road curvature
|
||||
self.road_curvature = self.fpf.road_curvature(modelData, v_ego)
|
||||
|
||||
def update_v_cruise(self, carState, controlsState, enabled, modelData, v_cruise, v_ego):
|
||||
v_ego_diff = max(carState.vEgoRaw - carState.vEgoCluster, 0)
|
||||
return min(v_cruise, self.mtsc_target, self.slc_target, self.vtsc_target) - v_ego_diff
|
||||
|
@ -48,6 +59,8 @@ class FrogPilotPlanner:
|
|||
frogpilot_plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState'])
|
||||
frogpilotPlan = frogpilot_plan_send.frogpilotPlan
|
||||
|
||||
frogpilotPlan.conditionalExperimental = self.cem.experimental_mode
|
||||
|
||||
frogpilotPlan.laneWidthLeft = self.lane_width_left
|
||||
frogpilotPlan.laneWidthRight = self.lane_width_right
|
||||
|
||||
|
@ -56,6 +69,11 @@ class FrogPilotPlanner:
|
|||
def update_frogpilot_params(self, params, params_memory):
|
||||
self.is_metric = params.get_bool("IsMetric")
|
||||
|
||||
self.conditional_experimental_mode = params.get_bool("ConditionalExperimental")
|
||||
if self.conditional_experimental_mode:
|
||||
self.cem.update_frogpilot_params(self.is_metric, params)
|
||||
params.put_bool("ExperimentalMode", True)
|
||||
|
||||
custom_ui = params.get_bool("CustomUI")
|
||||
self.blind_spot_path = params.get_bool("BlindSpotPath") and custom_ui
|
||||
|
||||
|
|
|
@ -4,6 +4,13 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
|||
const std::vector<std::tuple<QString, QString, QString, QString>> controlToggles {
|
||||
{"AlwaysOnLateral", "Always on Lateral", "Maintain openpilot lateral control when the brake or gas pedals are used.\n\nDeactivation occurs only through the 'Cruise Control' button.", "../frogpilot/assets/toggle_icons/icon_always_on_lateral.png"},
|
||||
|
||||
{"ConditionalExperimental", "Conditional Experimental Mode", "Automatically switches to 'Experimental Mode' under predefined conditions.", "../frogpilot/assets/toggle_icons/icon_conditional.png"},
|
||||
{"CECurves", "Curve Detected Ahead", "Switch to 'Experimental Mode' when a curve is detected.", ""},
|
||||
{"CENavigation", "Navigation Based", "Switch to 'Experimental Mode' based on navigation data. (i.e. Intersections, stop signs, etc.)", ""},
|
||||
{"CESlowerLead", "Slower Lead Detected Ahead", "Switch to 'Experimental Mode' when a slower lead vehicle is detected ahead.", ""},
|
||||
{"CEStopLights", "Stop Lights and Stop Signs", "Switch to 'Experimental Mode' when a stop light or stop sign is detected.", ""},
|
||||
{"CESignal", "Turn Signal When Below Highway Speeds", "Switch to 'Experimental Mode' when using turn signals below highway speeds to help assit with turns.", ""},
|
||||
|
||||
{"LateralTune", "Lateral Tuning", "Modify openpilot's steering behavior.", "../frogpilot/assets/toggle_icons/icon_lateral_tune.png"},
|
||||
|
||||
{"LongitudinalTune", "Longitudinal Tuning", "Modify openpilot's acceleration and braking behavior.", "../frogpilot/assets/toggle_icons/icon_longitudinal_tune.png"},
|
||||
|
@ -33,6 +40,44 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil
|
|||
}
|
||||
});
|
||||
|
||||
} else if (param == "ConditionalExperimental") {
|
||||
FrogPilotParamManageControl *conditionalExperimentalToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
|
||||
QObject::connect(conditionalExperimentalToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
|
||||
parentToggleClicked();
|
||||
conditionalSpeedsImperial->setVisible(!isMetric);
|
||||
conditionalSpeedsMetric->setVisible(isMetric);
|
||||
for (auto &[key, toggle] : toggles) {
|
||||
toggle->setVisible(conditionalExperimentalKeys.find(key.c_str()) != conditionalExperimentalKeys.end());
|
||||
}
|
||||
});
|
||||
toggle = conditionalExperimentalToggle;
|
||||
} else if (param == "CECurves") {
|
||||
FrogPilotParamValueControl *CESpeedImperial = new FrogPilotParamValueControl("CESpeed", "Below", "Switch to 'Experimental Mode' below this speed in absence of a lead vehicle.", "", 0, 99,
|
||||
std::map<int, QString>(), this, false, " mph");
|
||||
FrogPilotParamValueControl *CESpeedLeadImperial = new FrogPilotParamValueControl("CESpeedLead", " w/Lead", "Switch to 'Experimental Mode' below this speed when following a lead vehicle.", "", 0, 99,
|
||||
std::map<int, QString>(), this, false, " mph");
|
||||
conditionalSpeedsImperial = new FrogPilotDualParamControl(CESpeedImperial, CESpeedLeadImperial, this);
|
||||
addItem(conditionalSpeedsImperial);
|
||||
|
||||
FrogPilotParamValueControl *CESpeedMetric = new FrogPilotParamValueControl("CESpeed", "Below", "Switch to 'Experimental Mode' below this speed in absence of a lead vehicle.", "", 0, 150,
|
||||
std::map<int, QString>(), this, false, " kph");
|
||||
FrogPilotParamValueControl *CESpeedLeadMetric = new FrogPilotParamValueControl("CESpeedLead", " w/Lead", "Switch to 'Experimental Mode' below this speed when following a lead vehicle.", "", 0, 150,
|
||||
std::map<int, QString>(), this, false, " kph");
|
||||
conditionalSpeedsMetric = new FrogPilotDualParamControl(CESpeedMetric, CESpeedLeadMetric, this);
|
||||
addItem(conditionalSpeedsMetric);
|
||||
|
||||
std::vector<QString> curveToggles{"CECurvesLead"};
|
||||
std::vector<QString> curveToggleNames{tr("With Lead")};
|
||||
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, curveToggles, curveToggleNames);
|
||||
} else if (param == "CENavigation") {
|
||||
std::vector<QString> navigationToggles{"CENavigationIntersections", "CENavigationTurns", "CENavigationLead"};
|
||||
std::vector<QString> navigationToggleNames{tr("Intersections"), tr("Turns"), tr("With Lead")};
|
||||
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, navigationToggles, navigationToggleNames);
|
||||
} else if (param == "CEStopLights") {
|
||||
std::vector<QString> stopLightToggles{"CEStopLightsLead"};
|
||||
std::vector<QString> stopLightToggleNames{tr("With Lead")};
|
||||
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, stopLightToggles, stopLightToggleNames);
|
||||
|
||||
} else if (param == "LateralTune") {
|
||||
FrogPilotParamManageControl *lateralTuneToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
|
||||
QObject::connect(lateralTuneToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
|
||||
|
@ -141,6 +186,8 @@ void FrogPilotControlsPanel::updateMetric() {
|
|||
if (isMetric != previousIsMetric) {
|
||||
double distanceConversion = isMetric ? FOOT_TO_METER : METER_TO_FOOT;
|
||||
double speedConversion = isMetric ? MILE_TO_KM : KM_TO_MILE;
|
||||
params.putIntNonBlocking("CESpeed", std::nearbyint(params.getInt("CESpeed") * speedConversion));
|
||||
params.putIntNonBlocking("CESpeedLead", std::nearbyint(params.getInt("CESpeedLead") * speedConversion));
|
||||
}
|
||||
|
||||
if (isMetric) {
|
||||
|
@ -151,10 +198,16 @@ void FrogPilotControlsPanel::updateMetric() {
|
|||
}
|
||||
|
||||
void FrogPilotControlsPanel::parentToggleClicked() {
|
||||
conditionalSpeedsImperial->setVisible(false);
|
||||
conditionalSpeedsMetric->setVisible(false);
|
||||
|
||||
openParentToggle();
|
||||
}
|
||||
|
||||
void FrogPilotControlsPanel::hideSubToggles() {
|
||||
conditionalSpeedsImperial->setVisible(false);
|
||||
conditionalSpeedsMetric->setVisible(false);
|
||||
|
||||
for (auto &[key, toggle] : toggles) {
|
||||
bool subToggles = conditionalExperimentalKeys.find(key.c_str()) != conditionalExperimentalKeys.end() ||
|
||||
fireTheBabysitterKeys.find(key.c_str()) != fireTheBabysitterKeys.end() ||
|
||||
|
|
|
@ -25,7 +25,10 @@ private:
|
|||
void updateState(const UIState &s);
|
||||
void updateToggles();
|
||||
|
||||
std::set<QString> conditionalExperimentalKeys = {};
|
||||
FrogPilotDualParamControl *conditionalSpeedsImperial;
|
||||
FrogPilotDualParamControl *conditionalSpeedsMetric;
|
||||
|
||||
std::set<QString> conditionalExperimentalKeys = {"CECurves", "CECurvesLead", "CESlowerLead", "CENavigation", "CEStopLights", "CESignal"};
|
||||
std::set<QString> fireTheBabysitterKeys = {};
|
||||
std::set<QString> laneChangeKeys = {};
|
||||
std::set<QString> lateralTuneKeys = {};
|
||||
|
|
|
@ -9,6 +9,7 @@ import requests
|
|||
import cereal.messaging as messaging
|
||||
from cereal import log
|
||||
from openpilot.common.api import Api
|
||||
from openpilot.common.numpy_fast import interp
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import Ratekeeper
|
||||
from openpilot.selfdrive.navd.helpers import (Coordinate, coordinate_from_param,
|
||||
|
@ -61,6 +62,11 @@ class RouteEngine:
|
|||
self.mapbox_host = "https://maps.comma.ai"
|
||||
|
||||
# FrogPilot variables
|
||||
self.stop_coord = []
|
||||
self.stop_signal = []
|
||||
self.nav_condition = False
|
||||
self.noo_condition = False
|
||||
|
||||
self.update_frogpilot_params()
|
||||
|
||||
def update(self):
|
||||
|
@ -170,6 +176,16 @@ class RouteEngine:
|
|||
self.route = r['routes'][0]['legs'][0]['steps']
|
||||
self.route_geometry = []
|
||||
|
||||
# Iterate through the steps in self.route to find "stop_sign" and "traffic_light"
|
||||
if self.conditional_navigation_intersections:
|
||||
self.stop_signal = []
|
||||
self.stop_coord = []
|
||||
for step in self.route:
|
||||
for intersection in step["intersections"]:
|
||||
if "stop_sign" in intersection or "traffic_signal" in intersection:
|
||||
self.stop_signal.append(intersection["geometry_index"])
|
||||
self.stop_coord.append(Coordinate.from_mapbox_tuple(intersection["location"]))
|
||||
|
||||
maxspeed_idx = 0
|
||||
maxspeeds = r['routes'][0]['legs'][0]['annotation']['maxspeed']
|
||||
|
||||
|
@ -310,9 +326,39 @@ class RouteEngine:
|
|||
self.params.remove("NavDestination")
|
||||
self.clear_route()
|
||||
|
||||
# 5-10 Seconds to stop condition based on v_ego or minimum of 25 meters
|
||||
if self.conditional_navigation:
|
||||
v_ego = self.sm['carState'].vEgo
|
||||
seconds_to_stop = interp(v_ego, [0, 22.3, 44.7], [5, 10, 10])
|
||||
# Determine the location of the closest upcoming stopSign or trafficLight
|
||||
closest_condition_indices = [idx for idx in self.stop_signal if idx >= closest_idx]
|
||||
if closest_condition_indices:
|
||||
closest_condition_index = min(closest_condition_indices, key=lambda idx: abs(closest_idx - idx))
|
||||
index = self.stop_signal.index(closest_condition_index)
|
||||
|
||||
# Calculate the distance to the stopSign or trafficLight
|
||||
distance_to_condition = self.last_position.distance_to(self.stop_coord[index])
|
||||
if self.conditional_navigation_intersections and distance_to_condition < max((seconds_to_stop * v_ego), 25):
|
||||
self.nav_condition = True
|
||||
else:
|
||||
self.nav_condition = False # Not approaching any stopSign or trafficLight
|
||||
else:
|
||||
self.nav_condition = False # No more stopSign or trafficLight in array
|
||||
|
||||
# Determine if NoO distance to maneuver is upcoming
|
||||
if self.conditional_navigation_turns and distance_to_maneuver_along_geometry < max((seconds_to_stop * v_ego), 25):
|
||||
self.noo_condition = True
|
||||
else:
|
||||
self.noo_condition = False # Not approaching any NoO maneuver
|
||||
else:
|
||||
self.nav_condition = False
|
||||
self.noo_condition = False
|
||||
|
||||
frogpilot_plan_send = messaging.new_message('frogpilotNavigation')
|
||||
frogpilotNavigation = frogpilot_plan_send.frogpilotNavigation
|
||||
|
||||
frogpilotNavigation.navigationConditionMet = self.nav_condition or self.noo_condition
|
||||
|
||||
self.pm.send('frogpilotNavigation', frogpilot_plan_send)
|
||||
|
||||
def send_route(self):
|
||||
|
@ -364,10 +410,13 @@ class RouteEngine:
|
|||
# TODO: Check for going wrong way in segment
|
||||
|
||||
def update_frogpilot_params(self):
|
||||
self.conditional_navigation = self.params.get_bool("CENavigation")
|
||||
self.conditional_navigation_intersections = self.params.get_bool("CENavigationIntersections") and self.conditional_navigation
|
||||
self.conditional_navigation_turns = self.params.get_bool("CENavigationTurns") and self.conditional_navigation
|
||||
|
||||
def main():
|
||||
pm = messaging.PubMaster(['navInstruction', 'navRoute', 'frogpilotNavigation'])
|
||||
sm = messaging.SubMaster(['liveLocationKalman', 'managerState'])
|
||||
sm = messaging.SubMaster(['carState', 'liveLocationKalman', 'managerState'])
|
||||
|
||||
rk = Ratekeeper(1.0)
|
||||
route_engine = RouteEngine(sm, pm)
|
||||
|
|
|
@ -172,7 +172,7 @@ void TogglesPanel::updateToggles() {
|
|||
op_long_toggle->setVisible(CP.getExperimentalLongitudinalAvailable() && !is_release);
|
||||
if (hasLongitudinalControl(CP)) {
|
||||
// normal description and toggle
|
||||
experimental_mode_toggle->setEnabled(true);
|
||||
experimental_mode_toggle->setEnabled(!params.getBool("ConditionalExperimental"));
|
||||
experimental_mode_toggle->setDescription(e2e_description);
|
||||
long_personality_setting->setEnabled(true);
|
||||
} else {
|
||||
|
|
|
@ -175,7 +175,7 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
|||
|
||||
int margin = 40;
|
||||
int radius = 30;
|
||||
int offset = scene.always_on_lateral ? 25 : 0;
|
||||
int offset = scene.always_on_lateral || scene.conditional_experimental ? 25 : 0;
|
||||
if (alert.size == cereal::ControlsState::AlertSize::FULL) {
|
||||
margin = 0;
|
||||
radius = 0;
|
||||
|
@ -563,7 +563,7 @@ void AnnotatedCameraWidget::drawDriverState(QPainter &painter, const UIState *s)
|
|||
|
||||
// base icon
|
||||
int offset = UI_BORDER_SIZE + btn_size / 2;
|
||||
offset += alwaysOnLateral ? 25 : 0;
|
||||
offset += alwaysOnLateral || conditionalExperimental ? 25 : 0;
|
||||
int x = rightHandDM ? width() - offset : offset;
|
||||
int y = height() - offset;
|
||||
float opacity = dmActive ? 0.65 : 0.2;
|
||||
|
@ -759,9 +759,13 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) {
|
|||
blindSpotLeft = scene.blind_spot_left;
|
||||
blindSpotRight = scene.blind_spot_right;
|
||||
cameraView = scene.camera_view;
|
||||
conditionalExperimental = scene.conditional_experimental;
|
||||
conditionalSpeed = scene.conditional_speed;
|
||||
conditionalSpeedLead = scene.conditional_speed_lead;
|
||||
conditionalStatus = scene.conditional_status;
|
||||
experimentalMode = scene.experimental_mode;
|
||||
|
||||
if (alwaysOnLateral) {
|
||||
if (alwaysOnLateral || conditionalExperimental) {
|
||||
drawStatusBar(p);
|
||||
}
|
||||
|
||||
|
@ -793,9 +797,27 @@ void AnnotatedCameraWidget::drawStatusBar(QPainter &p) {
|
|||
p.setOpacity(1.0);
|
||||
p.drawRoundedRect(statusBarRect, 30, 30);
|
||||
|
||||
std::map<int, QString> conditionalStatusMap = {
|
||||
{0, "Conditional Experimental Mode ready"},
|
||||
{1, "Conditional Experimental overridden"},
|
||||
{2, "Experimental Mode manually activated"},
|
||||
{3, "Conditional Experimental overridden"},
|
||||
{4, "Experimental Mode manually activated"},
|
||||
{5, "Experimental Mode activated for navigation" + (mapOpen ? "" : QString(" instructions input"))},
|
||||
{6, "Experimental Mode activated due to" + (mapOpen ? "SLC" : QString(" no speed limit set"))},
|
||||
{7, "Experimental Mode activated due to" + (mapOpen ? " speed" : " speed being less than " + QString::number(conditionalSpeedLead) + (is_metric ? " kph" : " mph"))},
|
||||
{8, "Experimental Mode activated due to" + (mapOpen ? " speed" : " speed being less than " + QString::number(conditionalSpeed) + (is_metric ? " kph" : " mph"))},
|
||||
{9, "Experimental Mode activated for slower lead"},
|
||||
{10, "Experimental Mode activated for turn" + (mapOpen ? "" : QString(" / lane change"))},
|
||||
{11, "Experimental Mode activated for curve"},
|
||||
{12, "Experimental Mode activated for stop" + (mapOpen ? "" : QString(" sign / stop light"))},
|
||||
};
|
||||
|
||||
// Update status text
|
||||
if (alwaysOnLateralActive) {
|
||||
newStatus = QString("Always On Lateral active. Press the \"Cruise Control\" button to disable");
|
||||
} else if (conditionalExperimental) {
|
||||
newStatus = conditionalStatusMap[status != STATUS_DISENGAGED ? conditionalStatus : 0];
|
||||
}
|
||||
|
||||
// Check if status has changed
|
||||
|
|
|
@ -122,9 +122,13 @@ private:
|
|||
bool alwaysOnLateralActive;
|
||||
bool blindSpotLeft;
|
||||
bool blindSpotRight;
|
||||
bool conditionalExperimental;
|
||||
bool experimentalMode;
|
||||
|
||||
int cameraView;
|
||||
int conditionalSpeed;
|
||||
int conditionalSpeedLead;
|
||||
int conditionalStatus;
|
||||
|
||||
protected:
|
||||
void paintGL() override;
|
||||
|
|
|
@ -262,6 +262,10 @@ void ui_update_frogpilot_params(UIState *s) {
|
|||
scene.always_on_lateral = params.getBool("AlwaysOnLateral");
|
||||
scene.camera_view = params.getInt("CameraView");
|
||||
|
||||
scene.conditional_experimental = params.getBool("ConditionalExperimental");
|
||||
scene.conditional_speed = params.getInt("CESpeed");
|
||||
scene.conditional_speed_lead = params.getInt("CESpeedLead");
|
||||
|
||||
bool custom_onroad_ui = params.getBool("CustomUI");
|
||||
scene.acceleration_path = params.getBool("AccelerationPath") && custom_onroad_ui;
|
||||
scene.blind_spot_path = params.getBool("BlindSpotPath") && custom_onroad_ui;
|
||||
|
@ -337,6 +341,9 @@ void UIState::update() {
|
|||
}
|
||||
|
||||
// FrogPilot live variables that need to be constantly checked
|
||||
if (scene.conditional_experimental) {
|
||||
scene.conditional_status = paramsMemory.getInt("CEStatus");
|
||||
}
|
||||
}
|
||||
|
||||
void UIState::setPrimeType(PrimeType type) {
|
||||
|
|
|
@ -175,6 +175,7 @@ typedef struct UIScene {
|
|||
bool blind_spot_left;
|
||||
bool blind_spot_path;
|
||||
bool blind_spot_right;
|
||||
bool conditional_experimental;
|
||||
bool enabled;
|
||||
bool experimental_mode;
|
||||
|
||||
|
@ -182,6 +183,9 @@ typedef struct UIScene {
|
|||
float lane_width_right;
|
||||
|
||||
int camera_view;
|
||||
int conditional_speed;
|
||||
int conditional_speed_lead;
|
||||
int conditional_status;
|
||||
|
||||
QPolygonF track_adjacent_vertices[6];
|
||||
|
||||
|
|
Loading…
Reference in New Issue