Compare commits

..

46 Commits

Author SHA1 Message Date
Your Name
980f0aac00 wip 2024-07-05 16:30:39 -05:00
Your Name
0fc13d815d wip 2024-07-05 16:24:57 -05:00
Your Name
ac4d7efff1 wip 2024-07-05 16:21:43 -05:00
Your Name
a47fbb140d wip 2024-06-19 00:24:32 -05:00
Your Name
8225319314 wip 2024-06-17 18:34:32 -05:00
Your Name
3eca593af1 wip 2024-06-17 15:45:35 -05:00
Your Name
445138519d wip 2024-06-17 15:43:03 -05:00
Your Name
679a952f51 wip 2024-06-17 12:48:11 -05:00
Your Name
1b9097bc13 wip 2024-06-17 12:47:21 -05:00
Your Name
4c9c211f97 wip 2024-06-17 12:44:38 -05:00
Your Name
c94dc803dd wip 2024-06-17 12:40:02 -05:00
Your Name
33c59eadb3 wip 2024-06-17 12:39:24 -05:00
Your Name
92db8a5913 wip 2024-06-17 12:34:19 -05:00
Your Name
af3cacae53 wip 2024-06-17 12:33:20 -05:00
Your Name
ec7743c460 wip 2024-06-17 12:15:35 -05:00
Your Name
5e80ad8d05 wip 2024-06-17 12:14:25 -05:00
Your Name
a2cf02ea37 wip 2024-06-17 12:12:54 -05:00
Comma Device
75c91213a2 wip 2024-06-17 17:10:43 +00:00
Comma Device
7f182b7fae wip 2024-06-17 16:57:23 +00:00
Your Name
0c36ffdfde wip 2024-06-15 21:05:30 -05:00
Your Name
4702c22aa3 wip 2024-06-15 20:59:47 -05:00
Your Name
6ef4519798 wip 2024-06-15 20:49:08 -05:00
concordia
5e4c1e2427 wip 2024-06-15 20:45:56 -05:00
concordia
94581c908b wip 2024-06-15 20:40:09 -05:00
concordia
98d7133844 wip 2024-06-15 20:38:29 -05:00
concordia
3ae97fe0e5 wip 2024-06-15 20:33:14 -05:00
concordia
51561d3393 wip 2024-06-15 20:30:56 -05:00
concordia
be595765e4 wip 2024-06-15 20:28:00 -05:00
concordia
7bb4980119 wip 2024-06-15 20:25:53 -05:00
concordia
720c9ccbc8 wip 2024-06-15 20:20:54 -05:00
concordia
9dc2951e07 wip 2024-06-10 09:41:39 -05:00
concordia
7962409629 wip 2024-06-10 09:23:55 -05:00
Your Name
314e9b5d32 wip 2024-06-09 18:01:57 -05:00
Your Name
2c9e56a579 wip 2024-06-09 17:43:17 -05:00
Your Name
cee8330928 wip 2024-06-09 17:27:31 -05:00
Your Name
9172cb85ee wip 2024-06-09 17:23:37 -05:00
Your Name
ee0a308db6 wip 2024-06-09 17:19:09 -05:00
Your Name
32cbaa1049 wip 2024-06-09 17:17:02 -05:00
Your Name
5d58961187 wip 2024-06-09 17:09:24 -05:00
Your Name
6ee82f77f6 wip 2024-06-09 16:52:09 -05:00
Your Name
2e8654ba7f wip 2024-06-09 16:50:04 -05:00
Your Name
33afb79600 wip 2024-06-09 16:38:23 -05:00
Your Name
48c2f76109 wip 2024-06-09 16:37:35 -05:00
Your Name
00dd71abb2 wip 2024-06-09 16:17:44 -05:00
Your Name
763198bec1 wip 2024-06-09 16:09:02 -05:00
Your Name
a963ea0296 wip 2024-06-09 16:08:19 -05:00
28 changed files with 1532 additions and 296 deletions

View File

