Compare commits

...

23 Commits

Author SHA1 Message Date
FrogAi 235c1cab79 agnos 10.1.1 2025-07-05 12:59:50 -05:00
firestar5683 eb507d5ea8 Update interface.py 2025-07-05 11:35:11 -05:00
firestar5683 159ca85be2 Update tinygrad_modeld.py 2025-05-31 12:59:15 -05:00
FrogAi 40d8eb8a4e agnos 10.1.1 2025-05-26 20:47:53 -05:00
firestar5683 ebf77baf33 Vikander Model 2025-05-24 14:59:24 -05:00
firestar5683 7c2fa00aec Restore Sanity
AHHHHHHH
2025-05-18 13:19:38 -05:00
firestar5683 9bd0463c64 Update interface.py 2025-05-15 17:51:42 -05:00
firestar5683 e247249033 Update interface.py 2025-05-12 15:09:54 -05:00
firestar5683 ea48457d72 Update interface.py 2025-05-12 14:01:05 -05:00
firestar5683 8a4e817f6b Reapply "panda fix"
This reverts commit a8767be7b1.
2025-05-12 13:16:08 -05:00
firestar5683 a8767be7b1 Revert "panda fix"
This reverts commit 2d23f740cc.
2025-05-12 13:15:49 -05:00
firestar5683 0c249d253e Update interface.py 2025-05-12 01:53:59 -05:00
firestar5683 9bb9d6ed2c Panda fix 2025-05-12 00:19:48 -05:00
firestar5683 ceac092b67 Revert "panda fix"
This reverts commit 2d23f740cc.
2025-05-12 00:11:13 -05:00
firestar5683 2d23f740cc panda fix 2025-05-11 23:08:48 -05:00
firestar5683 80c20399f1 Panda Fix? 2025-05-11 18:08:54 -05:00
firestar5683 4f65f90567 Update interface.py 2025-05-11 01:33:49 -05:00
firestar5683 0a217baf18 Revert "Reapply "Tomb Raider 6""
This reverts commit f3de8169b9.
2025-05-11 01:33:48 -05:00
firestar5683 b81d6fb1eb StarPilot 2025-05-11 01:33:48 -05:00
firestar5683 944fc51f8a Reapply "Tomb Raider 6" 2025-05-11 01:33:48 -05:00
firestar5683 086570b29f Update carcontroller.py 2025-05-11 01:33:47 -05:00
firestar5683 8face05df0 Logging 2025-05-11 01:33:46 -05:00
firestar5683 7231aeb5ee TorqueTune/Paddle
panda
2025-05-11 01:33:46 -05:00
42 changed files with 346 additions and 137 deletions
+2
View File
@@ -1048,6 +1048,8 @@ struct ModelDataV2 {
struct Action { struct Action {
desiredCurvature @0 :Float32; desiredCurvature @0 :Float32;
desiredAcceleration @1 :Float32;
shouldStop @2 :Bool;
} }
} }
+1 -1
View File
@@ -13,7 +13,7 @@ from openpilot.frogpilot.assets.download_functions import GITLAB_URL, download_f
from openpilot.frogpilot.common.frogpilot_utilities import delete_file from openpilot.frogpilot.common.frogpilot_utilities import delete_file
from openpilot.frogpilot.common.frogpilot_variables import DEFAULT_CLASSIC_MODEL, DEFAULT_MODEL, DEFAULT_TINYGRAD_MODEL, MODELS_PATH, params, params_default, params_memory from openpilot.frogpilot.common.frogpilot_variables import DEFAULT_CLASSIC_MODEL, DEFAULT_MODEL, DEFAULT_TINYGRAD_MODEL, MODELS_PATH, params, params_default, params_memory
VERSION = "v14" VERSION = "v15"
CANCEL_DOWNLOAD_PARAM = "CancelModelDownload" CANCEL_DOWNLOAD_PARAM = "CancelModelDownload"
DOWNLOAD_PROGRESS_PARAM = "ModelDownloadProgress" DOWNLOAD_PROGRESS_PARAM = "ModelDownloadProgress"
Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

After

Width:  |  Height:  |  Size: 503 KiB

