FrogPilot setup
This commit is contained in:
39
selfdrive/controls/controlsd.py
Executable file → Normal file
39
selfdrive/controls/controlsd.py
Executable file → Normal file
@@ -5,7 +5,7 @@ import time
|
||||
import threading
|
||||
from typing import SupportsFloat
|
||||
|
||||
from cereal import car, log
|
||||
from cereal import car, log, custom
|
||||
from openpilot.common.numpy_fast import clip
|
||||
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL
|
||||
from openpilot.common.params import Params
|
||||
@@ -48,6 +48,8 @@ EventName = car.CarEvent.EventName
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
SafetyModel = car.CarParams.SafetyModel
|
||||
|
||||
FrogPilotEventName = custom.FrogPilotEvents
|
||||
|
||||
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
||||
CSID_MAP = {"1": EventName.roadCameraError, "2": EventName.wideRoadCameraError, "0": EventName.driverCameraError}
|
||||
ACTUATOR_FIELDS = tuple(car.CarControl.Actuators.schema.fields.keys())
|
||||
@@ -64,7 +66,8 @@ class Controls:
|
||||
|
||||
# Setup sockets
|
||||
self.pm = messaging.PubMaster(['sendcan', 'controlsState', 'carState',
|
||||
'carControl', 'onroadEvents', 'carParams'])
|
||||
'carControl', 'onroadEvents', 'carParams',
|
||||
'frogpilotCarControl'])
|
||||
|
||||
self.sensor_packets = ["accelerometer", "gyroscope"]
|
||||
self.camera_packets = ["roadCameraState", "driverCameraState", "wideRoadCameraState"]
|
||||
@@ -72,14 +75,17 @@ class Controls:
|
||||
self.log_sock = messaging.sub_sock('androidLog')
|
||||
self.can_sock = messaging.sub_sock('can', timeout=20)
|
||||
|
||||
# FrogPilot variables
|
||||
self.params = Params()
|
||||
self.params_memory = Params("/dev/shm/params")
|
||||
|
||||
ignore = self.sensor_packets + ['testJoystick']
|
||||
if SIMULATION:
|
||||
ignore += ['driverCameraState', 'managerState']
|
||||
self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration',
|
||||
'driverMonitoringState', 'longitudinalPlan', 'lateralPlan', 'liveLocationKalman',
|
||||
'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters',
|
||||
'testJoystick'] + self.camera_packets + self.sensor_packets,
|
||||
'testJoystick', 'frogpilotLongitudinalPlan'] + self.camera_packets + self.sensor_packets,
|
||||
ignore_alive=ignore, ignore_avg_freq=['radarState', 'testJoystick'], ignore_valid=['testJoystick', ])
|
||||
|
||||
if CI is None:
|
||||
@@ -90,8 +96,9 @@ class Controls:
|
||||
num_pandas = len(messaging.recv_one_retry(self.sm.sock['pandaStates']).pandaStates)
|
||||
experimental_long_allowed = self.params.get_bool("ExperimentalLongitudinalEnabled")
|
||||
self.CI, self.CP = get_car(self.can_sock, self.pm.sock['sendcan'], experimental_long_allowed, num_pandas)
|
||||
self.CS = self.CI.CS
|
||||
else:
|
||||
self.CI, self.CP = CI, CI.CP
|
||||
self.CI, self.CP, self.CS = CI, CI.CP, CI.CS
|
||||
|
||||
self.joystick_mode = self.params.get_bool("JoystickDebugMode")
|
||||
|
||||
@@ -106,6 +113,7 @@ class Controls:
|
||||
self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled")
|
||||
openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle")
|
||||
passive = self.params.get_bool("Passive") or not openpilot_enabled_toggle
|
||||
self.update_frogpilot_params()
|
||||
|
||||
# detect sound card presence and ensure successful init
|
||||
sounds_available = HARDWARE.get_sound_card_online()
|
||||
@@ -138,6 +146,7 @@ class Controls:
|
||||
|
||||
self.CC = car.CarControl.new_message()
|
||||
self.CS_prev = car.CarState.new_message()
|
||||
self.FPCC = custom.FrogPilotCarControl.new_message()
|
||||
self.AM = AlertManager()
|
||||
self.events = Events()
|
||||
|
||||
@@ -576,10 +585,15 @@ class Controls:
|
||||
|
||||
lat_plan = self.sm['lateralPlan']
|
||||
long_plan = self.sm['longitudinalPlan']
|
||||
frogpilot_long_plan = self.sm['frogpilotLongitudinalPlan']
|
||||
|
||||
CC = car.CarControl.new_message()
|
||||
CC.enabled = self.enabled
|
||||
|
||||
# Gear Check
|
||||
gear = car.CarState.GearShifter
|
||||
driving_gear = CS.gearShifter not in (gear.neutral, gear.park, gear.reverse, gear.unknown)
|
||||
|
||||
# Check which actuators can be enabled
|
||||
standstill = CS.vEgo <= max(self.CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED) or CS.standstill
|
||||
CC.latActive = self.active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \
|
||||
@@ -847,6 +861,12 @@ class Controls:
|
||||
# copy CarControl to pass to CarInterface on the next iteration
|
||||
self.CC = CC
|
||||
|
||||
# Publish FrogPilot variables
|
||||
fpcs_send = messaging.new_message('frogpilotCarControl')
|
||||
fpcs_send.valid = CS.canValid
|
||||
fpcs_send.frogpilotCarControl = self.FPCC
|
||||
self.pm.send('frogpilotCarControl', fpcs_send)
|
||||
|
||||
def step(self):
|
||||
start_time = time.monotonic()
|
||||
|
||||
@@ -885,10 +905,21 @@ class Controls:
|
||||
while True:
|
||||
self.step()
|
||||
self.rk.monitor_time()
|
||||
|
||||
# Update FrogPilot parameters
|
||||
if self.params_memory.get_bool("FrogPilotTogglesUpdated"):
|
||||
self.update_frogpilot_params()
|
||||
|
||||
except SystemExit:
|
||||
e.set()
|
||||
t.join()
|
||||
|
||||
def update_frogpilot_params(self):
|
||||
for obj in [self.CI, self.CS]:
|
||||
if hasattr(obj, 'update_frogpilot_params'):
|
||||
obj.update_frogpilot_params(self.params)
|
||||
|
||||
longitudinal_tune = self.params.get_bool("LongitudinalTune")
|
||||
|
||||
def main():
|
||||
controls = Controls()
|
||||
|
||||
@@ -40,7 +40,9 @@ class DesireHelper:
|
||||
self.prev_one_blinker = False
|
||||
self.desire = log.LateralPlan.Desire.none
|
||||
|
||||
def update(self, carstate, lateral_active, lane_change_prob):
|
||||
# FrogPilot variables
|
||||
|
||||
def update(self, carstate, modeldata, lateral_active, lane_change_prob, frogpilot_planner):
|
||||
v_ego = carstate.vEgo
|
||||
one_blinker = carstate.leftBlinker != carstate.rightBlinker
|
||||
below_lane_change_speed = v_ego < LANE_CHANGE_SPEED_MIN
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
from enum import IntEnum
|
||||
from typing import Dict, Union, Callable, List, Optional
|
||||
|
||||
from cereal import log, car
|
||||
from cereal import log, car, custom
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
@@ -16,6 +16,7 @@ AlertStatus = log.ControlsState.AlertStatus
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
|
||||
EventName = car.CarEvent.EventName
|
||||
FrogPilotEventName = custom.FrogPilotEvents
|
||||
|
||||
|
||||
# Alert priorities
|
||||
@@ -44,6 +45,7 @@ class ET:
|
||||
|
||||
# get event name from enum
|
||||
EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()}
|
||||
EVENT_NAME.update({v: k for k, v in FrogPilotEventName.schema.enumerants.items()})
|
||||
|
||||
|
||||
class Events:
|
||||
@@ -228,7 +230,7 @@ def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubM
|
||||
if "REPLAY" in os.environ:
|
||||
branch = "replay"
|
||||
|
||||
return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt)
|
||||
return StartupAlert("Hippity hoppity this is my property", "so I do what I want 🐸", alert_status=AlertStatus.frogpilot)
|
||||
|
||||
def below_engage_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
|
||||
return NoEntryAlert(f"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage")
|
||||
@@ -964,6 +966,8 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
|
||||
ET.NO_ENTRY: NoEntryAlert("Vehicle Sensors Calibrating"),
|
||||
},
|
||||
|
||||
# FrogPilot Events
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class LateralPlanner:
|
||||
|
||||
self.debug_mode = debug
|
||||
|
||||
def update(self, sm):
|
||||
def update(self, sm, frogpilot_planner):
|
||||
v_ego_car = sm['carState'].vEgo
|
||||
|
||||
# Parse model predictions
|
||||
@@ -46,9 +46,9 @@ class LateralPlanner:
|
||||
self.l_lane_change_prob = desire_state[log.LateralPlan.Desire.laneChangeLeft]
|
||||
self.r_lane_change_prob = desire_state[log.LateralPlan.Desire.laneChangeRight]
|
||||
lane_change_prob = self.l_lane_change_prob + self.r_lane_change_prob
|
||||
self.DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob)
|
||||
self.DH.update(sm['carState'], md, sm['carControl'].latActive, lane_change_prob, frogpilot_planner)
|
||||
|
||||
def publish(self, sm, pm):
|
||||
def publish(self, sm, pm, frogpilot_planner):
|
||||
plan_send = messaging.new_message('lateralPlan')
|
||||
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'modelV2'])
|
||||
|
||||
@@ -72,3 +72,5 @@ class LateralPlanner:
|
||||
lateralPlan.laneChangeDirection = self.DH.lane_change_direction
|
||||
|
||||
pm.send('lateralPlan', plan_send)
|
||||
|
||||
frogpilot_planner.publish_lateral(sm, pm, self.DH)
|
||||
|
||||
@@ -88,7 +88,9 @@ class LongitudinalPlanner:
|
||||
j = np.zeros(len(T_IDXS_MPC))
|
||||
return x, v, a, j
|
||||
|
||||
def update(self, sm):
|
||||
def update(self, sm, frogpilot_planner):
|
||||
frogpilot_planner.update(sm, self.mpc)
|
||||
|
||||
if self.param_read_counter % 50 == 0:
|
||||
self.read_param()
|
||||
self.param_read_counter += 1
|
||||
@@ -152,7 +154,7 @@ class LongitudinalPlanner:
|
||||
self.a_desired = float(interp(self.dt, ModelConstants.T_IDXS[:CONTROL_N], self.a_desired_trajectory))
|
||||
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
|
||||
|
||||
def publish(self, sm, pm):
|
||||
def publish(self, sm, pm, frogpilot_planner):
|
||||
plan_send = messaging.new_message('longitudinalPlan')
|
||||
|
||||
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState'])
|
||||
@@ -173,3 +175,5 @@ class LongitudinalPlanner:
|
||||
longitudinalPlan.personality = self.personality
|
||||
|
||||
pm.send('longitudinalPlan', plan_send)
|
||||
|
||||
frogpilot_planner.publish_longitudinal(sm, pm, self.mpc)
|
||||
|
||||
@@ -10,6 +10,8 @@ from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPl
|
||||
from openpilot.selfdrive.controls.lib.lateral_planner import LateralPlanner
|
||||
import cereal.messaging as messaging
|
||||
|
||||
from openpilot.selfdrive.frogpilot.functions.frogpilot_planner import FrogPilotPlanner
|
||||
|
||||
def cumtrapz(x, t):
|
||||
return np.concatenate([[0], np.cumsum(((x[0:-1] + x[1:])/2) * np.diff(t))])
|
||||
|
||||
@@ -32,29 +34,34 @@ def plannerd_thread():
|
||||
|
||||
cloudlog.info("plannerd is waiting for CarParams")
|
||||
params = Params()
|
||||
params_memory = Params("/dev/shm/params")
|
||||
with car.CarParams.from_bytes(params.get("CarParams", block=True)) as msg:
|
||||
CP = msg
|
||||
cloudlog.info("plannerd got CarParams: %s", CP.carName)
|
||||
|
||||
debug_mode = bool(int(os.getenv("DEBUG", "0")))
|
||||
|
||||
frogpilot_planner = FrogPilotPlanner(params)
|
||||
longitudinal_planner = LongitudinalPlanner(CP)
|
||||
lateral_planner = LateralPlanner(CP, debug=debug_mode)
|
||||
|
||||
pm = messaging.PubMaster(['longitudinalPlan', 'lateralPlan', 'uiPlan'])
|
||||
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'radarState', 'modelV2'],
|
||||
pm = messaging.PubMaster(['longitudinalPlan', 'lateralPlan', 'uiPlan', 'frogpilotLateralPlan', 'frogpilotLongitudinalPlan'])
|
||||
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'radarState', 'modelV2', 'frogpilotNavigation'],
|
||||
poll=['radarState', 'modelV2'], ignore_avg_freq=['radarState'])
|
||||
|
||||
while True:
|
||||
sm.update()
|
||||
|
||||
if sm.updated['modelV2']:
|
||||
lateral_planner.update(sm)
|
||||
lateral_planner.publish(sm, pm)
|
||||
longitudinal_planner.update(sm)
|
||||
longitudinal_planner.publish(sm, pm)
|
||||
lateral_planner.update(sm, frogpilot_planner)
|
||||
lateral_planner.publish(sm, pm, frogpilot_planner)
|
||||
longitudinal_planner.update(sm, frogpilot_planner)
|
||||
longitudinal_planner.publish(sm, pm, frogpilot_planner)
|
||||
publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner)
|
||||
|
||||
if params_memory.get_bool("FrogPilotTogglesUpdated"):
|
||||
frogpilot_planner.update_frogpilot_params(params)
|
||||
|
||||
def main():
|
||||
plannerd_thread()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user