@@ -234,10 +234,15 @@ std::unordered_map<std::string, uint32_t> keys = {
{"CarCruiseDisplayActual", PERSISTENT},
{"CarSpeedLimit", PERSISTENT},
{"CarSpeedLimitWarning", PERSISTENT},
{"CarSpeedLimitLiteral", PERSISTENT},
{"SpeedLimitLatDesired", PERSISTENT},
{"SpeedLimitVTSC", PERSISTENT},
// {"SpeedLimitLatDesired", PERSISTENT},
// {"SpeedLimitVTSC", PERSISTENT},
{"CPTLkasButtonAction", PERSISTENT},
{"ScreenDisaplayMode", PERSISTENT},
{"RadarDist", PERSISTENT},
{"ModelDist", PERSISTENT},

1
openpilot/cereal Symbolic link
View File

@@ -0,0 +1 @@
../cereal/

View File

@@ -1,5 +1,214 @@
-----
- screen off on lkas
- speed limit change chirp on cruise
-----
- fix manager / error recording / restart service on fail
- fix gps tracking
- dashcam
- better turning logic
- new settings UI
- experimental mode
------------
- revert a bunch of debugging in canfd
- configure it so i can toggle experimental via lkas
- if experimental enabled, then transmit experimental speed settings
- but only if no lead car or not decelerating. got to think of a condition
where we reengage if the lead is going too slow and we need to let stock long decel
- implement speed limit controller as a simple Warning
- implement a simple resume from standstill hack
- flesh all this out and prepare for trip. we will make auto match speed a future problem.
- continue on other projects and bench this one.
- this whole thing kind of sucks if i cant transmit buttons. keep trying.
- maybe curise_button and not cruise_button_alt will work?
-----
Latest:
- fix hiding path if disabled
- fix suspend on override behavior - override doesnt happen on always on lateral. need alternative check.
- fix & test lane line narrow on lane change view
- the acc cancel does nothing.
- must simulate actual button presses.
- add radar dist, model dist, radar speed, model speed to debug hud
- add wheel touched, wheel override to hud
- fix always on lateral saying its on when actually fully engaged
Notes on speed limit override:
- we need to capture the original speed and feed it to vtsc and model whule we
are under speed adjustment
------
- fix lane lines
- fix always on lateral detection
- position override under 25 mph suspends assist
- output the three speeds
- test - if engaged, adjust the speed twoards experimental one unit every second
- disable onroad on parked, not car off
- test that lkas button crashes controlsd, it should
- test that lkas button creates an alert, it should
- hyundai clsc https://github.com/garrettpall/openpilot/commit/5528198aa73d3d017d16ec4ca38306b11e5da0a8
- get ui to work on its own using no video feed, custom ui state inputs
- dress up ui
- add debug elements to ui with a boolean at top of onroad.cc to enable/disable:
- curviture
- current speed limit
- current cruise speed
- current experimental mode speed
- current distance to lead based on radar
- current distance to lead based on model draw distance
- current speed of lead
- when changing lanes and lateral disabled, draw a narrow single 'line' down center
- of computed path, and don't show side lane boundaries
- make side lanes 10% wider and the disengage mode 10% brighter
- make 25% of side lanes 50% darker than base
- hello world alert triggered by lkas btn
- hello world bootstrap dashboard
- button stuff:
- read paddle left (for full nudgeless lane change + blinker, reset to drive)
- read paddle right ("")
- read current drive mode, reset paddle mode to drive
- write pause, res, accel, mode, drive
wishlist: read / write info switcher, hvac, windows
wishlist: allow lane assist (not lane keep) on disengage
test:
- disable all canbus
- set speed limit during stock long
OP -> Oscar
- oscar - global clearpilot state var
- oscar.cs - clearpilot car state (populated by op variables for cp.planner)
- oscar.ce - clearpilot car event queue (array that can be pushed to from car)
- oscar.ceh - event queue history (for debug)
- oscar.clog - error and console.log style one off messages to transmit to logs or watching consoles
Oscar -> OP
- oscar.ps - clearpilot planner state (data from cp)
- oscar.pe - clearpilot planner event (one time events from planner to be processed by openpilot)
- oscar.peh - planner event history (for debug)
- oscar.plog - retransmits clog as well as additional data for UI based log consoles
- oscar - clearpilot's planner - nodejs process that synchronizes state between all processes and makes decisions
- settings menu
- - branch selector - release, stage, dev. Stage is my personal release branch. Should always be able to easilly switch to stage while im in a development state.
- unfuck the directory structure. new structure:
-
-------
- make functions
--- get_curvature
--- get_wheel_angle
--- get_distance_to_left_lane
--- get_distance_to_right_lane
--- are hands on wheel
--- distance traveled for lane change
--- distance to lead
- put these on a debug.
- Design alternate settings webview
- get speed limit display working
- get calculated experimental speed display working
- get button press emulation working
- get experimental mode working
- get speed limit set working
- dev enable lateral on blinker but no wheel pressure or no wheel presence
- bluetooth dummy device
- Test if activation fix works for op long, submit to frog maintain
- (test) disable all turn signal output commands - they are causing issues
- test "create_acc_cancel" on canfd on cc engaged on boot
- Create clearpilot process. manages behaviors.
- experiment with reduced jerk values
- test toggle stop all canbus output
- check if acc_cancel events are being made on idle in stock long, if so, its a bug.
- Warn if significantly slower traffic
behaviors:
- getting head mode - turn off babysitter with an alert on the screen that it is off, suspend for 10 minutes
- in this mode it should be extra grouchy if a curve is detected, slowdown is detected, or lane lines are weak
- lane change wrong way reenable lateral
- blinker signal wheel angle minor enable lateral
- wheel angle sharp only engage lateral if over lane edge unless hands not on wheel
- no lateral on turn signal - only enforce if model curvature > 10 degrees, hands on wheel, or wheel override (maybe curve not necessary?)
- basic lane keep - nudge wheel slightly if over line and still going straight and hands on wheel
- debug mode activated bu lkas
- See where disk free is going with NCDU and add smarter log rotation
- Maybe this has logs where it could show what happened to frogpilot process?
- Test supress cruise icon on long paused
- increase center lane brightness 50% and make it blueish
- make drive mode color much brighter and 30% more white
- maintain lateral on icon on stop on dash
- prevent engagement if disengaged and brakes are applied, just enable lateral
- edit manager to log all stderr output
- find a way to disable all logging unless debug mode enabled (screen setting)
- set up dash cam recordings
- disable dash cam and record in real logger mode if debug mode is entered
- Integrate here maps api for traffic data
- maybe even speed limit data? and location data?
- write a debug function for python that cats data to a screen terminal and optionally a log file
- if cruise already engaged when boot, just enable lateral
- reengage lateral if changing lanes and changing the wrong way
- speed limit display / over speed display / trigger set
- hack the buttons so we can press them
- auto set speed limit
- conditional experimenal mode
- ui conditional experimental mode, orange lines, show large font of desired speed in lower left
- hold down button to turn off screen, remember setting
- bluetooth dummy device
- dash cam
- change disk used on sidebar to disk free / percent used
-
- warn if lead is going more than 30 under my speed or 20 if auto mode is off
- mark os version different than release, forcing a os reinstall
- no prompt on os reinstall
Test features wizard:
- read paddles
- read speed
- adjust speed
- cancel / resume
- reset drive mode
- read radar distance
- activate blinkers
- disable changing lanes notices (tiny indicator is fine)
- speed limit display / over speed display
- hack the buttons so we can press them
- auto set speed limit

View File

@@ -1,174 +1,45 @@
-----
Latest:
- fix hiding path if disabled
- fix suspend on override behavior - override doesnt happen on always on lateral. need alternative check.
- fix & test lane line narrow on lane change view
- the acc cancel does nothing.
- must simulate actual button presses.
- add radar dist, model dist, radar speed, model speed to debug hud
- add wheel touched, wheel override to hud
- lkas button toggle display off / minimal / full / info
- fix always on lateral saying its on when actually fully engaged
- revert a bunch of debugging in canfd
Notes on speed limit override:
- we need to capture the original speed and feed it to vtsc and model whule we
are under speed adjustment
- fix it so it reads cruise state and uses it to determine program state exclusively
- always on lat in particular
------
- fix lane lines
- fix always on lateral detection
- position override under 25 mph suspends assist
- make override a state that can happen on always on lateral
- output the three speeds
- fix turning with override to disengage lower than 20
- test - if engaged, adjust the speed twoards experimental one unit every second
- configure it so i can toggle experimental via lkas
- disable onroad on parked, not car off
- if experimental enabled, then transmit experimental speed settings
- but only if no lead car or not decelerating. got to think of a condition
where we reengage if the lead is going too slow and we need to let stock long decel
- test that lkas button crashes controlsd, it should
- test that lkas button creates an alert, it should
- implement speed limit controller as a simple Warning
- hyundai clsc https://github.com/garrettpall/openpilot/commit/5528198aa73d3d017d16ec4ca38306b11e5da0a8
- implement a simple resume from standstill hack
- get ui to work on its own using no video feed, custom ui state inputs
- dress up ui
--- TRIP RELEASE ---
- add debug elements to ui with a boolean at top of onroad.cc to enable/disable:
- curviture
- current speed limit
- current cruise speed
- current experimental mode speed
- current distance to lead based on radar
- current distance to lead based on model draw distance
- current speed of lead
- configure orangepi wifi selector
- can i have it use phone bt tether?
- fix gps
- implement new onroad settings
- implement new offroad settings
- implement debug console (make it actually useful)
- implement dash cam
- implement dash cam viewer
- implement trip logger
- implement generic CLSC
- implement GM CLSC
- when changing lanes and lateral disabled, draw a narrow single 'line' down center
- of computed path, and don't show side lane boundaries
- CRAIG RELEASE -
- make side lanes 10% wider and the disengage mode 10% brighter
- make 25% of side lanes 50% darker than base
- implement logo selector
- update models, sync important changes from main
- update installer
- hello world alert triggered by lkas btn
- hello world bootstrap dashboard
- PUBLIC RELEASE -
- button stuff:
- read paddle left (for full nudgeless lane change + blinker, reset to drive)
- read paddle right ("")
- read current drive mode, reset paddle mode to drive
- write pause, res, accel, mode, drive
wishlist: read / write info switcher, hvac, windows
wishlist: allow lane assist (not lane keep) on disengage
test:
- disable all canbus
- set speed limit during stock long
OP -> Oscar
- oscar - global clearpilot state var
- oscar.cs - clearpilot car state (populated by op variables for cp.planner)
- oscar.ce - clearpilot car event queue (array that can be pushed to from car)
- oscar.ceh - event queue history (for debug)
- oscar.clog - error and console.log style one off messages to transmit to logs or watching consoles
Oscar -> OP
- oscar.ps - clearpilot planner state (data from cp)
- oscar.pe - clearpilot planner event (one time events from planner to be processed by openpilot)
- oscar.peh - planner event history (for debug)
- oscar.plog - retransmits clog as well as additional data for UI based log consoles
- oscar - clearpilot's planner - nodejs process that synchronizes state between all processes and makes decisions
- settings menu
- - branch selector - release, stage, dev. Stage is my personal release branch. Should always be able to easilly switch to stage while im in a development state.
- unfuck the directory structure. new structure:
-
-------
- make functions
--- get_curvature
--- get_wheel_angle
--- get_distance_to_left_lane
--- get_distance_to_right_lane
--- are hands on wheel
--- distance traveled for lane change
--- distance to lead
- put these on a debug.
- Design alternate settings webview
- get speed limit display working
- get calculated experimental speed display working
- get button press emulation working
- get experimental mode working
- get speed limit set working
- dev enable lateral on blinker but no wheel pressure or no wheel presence
- bluetooth dummy device
- Test if activation fix works for op long, submit to frog maintain
- (test) disable all turn signal output commands - they are causing issues
- test "create_acc_cancel" on canfd on cc engaged on boot
- Create clearpilot process. manages behaviors.
- experiment with reduced jerk values
- test toggle stop all canbus output
- check if acc_cancel events are being made on idle in stock long, if so, its a bug.
- Warn if significantly slower traffic
behaviors:
- getting head mode - turn off babysitter with an alert on the screen that it is off, suspend for 10 minutes
- in this mode it should be extra grouchy if a curve is detected, slowdown is detected, or lane lines are weak
- lane change wrong way reenable lateral
- blinker signal wheel angle minor enable lateral
- wheel angle sharp only engage lateral if over lane edge unless hands not on wheel
- no lateral on turn signal - only enforce if model curvature > 10 degrees, hands on wheel, or wheel override (maybe curve not necessary?)
- basic lane keep - nudge wheel slightly if over line and still going straight and hands on wheel
- debug mode activated bu lkas
- See where disk free is going with NCDU and add smarter log rotation
- Maybe this has logs where it could show what happened to frogpilot process?
- Test supress cruise icon on long paused
- increase center lane brightness 50% and make it blueish
- make drive mode color much brighter and 30% more white
- maintain lateral on icon on stop on dash
- prevent engagement if disengaged and brakes are applied, just enable lateral
- edit manager to log all stderr output
- find a way to disable all logging unless debug mode enabled (screen setting)
- set up dash cam recordings
- disable dash cam and record in real logger mode if debug mode is entered
- Integrate here maps api for traffic data
- maybe even speed limit data? and location data?
- write a debug function for python that cats data to a screen terminal and optionally a log file
- if cruise already engaged when boot, just enable lateral
- reengage lateral if changing lanes and changing the wrong way
- speed limit display / over speed display / trigger set
- hack the buttons so we can press them
- auto set speed limit
- conditional experimenal mode
- ui conditional experimental mode, orange lines, show large font of desired speed in lower left
- hold down button to turn off screen, remember setting
- bluetooth dummy device
- dash cam
- change disk used on sidebar to disk free / percent used
-
- warn if lead is going more than 30 under my speed or 20 if auto mode is off
- mark os version different than release, forcing a os reinstall
- no prompt on os reinstall
Test features wizard:
- read paddles
- read speed
- adjust speed
- cancel / resume
- reset drive mode
- read radar distance
- activate blinkers
Hyundai CLSC
Hyundai Paddle shifter lane change

View File

@@ -123,45 +123,41 @@ class CarController(CarControllerBase):
if self.frame % 5 == 0 and (not hda2 or hda2_long):
# CLEARPILOT TEST self.CS.lkas_enabled
# can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CC.latActive))
params_memory = Params("/dev/shm/params")
lkas_icon = params_memory.get_bool("CPTLkasButtonAction") or CS.lkas_enabled
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, lkas_icon, lkas_icon))
# params_memory = Params("/dev/shm/params")
# lkas_icon = params_memory.get_bool("CPTLkasButtonAction") or CS.lkas_enabled
# lkas_icon = CS.experimentalMode
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, False, False))
# can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CS.experimentalMode, False))
# blinkers
if hda2 and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, self.frame, CC.leftBlinker, CC.rightBlinker))
# params_memory = Params("/dev/shm/params")
params_memory = Params("/dev/shm/params")
if params_memory.get_bool("CPTLkasButtonAction"):
if self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_acc_control_alt(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units, hud_control))
self.accel_last = accel
# if params_memory.get_bool("CPTLkasButtonAction"):
# if self.frame % 10 == 0:
# for _ in range(20):
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.SET_DECEL, CS.cruise_can_msg))
# print("Decel")
# for _ in range(20):
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.SET_DECEL))
# can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
# can_sends.append(hyundaicanfd.create_acc_set_speed(self.packer, self.CP, self.CAN, CS.cruise_info, 50))
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
# print("Debug cancel executed")
if self.CP.openpilotLongitudinalControl:
if self.CP.openpilotLongitudinalControl: # or CS.experimentalMode:
if hda2:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
if self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units, hud_control))
self.accel_last = accel
else:
# else:
# Clearpilot
# If cruise control was enabled or idle on start, force cancel
# if CS.fix_main_enabled_cancel_main:
# CS.fix_main_enabled_cancel_main = False
# CC.cruiseControl.cancel = True
# button presses
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=False))
# can_sends.extend(self.create_button_messages(CC, CS, use_clu11=False))
else:
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
@@ -217,7 +213,7 @@ class CarController(CarControllerBase):
self.last_button_frame = self.frame
else:
if (self.frame - self.last_button_frame) * DT_CTRL > 0.25:
params_memory = Params("/dev/shm/params")
# params_memory = Params("/dev/shm/params")
# if params_memory.get_bool("CPTLkasButtonAction"):
# params_memory.put_bool("CPTLkasButtonAction", False)
# CC.cruiseControl.cancel = True
@@ -228,6 +224,7 @@ class CarController(CarControllerBase):
# pass
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
# for _ in range(20):
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.CANCEL))
# if CS.cruise_can_msg:
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.CANCEL, CS.cruise_can_msg))
# print("Try Cancel Button Alt")