+5 -2
View File
@@ -19,7 +19,6 @@ from cereal import log
from openpilot.common.realtime import DT_DMON, DT_HW from openpilot.common.realtime import DT_DMON, DT_HW
from openpilot.selfdrive.car.toyota.carcontroller import LOCK_CMD from openpilot.selfdrive.car.toyota.carcontroller import LOCK_CMD
from openpilot.system.hardware import HARDWARE from openpilot.system.hardware import HARDWARE
from openpilot.system.manager.process_config import managed_processes
from panda import Panda from panda import Panda
from openpilot.frogpilot.common.frogpilot_variables import EARTH_RADIUS, KONIK_PATH, MAPD_PATH, MAPS_PATH, params, params_memory from openpilot.frogpilot.common.frogpilot_variables import EARTH_RADIUS, KONIK_PATH, MAPD_PATH, MAPS_PATH, params, params_memory
@@ -39,6 +38,10 @@ locks = {
"update_openpilot": threading.Lock(), "update_openpilot": threading.Lock(),
} }
def get_managed_processes():
from openpilot.system.manager.process_config import managed_processes
return managed_processes
def run_thread_with_lock(name, target, args=(), report=True): def run_thread_with_lock(name, target, args=(), report=True):
if not running_threads.get(name, threading.Thread()).is_alive(): if not running_threads.get(name, threading.Thread()).is_alive():
with locks[name]: with locks[name]:
@@ -170,7 +173,7 @@ def restart_processes(sm):
if not any(ps.ignitionLine or ps.ignitionCan for ps in sm["pandaStates"] if ps.pandaType != log.PandaState.PandaType.unknown): if not any(ps.ignitionLine or ps.ignitionCan for ps in sm["pandaStates"] if ps.pandaType != log.PandaState.PandaType.unknown):
for name in ["mapd", "ui"]: for name in ["mapd", "ui"]:
managed_processes[name].stop(block=False, retry=False) get_managed_processes()[name].stop(block=False, retry=False)
def run_cmd(cmd, success_message, fail_message, report=True): def run_cmd(cmd, success_message, fail_message, report=True):
try: try:
+8 -4
View File
@@ -58,8 +58,8 @@ DEFAULT_MODEL = "national-public-radio"
DEFAULT_MODEL_NAME = "National Public Radio 👀📡" DEFAULT_MODEL_NAME = "National Public Radio 👀📡"
DEFAULT_MODEL_VERSION = "v6" DEFAULT_MODEL_VERSION = "v6"
DEFAULT_TINYGRAD_MODEL = "filet-o-fish" DEFAULT_TINYGRAD_MODEL = "tomb-raider"
DEFAULT_TINYGRAD_MODEL_NAME = "Filet-O-Fish 👀📡" DEFAULT_TINYGRAD_MODEL_NAME = "Vikander 👀📡"
DEFAULT_TINYGRAD_MODEL_VERSION = "v8" DEFAULT_TINYGRAD_MODEL_VERSION = "v8"
EXCLUDED_KEYS = { EXCLUDED_KEYS = {
@@ -373,12 +373,16 @@ misc_tuning_levels: list[tuple[str, str | bytes, int]] = [
("WheelControls", "", 2) ("WheelControls", "", 2)
] ]
def scale_threshold(v_ego):
return 0.0 if v_ego > 31.3 else np.interp(v_ego, [0, 17.9, 26.8, 35.8, 44.7], [0.63, 0.63, 0.65, 0.95, 0.95])
class FrogPilotVariables: class FrogPilotVariables:
def __init__(self): def __init__(self):
self.frogpilot_toggles = get_frogpilot_toggles(block=False) self.frogpilot_toggles = get_frogpilot_toggles(block=False)
self.tuning_levels = {key: lvl for key, _, lvl in frogpilot_default_params + misc_tuning_levels} self.tuning_levels = {key: lvl for key, _, lvl in frogpilot_default_params + misc_tuning_levels}
self.short_branch = get_build_metadata().channel self.short_branch = "FrogPilot-Staging"
self.development_branch = self.short_branch == "FrogPilot-Development" self.development_branch = self.short_branch == "FrogPilot-Development"
self.release_branch = self.short_branch == "FrogPilot" self.release_branch = self.short_branch == "FrogPilot"
self.staging_branch = self.short_branch == "FrogPilot-Staging" self.staging_branch = self.short_branch == "FrogPilot-Staging"
@@ -388,7 +392,7 @@ class FrogPilotVariables:
self.frogpilot_toggles.frogs_go_moo = Path("/persist/frogsgomoo.py").is_file() self.frogpilot_toggles.frogs_go_moo = Path("/persist/frogsgomoo.py").is_file()
self.frogpilot_toggles.block_user = self.development_branch and not self.frogpilot_toggles.frogs_go_moo self.frogpilot_toggles.block_user = self.development_branch and not self.frogpilot_toggles.frogs_go_moo
self.not_vetted = Path("/data/openpilot/not_vetted").is_file() self.not_vetted = False
self.frogpilot_toggles.use_konik_server = params.get_bool("UseKonikServer") self.frogpilot_toggles.use_konik_server = params.get_bool("UseKonikServer")
self.frogpilot_toggles.use_konik_server |= self.not_vetted self.frogpilot_toggles.use_konik_server |= self.not_vetted
@@ -2,7 +2,7 @@
from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.common.realtime import DT_MDL from openpilot.common.realtime import DT_MDL
from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT, CRUISING_SPEED, THRESHOLD, params_memory from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT, CRUISING_SPEED, THRESHOLD, params_memory, scale_threshold
class ConditionalExperimentalMode: class ConditionalExperimentalMode:
def __init__(self, FrogPilotPlanner): def __init__(self, FrogPilotPlanner):
@@ -53,7 +53,7 @@ class ConditionalExperimentalMode:
self.status_value = 8 self.status_value = 8
return True return True
if frogpilot_toggles.conditional_lead and self.slow_lead_detected: if frogpilot_toggles.conditional_lead and self.slow_lead_detected and v_ego <= 29.1:
self.status_value = 9 if self.frogpilot_planner.lead_one.vLead < 1 else 10 self.status_value = 9 if self.frogpilot_planner.lead_one.vLead < 1 else 10
return True return True
@@ -69,7 +69,7 @@ class ConditionalExperimentalMode:
def update_conditions(self, frogpilotCarState, v_ego, frogpilot_toggles): def update_conditions(self, frogpilotCarState, v_ego, frogpilot_toggles):
self.curve_detection(v_ego, frogpilot_toggles) self.curve_detection(v_ego, frogpilot_toggles)
self.slow_lead(frogpilot_toggles) self.slow_lead(frogpilot_toggles, v_ego)
self.stop_sign_and_light(frogpilotCarState, v_ego, frogpilot_toggles) self.stop_sign_and_light(frogpilotCarState, v_ego, frogpilot_toggles)
def curve_detection(self, v_ego, frogpilot_toggles): def curve_detection(self, v_ego, frogpilot_toggles):
@@ -78,13 +78,14 @@ class ConditionalExperimentalMode:
self.curvature_filter.update(self.frogpilot_planner.road_curvature_detected or curve_active) self.curvature_filter.update(self.frogpilot_planner.road_curvature_detected or curve_active)
self.curve_detected = self.curvature_filter.x >= THRESHOLD and v_ego > CRUISING_SPEED self.curve_detected = self.curvature_filter.x >= THRESHOLD and v_ego > CRUISING_SPEED
def slow_lead(self, frogpilot_toggles): def slow_lead(self, frogpilot_toggles, v_ego):
v_lead = self.frogpilot_planner.lead_one.vLead
if self.frogpilot_planner.tracking_lead: if self.frogpilot_planner.tracking_lead:
slower_lead = frogpilot_toggles.conditional_slower_lead and self.frogpilot_planner.frogpilot_following.slower_lead slower_lead = frogpilot_toggles.conditional_slower_lead and self.frogpilot_planner.frogpilot_following.slower_lead
stopped_lead = frogpilot_toggles.conditional_stopped_lead and self.frogpilot_planner.lead_one.vLead < 1 stopped_lead = frogpilot_toggles.conditional_stopped_lead and v_lead < 1
lead_threshold = scale_threshold(v_ego)
self.slow_lead_filter.update(slower_lead or stopped_lead) self.slow_lead_filter.update(slower_lead or stopped_lead)
self.slow_lead_detected = self.slow_lead_filter.x >= THRESHOLD self.slow_lead_detected = self.slow_lead_filter.x >= lead_threshold
else: else:
self.slow_lead_filter.x = 0 self.slow_lead_filter.x = 0
self.slow_lead_detected = False self.slow_lead_detected = False
@@ -1,6 +1,43 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import numpy as np import numpy as np
def cubic_interp(x, xp, fp):
"""Cubic interpolation using NumPy's native operations for speed."""
# Boundary conditions
if x <= xp[0]:
return fp[0]
elif x >= xp[-1]:
return fp[-1]
# Find interval
i = np.searchsorted(xp, x) - 1
i = max(0, min(i, len(xp)-2)) # clamp the index
# Normalized position
t = (x - xp[i]) / float(xp[i+1] - xp[i])
# Hermite cubic formula
return fp[i]*(1 - 3*t**2 + 2*t**3) + fp[i+1]*(3*t**2 - 2*t**3)
def akima_interp(x, xp, fp):
"""Akima-inspired interpolation with reduced overshoot characteristics."""
if x <= xp[0]:
return fp[0]
elif x >= xp[-1]:
return fp[-1]
i = np.searchsorted(xp, x) - 1
i = max(0, min(i, len(xp)-2)) # clamp the index
t = (x - xp[i]) / float(xp[i+1] - xp[i])
# Quintic polynomial to reduce overshoot
t2 = t*t
t4 = t2*t2
t3 = t2*t
return (fp[i]*(1 - 10*t3 + 15*t4 - 6*t3*t2)
+ fp[i+1]*(10*t3 - 15*t4 + 6*t3*t2))
from openpilot.selfdrive.controls.lib.longitudinal_planner import A_CRUISE_MIN, get_max_accel from openpilot.selfdrive.controls.lib.longitudinal_planner import A_CRUISE_MIN, get_max_accel
from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT from openpilot.frogpilot.common.frogpilot_variables import CITY_SPEED_LIMIT
@@ -11,26 +48,26 @@ A_CRUISE_MIN_SPORT = A_CRUISE_MIN * 2
# MPH = [0.0, 11, 22, 34, 45, 56, 89] # MPH = [0.0, 11, 22, 34, 45, 56, 89]
A_CRUISE_MAX_BP_CUSTOM = [0.0, 5., 10., 15., 20., 25., 40.] A_CRUISE_MAX_BP_CUSTOM = [0.0, 5., 10., 15., 20., 25., 40.]
A_CRUISE_MAX_VALS_ECO = [2.0, 1.5, 1.0, 0.8, 0.6, 0.4, 0.2] A_CRUISE_MAX_VALS_ECO = [2.0, 1.5, 1.0, 0.8, 0.6, 0.4, 0.2]
A_CRUISE_MAX_VALS_SPORT = [3.0, 2.5, 2.0, 1.5, 1.0, 0.8, 0.6] A_CRUISE_MAX_VALS_SPORT = [1.5, 1.5, 1.25, 1.5, 1.5, 1.5, 2.0]
A_CRUISE_MAX_VALS_SPORT_PLUS = [4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0] A_CRUISE_MAX_VALS_SPORT_PLUS = [2.5, 2.5, 3.0, 2.5, 2.5, 2.5, 2.5]
def get_max_accel_eco(v_ego): def get_max_accel_eco(v_ego):
return float(np.interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_ECO)) return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_ECO))
def get_max_accel_sport(v_ego): def get_max_accel_sport(v_ego):
return float(np.interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT)) return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT))
def get_max_accel_sport_plus(v_ego): def get_max_accel_sport_plus(v_ego):
return float(np.interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT_PLUS)) return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT_PLUS))
def get_max_accel_low_speeds(max_accel, v_cruise): def get_max_accel_low_speeds(max_accel, v_cruise):
return float(np.interp(v_cruise, [0., CITY_SPEED_LIMIT / 2, CITY_SPEED_LIMIT], [max_accel / 4, max_accel / 2, max_accel])) return float(akima_interp(v_cruise, [0., CITY_SPEED_LIMIT / 2, CITY_SPEED_LIMIT], [max_accel / 4, max_accel / 2, max_accel]))
def get_max_accel_ramp_off(max_accel, v_cruise, v_ego): def get_max_accel_ramp_off(max_accel, v_cruise, v_ego):
return float(np.interp(v_cruise - v_ego, [0., 1., 5., 10.], [0., 0.5, 1.0, max_accel])) return float(akima_interp(v_cruise - v_ego, [0., 1., 5., 10.], [0., 0.5, 1.0, max_accel]))
def get_max_allowed_accel(v_ego): def get_max_allowed_accel(v_ego):
return float(np.interp(v_ego, [0., 5., 20.], [4.0, 4.0, 2.0])) # ISO 15622:2018 return float(akima_interp(v_ego, [0., 5., 20.], [4.0, 4.0, 2.0])) # ISO 15622:2018
class FrogPilotAcceleration: class FrogPilotAcceleration:
def __init__(self, FrogPilotPlanner): def __init__(self, FrogPilotPlanner):
Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 402 KiB