View File

@@ -209,7 +209,7 @@ class CarState(CarStateBase):
self.lkas_previously_enabled = self.lkas_enabled
self.lkas_enabled = cp.vl["BCM_PO_11"]["LFA_Pressed"]
self.params_memory.put_int("CarSpeedLimitLiteral", self.calculate_speed_limit(cp, cp_cam))
# self.params_memory.put_int("CarSpeedLimitLiteral", self.calculate_speed_limit(cp, cp_cam))
self.params_memory.put_float("CarSpeedLimit", self.calculate_speed_limit(cp, cp_cam) * speed_conv)
self.params_memory.put_float("CarCruiseDisplayActual", cp_cruise.vl["SCC11"]["VSetDis"])
@@ -417,7 +417,7 @@ class CarState(CarStateBase):
# print("Set limit")
# print(self.calculate_speed_limit(cp, cp_cam))
self.params_memory.put_float("CarSpeedLimitLiteral", self.calculate_speed_limit(cp, cp_cam))
# self.params_memory.put_float("CarSpeedLimitLiteral", self.calculate_speed_limit(cp, cp_cam))
self.params_memory.put_float("CarSpeedLimit", self.calculate_speed_limit(cp, cp_cam) * speed_factor)
return ret

View File

@@ -236,10 +236,10 @@ def create_acc_cancel(packer, CP, CAN, cruise_info_copy):
# CLEARPILOT changed HDA icons
# This doesn't appear to do anything on my tucson
def create_lfahda_cluster(packer, CAN, enabled, lat_active):
def create_lfahda_cluster(packer, CAN, experimental, lat_active):
values = {
"HDA_ICON": 0, # Literally shows HDA. Maybe we use this to indicate experimental mode
"LFA_ICON": 2 if enabled else 1 if lat_active else 0
"LFA_ICON": 2 if experimental else 0
}
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)

0
selfdrive/clearpilot/resource/debug_ui_scene.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -77,6 +77,7 @@ class Controls:
self.params_storage = Params("/persist/params")
self.params_memory.put_bool("CPTLkasButtonAction", False)
self.params_memory.put_bool("ScreenDisaplayMode", 0)
self.radarless_model = self.params.get("Model", encoding='utf-8') in RADARLESS_MODELS
@@ -1239,16 +1240,21 @@ class Controls:
def clearpilot_state_control(self, CC, CS):
if any(be.pressed and be.type == FrogPilotButtonType.lkas for be in CS.buttonEvents):
# self.params_memory.put_bool("CPTLkasButtonAction", True)
if self.params_memory.get_bool("CPTLkasButtonAction"):
self.params_memory.put_bool("CPTLkasButtonAction", False)
else:
self.params_memory.put_bool("CPTLkasButtonAction", True)
# CS.lkas_enabled = self.params_memory.get_bool("CPTLkasButtonAction")
# if self.params_memory.get_bool("CPTLkasButtonAction"):
# self.params_memory.put_bool("CPTLkasButtonAction", False)
# else:
# self.params_memory.put_bool("CPTLkasButtonAction", True)
# Rotate display mode. These are mostly used in the frontend ui app.
max_display_mode = 1
current_display_mode = self.params_memory.get_int("ScreenDisaplayMode")
current_display_mode = current_display_mode + 1
if current_display_mode > max_display_mode:
current_display_mode = 0
self.params_memory.put_int("ScreenDisaplayMode", current_display_mode)
self.params_memory.put_int("SpeedLimitLatDesired", CC.actuators.speed * CV.MS_TO_MPH )
# CC.actuators.speed
# print ("Alive")
# self.params_memory.put_int("SpeedLimitLatDesired", CC.actuators.speed * CV.MS_TO_MPH )
return CC
def main():

View File

@@ -274,7 +274,7 @@ class FrogPilotPlanner:
frogpilotPlan.vtscControllingCurve = bool(self.mtsc_target > self.vtsc_target)
self.params_memory.put_int("SpeedLimitVTSC", frogpilotPlan.adjustedCruise)
# self.params_memory.put_int("SpeedLimitVTSC", frogpilotPlan.adjustedCruise)
pm.send('frogpilotPlan', frogpilot_plan_send)

View File

View File

View File

View File

View File

View File

@@ -149,6 +149,9 @@ def manager_init(frogpilot_functions) -> None:
("ForceFingerprint", "0"),
("ForceMPHDashboard", "0"),
("FPSCounter", "0"),
("FrogPilotDrives", "0"),
("FrogPilotKilometers", "0"),
("FrogPilotMinutes", "0"),
("FrogsGoMooTune", "1"),
("FullMap", "0"),
("GasRegenCmd", "0"),
@@ -169,7 +172,7 @@ def manager_init(frogpilot_functions) -> None:
("IncreaseThermalLimits", "0"),
("LaneChangeTime", "0"),
("LaneDetectionWidth", "60"),
("LaneLinesWidth", "2"),
("LaneLinesWidth", "4"),
("LateralTune", "1"),
("LeadDepartingAlert", "0"),
("LeadDetectionThreshold", "35"),
@@ -179,14 +182,6 @@ def manager_init(frogpilot_functions) -> None:
("LongPitch", "1"),
("LoudBlindspotAlert", "0"),
("LowVoltageShutdown", "11.8"),
("kiV1", "0.60"),
("kiV2", "0.45"),
("kiV3", "0.30"),
("kiV4", "0.15"),
("kpV1", "1.50"),
("kpV2", "1.00"),
("kpV3", "0.75"),
("kpV4", "0.50"),
("MapsSelected", ""),
("MapboxPublicKey", ""),
("MapboxSecretKey", ""),
@@ -277,7 +272,6 @@ def manager_init(frogpilot_functions) -> None:
("TrafficFollow", "0.5"),
("TrafficJerk", "1"),
("TrafficMode", "0"),
("Tuning", "1"),
("TurnAggressiveness", "100"),
("TurnDesires", "0"),
("UnlimitedLength", "1"),
@@ -341,14 +335,14 @@ def manager_init(frogpilot_functions) -> None:
os.environ['CLEAN'] = '1'
# init logging
# sentry.init(sentry.SentryProject.SELFDRIVE)
# cloudlog.bind_global(dongle_id=dongle_id,
# version=get_version(),
# origin=get_normalized_origin(),
# branch=get_short_branch(),
# commit=get_commit(),
# dirty=is_dirty(),
# device=HARDWARE.get_device_type())
sentry.init(sentry.SentryProject.SELFDRIVE)
cloudlog.bind_global(dongle_id=dongle_id,
version=get_version(),
origin=get_normalized_origin(),
branch=get_short_branch(),
commit=get_commit(),
dirty=is_dirty(),
device=HARDWARE.get_device_type())
# preimport all processes
for p in managed_processes.values():
@@ -366,11 +360,8 @@ def manager_cleanup() -> None:
cloudlog.info("everything is dead")
last_running = ""
def manager_thread(frogpilot_functions) -> None:
global last_running
cloudlog.bind(daemon="manager")
cloudlog.info("manager start")
cloudlog.info({"environ": os.environ})
@@ -422,12 +413,8 @@ def manager_thread(frogpilot_functions) -> None:
running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
for p in managed_processes.values() if p.proc)
# clearpilot
if (running != last_running):
print(running)
cloudlog.debug(running)
last_running = running
print(running)
cloudlog.debug(running)
# send managerState
msg = messaging.new_message('managerState', valid=True)
@@ -436,7 +423,7 @@ def manager_thread(frogpilot_functions) -> None:
# Exit main loop when uninstall/shutdown/reboot is needed
shutdown = False
for param in ("DoUninstall", "DoShutdown", "DoReboot", "DoSoftReboot"):
for param in ("DoUninstall", "DoShutdown", "DoReboot"):
if params.get_bool(param):
shutdown = True
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
@@ -477,9 +464,6 @@ def main() -> None:
elif params.get_bool("DoReboot"):
cloudlog.warning("reboot")
HARDWARE.reboot()
elif params.get_bool("DoSoftReboot"):
cloudlog.warning("softreboot")
HARDWARE.soft_reboot()
elif params.get_bool("DoShutdown"):
cloudlog.warning("shutdown")
HARDWARE.shutdown()

View File