@@ -40,7 +40,7 @@
text-align: center; text-align: center;
} }
</style> </style>
<title>FrogPilot: {% block title %}{% endblock %}</title> <title>StarPilot: {% block title %}{% endblock %}</title>
</head> </head>
<body> <body>
<nav class="navbar navbar-fixed-top navbar-expand-sm navbar-dark bg-dark"> <nav class="navbar navbar-fixed-top navbar-expand-sm navbar-dark bg-dark">
+10 -9
View File
@@ -56,7 +56,7 @@ def fill_lane_line_meta(builder, lane_lines, lane_line_probs):
builder.rightProb = lane_line_probs[2] builder.rightProb = lane_line_probs[2]
def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._DynamicStructBuilder, def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._DynamicStructBuilder,
net_output_data: dict[str, np.ndarray], v_ego: float, delay: float, net_output_data: dict[str, np.ndarray], action: log.ModelDataV2.Action,
publish_state: PublishState, vipc_frame_id: int, vipc_frame_id_extra: int, publish_state: PublishState, vipc_frame_id: int, vipc_frame_id_extra: int,
frame_id: int, frame_drop: float, timestamp_eof: int, model_execution_time: float, frame_id: int, frame_drop: float, timestamp_eof: int, model_execution_time: float,
valid: bool) -> None: valid: bool) -> None:
@@ -71,7 +71,8 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D
driving_model_data.frameIdExtra = vipc_frame_id_extra driving_model_data.frameIdExtra = vipc_frame_id_extra
driving_model_data.frameDropPerc = frame_drop_perc driving_model_data.frameDropPerc = frame_drop_perc
driving_model_data.modelExecutionTime = model_execution_time driving_model_data.modelExecutionTime = model_execution_time
driving_model_data.action.desiredCurvature = float(net_output_data['desired_curvature'][0,0])
driving_model_data.action = action
modelV2 = extended_msg.modelV2 modelV2 = extended_msg.modelV2
modelV2.frameId = vipc_frame_id modelV2.frameId = vipc_frame_id
@@ -89,17 +90,17 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D
fill_xyzt(modelV2.orientationRate, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.ORIENTATION_RATE].T) fill_xyzt(modelV2.orientationRate, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.ORIENTATION_RATE].T)
# temporal pose # temporal pose
temporal_pose = modelV2.temporalPose #temporal_pose = modelV2.temporalPose
temporal_pose.trans = net_output_data['sim_pose'][0,:ModelConstants.POSE_WIDTH//2].tolist() #temporal_pose.trans = net_output_data['sim_pose'][0,:ModelConstants.POSE_WIDTH//2].tolist()
temporal_pose.transStd = net_output_data['sim_pose_stds'][0,:ModelConstants.POSE_WIDTH//2].tolist() #temporal_pose.transStd = net_output_data['sim_pose_stds'][0,:ModelConstants.POSE_WIDTH//2].tolist()
temporal_pose.rot = net_output_data['sim_pose'][0,ModelConstants.POSE_WIDTH//2:].tolist() #temporal_pose.rot = net_output_data['sim_pose'][0,ModelConstants.POSE_WIDTH//2:].tolist()
temporal_pose.rotStd = net_output_data['sim_pose_stds'][0,ModelConstants.POSE_WIDTH//2:].tolist() #temporal_pose.rotStd = net_output_data['sim_pose_stds'][0,ModelConstants.POSE_WIDTH//2:].tolist()
# poly path # poly path
fill_xyz_poly(driving_model_data.path, ModelConstants.POLY_PATH_DEGREE, *net_output_data['plan'][0,:,Plan.POSITION].T) fill_xyz_poly(driving_model_data.path, ModelConstants.POLY_PATH_DEGREE, *net_output_data['plan'][0,:,Plan.POSITION].T)
# lateral planning # action
modelV2.action.desiredCurvature = float(net_output_data['desired_curvature'][0,0]) modelV2.action = action
# times at X_IDXS of edges and lines aren't used # times at X_IDXS of edges and lines aren't used
LINE_T_IDXS: list[float] = [] LINE_T_IDXS: list[float] = []
@@ -88,6 +88,12 @@ class Parser:
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,)) self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,))
self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
self.parse_mdn('lead', outs, in_N=ModelConstants.LEAD_MHP_N, out_N=ModelConstants.LEAD_MHP_SELECTION,
out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH))
for k in ['lead_prob', 'lane_lines_prob']:
self.parse_binary_crossentropy(k, outs)
self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(ModelConstants.DESIRE_PRED_LEN,ModelConstants.DESIRE_PRED_WIDTH)) self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(ModelConstants.DESIRE_PRED_LEN,ModelConstants.DESIRE_PRED_WIDTH))
self.parse_binary_crossentropy('meta', outs) self.parse_binary_crossentropy('meta', outs)
return outs return outs
@@ -95,17 +101,10 @@ class Parser:
def parse_policy_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: def parse_policy_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION, self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION,
out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH)) out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH))
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
self.parse_mdn('sim_pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('lead', outs, in_N=ModelConstants.LEAD_MHP_N, out_N=ModelConstants.LEAD_MHP_SELECTION,
out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH))
if 'lat_planner_solution' in outs: if 'lat_planner_solution' in outs:
self.parse_mdn('lat_planner_solution', outs, in_N=0, out_N=0, out_shape=(ModelConstants.IDX_N,ModelConstants.LAT_PLANNER_SOLUTION_WIDTH)) self.parse_mdn('lat_planner_solution', outs, in_N=0, out_N=0, out_shape=(ModelConstants.IDX_N,ModelConstants.LAT_PLANNER_SOLUTION_WIDTH))
if 'desired_curvature' in outs: if 'desired_curvature' in outs:
self.parse_mdn('desired_curvature', outs, in_N=0, out_N=0, out_shape=(ModelConstants.DESIRED_CURV_WIDTH,)) self.parse_mdn('desired_curvature', outs, in_N=0, out_N=0, out_shape=(ModelConstants.DESIRED_CURV_WIDTH,))
for k in ['lead_prob', 'lane_lines_prob']:
self.parse_binary_crossentropy(k, outs)
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,)) self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,))
return outs return outs
+38 -6
View File
@@ -20,19 +20,21 @@ from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.common.realtime import config_realtime_process from openpilot.common.realtime import config_realtime_process, DT_MDL
from openpilot.common.transformations.camera import DEVICE_CAMERAS from openpilot.common.transformations.camera import DEVICE_CAMERAS
from openpilot.common.transformations.model import get_warp_matrix from openpilot.common.transformations.model import get_warp_matrix
from openpilot.system import sentry from openpilot.system import sentry
from openpilot.selfdrive.car.car_helpers import get_demo_car_params from openpilot.selfdrive.car.car_helpers import get_demo_car_params
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan_tomb_raider, smooth_value, get_curvature_from_plan
from openpilot.frogpilot.tinygrad_modeld.parse_model_outputs import Parser from openpilot.frogpilot.tinygrad_modeld.parse_model_outputs import Parser
from openpilot.frogpilot.tinygrad_modeld.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState from openpilot.frogpilot.tinygrad_modeld.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState
from openpilot.frogpilot.tinygrad_modeld.constants import ModelConstants from openpilot.frogpilot.tinygrad_modeld.constants import ModelConstants, Plan
from openpilot.frogpilot.tinygrad_modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext from openpilot.frogpilot.tinygrad_modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext
from openpilot.frogpilot.common.frogpilot_variables import get_frogpilot_toggles from openpilot.frogpilot.common.frogpilot_variables import get_frogpilot_toggles
PROCESS_NAME = "frogpilot.tinygrad_modeld.tinygrad_modeld" PROCESS_NAME = "frogpilot.tinygrad_modeld.tinygrad_modeld"
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
@@ -41,6 +43,30 @@ POLICY_PKL_PATH = Path(__file__).parent / 'models/driving_policy_tinygrad.pkl'
VISION_METADATA_PATH = Path(__file__).parent / 'models/driving_vision_metadata.pkl' VISION_METADATA_PATH = Path(__file__).parent / 'models/driving_vision_metadata.pkl'
POLICY_METADATA_PATH = Path(__file__).parent / 'models/driving_policy_metadata.pkl' POLICY_METADATA_PATH = Path(__file__).parent / 'models/driving_policy_metadata.pkl'
LAT_SMOOTH_SECONDS = 0.2
LONG_SMOOTH_SECONDS = 0.2
MIN_LAT_CONTROL_SPEED = 0.3
def get_action_from_model(model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action:
plan = model_output['plan'][0]
desired_accel, should_stop = get_accel_from_plan_tomb_raider(plan[:,Plan.VELOCITY][:,0],
plan[:,Plan.ACCELERATION][:,0],
ModelConstants.T_IDXS,
action_t=long_action_t)
desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, LONG_SMOOTH_SECONDS)
desired_curvature = model_output['desired_curvature'][0, 0]
if v_ego > MIN_LAT_CONTROL_SPEED:
desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, LAT_SMOOTH_SECONDS)
else:
desired_curvature = prev_action.desiredCurvature
return log.ModelDataV2.Action(desiredCurvature=float(desired_curvature),
desiredAcceleration=float(desired_accel),
shouldStop=bool(should_stop))
class FrameMeta: class FrameMeta:
frame_id: int = 0 frame_id: int = 0
timestamp_sof: int = 0 timestamp_sof: int = 0
@@ -148,7 +174,7 @@ class ModelState:
# TODO model only uses last value now # 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] = self.full_prev_desired_curv[0,1:]
self.full_prev_desired_curv[0,-1,:] = policy_outputs_dict['desired_curvature'][0, :] 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*self.full_prev_desired_curv[0, self.temporal_idxs]
combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict}
if SEND_RAW_PRED: if SEND_RAW_PRED:
@@ -223,7 +249,10 @@ def main(demo=False):
cloudlog.info("tinygrad_modeld got CarParams: %s", CP.carName) cloudlog.info("tinygrad_modeld got CarParams: %s", CP.carName)
# TODO this needs more thought, use .2s extra for now to estimate other delays # TODO this needs more thought, use .2s extra for now to estimate other delays
steer_delay = CP.steerActuatorDelay + .2 # TODO Move smooth seconds to action function
lat_delay = CP.steerActuatorDelay + .2 + LAT_SMOOTH_SECONDS
long_delay = CP.longitudinalActuatorDelay + LONG_SMOOTH_SECONDS
prev_action = log.ModelDataV2.Action()
DH = DesireHelper() DH = DesireHelper()
@@ -268,7 +297,7 @@ def main(demo=False):
is_rhd = sm["driverMonitoringState"].isRHD is_rhd = sm["driverMonitoringState"].isRHD
frame_id = sm["roadCameraState"].frameId frame_id = sm["roadCameraState"].frameId
v_ego = max(sm["carState"].vEgo, 0.) v_ego = max(sm["carState"].vEgo, 0.)
lateral_control_params = np.array([v_ego, steer_delay], dtype=np.float32) lateral_control_params = np.array([v_ego, lat_delay], dtype=np.float32)
if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']: if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']:
device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32) device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32)
dc = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))] dc = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))]
@@ -311,7 +340,10 @@ def main(demo=False):
modelv2_send = messaging.new_message('modelV2') modelv2_send = messaging.new_message('modelV2')
drivingdata_send = messaging.new_message('drivingModelData') drivingdata_send = messaging.new_message('drivingModelData')
posenet_send = messaging.new_message('cameraOdometry') posenet_send = messaging.new_message('cameraOdometry')
fill_model_msg(drivingdata_send, modelv2_send, model_output, v_ego, steer_delay,
action = get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego)
prev_action = action
fill_model_msg(drivingdata_send, modelv2_send, model_output, action,
publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id, publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id,
frame_drop_ratio, meta_main.timestamp_eof, model_execution_time, live_calib_seen) frame_drop_ratio, meta_main.timestamp_eof, model_execution_time, live_calib_seen)
+1
View File
@@ -1,5 +1,6 @@
#!/usr/bin/bash #!/usr/bin/bash
if [ -z "$BASEDIR" ]; then if [ -z "$BASEDIR" ]; then
BASEDIR="/data/openpilot" BASEDIR="/data/openpilot"
fi fi
+1 -1
View File
@@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1 export VECLIB_MAXIMUM_THREADS=1
if [ -z "$AGNOS_VERSION" ]; then if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="10.1" export AGNOS_VERSION="10.1.1"
fi fi
export STAGING_ROOT="/data/safe_staging" export STAGING_ROOT="/data/safe_staging"
+14 -3
View File
@@ -82,6 +82,12 @@ VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ;
BO_ 189 EBCMRegenPaddle: 7 K17_EBCM BO_ 189 EBCMRegenPaddle: 7 K17_EBCM
SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO
SG_ Byte1 : 8|8@1+ (1,0) [0|255] "" NEO
SG_ Byte2 : 16|8@1+ (1,0) [0|255] "" NEO
SG_ Byte3 : 24|8@1+ (1,0) [0|255] "" NEO
SG_ Byte4 : 32|8@1+ (1,0) [0|255] "" NEO
SG_ Byte5 : 40|8@1+ (1,0) [0|255] "" NEO
SG_ Byte6 : 48|8@1+ (1,0) [0|255] "" NEO
BO_ 190 ECMAcceleratorPos: 6 K20_ECM BO_ 190 ECMAcceleratorPos: 6 K20_ECM
SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO
@@ -192,10 +198,15 @@ BO_ 500 SportMode: 6 XXX
SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX
BO_ 501 ECMPRDNL2: 8 K20_ECM BO_ 501 ECMPRDNL2: 8 K20_ECM
SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO SG_ Byte0 : 0|8@1+ (1,0) [0|255] "" NEO
SG_ Byte1 : 8|8@1+ (1,0) [0|255] "" NEO
SG_ Byte2 : 16|8@1+ (1,0) [0|255] "" NEO
SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO
SG_ Byte4 : 32|8@1+ (1,0) [0|255] "" NEO
SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO
SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO
SG_ Byte7 : 56|8@1+ (1,0) [0|255] "" NEO
BO_ 532 BRAKE_RELATED: 6 XXX BO_ 532 BRAKE_RELATED: 6 XXX
SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX
@@ -370,6 +381,6 @@ VAL_ 715 GasRegenCmdActive 1 "Active" 0 "Inactive" ;
VAL_ 320 Intellibeam 1 "Active" 0 "Inactive" ; VAL_ 320 Intellibeam 1 "Active" 0 "Inactive" ;
VAL_ 320 HighBeamsActive 1 "Active" 0 "Inactive" ; VAL_ 320 HighBeamsActive 1 "Active" 0 "Inactive" ;
VAL_ 320 HighBeamsTemporary 1 "Active" 0 "Inactive" ; VAL_ 320 HighBeamsTemporary 1 "Active" 0 "Inactive" ;
VAL_ 501 PRNDL2 6 "L" 4 "D" 3 "N" 2 "R" 1 "P" 0 "Shifting"; VAL_ 501 PRNDL2 7 "L2" 6 "L" 5 "L3" 4 "D" 3 "N" 2 "R" 1 "P" 0 "Shifting";
VAL_ 501 TransmissionState 11 "Shifting" 10 "Reverse" 9 "Forward" 8 "Disengaged"; VAL_ 501 TransmissionState 11 "Shifting" 10 "Reverse" 9 "Forward" 8 "Disengaged";
VAL_ 501 ManualMode 1 "Active" 0 "Inactive" VAL_ 501 ManualMode 1 "Active" 0 "Inactive"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 418 KiB