@@ -0,0 +1,519 @@
#!/usr/bin/env python3
import datetime
import os
import signal
import subprocess
import sys
import threading
import time
import traceback
from cereal import log
import cereal.messaging as messaging
import openpilot.selfdrive.sentry as sentry
from openpilot.common.params import Params, ParamKeyType
from openpilot.common.text_window import TextWindow
from openpilot.common.time import system_time_valid
from openpilot.system.hardware import HARDWARE, PC
from openpilot.selfdrive.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog
from openpilot.selfdrive.manager.process import ensure_running
from openpilot.selfdrive.manager.process_config import managed_processes
from openpilot.selfdrive.athena.registration import register, UNREGISTERED_DONGLE_ID
from openpilot.common.swaglog import cloudlog, add_file_handler
from openpilot.system.version import is_dirty, get_commit, get_version, get_origin, get_short_branch, \
get_normalized_origin, terms_version, training_version, \
is_tested_branch, is_release_branch, get_commit_date
from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_functions import FrogPilotFunctions
from openpilot.selfdrive.frogpilot.controls.lib.model_manager import DEFAULT_MODEL, DEFAULT_MODEL_NAME, delete_deprecated_models
def frogpilot_boot_functions(frogpilot_functions):
try:
delete_deprecated_models()
while not system_time_valid():
print("Waiting for system time to become valid...")
time.sleep(1)
try:
frogpilot_functions.backup_frogpilot()
except subprocess.CalledProcessError as e:
print(f"Failed to backup FrogPilot. Error: {e}")
return
try:
frogpilot_functions.backup_toggles()
except subprocess.CalledProcessError as e:
print(f"Failed to backup toggles. Error: {e}")
return
except Exception as e:
print(f"An unexpected error occurred: {e}")
def manager_init(frogpilot_functions) -> None:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
log_dir = f"/data/log2/{timestamp}"
os.makedirs(log_dir, exist_ok=True)
frogpilot_boot = threading.Thread(target=frogpilot_boot_functions, args=(frogpilot_functions,))
frogpilot_boot.start()
save_bootlog()
params = Params()
params_storage = Params("/persist/params")
params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
if is_release_branch():
params.clear_all(ParamKeyType.DEVELOPMENT_ONLY)
default_params: list[tuple[str, str | bytes]] = [
("CarParamsPersistent", ""),
("CompletedTrainingVersion", "0"),
("DisengageOnAccelerator", "0"),
("ExperimentalLongitudinalEnabled", "1"),
("GsmMetered", "1"),
("HasAcceptedTerms", "0"),
("IsLdwEnabled", "0"),
("IsMetric", "0"),
("LanguageSetting", "main_en"),
("NavSettingLeftSide", "0"),
("NavSettingTime24h", "0"),
("OpenpilotEnabledToggle", "1"),
("RecordFront", "0"),
("LongitudinalPersonality", str(log.LongitudinalPersonality.standard)),
# Default FrogPilot parameters
("AccelerationPath", "1"),
("AccelerationProfile", "2"),
("AdjacentPath", "0"),
("AdjacentPathMetrics", "0"),
("AggressiveAcceleration", "1"),
("AggressiveFollow", "1.25"),
("AggressiveJerk", "0.5"),
("AlertVolumeControl", "0"),
("AlwaysOnLateral", "1"),
("AlwaysOnLateralMain", "0"),
("AMapKey1", ""),
("AMapKey2", ""),
("AutomaticUpdates", "0"),
("BlindSpotPath", "1"),
("CameraView", "2"),
("CarMake", ""),
("CarModel", ""),
("CECurves", "1"),
("CENavigation", "1"),
("CENavigationIntersections", "1"),
("CENavigationLead", "1"),
("CENavigationTurns", "1"),
("CESignal", "1"),
("CESlowerLead", "1"),
("CESpeed", "0"),
("CESpeedLead", "0"),
("CEStopLights", "1"),
("CEStopLightsLead", "0"),
("Compass", "1"),
("ConditionalExperimental", "1"),
("CrosstrekTorque", "1"),
("CurveSensitivity", "100"),
("CustomAlerts", "1"),
("CustomColors", "1"),
("CustomCruise", "1"),
("CustomCruiseLong", "5"),
("CustomIcons", "1"),
("CustomPaths", "1"),
("CustomPersonalities", "1"),
("CustomSignals", "1"),
("CustomSounds", "1"),
("CustomTheme", "1"),
("CustomUI", "1"),
("CydiaTune", "0"),
("DecelerationProfile", "1"),
("DeveloperUI", "0"),
("DeviceManagement", "1"),
("DeviceShutdown", "9"),
("DisableMTSCSmoothing", "0"),
("DisableOnroadUploads", "0"),
("DisableOpenpilotLongitudinal", "0"),
("DisableVTSCSmoothing", "0"),
("DisengageVolume", "100"),
("DragonPilotTune", "0"),
("DriverCamera", "0"),
("DynamicPathWidth", "0"),
("EngageVolume", "100"),
("EVTable", "1"),
("ExperimentalModeActivation", "1"),
("ExperimentalModeViaDistance", "1"),
("ExperimentalModeViaLKAS", "1"),
("ExperimentalModeViaTap", "0"),
("Fahrenheit", "0"),
("ForceAutoTune", "1"),
("ForceFingerprint", "0"),
("ForceMPHDashboard", "0"),
("FPSCounter", "0"),
("FrogsGoMooTune", "1"),
("FullMap", "0"),
("GasRegenCmd", "0"),
("GMapKey", ""),
("GoatScream", "1"),
("GreenLightAlert", "0"),
("HideAlerts", "0"),
("HideAOLStatusBar", "0"),
("HideCEMStatusBar", "0"),
("HideLeadMarker", "0"),
("HideMapIcon", "0"),
("HideMaxSpeed", "0"),
("HideSpeed", "0"),
("HideSpeedUI", "0"),
("HideUIElements", "0"),
("HigherBitrate", "0"),
("HolidayThemes", "1"),
("IncreaseThermalLimits", "0"),
("LaneChangeTime", "0"),
("LaneDetectionWidth", "60"),
("LaneLinesWidth", "2"),
("LateralTune", "1"),
("LeadDepartingAlert", "0"),
("LeadDetectionThreshold", "35"),
("LeadInfo", "0"),
("LockDoors", "1"),
("LongitudinalTune", "1"),
("LongPitch", "1"),
("LoudBlindspotAlert", "0"),
("LowVoltageShutdown", "11.8"),
("kiV1", "0.60"),
("kiV2", "0.45"),
("kiV3", "0.30"),
("kiV4", "0.15"),
("kpV1", "1.50"),
("kpV2", "1.00"),
("kpV3", "0.75"),
("kpV4", "0.50"),
("MapsSelected", ""),
("MapboxPublicKey", ""),
("MapboxSecretKey", ""),
("MapStyle", "0"),
("MTSCAggressiveness", "100"),
("MTSCCurvatureCheck", "0"),
("Model", DEFAULT_MODEL),
("ModelName", DEFAULT_MODEL_NAME),
("ModelSelector", "1"),
("ModelUI", "1"),
("MTSCEnabled", "1"),
("NNFF", "1"),
("NNFFLite", "1"),
("NoLogging", "0"),
("NoUploads", "0"),
("NudgelessLaneChange", "1"),
("NumericalTemp", "0"),
("OfflineMode", "1"),
("Offset1", "5"),
("Offset2", "5"),
("Offset3", "5"),
("Offset4", "10"),
("OneLaneChange", "1"),
("OnroadDistanceButton", "0"),
("PathEdgeWidth", "20"),
("PathWidth", "61"),
("PauseAOLOnBrake", "0"),
("PauseLateralOnSignal", "0"),
("PedalsOnUI", "1"),
("PreferredSchedule", "0"),
("PromptVolume", "100"),
("PromptDistractedVolume", "100"),
("QOLControls", "1"),
("QOLVisuals", "1"),
("RandomEvents", "0"),
("RefuseVolume", "100"),
("RelaxedFollow", "1.75"),
("RelaxedJerk", "1.0"),
("ReverseCruise", "0"),
("ReverseCruiseUI", "1"),
("RoadEdgesWidth", "2"),
("RoadNameUI", "1"),
("RotatingWheel", "1"),
("ScreenBrightness", "101"),
("ScreenBrightnessOnroad", "101"),
("ScreenManagement", "1"),
("ScreenRecorder", "1"),
("ScreenTimeout", "30"),
("ScreenTimeoutOnroad", "30"),
("SearchInput", "0"),
("SetSpeedLimit", "0"),
("SetSpeedOffset", "0"),
("ShowCPU", "0"),
("ShowGPU", "0"),
("ShowIP", "0"),
("ShowJerk", "1"),
("ShowMemoryUsage", "0"),
("ShowSLCOffset", "1"),
("ShowSLCOffsetUI", "1"),
("ShowStorageLeft", "0"),
("ShowStorageUsed", "0"),
("ShowTuning", "1"),
("Sidebar", "0"),
("SLCConfirmation", "1"),
("SLCConfirmationLower", "1"),
("SLCConfirmationHigher", "1"),
("SLCFallback", "2"),
("SLCLookaheadHigher", "5"),
("SLCLookaheadLower", "5"),
("SLCOverride", "1"),
("SLCPriority1", "Dashboard"),
("SLCPriority2", "Offline Maps"),
("SLCPriority3", "Navigation"),
("SmoothBraking", "1"),
("SmoothBrakingFarLead", "0"),
("SmoothBrakingJerk", "0"),
("SNGHack", "1"),
("SpeedLimitChangedAlert", "1"),
("SpeedLimitController", "1"),
("StandardFollow", "1.45"),
("StandardJerk", "1.0"),
("StandbyMode", "0"),
("SteerRatio", "0"),
("StockTune", "0"),
("StoppingDistance", "0"),
("TacoTune", "1"),
("ToyotaDoors", "0"),
("TrafficFollow", "0.5"),
("TrafficJerk", "1"),
("TrafficMode", "0"),
("Tuning", "1"),
("TurnAggressiveness", "100"),
("TurnDesires", "0"),
("UnlimitedLength", "1"),
("UnlockDoors", "1"),
("UseSI", "1"),
("UseVienna", "0"),
("VisionTurnControl", "1"),
("WarningSoftVolume", "100"),
("WarningImmediateVolume", "100"),
("WheelIcon", "3"),
("WheelSpeed", "0")
]
if not PC:
default_params.append(("LastUpdateTime", datetime.datetime.utcnow().isoformat().encode('utf8')))
if params.get_bool("RecordFrontLock"):
params.put_bool("RecordFront", True)
# set unset params
for k, v in default_params:
if params.get(k) is None:
if params_storage.get(k) is None:
params.put(k, v)
else:
params.put(k, params_storage.get(k))
else:
params_storage.put(k, params.get(k))
# Create folders needed for msgq
try:
os.mkdir("/dev/shm")
except FileExistsError:
pass
except PermissionError:
print("WARNING: failed to make /dev/shm")
# set version params
params.put("Version", get_version())
params.put("TermsVersion", terms_version)
params.put("TrainingVersion", training_version)
params.put("GitCommit", get_commit())
params.put("GitCommitDate", get_commit_date())
params.put("GitBranch", get_short_branch())
params.put("GitRemote", get_origin())
params.put_bool("IsTestedBranch", is_tested_branch())
params.put_bool("IsReleaseBranch", is_release_branch())
# set dongle id
reg_res = register(show_spinner=True)
if reg_res:
dongle_id = reg_res
else:
serial = params.get("HardwareSerial")
raise Exception(f"Registration failed for device {serial}")
os.environ['DONGLE_ID'] = dongle_id # Needed for swaglog
os.environ['GIT_ORIGIN'] = get_normalized_origin() # Needed for swaglog
os.environ['GIT_BRANCH'] = get_short_branch() # Needed for swaglog
os.environ['GIT_COMMIT'] = get_commit() # Needed for swaglog
if not is_dirty():
os.environ['CLEAN'] = '1'
# init logging
# sentry.init(sentry.SentryProject.SELFDRIVE)
# cloudlog.bind_global(dongle_id=dongle_id,
# version=get_version(),
# origin=get_normalized_origin(),
# branch=get_short_branch(),
# commit=get_commit(),
# dirty=is_dirty(),
# device=HARDWARE.get_device_type())
# preimport all processes
for p in managed_processes.values():
p.prepare()
return log_dir
def manager_cleanup() -> None:
# send signals to kill all procs
for p in managed_processes.values():
p.stop(block=False)
# ensure all are killed
for p in managed_processes.values():
p.stop(block=True)
cloudlog.info("everything is dead")
last_running = ""
def manager_thread(frogpilot_functions, log_dir) -> None:
global last_running
cloudlog.bind(daemon="manager")
cloudlog.info("manager start")
cloudlog.info({"environ": os.environ})
params = Params()
params_memory = Params("/dev/shm/params")
ignore: list[str] = []
if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID):
ignore += ["manage_athenad", "uploader"]
if os.getenv("NOBOARD") is not None:
ignore.append("pandad")
ignore += [x for x in os.getenv("BLOCK", "").split(",") if len(x) > 0]
sm = messaging.SubMaster(['deviceState', 'carParams'], poll='deviceState')
pm = messaging.PubMaster(['managerState'])
write_onroad_params(False, params)
ensure_running(managed_processes.values(), False, params=params, CP=sm['carParams'], not_run=ignore, log_dir=log_dir)
started_prev = False
while True:
sm.update(1000)
openpilot_crashed = os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt'))
if openpilot_crashed:
frogpilot_functions.delete_logs()
started = sm['deviceState'].started
if started and not started_prev:
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
if openpilot_crashed:
os.remove(os.path.join(sentry.CRASHES_DIR, 'error.txt'))
elif not started and started_prev:
params.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
params_memory.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
# update onroad params, which drives boardd's safety setter thread
if started != started_prev:
write_onroad_params(started, params)
started_prev = started
ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore, log_dir=log_dir)
running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
for p in managed_processes.values() if p.proc)
# clearpilot
if (running != last_running):
print(running)
cloudlog.debug(running)
last_running = running
# send managerState
msg = messaging.new_message('managerState', valid=True)
msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()]
pm.send('managerState', msg)
# Exit main loop when uninstall/shutdown/reboot is needed
shutdown = False
for param in ("DoUninstall", "DoShutdown", "DoReboot", "DoSoftReboot"):
if params.get_bool(param):
shutdown = True
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
cloudlog.warning(f"Shutting down manager - {param} set")
if shutdown:
break
def main() -> None:
frogpilot_functions = FrogPilotFunctions()
try:
frogpilot_functions.setup_frogpilot()
except subprocess.CalledProcessError as e:
print(f"Failed to setup FrogPilot. Error: {e}")
return
log_dir = manager_init(frogpilot_functions)
if os.getenv("PREPAREONLY") is not None:
return
# SystemExit on sigterm
signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1))
try:
manager_thread(frogpilot_functions, log_dir)
except Exception:
traceback.print_exc()
sentry.capture_exception()
finally:
manager_cleanup()
params = Params()
if params.get_bool("DoUninstall"):
cloudlog.warning("uninstalling")
frogpilot_functions.uninstall_frogpilot()
elif params.get_bool("DoReboot"):
cloudlog.warning("reboot")
HARDWARE.reboot()
elif params.get_bool("DoSoftReboot"):
cloudlog.warning("softreboot")
HARDWARE.soft_reboot()
elif params.get_bool("DoShutdown"):
cloudlog.warning("shutdown")
HARDWARE.shutdown()
if __name__ == "__main__":
unblock_stdout()
try:
main()
except KeyboardInterrupt:
print("got CTRL-C, exiting")
except Exception:
add_file_handler(cloudlog)
cloudlog.exception("Manager failed to start")
try:
managed_processes['ui'].stop()
except Exception:
pass
# Show last 3 lines of traceback
error = traceback.format_exc(-3)
error = "Manager failed to start\n\n" + error
with TextWindow(error) as t:
t.wait_for_exit()
raise
# manual exit because we are forked
sys.exit(0)

View File

@@ -2,6 +2,7 @@ import importlib
import os
import signal
import struct
import datetime
import time
import subprocess
from collections.abc import Callable, ValuesView
@@ -20,6 +21,11 @@ from openpilot.common.swaglog import cloudlog
WATCHDOG_FN = "/dev/shm/wd_"
ENABLE_WATCHDOG = os.getenv("NO_WATCHDOG") is None
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
_log_dir = f"/data/log2/{timestamp}"
os.makedirs(_log_dir, exist_ok=True)
def launcher(proc: str, name: str) -> None:
try:
@@ -54,7 +60,6 @@ def nativelauncher(pargs: list[str], cwd: str, name: str) -> None:
os.chdir(cwd)
os.execvp(pargs[0], pargs)
def join_process(process: Process, timeout: float) -> None:
# Process().join(timeout) will hang due to a python 3 bug: https://bugs.python.org/issue28382
# We have to poll the exitcode instead
@@ -189,6 +194,9 @@ class NativeProcess(ManagerProcess):
if self.proc is not None:
return
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
cwd = os.path.join(BASEDIR, self.cwd)
cloudlog.info(f"starting process {self.name}")
@@ -221,6 +229,8 @@ class PythonProcess(ManagerProcess):
if self.proc is not None:
return
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
cloudlog.info(f"starting python {self.module}")
self.proc = Process(name=self.name, target=self.launcher, args=(self.module, self.name))
self.proc.start()
@@ -238,6 +248,7 @@ class DaemonProcess(ManagerProcess):
self.enabled = enabled
self.params = None
@staticmethod
def should_run(started, params, CP):
return True
@@ -249,6 +260,9 @@ class DaemonProcess(ManagerProcess):
if self.params is None:
self.params = Params()
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
pid = self.params.get(self.param_name, encoding='utf-8')
if pid is not None:
try:
@@ -264,8 +278,8 @@ class DaemonProcess(ManagerProcess):
cloudlog.info(f"starting daemon {self.name}")
proc = subprocess.Popen(['python', '-m', self.module],
stdin=open('/dev/null'),
stdout=open('/dev/null', 'w'),
stderr=open('/dev/null', 'w'),
stdout=open(log_path, 'a'),
stderr=subprocess.STDOUT,
preexec_fn=os.setpgrp)
self.params.put(self.param_name, str(proc.pid))
@@ -276,6 +290,7 @@ class DaemonProcess(ManagerProcess):
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None,
not_run: list[str] | None=None) -> list[ManagerProcess]:
if not_run is None:
not_run = []

View File

@@ -28,10 +28,10 @@ def ublox(started, params, CP: car.CarParams) -> bool:
use_ublox = ublox_available()
if use_ublox != params.get_bool("UbloxAvailable"):
params.put_bool("UbloxAvailable", use_ublox)
return started and use_ublox
return use_ublox
def qcomgps(started, params, CP: car.CarParams) -> bool:
return started and not ublox_available()
return not ublox_available()
def always_run(started, params, CP: car.CarParams) -> bool:
return True
@@ -78,13 +78,13 @@ procs = [
PythonProcess("controlsd", "selfdrive.controls.controlsd", only_onroad),
PythonProcess("deleter", "system.loggerd.deleter", always_run),
PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(not PC or WEBCAM)),
#PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI),
#PythonProcess("ugpsd", "system.ugpsd", only_onroad, enabled=TICI),
# PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), # Fixme
# PythonProcess("ugpsd", "system.ugpsd", only_onroad, enabled=TICI),
#PythonProcess("navd", "selfdrive.navd.navd", only_onroad),
PythonProcess("pandad", "selfdrive.boardd.pandad", always_run),
PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad),
#NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
#PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
PythonProcess("plannerd", "selfdrive.controls.plannerd", only_onroad),
PythonProcess("radard", "selfdrive.controls.radard", only_onroad),
PythonProcess("thermald", "selfdrive.thermald.thermald", always_run),