+2 -1
View File
@@ -209,7 +209,8 @@ def get_car(logcan, sendcan, experimental_long_allowed, params, num_pandas=1, fr
CP.fingerprintSource = source CP.fingerprintSource = source
CP.fuzzyFingerprint = not exact_match CP.fuzzyFingerprint = not exact_match
return get_car_interface(CP, FPCP), CP, FPCP interface_instance = get_car_interface(CP, None)
return interface_instance, CP, FPCP
def write_car_param(platform=MOCK.MOCK): def write_car_param(platform=MOCK.MOCK):
params = Params() params = Params()
+7 -8
View File
@@ -57,17 +57,16 @@ class CarController(CarControllerBase):
self.accel_g = 0.0 self.accel_g = 0.0
@staticmethod @staticmethod
def calc_pedal_command(accel: float, long_active: bool) -> float: def calc_pedal_command(accel: float, long_active: bool, car_velocity) -> float:
if not long_active: return 0. if not long_active: return 0.
zero = 0.15625 # 40/256 if accel < -0.5:
if accel > 0.: pedal_gas = 0
# Scales the accel from 0-1 to 0.156-1
pedal_gas = clip(((1 - zero) * accel + zero), 0., 1.)
else: else:
# if accel is negative, -0.1 -> 0.015625
pedal_gas = clip(zero + accel, 0., zero) # Make brake the same size as gas, but clip to regen
pedaloffset = interp(car_velocity, [0., 3, 6, 30], [0.10, 0.175, 0.240, 0.240])
pedal_gas = clip((pedaloffset + accel * 0.6), 0.0, 1.0)
return pedal_gas return pedal_gas
@@ -160,7 +159,7 @@ class CarController(CarControllerBase):
self.apply_gas = self.params.INACTIVE_REGEN self.apply_gas = self.params.INACTIVE_REGEN
if self.CP.carFingerprint in CC_ONLY_CAR: if self.CP.carFingerprint in CC_ONLY_CAR:
# gas interceptor only used for full long control on cars without ACC # gas interceptor only used for full long control on cars without ACC
interceptor_gas_cmd = self.calc_pedal_command(actuators.accel, CC.longActive) interceptor_gas_cmd = self.calc_pedal_command(actuators.accel, CC.longActive, CS.out.vEgo)
if self.CP.enableGasInterceptor and self.apply_gas > self.params.INACTIVE_REGEN and CS.out.cruiseState.standstill: if self.CP.enableGasInterceptor and self.apply_gas > self.params.INACTIVE_REGEN and CS.out.cruiseState.standstill:
# "Tap" the accelerator pedal to re-engage ACC # "Tap" the accelerator pedal to re-engage ACC
+7 -2
View File
@@ -92,11 +92,16 @@ class CarState(CarStateBase):
# Regen braking is braking # Regen braking is braking
if self.CP.transmissionType == TransmissionType.direct: if self.CP.transmissionType == TransmissionType.direct:
ret.regenBraking = pt_cp.vl["EBCMRegenPaddle"]["RegenPaddle"] != 0 ret.regenBraking = pt_cp.vl["EBCMRegenPaddle"]["RegenPaddle"] != 0
self.single_pedal_mode = ret.gearShifter == GearShifter.low or pt_cp.vl["EVDriveMode"]["SinglePedalModeActive"] == 1 or (ret.regenBraking and GearShifter.manumatic) self.single_pedal_mode = (
ret.gearShifter == GearShifter.low
or pt_cp.vl["EVDriveMode"]["SinglePedalModeActive"] == 1
or pt_cp.vl["ECMPRDNL2"]["TransmissionState"] == 21
or (ret.regenBraking and GearShifter.manumatic)
)
if self.CP.enableGasInterceptor: if self.CP.enableGasInterceptor:
ret.gas = (pt_cp.vl["GAS_SENSOR"]["INTERCEPTOR_GAS"] + pt_cp.vl["GAS_SENSOR"]["INTERCEPTOR_GAS2"]) / 2. ret.gas = (pt_cp.vl["GAS_SENSOR"]["INTERCEPTOR_GAS"] + pt_cp.vl["GAS_SENSOR"]["INTERCEPTOR_GAS2"]) / 2.
threshold = 10 if self.CP.carFingerprint in CAMERA_ACC_CAR else 4 # Panda 515 threshold = 10.88. Set lower to avoid panda blocking messages and GasInterceptor faulting. threshold = 12 if self.CP.carFingerprint in CAMERA_ACC_CAR else 4 # Panda 515 threshold = 10.88. Set lower to avoid panda blocking messages and GasInterceptor faulting.
ret.gasPressed = ret.gas > threshold ret.gasPressed = ret.gas > threshold
else: else:
ret.gas = pt_cp.vl["AcceleratorPedal2"]["AcceleratorPedal2"] / 254. ret.gas = pt_cp.vl["AcceleratorPedal2"]["AcceleratorPedal2"] / 254.
+27 -29
View File
@@ -29,8 +29,8 @@ CAM_MSG = 0x320 # AEBCmd
ACCELERATOR_POS_MSG = 0xbe ACCELERATOR_POS_MSG = 0xbe
NON_LINEAR_TORQUE_PARAMS = { NON_LINEAR_TORQUE_PARAMS = {
CAR.CHEVROLET_BOLT_EUV: [2.6531724862969748, 1.0, 0.1919764879840985, 0.009054123646805178], CAR.CHEVROLET_BOLT_EUV: [1.8, 1.1, 0.290, -0.045],
CAR.CHEVROLET_BOLT_CC: [2.6531724862969748, 1.0, 0.1919764879840985, 0.009054123646805178], CAR.CHEVROLET_BOLT_CC: [1.8, 1.1, 0.290, -0.045],
CAR.GMC_ACADIA: [4.78003305, 1.0, 0.3122, 0.05591772], CAR.GMC_ACADIA: [4.78003305, 1.0, 0.3122, 0.05591772],
CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122] CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122]
} }
@@ -74,8 +74,8 @@ class CarInterface(CarInterfaceBase):
# ToDo: To generalize to other GMs, explore tanh function as the nonlinear # ToDo: To generalize to other GMs, explore tanh function as the nonlinear
non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint) non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint)
assert non_linear_torque_params, "The params are not defined" assert non_linear_torque_params, "The params are not defined"
a, b, c, _ = non_linear_torque_params a, b, c, d = non_linear_torque_params
steer_torque = (sig(latcontrol_inputs.lateral_acceleration * a) * b) + (latcontrol_inputs.lateral_acceleration * c) steer_torque = (sig(latcontrol_inputs.lateral_acceleration * a) * b) + (latcontrol_inputs.lateral_acceleration * c) + d
return float(steer_torque) + friction return float(steer_torque) + friction
def torque_from_lateral_accel_neural(self, latcontrol_inputs: LatControlInputs, torque_params: car.CarParams.LateralTorqueTuning, lateral_accel_error: float, def torque_from_lateral_accel_neural(self, latcontrol_inputs: LatControlInputs, torque_params: car.CarParams.LateralTorqueTuning, lateral_accel_error: float,
@@ -87,13 +87,7 @@ class CarInterface(CarInterfaceBase):
return float(self.neural_ff_model.predict(inputs)) + friction return float(self.neural_ff_model.predict(inputs)) + friction
def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType: def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType:
if self.CP.carFingerprint in (CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_BOLT_CC):
self.neural_ff_model = NanoFFModel(NEURAL_PARAMS_PATH, self.CP.carFingerprint)
return self.torque_from_lateral_accel_neural
elif self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
return self.torque_from_lateral_accel_siglin return self.torque_from_lateral_accel_siglin
else:
return self.torque_from_lateral_accel_linear
@staticmethod @staticmethod
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs, frogpilot_toggles): def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs, frogpilot_toggles):
@@ -104,13 +98,15 @@ class CarInterface(CarInterfaceBase):
if PEDAL_MSG in fingerprint[0]: if PEDAL_MSG in fingerprint[0]:
ret.enableGasInterceptor = True ret.enableGasInterceptor = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_GAS_INTERCEPTOR
# When a pedal interceptor is present, always use normal longitudinal (block stock cruise)
experimental_long = False
if candidate in EV_CAR: if candidate in EV_CAR:
ret.transmissionType = TransmissionType.direct ret.transmissionType = TransmissionType.direct
else: else:
ret.transmissionType = TransmissionType.automatic ret.transmissionType = TransmissionType.automatic
ret.longitudinalTuning.kiBP = [5., 35.] ret.longitudinalTuning.kiBP = [5., 35., 60.]
if candidate in CAMERA_ACC_CAR: if candidate in CAMERA_ACC_CAR:
ret.experimentalLongitudinalAvailable = candidate not in CC_ONLY_CAR ret.experimentalLongitudinalAvailable = candidate not in CC_ONLY_CAR
@@ -122,13 +118,14 @@ class CarInterface(CarInterfaceBase):
ret.minSteerSpeed = 10 * CV.KPH_TO_MS ret.minSteerSpeed = 10 * CV.KPH_TO_MS
# Tuning for experimental long # Tuning for experimental long
ret.longitudinalTuning.kiV = [2.0, 1.5] ret.longitudinalTuning.kiV = [0.5, 0.5, 0.5]
ret.vEgoStopping = 0.1 ret.vEgoStopping = 0.1
ret.vEgoStarting = 0.1 ret.vEgoStarting = 0.1
ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling ret.stoppingDecelRate = 1.0 # reach brake quickly after enabling
ret.vEgoStopping = 0.25 ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25 ret.vEgoStarting = 0.25
ret.stopAccel = -0.25
if experimental_long: if experimental_long:
ret.pcmCruise = False ret.pcmCruise = False
@@ -136,7 +133,7 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
elif candidate in SDGM_CAR: elif candidate in SDGM_CAR:
ret.longitudinalTuning.kiV = [0., 0.] # TODO: tuning ret.longitudinalTuning.kiV = [0., 0., 0.] # TODO: tuning
ret.experimentalLongitudinalAvailable = False ret.experimentalLongitudinalAvailable = False
ret.networkLocation = NetworkLocation.fwdCamera ret.networkLocation = NetworkLocation.fwdCamera
ret.pcmCruise = True ret.pcmCruise = True
@@ -155,7 +152,7 @@ class CarInterface(CarInterfaceBase):
ret.minSteerSpeed = 7 * CV.MPH_TO_MS ret.minSteerSpeed = 7 * CV.MPH_TO_MS
# Tuning # Tuning
ret.longitudinalTuning.kiV = [2.4, 1.5] ret.longitudinalTuning.kiV = [0.5, 0.5, 0.5]
if ret.enableGasInterceptor: if ret.enableGasInterceptor:
# Need to set ASCM long limits when using pedal interceptor, instead of camera ACC long limits # Need to set ASCM long limits when using pedal interceptor, instead of camera ACC long limits
@@ -206,6 +203,7 @@ class CarInterface(CarInterfaceBase):
elif candidate in (CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_BOLT_CC): elif candidate in (CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_BOLT_CC):
ret.steerActuatorDelay = 0.2 ret.steerActuatorDelay = 0.2
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
ret.lateralTuning.torque.kp = 0.6
if ret.enableGasInterceptor: if ret.enableGasInterceptor:
# ACC Bolts use pedal for full longitudinal control, not just sng # ACC Bolts use pedal for full longitudinal control, not just sng
@@ -271,13 +269,13 @@ class CarInterface(CarInterfaceBase):
ret.stoppingControl = True ret.stoppingControl = True
ret.autoResumeSng = True ret.autoResumeSng = True
if candidate in CC_ONLY_CAR: if candidate in CC_ONLY_CAR: #pedal interceptor tuning
ret.flags |= GMFlags.PEDAL_LONG.value ret.flags |= GMFlags.PEDAL_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_PEDAL_LONG ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_PEDAL_LONG
# Note: Low speed, stop and go not tested. Should be fairly smooth on highway # Note: Low speed, stop and go not tested. Should be fairly smooth on highway
ret.longitudinalTuning.kiBP = [0.0, 5., 35.] ret.longitudinalTuning.kiBP = [0., 3., 6., 35.]
ret.longitudinalTuning.kiV = [0.0, 0.35, 0.5] ret.longitudinalTuning.kiV = [0.125, 0.175, 0.225, 0.33]
ret.longitudinalTuning.kf = 0.15 ret.longitudinalTuning.kf = 0.25
ret.stoppingDecelRate = 0.8 ret.stoppingDecelRate = 0.8
else: # Pedal used for SNG, ACC for longitudinal control otherwise else: # Pedal used for SNG, ACC for longitudinal control otherwise
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
@@ -293,17 +291,17 @@ class CarInterface(CarInterfaceBase):
ret.minEnableSpeed = 24 * CV.MPH_TO_MS ret.minEnableSpeed = 24 * CV.MPH_TO_MS
ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long ret.openpilotLongitudinalControl = not frogpilot_toggles.disable_openpilot_long
ret.pcmCruise = False ret.pcmCruise = False
experimental_long = False
ret.stoppingDecelRate = 11.18 # == 25 mph/s (.04 rate) if not ret.enableGasInterceptor and candidate in CC_ONLY_CAR: #redneck tuning
ret.longitudinalTuning.kpBP = [10.7, 10.8, 28.] # 10.7 m/s == 24 mph
ret.longitudinalTuning.deadzoneBP = [0.] ret.longitudinalTuning.kpV = [0., 20., 20.] # set lower end to 0 since we can't drive below that speed
ret.longitudinalTuning.deadzoneV = [0.56] # == 2 km/h/s, 1.25 mph/s ret.longitudinalTuning.deadzoneBP = [0.]
ret.longitudinalActuatorDelay = 1. # TODO: measure this ret.longitudinalTuning.deadzoneV = [0.56] # == 2 km/h/s, 1.25 mph/s
ret.longitudinalActuatorDelay = 1. # TODO: measure this
ret.longitudinalTuning.kpBP = [10.7, 10.8, 28.] # 10.7 m/s == 24 mph ret.longitudinalTuning.kiBP = [0.]
ret.longitudinalTuning.kpV = [0., 20., 20.] # set lower end to 0 since we can't drive below that speed ret.longitudinalTuning.kiV = [0.1]
ret.longitudinalTuning.kiBP = [0.] ret.stoppingDecelRate = 11.18 # == 25 mph/s (.04 rate)
ret.longitudinalTuning.kiV = [0.1]
if candidate in CC_ONLY_CAR: if candidate in CC_ONLY_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC
+5 -5
View File
@@ -205,15 +205,15 @@ class CAR(Platforms):
CHEVROLET_SUBURBAN.specs, CHEVROLET_SUBURBAN.specs,
) )
GMC_YUKON_CC = GMPlatformConfig( GMC_YUKON_CC = GMPlatformConfig(
[GMCarDocs("GMC Yukon - No-ACC")], [GMCarDocs("GMC Yukon No ACC")],
CarSpecs(mass=2541, wheelbase=2.95, steerRatio=16.3, centerToFrontRatio=0.4), CarSpecs(mass=2541, wheelbase=2.95, steerRatio=16.3, centerToFrontRatio=0.4),
) )
CADILLAC_CT6_CC = GMPlatformConfig( CADILLAC_CT6_CC = GMPlatformConfig(
[GMCarDocs("Cadillac CT6 - No-ACC")], [GMCarDocs("Cadillac CT6 No ACC")],
CarSpecs(mass=2358, wheelbase=3.11, steerRatio=17.7, centerToFrontRatio=0.4), CarSpecs(mass=2358, wheelbase=3.11, steerRatio=17.7, centerToFrontRatio=0.4),
) )
CHEVROLET_TRAILBLAZER_CC = GMPlatformConfig( CHEVROLET_TRAILBLAZER_CC = GMPlatformConfig(
[GMCarDocs("Chevrolet Trailblazer 2021-22 - No-ACC")], [GMCarDocs("Chevrolet Trailblazer 2021-22")],
CHEVROLET_TRAILBLAZER.specs, CHEVROLET_TRAILBLAZER.specs,
) )
CADILLAC_XT4 = GMPlatformConfig( CADILLAC_XT4 = GMPlatformConfig(
@@ -221,7 +221,7 @@ class CAR(Platforms):
CarSpecs(mass=1660, wheelbase=2.78, steerRatio=14.4, centerToFrontRatio=0.4), CarSpecs(mass=1660, wheelbase=2.78, steerRatio=14.4, centerToFrontRatio=0.4),
) )
CADILLAC_XT5_CC = GMPlatformConfig( CADILLAC_XT5_CC = GMPlatformConfig(
[GMCarDocs("Cadillac XT5 - No-ACC")], [GMCarDocs("Cadillac XT5 No ACC")],
CarSpecs(mass=1810, wheelbase=2.86, steerRatio=16.34, centerToFrontRatio=0.5), CarSpecs(mass=1810, wheelbase=2.86, steerRatio=16.34, centerToFrontRatio=0.5),
) )
CHEVROLET_TRAVERSE = GMPlatformConfig( CHEVROLET_TRAVERSE = GMPlatformConfig(
@@ -233,7 +233,7 @@ class CAR(Platforms):
CarSpecs(mass=2050, wheelbase=2.86, steerRatio=16.0, centerToFrontRatio=0.5), CarSpecs(mass=2050, wheelbase=2.86, steerRatio=16.0, centerToFrontRatio=0.5),
) )
CHEVROLET_MALIBU_CC = GMPlatformConfig( CHEVROLET_MALIBU_CC = GMPlatformConfig(
[GMCarDocs("Chevrolet Malibu 2023 - No-ACC")], [GMCarDocs("Chevrolet Malibu 2023 No ACC")],
CarSpecs(mass=1450, wheelbase=2.8, steerRatio=15.8, centerToFrontRatio=0.4), CarSpecs(mass=1450, wheelbase=2.8, steerRatio=15.8, centerToFrontRatio=0.4),
) )
CHEVROLET_TRAX = GMPlatformConfig( CHEVROLET_TRAX = GMPlatformConfig(
+5 -4
View File
@@ -218,9 +218,10 @@ class CarInterfaceBase(ABC):
self.silent_steer_warning = True self.silent_steer_warning = True
self.v_ego_cluster_seen = False self.v_ego_cluster_seen = False
self.CS = CarState(CP, FPCP) self.CS = CarState(CP, None)
self.cp = self.CS.get_can_parser(CP, FPCP) fp = FPCP if FPCP is not None else getattr(self, "FPCP", None)
self.cp_cam = self.CS.get_cam_can_parser(CP, FPCP) self.cp = self.CS.get_can_parser(CP, fp)
self.cp_cam = self.CS.get_cam_can_parser(CP, fp)
self.cp_adas = self.CS.get_adas_can_parser(CP) self.cp_adas = self.CS.get_adas_can_parser(CP)
self.cp_body = self.CS.get_body_can_parser(CP) self.cp_body = self.CS.get_body_can_parser(CP)
self.cp_loopback = self.CS.get_loopback_can_parser(CP) self.cp_loopback = self.CS.get_loopback_can_parser(CP)
@@ -411,7 +412,7 @@ class CarInterfaceBase(ABC):
tune.init('torque') tune.init('torque')
tune.torque.useSteeringAngle = use_steering_angle tune.torque.useSteeringAngle = use_steering_angle
tune.torque.kp = 1.0 tune.torque.kp = 0.6
tune.torque.kf = 1.0 tune.torque.kf = 1.0
tune.torque.ki = 0.1 tune.torque.ki = 0.1
tune.torque.friction = params['FRICTION'] tune.torque.friction = params['FRICTION']
+31 -1
View File
@@ -1,9 +1,10 @@
import math import math
import numpy as np
from cereal import car, log from cereal import car, log
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.common.numpy_fast import clip, interp from openpilot.common.numpy_fast import clip, interp
from openpilot.common.realtime import DT_CTRL from openpilot.common.realtime import DT_CTRL, DT_MDL
# WARNING: this value was determined based on the model's training distribution, # WARNING: this value was determined based on the model's training distribution,
# model predictions above this speed can be unpredictable # model predictions above this speed can be unpredictable
@@ -178,6 +179,9 @@ def apply_center_deadzone(error, deadzone):
def rate_limit(new_value, last_value, dw_step, up_step): def rate_limit(new_value, last_value, dw_step, up_step):
return clip(new_value, last_value + dw_step, last_value + up_step) return clip(new_value, last_value + dw_step, last_value + up_step)
def smooth_value(val, prev_val, tau, dt=DT_MDL):
alpha = 1 - np.exp(-dt/tau) if tau > 0 else 1
return alpha * val + (1 - alpha) * prev_val
def clip_curvature(v_ego, prev_curvature, new_curvature, planner_curves): def clip_curvature(v_ego, prev_curvature, new_curvature, planner_curves):
if planner_curves: if planner_curves:
@@ -208,3 +212,29 @@ def get_speed_error(modelV2: log.ModelDataV2, v_ego: float) -> float:
vel_err = clip(modelV2.temporalPose.trans[0] - v_ego, -MAX_VEL_ERR, MAX_VEL_ERR) vel_err = clip(modelV2.temporalPose.trans[0] - v_ego, -MAX_VEL_ERR, MAX_VEL_ERR)
return float(vel_err) return float(vel_err)
return 0.0 return 0.0
def get_accel_from_plan_tomb_raider(speeds, accels, t_idxs, action_t=DT_MDL, vEgoStopping=0.05):
if len(speeds) == len(t_idxs):
v_now = speeds[0]
a_now = accels[0]
v_target = np.interp(action_t, t_idxs, speeds)
a_target = 2 * (v_target - v_now) / (action_t) - a_now
v_target_1sec = np.interp(action_t + 1.0, t_idxs, speeds)
else:
v_target = 0.0
v_target_1sec = 0.0
a_target = 0.0
should_stop = (v_target < vEgoStopping and
v_target_1sec < vEgoStopping)
return a_target, should_stop
def curv_from_psis(psi_target, psi_rate, vego, action_t):
vego = np.clip(vego, MIN_SPEED, np.inf)
curv_from_psi = psi_target / (vego * action_t)
return 2*curv_from_psi - psi_rate / vego
def get_curvature_from_plan(yaws, yaw_rates, t_idxs, vego, action_t):
psi_target = np.interp(action_t, t_idxs, yaws)
psi_rate = yaw_rates[0]
return curv_from_psis(psi_target, psi_rate, vego, action_t)
+48 -4
View File
@@ -4,6 +4,8 @@ from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_deadzone from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_deadzone
from openpilot.selfdrive.controls.lib.pid import PIDController from openpilot.selfdrive.controls.lib.pid import PIDController
from openpilot.selfdrive.modeld.constants import ModelConstants from openpilot.selfdrive.modeld.constants import ModelConstants
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.car.gm.values import CarControllerParams
CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
@@ -85,17 +87,48 @@ def long_control_state_trans_old_long(CP, active, long_control_state, v_ego, v_t
return long_control_state return long_control_state
class LongControl: class LongControl:
def __init__(self, CP): def __init__(self, CP):
self.CP = CP self.CP = CP
self.long_control_state = LongCtrlState.off self.long_control_state = LongCtrlState.off
self.experimental_mode = False
self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV),
(CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV),
k_f=CP.longitudinalTuning.kf, rate=1 / DT_CTRL) k_f=CP.longitudinalTuning.kf, rate=1 / DT_CTRL,
pos_p_limit=None)
self.v_pid = 0.0 self.v_pid = 0.0
self._mode_setup()
self.last_output_accel = 0.0 self.last_output_accel = 0.0
def update_mpc_mode(self, experimental_mode):
new_mode = 'blended' if experimental_mode else 'acc'
if self.transitioning and self.prev_mode == 'blended' and self.current_mode == 'acc':
self.mode_transition_timer = 0.0
if new_mode != self.current_mode:
self.prev_mode = self.current_mode
self.transitioning = True
self.mode_transition_timer = 0.0
self.mode_transition_filter.x = self.last_output_accel
self.current_mode = new_mode
if self.transitioning:
self.mode_transition_timer += DT_CTRL
if self.mode_transition_timer >= self.mode_transition_duration:
self.transitioning = False
def _mode_setup(self):
self.prev_mode = 'acc'
self.current_mode = 'acc'
self.mode_transition_filter = FirstOrderFilter(0.0, 0.5, DT_CTRL)
self.mode_transition_timer = 0.0
self.mode_transition_duration = 1.0
self.transitioning = False
def reset(self): def reset(self):
self.pid.reset() self.pid.reset()
@@ -124,8 +157,19 @@ class LongControl:
else: # LongCtrlState.pid else: # LongCtrlState.pid
error = a_target - CS.aEgo error = a_target - CS.aEgo
output_accel = self.pid.update(error, speed=CS.vEgo, self.update_mpc_mode(self.experimental_mode)
feedforward=a_target) raw_output_accel = self.pid.update(error, speed=CS.vEgo, feedforward=a_target)
if self.transitioning and self.prev_mode == 'acc' and self.current_mode == 'blended':
if raw_output_accel < 0 and raw_output_accel < self.last_output_accel:
progress = min(1.0, self.mode_transition_timer / self.mode_transition_duration)
blend_factor = 1.0 - (1.0 - progress) * (1.0 - abs(raw_output_accel / CarControllerParams.ACCEL_MIN))
output_accel = self.last_output_accel + (raw_output_accel - self.last_output_accel) * blend_factor
else:
output_accel = raw_output_accel
else:
output_accel = raw_output_accel
self.last_output_accel = clip(output_accel, accel_limits[0], accel_limits[1]) self.last_output_accel = clip(output_accel, accel_limits[0], accel_limits[1])
return self.last_output_accel return self.last_output_accel
+23 -6
View File
@@ -13,7 +13,7 @@ from openpilot.selfdrive.car.interfaces import ACCEL_MIN, ACCEL_MAX
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState
from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import LongitudinalMpc from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import LongitudinalMpc
from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import T_IDXS as T_IDXS_MPC, LEAD_ACCEL_TAU from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import T_IDXS as T_IDXS_MPC, LEAD_ACCEL_TAU
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, CONTROL_N, get_speed_error from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, CONTROL_N, get_speed_error, get_accel_from_plan_tomb_raider
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
LON_MPC_STEP = 0.2 # first step is 0.2s LON_MPC_STEP = 0.2 # first step is 0.2s
@@ -203,8 +203,12 @@ class LongitudinalPlanner:
throttle_prob = 1.0 throttle_prob = 1.0
return x, v, a, j, throttle_prob return x, v, a, j, throttle_prob
def update(self, radarless_model, sm, frogpilot_toggles): def update(self, radarless_model, tomb_raider, sm, frogpilot_toggles):
self.mpc.mode = 'blended' if sm['controlsState'].experimentalMode else 'acc' if tomb_raider:
self.mpc.mode = 'acc'
self.mode = 'blended' if sm['controlsState'].experimentalMode else 'acc'
else:
self.mpc.mode = 'blended' if sm['controlsState'].experimentalMode else 'acc'
if len(sm['carControl'].orientationNED) == 3: if len(sm['carControl'].orientationNED) == 3:
accel_coast = get_coast_accel(sm['carControl'].orientationNED[1]) accel_coast = get_coast_accel(sm['carControl'].orientationNED[1])
@@ -294,7 +298,7 @@ class LongitudinalPlanner:
self.a_desired = float(interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory)) self.a_desired = float(interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory))
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0 self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
def publish(self, classic_model, sm, pm, frogpilot_toggles): def publish(self, classic_model, tomb_raider, sm, pm, frogpilot_toggles):
plan_send = messaging.new_message('longitudinalPlan') plan_send = messaging.new_message('longitudinalPlan')
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState']) plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState'])
@@ -314,12 +318,25 @@ class LongitudinalPlanner:
if classic_model: if classic_model:
a_target, should_stop = get_accel_from_plan_classic(self.CP, longitudinalPlan.speeds, longitudinalPlan.accels, vEgoStopping=frogpilot_toggles.vEgoStopping) a_target, should_stop = get_accel_from_plan_classic(self.CP, longitudinalPlan.speeds, longitudinalPlan.accels, vEgoStopping=frogpilot_toggles.vEgoStopping)
elif tomb_raider:
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
output_a_target_mpc, output_should_stop_mpc = get_accel_from_plan_tomb_raider(self.v_desired_trajectory, self.a_desired_trajectory, CONTROL_N_T_IDX,
action_t=action_t, vEgoStopping=frogpilot_toggles.vEgoStopping)
output_a_target_e2e = sm['modelV2'].action.desiredAcceleration
output_should_stop_e2e = sm['modelV2'].action.shouldStop
if self.mode == 'acc':
a_target = output_a_target_mpc
should_stop = output_should_stop_mpc
else:
a_target = min(output_a_target_mpc, output_a_target_e2e)
should_stop = output_should_stop_e2e or output_should_stop_mpc
else: else:
action_t = self.CP.longitudinalActuatorDelay + DT_MDL action_t = self.CP.longitudinalActuatorDelay + DT_MDL
a_target, should_stop = get_accel_from_plan(longitudinalPlan.speeds, longitudinalPlan.accels, a_target, should_stop = get_accel_from_plan(longitudinalPlan.speeds, longitudinalPlan.accels,
action_t=action_t, vEgoStopping=frogpilot_toggles.vEgoStopping) action_t=action_t, vEgoStopping=frogpilot_toggles.vEgoStopping)
longitudinalPlan.aTarget = a_target longitudinalPlan.aTarget = float(a_target)
longitudinalPlan.shouldStop = should_stop longitudinalPlan.shouldStop = bool(should_stop)
longitudinalPlan.allowBrake = True longitudinalPlan.allowBrake = True
longitudinalPlan.allowThrottle = self.allow_throttle longitudinalPlan.allowThrottle = self.allow_throttle
+10 -1
View File
@@ -5,7 +5,9 @@ from openpilot.common.numpy_fast import clip, interp
class PIDController: class PIDController:
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100): def __init__(self, k_p, k_i, k_f=0., k_d=0.,
pos_limit=1e308, neg_limit=-1e308, rate=100,
pos_p_limit=None, neg_p_limit=None):
self._k_p = k_p self._k_p = k_p
self._k_i = k_i self._k_i = k_i
self._k_d = k_d self._k_d = k_d
@@ -20,6 +22,9 @@ class PIDController:
self.pos_limit = pos_limit self.pos_limit = pos_limit
self.neg_limit = neg_limit self.neg_limit = neg_limit
self.pos_p_limit = pos_p_limit
self.neg_p_limit = neg_p_limit
self.i_unwind_rate = 0.3 / rate self.i_unwind_rate = 0.3 / rate
self.i_rate = 1.0 / rate self.i_rate = 1.0 / rate
self.speed = 0.0 self.speed = 0.0
@@ -53,6 +58,10 @@ class PIDController:
self.speed = speed self.speed = speed
self.p = float(error) * self.k_p self.p = float(error) * self.k_p
if self.pos_p_limit is not None and self.p > self.pos_p_limit:
self.p = self.pos_p_limit
elif self.neg_p_limit is not None and self.p < self.neg_p_limit:
self.p = self.neg_p_limit
self.f = feedforward * self.k_f self.f = feedforward * self.k_f
self.d = error_rate * self.k_d self.d = error_rate * self.k_d
+3 -2
View File
@@ -39,12 +39,13 @@ def plannerd_thread():
classic_model = frogpilot_toggles.classic_model classic_model = frogpilot_toggles.classic_model
radarless_model = frogpilot_toggles.radarless_model radarless_model = frogpilot_toggles.radarless_model
tomb_raider = frogpilot_toggles.model == "tomb-raider"
while True: while True:
sm.update() sm.update()
if sm.updated['modelV2']: if sm.updated['modelV2']:
longitudinal_planner.update(radarless_model, sm, frogpilot_toggles) longitudinal_planner.update(radarless_model, tomb_raider, sm, frogpilot_toggles)
longitudinal_planner.publish(classic_model, sm, pm, frogpilot_toggles) longitudinal_planner.publish(classic_model, tomb_raider, sm, pm, frogpilot_toggles)
publish_ui_plan(sm, pm, longitudinal_planner) publish_ui_plan(sm, pm, longitudinal_planner)
# Update FrogPilot parameters # Update FrogPilot parameters
+9 -7
View File
@@ -18,7 +18,7 @@ from openpilot.common.simple_kalman import KF1D
from openpilot.frogpilot.common.frogpilot_variables import get_frogpilot_toggles from openpilot.frogpilot.common.frogpilot_variables import get_frogpilot_toggles
# Default lead acceleration decay set to 50% at 1s # Default lead acceleration decay set to 50% at 1s
_LEAD_ACCEL_TAU = 1.5 _LEAD_ACCEL_TAU = 0.6
# radar tracks # radar tracks
SPEED, ACCEL = 0, 1 # Kalman filter states enum SPEED, ACCEL = 0, 1 # Kalman filter states enum
@@ -79,7 +79,7 @@ class Track:
# Learn if constant acceleration # Learn if constant acceleration
if abs(self.aLeadK) < 0.5: if abs(self.aLeadK) < 0.5:
self.aLeadTau.x = _LEAD_ACCEL_TAU self.aLeadTau.x = min(max(self.aLeadTau, 1e-2) * 1.1, _LEAD_ACCEL_TAU)
else: else:
self.aLeadTau.update(0.0) self.aLeadTau.update(0.0)
@@ -163,14 +163,16 @@ def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks
def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: float, model_v_ego: float): def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: float, model_v_ego: float):
lead_v_rel_pred = lead_msg.v[0] - model_v_ego prev_aLeadK = getattr(get_RadarState_from_vision, "prev_aLeadK", 0.0)
blended_aLeadK = 0.8 * float(lead_msg.a[0]) + 0.2 * prev_aLeadK
get_RadarState_from_vision.prev_aLeadK = blended_aLeadK
return { return {
"dRel": float(lead_msg.x[0] - RADAR_TO_CAMERA), "dRel": float(lead_msg.x[0] - RADAR_TO_CAMERA),
"yRel": float(-lead_msg.y[0]), "yRel": float(-lead_msg.y[0]),
"vRel": float(lead_v_rel_pred), "vRel": float(lead_msg.v[0] - model_v_ego),
"vLead": float(v_ego + lead_v_rel_pred), "vLead": float(v_ego + (lead_msg.v[0] - model_v_ego)),
"vLeadK": float(v_ego + lead_v_rel_pred), "vLeadK": float(v_ego + (lead_msg.v[0] - model_v_ego)),
"aLeadK": float(lead_msg.a[0]), "aLeadK": blended_aLeadK,
"aLeadTau": 0.3, "aLeadTau": 0.3,
"fcw": False, "fcw": False,
"modelProb": float(lead_msg.prob), "modelProb": float(lead_msg.prob),
BIN
View File
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 402 KiB

+16 -11
View File
@@ -1,13 +1,18 @@
[ [
{ {
"name": "boot", "name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-5674ea6767e7198cf1e7def3de66a57061f001ed76d43dc4b4f84de545c53c6f.img.xz", "url": "https://www.dropbox.com/scl/fi/z8gcamb7n78xqb515kfgq/boot.img.xz?rlkey=r2zxothb3pz0q9rtqysr1zhwv&st=f0acze3w&dl=1",
"hash": "5674ea6767e7198cf1e7def3de66a57061f001ed76d43dc4b4f84de545c53c6f", "hash": "b997aae3f1c93de82449ef7f23f30ff482b0978f3d0ac08219366f9ce362ad7a",
"hash_raw": "5674ea6767e7198cf1e7def3de66a57061f001ed76d43dc4b4f84de545c53c6f", "hash_raw": "b997aae3f1c93de82449ef7f23f30ff482b0978f3d0ac08219366f9ce362ad7a",
"size": 16029696, "size": 16029696,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true "has_ab": true,
"alt": {
"hash": "5674ea6767e7198cf1e7def3de66a57061f001ed76d43dc4b4f84de545c53c6f",
"url": "https://commadist.azureedge.net/agnosupdate/boot-5674ea6767e7198cf1e7def3de66a57061f001ed76d43dc4b4f84de545c53c6f.img.xz",
"size": 16029696
}
}, },
{ {
"name": "abl", "name": "abl",
@@ -61,17 +66,17 @@
}, },
{ {
"name": "system", "name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-1badfe72851628d6cf9200a53a6151bb4e797b49c717141409fc57138eae388a.img.xz", "url": "https://www.dropbox.com/scl/fi/n22f3eex1z52dbrhhxqry/system.img.xz?rlkey=yw4ult7s3sdm6b7d31hrm3zx8&st=of6m7zis&dl=1",
"hash": "328e90c62068222dfd98f71dd3f6251fcb962f082b49c6be66ab2699f5db6f4f", "hash": "be1c6bb9ee5e06779087b1b81e09b6df61d942566b0f8d4539c452179c661782",
"hash_raw": "1badfe72851628d6cf9200a53a6151bb4e797b49c717141409fc57138eae388a", "hash_raw": "a5f84e68d199466fda5c9aead760b90a4cd2d2ef9a418708b9794d95bb03ec5b",
"size": 10737418240, "size": 10737418240,
"sparse": true, "sparse": true,
"full_check": false, "full_check": false,
"has_ab": true, "has_ab": true,
"alt": { "alt": {
"hash": "bc11d2148f29862ee1326aca2af1cf6bbf5fed831e3f8f6b8f7a0f110dfe8d26", "hash": "328e90c62068222dfd98f71dd3f6251fcb962f082b49c6be66ab2699f5db6f4f",
"url": "https://commadist.azureedge.net/agnosupdate/system-skip-chunks-1badfe72851628d6cf9200a53a6151bb4e797b49c717141409fc57138eae388a.img.xz", "url": "https://commadist.azureedge.net/agnosupdate/system-1badfe72851628d6cf9200a53a6151bb4e797b49c717141409fc57138eae388a.img.xz",
"size": 4548070000 "size": 10737418240
} }
} }
] ]
+13 -7
View File
@@ -168,18 +168,24 @@ def extract_compressed_image(target_slot_number: int, partition: dict, cloudlog)
last_p = p last_p = p
print(f"Installing {partition['name']}: {p}", flush=True) print(f"Installing {partition['name']}: {p}", flush=True)
if raw_hash.hexdigest().lower() != partition['hash_raw'].lower(): written_size = out.tell()
raise Exception(f"Raw hash mismatch '{raw_hash.hexdigest().lower()}'") expected_size = partition['size']
actual_raw_hash = raw_hash.hexdigest().lower()
expected_raw_hash = partition['hash_raw'].lower()
actual_final_hash = downloader.sha256.hexdigest().lower()
expected_final_hash = partition['hash'].lower()
if downloader.sha256.hexdigest().lower() != partition['hash'].lower(): if actual_raw_hash != expected_raw_hash:
raise Exception("Uncompressed hash mismatch") raise Exception(f"Raw hash mismatch: got {actual_raw_hash}, expected {expected_raw_hash}")
if out.tell() != partition['size']: if actual_final_hash != expected_final_hash:
raise Exception("Uncompressed size mismatch") raise Exception(f"Uncompressed hash mismatch: got {actual_final_hash}, expected {expected_final_hash}")
if written_size != expected_size:
raise Exception(f"Uncompressed size mismatch: wrote {written_size} bytes, expected {expected_size} bytes")
os.sync() os.sync()
def extract_casync_image(target_slot_number: int, partition: dict, cloudlog): def extract_casync_image(target_slot_number: int, partition: dict, cloudlog):
path = get_partition_path(target_slot_number, partition) path = get_partition_path(target_slot_number, partition)
seed_path = path[:-1] + ('b' if path[-1] == 'a' else 'a') seed_path = path[:-1] + ('b' if path[-1] == 'a' else 'a')