View File

@@ -0,0 +1,251 @@
import importlib
import os
import signal
import struct
import time
import subprocess
from collections.abc import Callable, ValuesView
from abc import ABC, abstractmethod
from multiprocessing import Process
from setproctitle import setproctitle
from cereal import car, log
import cereal.messaging as messaging
import openpilot.selfdrive.sentry as sentry
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
WATCHDOG_FN = "/dev/shm/wd_"
ENABLE_WATCHDOG = os.getenv("NO_WATCHDOG") is None
ENABLE_WATCHDOG = False # Fixme
_log_dir = ""
def nativelauncher(pargs: list[str], cwd: str, name: str, log_path: str) -> None:
os.environ['MANAGER_DAEMON'] = name
with open(log_path, 'a') as log_file:
os.chdir(cwd)
proc = subprocess.Popen(pargs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True)
log_file.write("Started "+name)
for line in proc.stdout:
print(line, end='')
log_file.write(line)
proc.wait()
def launcher(proc: str, name: str, log_path: str) -> None:
for _ in iter(int, 1):
try:
mod = importlib.import_module(proc)
setproctitle(proc)
messaging.context = messaging.Context()
cloudlog.bind(daemon=name)
sentry.set_tag("daemon", name)
with open(log_path, 'a') as log_file, subprocess.Popen(['python', '-m', proc], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) as proc:
log_file.write("Started "+name)
for line in proc.stdout:
print(line, end='')
log_file.write(line)
proc.wait()
except Exception as e:
print ("Fatal: "+name)
print (e)
sentry.capture_exception()
def join_process(process: Process, timeout: float) -> None:
t = time.monotonic()
while time.monotonic() - t < timeout and process.exitcode is None:
time.sleep(0.001)
class ManagerProcess(ABC):
daemon = False
sigkill = False
should_run: Callable[[bool, Params, car.CarParams], bool]
proc: Process | None = None
enabled = True
name = ""
last_watchdog_time = 0
watchdog_max_dt: int | None = None
watchdog_seen = False
shutting_down = False
@abstractmethod
def prepare(self) -> None:
pass
@abstractmethod
def start(self) -> None:
pass
def restart(self) -> None:
if self.proc is not None and self.proc.exitcode is not None:
self.stop(sig=signal.SIGKILL, block=False)
self.start()
def check_watchdog(self, started: bool) -> None:
if self.watchdog_max_dt is None or self.proc is None:
return
try:
fn = WATCHDOG_FN + str(self.proc.pid)
with open(fn, "rb") as f:
self.last_watchdog_time = struct.unpack('Q', f.read())[0]
except Exception:
pass
dt = time.monotonic() - self.last_watchdog_time / 1e9
if dt > self.watchdog_max_dt:
if (self.watchdog_seen or self.always_watchdog and self.proc.exitcode is not None) and ENABLE_WATCHDOG:
cloudlog.error(f"Watchdog timeout for {self.name} (exitcode {self.proc.exitcode}) restarting ({started=})")
self.restart()
else:
self.watchdog_seen = True
def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals = None) -> int | None:
if self.proc is None:
return None
if self.proc.exitcode is None:
if not self.shutting_down:
cloudlog.info(f"killing {self.name}")
if sig is None:
sig = signal.SIGKILL if self.sigkill else signal.SIGINT
self.signal(sig)
self.shutting_down = True
if not block:
return None
join_process(self.proc, 5)
if self.proc.exitcode is None and retry:
cloudlog.info(f"killing {self.name} with SIGKILL")
self.signal(signal.SIGKILL)
self.proc.join()
ret = self.proc.exitcode
cloudlog.info(f"{self.name} is dead with {ret}")
if self.proc.exitcode is not None:
self.shutting_down = False
self.proc = None
return ret
def signal(self, sig: int) -> None:
if self.proc is None or self.proc.exitcode is not None or self.proc.pid is None:
return
cloudlog.info(f"sending signal {sig} to {self.name}")
os.kill(self.proc.pid, sig)
def get_process_state_msg(self):
state = log.ManagerState.ProcessState.new_message()
state.name = self.name
if self.proc:
state.running = self.proc.is_alive()
state.shouldBeRunning = self.proc is not None and not self.shutting_down
state.pid = self.proc.pid or 0
state.exitCode = self.proc.exitcode or 0
return state
class NativeProcess(ManagerProcess):
def __init__(self, name, cwd, cmdline, should_run, enabled=True, sigkill=False, watchdog_max_dt=None, always_watchdog=False):
self.name = name
self.cwd = cwd
self.cmdline = cmdline
self.should_run = should_run
self.enabled = enabled
self.sigkill = sigkill
self.watchdog_max_dt = watchdog_max_dt
self.launcher = nativelauncher
self.always_watchdog = always_watchdog
def prepare(self) -> None:
pass
def start(self) -> None:
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
if self.shutting_down or self.proc is not None:
return
self.proc = Process(target=nativelauncher, args=(self.cmdline, os.path.join(BASEDIR, self.cwd), self.name, log_path))
self.proc.start()
class PythonProcess(ManagerProcess):
def __init__(self, name, module, should_run, enabled=True, sigkill=False, watchdog_max_dt=None):
self.name = name
self.module = module
self.should_run = should_run
self.enabled = enabled
self.sigkill = sigkill
self.watchdog_max_dt = watchdog_max_dt
self.launcher = launcher
def prepare(self) -> None:
if self.enabled:
cloudlog.info(f"preimporting {self.module}")
importlib.import_module(self.module)
def start(self) -> None:
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
if self.shutting_down or self.proc is not None:
return
self.proc = Process(name=self.name, target=launcher, args=(self.module, self.name, log_path))
self.proc.start()
self.watchdog_seen = False
self.shutting_down = False
class DaemonProcess(ManagerProcess):
"""Python process that has to stay running across manager restart.
This is used for athena so you don't lose SSH access when restarting manager."""
def __init__(self, name, module, param_name, enabled=True):
self.name = name
self.module = module
self.param_name = param_name
self.enabled = enabled
self.params = None
@staticmethod
def should_run(started, params, CP):
return True
def prepare(self) -> None:
pass
def start(self) -> None:
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
if self.params is None:
self.params = Params()
pid = self.params.get(self.param_name, encoding='utf-8')
if pid is not None:
try:
os.kill(int(pid), 0)
return # Process is already running
except OSError:
pass # Process not running, continue to start it
cloudlog.info(f"starting daemon {self.name}")
self.proc = subprocess.Popen(['python', '-m', self.module],
stdin=open('/dev/null'),
stdout=open(log_path, 'a'),
stderr=subprocess.STDOUT,
preexec_fn=os.setpgrp)
self.params.put(self.param_name, str(self.proc.pid))
def stop(self, retry=True, block=True, sig=None) -> None:
pass
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None, not_run: list[str] | None=None, log_dir: str = None) -> list[ManagerProcess]:
global _log_dir
_log_dir = log_dir
if not_run is None:
not_run = []
running = []
for p in procs:
if p.enabled and p.name not in not_run and p.should_run(started, params, CP):
if p.proc is None or (hasattr(p.proc, 'exitcode') and p.proc.exitcode is not None):
p.start()
running.append(p)
else:
p.stop(block=False)
p.check_watchdog(started)
return running

View File

@@ -0,0 +1,350 @@
import importlib
import os
import signal
import struct
import datetime
import time
import subprocess
from collections.abc import Callable, ValuesView
from abc import ABC, abstractmethod
from multiprocessing import Process
from setproctitle import setproctitle
from cereal import car, log
import cereal.messaging as messaging
import openpilot.selfdrive.sentry as sentry
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
WATCHDOG_FN = "/dev/shm/wd_"
ENABLE_WATCHDOG = os.getenv("NO_WATCHDOG") is None
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
_log_dir = f"/data/log2/{timestamp}"
os.makedirs(_log_dir, exist_ok=True)
# def launcher(proc: str, name: str, log_path: str) -> None:
# try:
# # import the process
# mod = importlib.import_module(proc)
# global _log_dir
# log_path = os.path.join(_log_dir, f"{name}.log")
# # rename the process
# setproctitle(proc)
# # create new context since we forked
# messaging.context = messaging.Context()
# # add daemon name tag to logs
# cloudlog.bind(daemon=name)
# sentry.set_tag("daemon", name)
# # exec the process
# mod.main()
# except KeyboardInterrupt:
# cloudlog.warning(f"child {proc} got SIGINT")
# except Exception as e:
# # can't install the crash handler because sys.excepthook doesn't play nice
# # with threads, so catch it here.
# with open(log_path, 'a') as file: file.write(str(e)+"\n")
# sentry.capture_exception()
# raise
def launcher(proc: str, name: str) -> None:
try:
# Import the process module
mod = importlib.import_module(proc)
# Path for logging
global _log_dir
log_path = os.path.join(_log_dir, f"{name}.log")
# Rename the process
setproctitle(name)
# Create new context since we forked
messaging.context = messaging.Context()
# Add daemon name tag to logs
cloudlog.bind(daemon=name)
sentry.set_tag("daemon", name)
# Command construction
command = f"bash -c 'python -m {proc} 2>&1 | tee {log_path}'"
# Execute the command
subprocess.run(command, shell=True, executable='/bin/bash', cwd=os.path.dirname(mod.__file__))
except KeyboardInterrupt:
cloudlog.warning(f"child {proc} got SIGINT")
except Exception as e:
with open(log_path, 'a') as file:
file.write(str(e) + "\n")
sentry.capture_exception()
raise
def nativelauncher(pargs: list[str], cwd: str, name: str) -> None:
os.environ['MANAGER_DAEMON'] = name
global _log_dir
log_path = os.path.join(_log_dir, f"{name}.log")
# Command construction
command = f"bash -c \"{ ' '.join(pargs) } 2>&1 | tee {log_path}\""
# Execute the command in the specified directory
subprocess.run(command, shell=True, cwd=cwd, executable='/bin/bash')
def join_process(process: Process, timeout: float) -> None:
# Process().join(timeout) will hang due to a python 3 bug: https://bugs.python.org/issue28382
# We have to poll the exitcode instead
t = time.monotonic()
while time.monotonic() - t < timeout and process.exitcode is None:
time.sleep(0.001)
class ManagerProcess(ABC):
daemon = False
sigkill = False
should_run: Callable[[bool, Params, car.CarParams], bool]
proc: Process | None = None
enabled = True
name = ""
last_watchdog_time = 0
watchdog_max_dt: int | None = None
watchdog_seen = False
shutting_down = False
@abstractmethod
def prepare(self) -> None:
pass
@abstractmethod
def start(self) -> None:
pass
def restart(self) -> None:
self.stop(sig=signal.SIGKILL)
self.start()
def check_watchdog(self, started: bool) -> None:
if self.watchdog_max_dt is None or self.proc is None:
return
try:
fn = WATCHDOG_FN + str(self.proc.pid)
with open(fn, "rb") as f:
# TODO: why can't pylint find struct.unpack?
self.last_watchdog_time = struct.unpack('Q', f.read())[0]
except Exception:
pass
dt = time.monotonic() - self.last_watchdog_time / 1e9
if dt > self.watchdog_max_dt:
if (self.watchdog_seen or self.always_watchdog and self.proc.exitcode is not None) and ENABLE_WATCHDOG:
cloudlog.error(f"Watchdog timeout for {self.name} (exitcode {self.proc.exitcode}) restarting ({started=})")
self.restart()
else:
self.watchdog_seen = True
def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals = None) -> int | None:
if self.proc is None:
return None
if self.proc.exitcode is None:
if not self.shutting_down:
cloudlog.info(f"killing {self.name}")
if sig is None:
sig = signal.SIGKILL if self.sigkill else signal.SIGINT
self.signal(sig)
self.shutting_down = True
if not block:
return None
join_process(self.proc, 5)
# If process failed to die send SIGKILL
if self.proc.exitcode is None and retry:
cloudlog.info(f"killing {self.name} with SIGKILL")
self.signal(signal.SIGKILL)
self.proc.join()
ret = self.proc.exitcode
cloudlog.info(f"{self.name} is dead with {ret}")
if self.proc.exitcode is not None:
self.shutting_down = False
self.proc = None
return ret
def signal(self, sig: int) -> None:
if self.proc is None:
return
# Don't signal if already exited
if self.proc.exitcode is not None and self.proc.pid is not None:
return
# Can't signal if we don't have a pid
if self.proc.pid is None:
return
cloudlog.info(f"sending signal {sig} to {self.name}")
os.kill(self.proc.pid, sig)
def get_process_state_msg(self):
state = log.ManagerState.ProcessState.new_message()
state.name = self.name
if self.proc:
state.running = self.proc.is_alive()
state.shouldBeRunning = self.proc is not None and not self.shutting_down
state.pid = self.proc.pid or 0
state.exitCode = self.proc.exitcode or 0
return state
class NativeProcess(ManagerProcess):
def __init__(self, name, cwd, cmdline, should_run, enabled=True, sigkill=False, watchdog_max_dt=None, always_watchdog=False):
self.name = name
self.cwd = cwd
self.cmdline = cmdline
self.should_run = should_run
self.enabled = enabled
self.sigkill = sigkill
self.watchdog_max_dt = watchdog_max_dt
self.launcher = nativelauncher
self.always_watchdog = always_watchdog
def prepare(self) -> None:
pass
def start(self) -> None:
# In case we only tried a non blocking stop we need to stop it before restarting
if self.shutting_down:
self.stop()
if self.proc is not None:
return
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
cwd = os.path.join(BASEDIR, self.cwd)
cloudlog.info(f"starting process {self.name}")
self.proc = Process(name=self.name, target=self.launcher, args=(self.cmdline, cwd, self.name))
self.proc.start()
self.watchdog_seen = False
self.shutting_down = False
class PythonProcess(ManagerProcess):
def __init__(self, name, module, should_run, enabled=True, sigkill=False, watchdog_max_dt=None):
self.name = name
self.module = module
self.should_run = should_run
self.enabled = enabled
self.sigkill = sigkill
self.watchdog_max_dt = watchdog_max_dt
self.launcher = launcher
def prepare(self) -> None:
if self.enabled:
cloudlog.info(f"preimporting {self.module}")
importlib.import_module(self.module)
def start(self) -> None:
# In case we only tried a non blocking stop we need to stop it before restarting
if self.shutting_down:
self.stop()
if self.proc is not None:
return
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
cloudlog.info(f"starting python {self.module}")
self.proc = Process(name=self.name, target=self.launcher, args=(self.module, self.name))
self.proc.start()
self.watchdog_seen = False
self.shutting_down = False
class DaemonProcess(ManagerProcess):
"""Python process that has to stay running across manager restart.
This is used for athena so you don't lose SSH access when restarting manager."""
def __init__(self, name, module, param_name, enabled=True):
self.name = name
self.module = module
self.param_name = param_name
self.enabled = enabled
self.params = None
@staticmethod
def should_run(started, params, CP):
return True
def prepare(self) -> None:
pass
def start(self) -> None:
if self.params is None:
self.params = Params()
global _log_dir
log_path = _log_dir+"/"+self.name+".log"
pid = self.params.get(self.param_name, encoding='utf-8')
if pid is not None:
try:
os.kill(int(pid), 0)
with open(f'/proc/{pid}/cmdline') as f:
if self.module in f.read():
# daemon is running
return
except (OSError, FileNotFoundError):
# process is dead
pass
cloudlog.info(f"starting daemon {self.name}")
proc = subprocess.Popen(['python', '-m', self.module],
stdin=open('/dev/null'),
stdout=open(log_path, 'a'),
stderr=subprocess.STDOUT,
preexec_fn=os.setpgrp)
self.params.put(self.param_name, str(proc.pid))
def stop(self, retry=True, block=True, sig=None) -> None:
pass
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None,
not_run: list[str] | None=None) -> list[ManagerProcess]:
if not_run is None:
not_run = []
running = []
for p in procs:
if p.enabled and p.name not in not_run and p.should_run(started, params, CP):
running.append(p)
else:
p.stop(block=False)
p.check_watchdog(started)
for p in running:
p.start()
return running

View File

@@ -29,6 +29,8 @@
// p.restore();
// }
bool alert_is_visible = false;
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(UI_BORDER_SIZE);
@@ -175,52 +177,6 @@ void OnroadWindow::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
if (scene.fps_counter) {
qint64 currentMillis = QDateTime::currentMSecsSinceEpoch();
auto fpsQueue = std::queue<std::pair<qint64, double>>();
static double avgFPS = 0.0;
static double maxFPS = 0.0;
static double minFPS = 99.9;
minFPS = qMin(minFPS, fps);
maxFPS = qMax(maxFPS, fps);
fpsQueue.push({currentMillis, fps});
while (!fpsQueue.empty() && currentMillis - fpsQueue.front().first > 60000) {
fpsQueue.pop();
}
if (!fpsQueue.empty()) {
double totalFPS = 0;
for (auto tempQueue = fpsQueue; !tempQueue.empty(); tempQueue.pop()) {
totalFPS += tempQueue.front().second;
}
avgFPS = totalFPS / fpsQueue.size();
}
QString fpsDisplayString = QString("FPS: %1 (%2) | Min: %3 | Max: %4 | Avg: %5")
.arg(qRound(fps))
.arg(paramsMemory.getInt("CameraFPS"))
.arg(qRound(minFPS))
.arg(qRound(maxFPS))
.arg(qRound(avgFPS));
p.setFont(InterFont(28, QFont::DemiBold));
p.setRenderHint(QPainter::TextAntialiasing);
p.setPen(Qt::white);
QRect currentRect = rect();
int textWidth = p.fontMetrics().horizontalAdvance(fpsDisplayString);
int xPos = (currentRect.width() - textWidth) / 2;
int yPos = currentRect.bottom() - 5;
p.drawText(xPos, yPos, fpsDisplayString);
update();
}
QString logicsDisplayString = QString();
if (scene.show_jerk) {
logicsDisplayString += QString("Acceleration Jerk: %1 (%2%3) | Speed Jerk: %4 (%5%6) | ")
@@ -259,6 +215,14 @@ void OnroadWindow::paintEvent(QPaintEvent *event) {
}
}
// void OnroadWindow::update_screen_on_off() {
// int screenDisaplayMode = paramsMemory.getInt("ScreenDisaplayMode");
// if (screenDisaplayMode == 1) {
// // Conditionally off
// }
// }
// ***** onroad widgets *****
// OnroadAlerts
@@ -270,6 +234,8 @@ void OnroadAlerts::updateAlert(const Alert &a) {
}
void OnroadAlerts::paintEvent(QPaintEvent *event) {
alert_is_visible = false;
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
return;
}
@@ -278,6 +244,8 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
return;
}
alert_is_visible = true;
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = {
{cereal::ControlsState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420},
@@ -420,7 +388,19 @@ if (edgeColor != bgColor) {
}
void AnnotatedCameraWidget::drawHud(QPainter &p) {
// Blank when screenDisplayMode=1
p.save();
int screenDisaplayMode = paramsMemory.getInt("ScreenDisaplayMode");
if (screenDisaplayMode == 1 && !alert_is_visible) {
// Draw black, filled, full-size rectangle to blank the screen
// p.fillRect(0, 0, width(), height(), Qt::black);
// p.restore();
Hardware::set_display_power(false);
return;
} else {
Hardware::set_display_power(true);
}
// Header gradient
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
@@ -438,20 +418,20 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
p.restore();
// if (!scene.hide_max_speed) {
drawSpeedWidget(p, 60, 45, QString("MAX"), setSpeedStr, QColor(0xff, 0xff, 0xff));
// drawSpeedWidget(p, 60, 45, QString("MAX"), setSpeedStr, QColor(0xff, 0xff, 0xff));
// }
// Todo: needs to be changed to calculate off of actual speed limit for release
QString speedLimitStr = QString::number(paramsMemory.getInt("CarSpeedLimitLiteral"));
drawSpeedWidget(p, 60, 45 + (225), QString("Limit"), speedLimitStr, QColor(0xff, 0xff, 0xff));
// // Todo: needs to be changed to calculate off of actual speed limit for release
// QString speedLimitStr = QString::number(paramsMemory.getInt("CarSpeedLimitLiteral"));
// drawSpeedWidget(p, 60, 45 + (225), QString("Limit"), speedLimitStr, QColor(0xff, 0xff, 0xff));
// Todo: needs to be changed to calculate off of actual speed limit for release
QString SpeedLimitLatDesired = QString::number(paramsMemory.getInt("SpeedLimitLatDesired"));
drawSpeedWidget(p, 60, 45 + (225 * 2), QString("Exp"), SpeedLimitLatDesired, QColor(0xff, 0xff, 0xff));
// // Todo: needs to be changed to calculate off of actual speed limit for release
// QString SpeedLimitLatDesired = QString::number(paramsMemory.getInt("SpeedLimitLatDesired"));
// drawSpeedWidget(p, 60, 45 + (225 * 2), QString("Exp"), SpeedLimitLatDesired, QColor(0xff, 0xff, 0xff));
// Todo: needs to be changed to calculate off of actual speed limit for release
QString adjustedCruise = QString::number(paramsMemory.getInt("SpeedLimitVTSC"));
drawSpeedWidget(p, 60, 45 + (225 * 3), QString("VTSC"), adjustedCruise, QColor(0xff, 0xff, 0xff));
// // Todo: needs to be changed to calculate off of actual speed limit for release
// QString adjustedCruise = QString::number(paramsMemory.getInt("SpeedLimitVTSC"));
// drawSpeedWidget(p, 60, 45 + (225 * 3), QString("VTSC"), adjustedCruise, QColor(0xff, 0xff, 0xff));
// Todo: lead speed
// Todo: Experimental speed
@@ -881,7 +861,8 @@ void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) {
const auto &lead = model.getLeadsV3()[i];
auto lead_drel = lead.getX()[0];
if (lead.getProb() > 0.5 && (prev_drel < 0 || std::abs(lead_drel - prev_drel) > 3.0)) {
drawLead(painter, lead, s->scene.lead_vertices[i], v_ego);
// Disabled for the moment.
// drawLead(painter, lead, s->scene.lead_vertices[i], v_ego);
}
prev_drel = lead_drel;
}

View File

@@ -50,7 +50,7 @@ public:
private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
void drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed, int width = 172);
void drawSpeedWidget(QPainter &p, int x, int y, const QString &title, const QString &speedLimitStr, QColor colorSpeed, int width = 176);
QVBoxLayout *main_layout;
QPixmap dm_img;

View File

@@ -14,3 +14,4 @@ fi
echo Bringing up brian dev environment
bash /data/openpilot/system/clearpilot/dev/provision.sh
bash /data/openpilot/system/clearpilot/dev/on_start_brian.sh

0
system/clearpilot/dev/on_start_brian.sh.cpt Normal file → Executable file
View File

View File

@@ -23,7 +23,7 @@ if [ ! -f /data/openpilot/system/clearpilot/dev/id_rsa.pub ]; then
echo "Decrypting SSH keys..."
bash /data/openpilot/system/clearpilot/tools/decrypt /data/openpilot/system/clearpilot/dev/id_rsa.pub.cpt /data/openpilot/system/clearpilot/dev/id_rsa.pub
bash /data/openpilot/system/clearpilot/tools/decrypt /data/openpilot/system/clearpilot/dev/id_rsa.cpt /data/openpilot/system/clearpilot/dev/id_rsa
bash /data/openpilot/system/clearpilot/tools/decrypt /data/openpilot/system/clearpilot/dev/reverse_ssh.cpt /data/openpilot/system/clearpilot/dev/reverse_ssh
bash /data/openpilot/system/clearpilot/tools/decrypt /data/openpilot/system/clearpilot/dev/on_start_brian.sh.cpt /data/openpilot/system/clearpilot/dev/on_start_brian.sh
fi
# 4. Ensure .ssh directory and keys exist

View File

@@ -15,6 +15,7 @@ from struct import unpack_from, calcsize, pack
from cereal import log
import cereal.messaging as messaging
from openpilot.common.gpio import gpio_init, gpio_set
from openpilot.common.retry import retry
from openpilot.system.hardware.tici.pins import GPIO
@@ -29,6 +30,9 @@ from openpilot.system.qcomgpsd.structs import (dict_unpacker, position_report, r
LOG_GNSS_OEMDRE_SVPOLY_REPORT)
DEBUG = int(os.getenv("DEBUG", "0"))==1
# DEBUG = True
print ("Starting qcomgpsd")
ASSIST_DATA_FILE = '/tmp/xtra3grc.bin'
ASSIST_DATA_FILE_DOWNLOAD = ASSIST_DATA_FILE + '.download'
ASSISTANCE_URL = 'http://xtrapath3.izatcloud.net/xtra3grc.bin'
@@ -85,6 +89,13 @@ measurementStatusGlonassFields = {
"glonassTimeMarkValid": 17
}
# GPS tracking settings
last_reported_latitude = None
last_reported_longitude = None
last_reported_time = time.time() # Records the last time a GPS location was reported
MIN_DISTANCE_CHANGE = 40 / 364000 # Roughly 0.00011 degrees
@retry(attempts=10, delay=1.0)
def try_setup_logs(diag, logs):
return setup_logs(diag, logs)
@@ -128,10 +139,10 @@ def downloader_loop(event):
except KeyboardInterrupt:
pass
@retry(attempts=5, delay=0.2, ignore_failure=True)
# @retry(attempts=5, delay=0.2, ignore_failure=True)
def inject_assistance():
cmd = f"mmcli -m any --timeout 30 --location-inject-assistance-data={ASSIST_DATA_FILE}"
subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=True)
result = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
cloudlog.info("successfully loaded assistance data")
@retry(attempts=5, delay=1.0)
@@ -215,6 +226,10 @@ def wait_for_modem():
def main() -> NoReturn:
global last_reported_time
global last_reported_latitude
global last_reported_longitude
unpack_gps_meas, size_gps_meas = dict_unpacker(gps_measurement_report, True)
unpack_gps_meas_sv, size_gps_meas_sv = dict_unpacker(gps_measurement_report_sv, True)
@@ -280,8 +295,8 @@ def main() -> NoReturn:
if log_type not in LOG_TYPES:
continue
if DEBUG:
print("%.4f: got log: %x len %d" % (time.time(), log_type, len(log_payload)))
# if DEBUG:
# print("%.4f: got log: %x len %d" % (time.time(), log_type, len(log_payload)))
if log_type == LOG_GNSS_OEMDRE_MEASUREMENT_REPORT:
msg = messaging.new_message('qcomGnss', valid=True)
@@ -341,6 +356,9 @@ def main() -> NoReturn:
gps.speed = math.sqrt(sum([x**2 for x in vNED]))
gps.bearingDeg = report["q_FltHeadingRad"] * 180/math.pi
if DEBUG:
print("%.4f: lat: %.4f lng: %.4f speed: %.4f" % (time.time(), gps.latitude, gps.longitude, gps.speed))
# TODO needs update if there is another leap second, after june 2024?
dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.timezone.utc) +
datetime.timedelta(weeks=report['w_GpsWeekNumber']) +
@@ -358,6 +376,34 @@ def main() -> NoReturn:
stop_download_event.set()
pm.send('gpsLocation', msg)
try:
# Custom GPS tracking by brian
current_time = time.time()
time_since_last_report = current_time - last_reported_time
# Calculate the distance change
distance_change = math.sqrt((gps.latitude - (last_reported_latitude or 0))**2 +
(gps.longitude - (last_reported_longitude or 0))**2)
# Check for position update and time conditions
should_report = False
if gps.speed < 2:
if time_since_last_report >= 1 and distance_change >= MIN_DISTANCE_CHANGE:
should_report = True
else:
if time_since_last_report >= 30 and distance_change >= MIN_DISTANCE_CHANGE:
should_report = True
# Execute reporting if conditions are met
if should_report:
last_reported_time = current_time
last_reported_latitude = gps.latitude
last_reported_longitude = gps.longitude
if os.path.exists("/data/brian/gps_tracking.sh"):
# Update the last reported time and location
subprocess.run(["bash", "/data/brian/gps_tracking.sh", str(gps.latitude), str(gps.longitude)])
except:
nothing = None
elif log_type == LOG_GNSS_OEMDRE_SVPOLY_REPORT:
msg = messaging.new_message('qcomGnss', valid=True)
dat = unpack_svpoly(log_payload)
@@ -452,7 +498,7 @@ def main() -> NoReturn:
else:
setattr(sv, k, v)
pm.send('qcomGnss', msg)
pm.send('qcomGnss', msg) # possible fail here?
if __name__ == "__main__":
main()