Compare commits
46 Commits
7f63e51658
...
clearpilot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
980f0aac00 | ||
|
|
0fc13d815d | ||
|
|
ac4d7efff1 | ||
|
|
a47fbb140d | ||
|
|
8225319314 | ||
|
|
3eca593af1 | ||
|
|
445138519d | ||
|
|
679a952f51 | ||
|
|
1b9097bc13 | ||
|
|
4c9c211f97 | ||
|
|
c94dc803dd | ||
|
|
33c59eadb3 | ||
|
|
92db8a5913 | ||
|
|
af3cacae53 | ||
|
|
ec7743c460 | ||
|
|
5e80ad8d05 | ||
|
|
a2cf02ea37 | ||
|
|
75c91213a2 | ||
|
|
7f182b7fae | ||
|
|
0c36ffdfde | ||
|
|
4702c22aa3 | ||
|
|
6ef4519798 | ||
|
|
5e4c1e2427 | ||
|
|
94581c908b | ||
|
|
98d7133844 | ||
|
|
3ae97fe0e5 | ||
|
|
51561d3393 | ||
|
|
be595765e4 | ||
|
|
7bb4980119 | ||
|
|
720c9ccbc8 | ||
|
|
9dc2951e07 | ||
|
|
7962409629 | ||
|
|
314e9b5d32 | ||
|
|
2c9e56a579 | ||
|
|
cee8330928 | ||
|
|
9172cb85ee | ||
|
|
ee0a308db6 | ||
|
|
32cbaa1049 | ||
|
|
5d58961187 | ||
|
|
6ee82f77f6 | ||
|
|
2e8654ba7f | ||
|
|
33afb79600 | ||
|
|
48c2f76109 | ||
|
|
00dd71abb2 | ||
|
|
763198bec1 | ||
|
|
a963ea0296 |
@@ -234,10 +234,15 @@ std::unordered_map<std::string, uint32_t> keys = {
|
|||||||
|
|
||||||
{"CarCruiseDisplayActual", PERSISTENT},
|
{"CarCruiseDisplayActual", PERSISTENT},
|
||||||
{"CarSpeedLimit", PERSISTENT},
|
{"CarSpeedLimit", PERSISTENT},
|
||||||
|
|
||||||
|
{"CarSpeedLimitWarning", PERSISTENT},
|
||||||
{"CarSpeedLimitLiteral", PERSISTENT},
|
{"CarSpeedLimitLiteral", PERSISTENT},
|
||||||
{"SpeedLimitLatDesired", PERSISTENT},
|
|
||||||
{"SpeedLimitVTSC", PERSISTENT},
|
// {"SpeedLimitLatDesired", PERSISTENT},
|
||||||
|
// {"SpeedLimitVTSC", PERSISTENT},
|
||||||
|
|
||||||
{"CPTLkasButtonAction", PERSISTENT},
|
{"CPTLkasButtonAction", PERSISTENT},
|
||||||
|
{"ScreenDisaplayMode", PERSISTENT},
|
||||||
|
|
||||||
{"RadarDist", PERSISTENT},
|
{"RadarDist", PERSISTENT},
|
||||||
{"ModelDist", PERSISTENT},
|
{"ModelDist", PERSISTENT},
|
||||||
|
|||||||
1
openpilot/cereal
Symbolic link
1
openpilot/cereal
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cereal/
|
||||||
@@ -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)
|
- disable changing lanes notices (tiny indicator is fine)
|
||||||
|
|
||||||
- speed limit display / over speed display
|
- speed limit display / over speed display
|
||||||
- hack the buttons so we can press them
|
- hack the buttons so we can press them
|
||||||
- auto set speed limit
|
- auto set speed limit
|
||||||
|
|||||||
@@ -1,174 +1,45 @@
|
|||||||
-----
|
- lkas button toggle display off / minimal / full / info
|
||||||
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
|
- revert a bunch of debugging in canfd
|
||||||
|
|
||||||
Notes on speed limit override:
|
- fix it so it reads cruise state and uses it to determine program state exclusively
|
||||||
- we need to capture the original speed and feed it to vtsc and model whule we
|
- always on lat in particular
|
||||||
are under speed adjustment
|
|
||||||
|
|
||||||
------
|
- make override a state that can happen on always on lateral
|
||||||
- fix lane lines
|
|
||||||
- fix always on lateral detection
|
|
||||||
- position override under 25 mph suspends assist
|
|
||||||
|
|
||||||
- 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
|
- implement speed limit controller as a simple Warning
|
||||||
- test that lkas button creates an alert, it should
|
|
||||||
|
|
||||||
- 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
|
--- TRIP RELEASE ---
|
||||||
- dress up ui
|
|
||||||
|
|
||||||
- add debug elements to ui with a boolean at top of onroad.cc to enable/disable:
|
- configure orangepi wifi selector
|
||||||
- curviture
|
- can i have it use phone bt tether?
|
||||||
- current speed limit
|
- fix gps
|
||||||
- current cruise speed
|
- implement new onroad settings
|
||||||
- current experimental mode speed
|
- implement new offroad settings
|
||||||
- current distance to lead based on radar
|
- implement debug console (make it actually useful)
|
||||||
- current distance to lead based on model draw distance
|
- implement dash cam
|
||||||
- current speed of lead
|
- 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
|
- CRAIG RELEASE -
|
||||||
- of computed path, and don't show side lane boundaries
|
|
||||||
|
|
||||||
- make side lanes 10% wider and the disengage mode 10% brighter
|
- implement logo selector
|
||||||
- make 25% of side lanes 50% darker than base
|
- update models, sync important changes from main
|
||||||
|
- update installer
|
||||||
|
|
||||||
- hello world alert triggered by lkas btn
|
- PUBLIC RELEASE -
|
||||||
- hello world bootstrap dashboard
|
|
||||||
|
|
||||||
- button stuff:
|
Hyundai CLSC
|
||||||
- read paddle left (for full nudgeless lane change + blinker, reset to drive)
|
Hyundai Paddle shifter lane change
|
||||||
- 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
|
|
||||||
@@ -123,45 +123,41 @@ class CarController(CarControllerBase):
|
|||||||
if self.frame % 5 == 0 and (not hda2 or hda2_long):
|
if self.frame % 5 == 0 and (not hda2 or hda2_long):
|
||||||
# CLEARPILOT TEST self.CS.lkas_enabled
|
# CLEARPILOT TEST self.CS.lkas_enabled
|
||||||
# can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CC.latActive))
|
# can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CC.latActive))
|
||||||
params_memory = Params("/dev/shm/params")
|
# params_memory = Params("/dev/shm/params")
|
||||||
lkas_icon = params_memory.get_bool("CPTLkasButtonAction") or CS.lkas_enabled
|
# 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))
|
# 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
|
# blinkers
|
||||||
if hda2 and self.CP.flags & HyundaiFlags.ENABLE_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))
|
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")
|
||||||
params_memory = Params("/dev/shm/params")
|
# if params_memory.get_bool("CPTLkasButtonAction"):
|
||||||
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 self.frame % 10 == 0:
|
# if self.frame % 10 == 0:
|
||||||
# for _ in range(20):
|
# 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))
|
# can_sends.append(hyundaicanfd.create_buttons_alt(self.packer, self.CP, self.CAN, CS.buttons_counter+1, Buttons.SET_DECEL))
|
||||||
# print("Decel")
|
|
||||||
# can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
# 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_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))
|
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
|
||||||
# print("Debug cancel executed")
|
# print("Debug cancel executed")
|
||||||
|
|
||||||
if self.CP.openpilotLongitudinalControl:
|
if self.CP.openpilotLongitudinalControl: # or CS.experimentalMode:
|
||||||
if hda2:
|
if hda2:
|
||||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||||
if self.frame % 2 == 0:
|
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,
|
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))
|
set_speed_in_units, hud_control))
|
||||||
self.accel_last = accel
|
self.accel_last = accel
|
||||||
else:
|
# else:
|
||||||
# Clearpilot
|
# Clearpilot
|
||||||
# If cruise control was enabled or idle on start, force cancel
|
# If cruise control was enabled or idle on start, force cancel
|
||||||
# if CS.fix_main_enabled_cancel_main:
|
# if CS.fix_main_enabled_cancel_main:
|
||||||
# CS.fix_main_enabled_cancel_main = False
|
# CS.fix_main_enabled_cancel_main = False
|
||||||
# CC.cruiseControl.cancel = True
|
# CC.cruiseControl.cancel = True
|
||||||
# button presses
|
# 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:
|
else:
|
||||||
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
|
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,
|
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
|
||||||
@@ -217,7 +213,7 @@ class CarController(CarControllerBase):
|
|||||||
self.last_button_frame = self.frame
|
self.last_button_frame = self.frame
|
||||||
else:
|
else:
|
||||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.25:
|
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"):
|
# if params_memory.get_bool("CPTLkasButtonAction"):
|
||||||
# params_memory.put_bool("CPTLkasButtonAction", False)
|
# params_memory.put_bool("CPTLkasButtonAction", False)
|
||||||
# CC.cruiseControl.cancel = True
|
# CC.cruiseControl.cancel = True
|
||||||
@@ -228,6 +224,7 @@ class CarController(CarControllerBase):
|
|||||||
# pass
|
# pass
|
||||||
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
|
# can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info))
|
||||||
# for _ in range(20):
|
# 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:
|
# 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))
|
# 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")
|
# print("Try Cancel Button Alt")
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class CarState(CarStateBase):
|
|||||||
self.lkas_previously_enabled = self.lkas_enabled
|
self.lkas_previously_enabled = self.lkas_enabled
|
||||||
self.lkas_enabled = cp.vl["BCM_PO_11"]["LFA_Pressed"]
|
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("CarSpeedLimit", self.calculate_speed_limit(cp, cp_cam) * speed_conv)
|
||||||
self.params_memory.put_float("CarCruiseDisplayActual", cp_cruise.vl["SCC11"]["VSetDis"])
|
self.params_memory.put_float("CarCruiseDisplayActual", cp_cruise.vl["SCC11"]["VSetDis"])
|
||||||
|
|
||||||
@@ -417,7 +417,7 @@ class CarState(CarStateBase):
|
|||||||
|
|
||||||
# print("Set limit")
|
# print("Set limit")
|
||||||
# print(self.calculate_speed_limit(cp, cp_cam))
|
# 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)
|
self.params_memory.put_float("CarSpeedLimit", self.calculate_speed_limit(cp, cp_cam) * speed_factor)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@@ -236,10 +236,10 @@ def create_acc_cancel(packer, CP, CAN, cruise_info_copy):
|
|||||||
|
|
||||||
# CLEARPILOT changed HDA icons
|
# CLEARPILOT changed HDA icons
|
||||||
# This doesn't appear to do anything on my tucson
|
# 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 = {
|
values = {
|
||||||
"HDA_ICON": 0, # Literally shows HDA. Maybe we use this to indicate experimental mode
|
"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)
|
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
0
selfdrive/clearpilot/resource/debug_ui_scene.png
Normal file → Executable file
0
selfdrive/clearpilot/resource/debug_ui_scene.png
Normal file → Executable file
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.0 MiB |
@@ -77,6 +77,7 @@ class Controls:
|
|||||||
self.params_storage = Params("/persist/params")
|
self.params_storage = Params("/persist/params")
|
||||||
|
|
||||||
self.params_memory.put_bool("CPTLkasButtonAction", False)
|
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
|
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):
|
def clearpilot_state_control(self, CC, CS):
|
||||||
if any(be.pressed and be.type == FrogPilotButtonType.lkas for be in CS.buttonEvents):
|
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")
|
|
||||||
|
|
||||||
self.params_memory.put_int("SpeedLimitLatDesired", CC.actuators.speed * CV.MS_TO_MPH )
|
# if self.params_memory.get_bool("CPTLkasButtonAction"):
|
||||||
# CC.actuators.speed
|
# self.params_memory.put_bool("CPTLkasButtonAction", False)
|
||||||
# print ("Alive")
|
# 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 )
|
||||||
return CC
|
return CC
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ class FrogPilotPlanner:
|
|||||||
|
|
||||||
frogpilotPlan.vtscControllingCurve = bool(self.mtsc_target > self.vtsc_target)
|
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)
|
pm.send('frogpilotPlan', frogpilot_plan_send)
|
||||||
|
|
||||||
|
|||||||
0
selfdrive/frogpilot/screenrecorder/moc_screenrecorder.cc
Normal file → Executable file
0
selfdrive/frogpilot/screenrecorder/moc_screenrecorder.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_control_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_control_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_vehicle_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_vehicle_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_visual_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/offroad/moc_visual_settings.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/widgets/moc_frogpilot_controls.cc
Normal file → Executable file
0
selfdrive/frogpilot/ui/qt/widgets/moc_frogpilot_controls.cc
Normal file → Executable file
@@ -149,6 +149,9 @@ def manager_init(frogpilot_functions) -> None:
|
|||||||
("ForceFingerprint", "0"),
|
("ForceFingerprint", "0"),
|
||||||
("ForceMPHDashboard", "0"),
|
("ForceMPHDashboard", "0"),
|
||||||
("FPSCounter", "0"),
|
("FPSCounter", "0"),
|
||||||
|
("FrogPilotDrives", "0"),
|
||||||
|
("FrogPilotKilometers", "0"),
|
||||||
|
("FrogPilotMinutes", "0"),
|
||||||
("FrogsGoMooTune", "1"),
|
("FrogsGoMooTune", "1"),
|
||||||
("FullMap", "0"),
|
("FullMap", "0"),
|
||||||
("GasRegenCmd", "0"),
|
("GasRegenCmd", "0"),
|
||||||
@@ -169,7 +172,7 @@ def manager_init(frogpilot_functions) -> None:
|
|||||||
("IncreaseThermalLimits", "0"),
|
("IncreaseThermalLimits", "0"),
|
||||||
("LaneChangeTime", "0"),
|
("LaneChangeTime", "0"),
|
||||||
("LaneDetectionWidth", "60"),
|
("LaneDetectionWidth", "60"),
|
||||||
("LaneLinesWidth", "2"),
|
("LaneLinesWidth", "4"),
|
||||||
("LateralTune", "1"),
|
("LateralTune", "1"),
|
||||||
("LeadDepartingAlert", "0"),
|
("LeadDepartingAlert", "0"),
|
||||||
("LeadDetectionThreshold", "35"),
|
("LeadDetectionThreshold", "35"),
|
||||||
@@ -179,14 +182,6 @@ def manager_init(frogpilot_functions) -> None:
|
|||||||
("LongPitch", "1"),
|
("LongPitch", "1"),
|
||||||
("LoudBlindspotAlert", "0"),
|
("LoudBlindspotAlert", "0"),
|
||||||
("LowVoltageShutdown", "11.8"),
|
("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", ""),
|
("MapsSelected", ""),
|
||||||
("MapboxPublicKey", ""),
|
("MapboxPublicKey", ""),
|
||||||
("MapboxSecretKey", ""),
|
("MapboxSecretKey", ""),
|
||||||
@@ -277,7 +272,6 @@ def manager_init(frogpilot_functions) -> None:
|
|||||||
("TrafficFollow", "0.5"),
|
("TrafficFollow", "0.5"),
|
||||||
("TrafficJerk", "1"),
|
("TrafficJerk", "1"),
|
||||||
("TrafficMode", "0"),
|
("TrafficMode", "0"),
|
||||||
("Tuning", "1"),
|
|
||||||
("TurnAggressiveness", "100"),
|
("TurnAggressiveness", "100"),
|
||||||
("TurnDesires", "0"),
|
("TurnDesires", "0"),
|
||||||
("UnlimitedLength", "1"),
|
("UnlimitedLength", "1"),
|
||||||
@@ -341,14 +335,14 @@ def manager_init(frogpilot_functions) -> None:
|
|||||||
os.environ['CLEAN'] = '1'
|
os.environ['CLEAN'] = '1'
|
||||||
|
|
||||||
# init logging
|
# init logging
|
||||||
# sentry.init(sentry.SentryProject.SELFDRIVE)
|
sentry.init(sentry.SentryProject.SELFDRIVE)
|
||||||
# cloudlog.bind_global(dongle_id=dongle_id,
|
cloudlog.bind_global(dongle_id=dongle_id,
|
||||||
# version=get_version(),
|
version=get_version(),
|
||||||
# origin=get_normalized_origin(),
|
origin=get_normalized_origin(),
|
||||||
# branch=get_short_branch(),
|
branch=get_short_branch(),
|
||||||
# commit=get_commit(),
|
commit=get_commit(),
|
||||||
# dirty=is_dirty(),
|
dirty=is_dirty(),
|
||||||
# device=HARDWARE.get_device_type())
|
device=HARDWARE.get_device_type())
|
||||||
|
|
||||||
# preimport all processes
|
# preimport all processes
|
||||||
for p in managed_processes.values():
|
for p in managed_processes.values():
|
||||||
@@ -366,11 +360,8 @@ def manager_cleanup() -> None:
|
|||||||
|
|
||||||
cloudlog.info("everything is dead")
|
cloudlog.info("everything is dead")
|
||||||
|
|
||||||
last_running = ""
|
|
||||||
|
|
||||||
def manager_thread(frogpilot_functions) -> None:
|
def manager_thread(frogpilot_functions) -> None:
|
||||||
global last_running
|
|
||||||
|
|
||||||
cloudlog.bind(daemon="manager")
|
cloudlog.bind(daemon="manager")
|
||||||
cloudlog.info("manager start")
|
cloudlog.info("manager start")
|
||||||
cloudlog.info({"environ": os.environ})
|
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)
|
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)
|
for p in managed_processes.values() if p.proc)
|
||||||
|
|
||||||
# clearpilot
|
|
||||||
if (running != last_running):
|
|
||||||
print(running)
|
print(running)
|
||||||
cloudlog.debug(running)
|
cloudlog.debug(running)
|
||||||
last_running = running
|
|
||||||
|
|
||||||
# send managerState
|
# send managerState
|
||||||
msg = messaging.new_message('managerState', valid=True)
|
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
|
# Exit main loop when uninstall/shutdown/reboot is needed
|
||||||
shutdown = False
|
shutdown = False
|
||||||
for param in ("DoUninstall", "DoShutdown", "DoReboot", "DoSoftReboot"):
|
for param in ("DoUninstall", "DoShutdown", "DoReboot"):
|
||||||
if params.get_bool(param):
|
if params.get_bool(param):
|
||||||
shutdown = True
|
shutdown = True
|
||||||
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
|
params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}")
|
||||||
@@ -477,9 +464,6 @@ def main() -> None:
|
|||||||
elif params.get_bool("DoReboot"):
|
elif params.get_bool("DoReboot"):
|
||||||
cloudlog.warning("reboot")
|
cloudlog.warning("reboot")
|
||||||
HARDWARE.reboot()
|
HARDWARE.reboot()
|
||||||
elif params.get_bool("DoSoftReboot"):
|
|
||||||
cloudlog.warning("softreboot")
|
|
||||||
HARDWARE.soft_reboot()
|
|
||||||
elif params.get_bool("DoShutdown"):
|
elif params.get_bool("DoShutdown"):
|
||||||
cloudlog.warning("shutdown")
|
cloudlog.warning("shutdown")
|
||||||
HARDWARE.shutdown()
|
HARDWARE.shutdown()
|
||||||
|
|||||||
519
selfdrive/manager/manager_wip.txt
Normal file
519
selfdrive/manager/manager_wip.txt
Normal 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)
|
||||||
@@ -2,6 +2,7 @@ import importlib
|
|||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import struct
|
import struct
|
||||||
|
import datetime
|
||||||
import time
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections.abc import Callable, ValuesView
|
from collections.abc import Callable, ValuesView
|
||||||
@@ -20,6 +21,11 @@ from openpilot.common.swaglog import cloudlog
|
|||||||
WATCHDOG_FN = "/dev/shm/wd_"
|
WATCHDOG_FN = "/dev/shm/wd_"
|
||||||
ENABLE_WATCHDOG = os.getenv("NO_WATCHDOG") is None
|
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:
|
def launcher(proc: str, name: str) -> None:
|
||||||
try:
|
try:
|
||||||
@@ -54,7 +60,6 @@ def nativelauncher(pargs: list[str], cwd: str, name: str) -> None:
|
|||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
os.execvp(pargs[0], pargs)
|
os.execvp(pargs[0], pargs)
|
||||||
|
|
||||||
|
|
||||||
def join_process(process: Process, timeout: float) -> None:
|
def join_process(process: Process, timeout: float) -> None:
|
||||||
# Process().join(timeout) will hang due to a python 3 bug: https://bugs.python.org/issue28382
|
# Process().join(timeout) will hang due to a python 3 bug: https://bugs.python.org/issue28382
|
||||||
# We have to poll the exitcode instead
|
# We have to poll the exitcode instead
|
||||||
@@ -190,6 +195,9 @@ class NativeProcess(ManagerProcess):
|
|||||||
if self.proc is not None:
|
if self.proc is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
global _log_dir
|
||||||
|
log_path = _log_dir+"/"+self.name+".log"
|
||||||
|
|
||||||
cwd = os.path.join(BASEDIR, self.cwd)
|
cwd = os.path.join(BASEDIR, self.cwd)
|
||||||
cloudlog.info(f"starting process {self.name}")
|
cloudlog.info(f"starting process {self.name}")
|
||||||
self.proc = Process(name=self.name, target=self.launcher, args=(self.cmdline, cwd, self.name))
|
self.proc = Process(name=self.name, target=self.launcher, args=(self.cmdline, cwd, self.name))
|
||||||
@@ -221,6 +229,8 @@ class PythonProcess(ManagerProcess):
|
|||||||
if self.proc is not None:
|
if self.proc is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
global _log_dir
|
||||||
|
log_path = _log_dir+"/"+self.name+".log"
|
||||||
cloudlog.info(f"starting python {self.module}")
|
cloudlog.info(f"starting python {self.module}")
|
||||||
self.proc = Process(name=self.name, target=self.launcher, args=(self.module, self.name))
|
self.proc = Process(name=self.name, target=self.launcher, args=(self.module, self.name))
|
||||||
self.proc.start()
|
self.proc.start()
|
||||||
@@ -238,6 +248,7 @@ class DaemonProcess(ManagerProcess):
|
|||||||
self.enabled = enabled
|
self.enabled = enabled
|
||||||
self.params = None
|
self.params = None
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def should_run(started, params, CP):
|
def should_run(started, params, CP):
|
||||||
return True
|
return True
|
||||||
@@ -249,6 +260,9 @@ class DaemonProcess(ManagerProcess):
|
|||||||
if self.params is None:
|
if self.params is None:
|
||||||
self.params = Params()
|
self.params = Params()
|
||||||
|
|
||||||
|
global _log_dir
|
||||||
|
log_path = _log_dir+"/"+self.name+".log"
|
||||||
|
|
||||||
pid = self.params.get(self.param_name, encoding='utf-8')
|
pid = self.params.get(self.param_name, encoding='utf-8')
|
||||||
if pid is not None:
|
if pid is not None:
|
||||||
try:
|
try:
|
||||||
@@ -264,8 +278,8 @@ class DaemonProcess(ManagerProcess):
|
|||||||
cloudlog.info(f"starting daemon {self.name}")
|
cloudlog.info(f"starting daemon {self.name}")
|
||||||
proc = subprocess.Popen(['python', '-m', self.module],
|
proc = subprocess.Popen(['python', '-m', self.module],
|
||||||
stdin=open('/dev/null'),
|
stdin=open('/dev/null'),
|
||||||
stdout=open('/dev/null', 'w'),
|
stdout=open(log_path, 'a'),
|
||||||
stderr=open('/dev/null', 'w'),
|
stderr=subprocess.STDOUT,
|
||||||
preexec_fn=os.setpgrp)
|
preexec_fn=os.setpgrp)
|
||||||
|
|
||||||
self.params.put(self.param_name, str(proc.pid))
|
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,
|
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None,
|
||||||
not_run: list[str] | None=None) -> list[ManagerProcess]:
|
not_run: list[str] | None=None) -> list[ManagerProcess]:
|
||||||
|
|
||||||
if not_run is None:
|
if not_run is None:
|
||||||
not_run = []
|
not_run = []
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ def ublox(started, params, CP: car.CarParams) -> bool:
|
|||||||
use_ublox = ublox_available()
|
use_ublox = ublox_available()
|
||||||
if use_ublox != params.get_bool("UbloxAvailable"):
|
if use_ublox != params.get_bool("UbloxAvailable"):
|
||||||
params.put_bool("UbloxAvailable", use_ublox)
|
params.put_bool("UbloxAvailable", use_ublox)
|
||||||
return started and use_ublox
|
return use_ublox
|
||||||
|
|
||||||
def qcomgps(started, params, CP: car.CarParams) -> bool:
|
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:
|
def always_run(started, params, CP: car.CarParams) -> bool:
|
||||||
return True
|
return True
|
||||||
@@ -78,13 +78,13 @@ procs = [
|
|||||||
PythonProcess("controlsd", "selfdrive.controls.controlsd", only_onroad),
|
PythonProcess("controlsd", "selfdrive.controls.controlsd", only_onroad),
|
||||||
PythonProcess("deleter", "system.loggerd.deleter", always_run),
|
PythonProcess("deleter", "system.loggerd.deleter", always_run),
|
||||||
PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(not PC or WEBCAM)),
|
PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(not PC or WEBCAM)),
|
||||||
#PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI),
|
# PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), # Fixme
|
||||||
#PythonProcess("ugpsd", "system.ugpsd", only_onroad, enabled=TICI),
|
# PythonProcess("ugpsd", "system.ugpsd", only_onroad, enabled=TICI),
|
||||||
#PythonProcess("navd", "selfdrive.navd.navd", only_onroad),
|
#PythonProcess("navd", "selfdrive.navd.navd", only_onroad),
|
||||||
PythonProcess("pandad", "selfdrive.boardd.pandad", always_run),
|
PythonProcess("pandad", "selfdrive.boardd.pandad", always_run),
|
||||||
PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad),
|
PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad),
|
||||||
#NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
|
NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI),
|
||||||
#PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
|
PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI),
|
||||||
PythonProcess("plannerd", "selfdrive.controls.plannerd", only_onroad),
|
PythonProcess("plannerd", "selfdrive.controls.plannerd", only_onroad),
|
||||||
PythonProcess("radard", "selfdrive.controls.radard", only_onroad),
|
PythonProcess("radard", "selfdrive.controls.radard", only_onroad),
|
||||||
PythonProcess("thermald", "selfdrive.thermald.thermald", always_run),
|
PythonProcess("thermald", "selfdrive.thermald.thermald", always_run),
|
||||||
|
|||||||
251
selfdrive/manager/process_wip.txt
Normal file
251
selfdrive/manager/process_wip.txt
Normal 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
|
||||||
350
selfdrive/manager/process_wip2.txt
Normal file
350
selfdrive/manager/process_wip2.txt
Normal 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
|
||||||
@@ -29,6 +29,8 @@
|
|||||||
// p.restore();
|
// p.restore();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
bool alert_is_visible = false;
|
||||||
|
|
||||||
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) {
|
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) {
|
||||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||||
main_layout->setMargin(UI_BORDER_SIZE);
|
main_layout->setMargin(UI_BORDER_SIZE);
|
||||||
@@ -175,52 +177,6 @@ void OnroadWindow::paintEvent(QPaintEvent *event) {
|
|||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
|
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();
|
QString logicsDisplayString = QString();
|
||||||
if (scene.show_jerk) {
|
if (scene.show_jerk) {
|
||||||
logicsDisplayString += QString("Acceleration Jerk: %1 (%2%3) | Speed Jerk: %4 (%5%6) | ")
|
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 *****
|
// ***** onroad widgets *****
|
||||||
|
|
||||||
// OnroadAlerts
|
// OnroadAlerts
|
||||||
@@ -270,6 +234,8 @@ void OnroadAlerts::updateAlert(const Alert &a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
||||||
|
alert_is_visible = false;
|
||||||
|
|
||||||
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
|
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -278,6 +244,8 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alert_is_visible = true;
|
||||||
|
|
||||||
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = {
|
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = {
|
||||||
{cereal::ControlsState::AlertSize::SMALL, 271},
|
{cereal::ControlsState::AlertSize::SMALL, 271},
|
||||||
{cereal::ControlsState::AlertSize::MID, 420},
|
{cereal::ControlsState::AlertSize::MID, 420},
|
||||||
@@ -420,8 +388,20 @@ if (edgeColor != bgColor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AnnotatedCameraWidget::drawHud(QPainter &p) {
|
void AnnotatedCameraWidget::drawHud(QPainter &p) {
|
||||||
|
// Blank when screenDisplayMode=1
|
||||||
p.save();
|
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
|
// Header gradient
|
||||||
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
|
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
|
||||||
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
|
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
|
||||||
@@ -438,20 +418,20 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
|
|||||||
p.restore();
|
p.restore();
|
||||||
|
|
||||||
// if (!scene.hide_max_speed) {
|
// 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
|
// // Todo: needs to be changed to calculate off of actual speed limit for release
|
||||||
QString speedLimitStr = QString::number(paramsMemory.getInt("CarSpeedLimitLiteral"));
|
// QString speedLimitStr = QString::number(paramsMemory.getInt("CarSpeedLimitLiteral"));
|
||||||
drawSpeedWidget(p, 60, 45 + (225), QString("Limit"), speedLimitStr, QColor(0xff, 0xff, 0xff));
|
// 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
|
// // Todo: needs to be changed to calculate off of actual speed limit for release
|
||||||
QString SpeedLimitLatDesired = QString::number(paramsMemory.getInt("SpeedLimitLatDesired"));
|
// QString SpeedLimitLatDesired = QString::number(paramsMemory.getInt("SpeedLimitLatDesired"));
|
||||||
drawSpeedWidget(p, 60, 45 + (225 * 2), QString("Exp"), SpeedLimitLatDesired, QColor(0xff, 0xff, 0xff));
|
// 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
|
// // Todo: needs to be changed to calculate off of actual speed limit for release
|
||||||
QString adjustedCruise = QString::number(paramsMemory.getInt("SpeedLimitVTSC"));
|
// QString adjustedCruise = QString::number(paramsMemory.getInt("SpeedLimitVTSC"));
|
||||||
drawSpeedWidget(p, 60, 45 + (225 * 3), QString("VTSC"), adjustedCruise, QColor(0xff, 0xff, 0xff));
|
// drawSpeedWidget(p, 60, 45 + (225 * 3), QString("VTSC"), adjustedCruise, QColor(0xff, 0xff, 0xff));
|
||||||
|
|
||||||
// Todo: lead speed
|
// Todo: lead speed
|
||||||
// Todo: Experimental speed
|
// Todo: Experimental speed
|
||||||
@@ -881,7 +861,8 @@ void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) {
|
|||||||
const auto &lead = model.getLeadsV3()[i];
|
const auto &lead = model.getLeadsV3()[i];
|
||||||
auto lead_drel = lead.getX()[0];
|
auto lead_drel = lead.getX()[0];
|
||||||
if (lead.getProb() > 0.5 && (prev_drel < 0 || std::abs(lead_drel - prev_drel) > 3.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;
|
prev_drel = lead_drel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
|
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;
|
QVBoxLayout *main_layout;
|
||||||
QPixmap dm_img;
|
QPixmap dm_img;
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ fi
|
|||||||
echo Bringing up brian dev environment
|
echo Bringing up brian dev environment
|
||||||
|
|
||||||
bash /data/openpilot/system/clearpilot/dev/provision.sh
|
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
0
system/clearpilot/dev/on_start_brian.sh.cpt
Normal file → Executable file
@@ -23,7 +23,7 @@ if [ ! -f /data/openpilot/system/clearpilot/dev/id_rsa.pub ]; then
|
|||||||
echo "Decrypting SSH keys..."
|
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.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/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
|
fi
|
||||||
|
|
||||||
# 4. Ensure .ssh directory and keys exist
|
# 4. Ensure .ssh directory and keys exist
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from struct import unpack_from, calcsize, pack
|
|||||||
|
|
||||||
from cereal import log
|
from cereal import log
|
||||||
import cereal.messaging as messaging
|
import cereal.messaging as messaging
|
||||||
|
|
||||||
from openpilot.common.gpio import gpio_init, gpio_set
|
from openpilot.common.gpio import gpio_init, gpio_set
|
||||||
from openpilot.common.retry import retry
|
from openpilot.common.retry import retry
|
||||||
from openpilot.system.hardware.tici.pins import GPIO
|
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)
|
LOG_GNSS_OEMDRE_SVPOLY_REPORT)
|
||||||
|
|
||||||
DEBUG = int(os.getenv("DEBUG", "0"))==1
|
DEBUG = int(os.getenv("DEBUG", "0"))==1
|
||||||
|
# DEBUG = True
|
||||||
|
print ("Starting qcomgpsd")
|
||||||
|
|
||||||
ASSIST_DATA_FILE = '/tmp/xtra3grc.bin'
|
ASSIST_DATA_FILE = '/tmp/xtra3grc.bin'
|
||||||
ASSIST_DATA_FILE_DOWNLOAD = ASSIST_DATA_FILE + '.download'
|
ASSIST_DATA_FILE_DOWNLOAD = ASSIST_DATA_FILE + '.download'
|
||||||
ASSISTANCE_URL = 'http://xtrapath3.izatcloud.net/xtra3grc.bin'
|
ASSISTANCE_URL = 'http://xtrapath3.izatcloud.net/xtra3grc.bin'
|
||||||
@@ -85,6 +89,13 @@ measurementStatusGlonassFields = {
|
|||||||
"glonassTimeMarkValid": 17
|
"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)
|
@retry(attempts=10, delay=1.0)
|
||||||
def try_setup_logs(diag, logs):
|
def try_setup_logs(diag, logs):
|
||||||
return setup_logs(diag, logs)
|
return setup_logs(diag, logs)
|
||||||
@@ -128,10 +139,10 @@ def downloader_loop(event):
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@retry(attempts=5, delay=0.2, ignore_failure=True)
|
# @retry(attempts=5, delay=0.2, ignore_failure=True)
|
||||||
def inject_assistance():
|
def inject_assistance():
|
||||||
cmd = f"mmcli -m any --timeout 30 --location-inject-assistance-data={ASSIST_DATA_FILE}"
|
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")
|
cloudlog.info("successfully loaded assistance data")
|
||||||
|
|
||||||
@retry(attempts=5, delay=1.0)
|
@retry(attempts=5, delay=1.0)
|
||||||
@@ -215,6 +226,10 @@ def wait_for_modem():
|
|||||||
|
|
||||||
|
|
||||||
def main() -> NoReturn:
|
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, size_gps_meas = dict_unpacker(gps_measurement_report, True)
|
||||||
unpack_gps_meas_sv, size_gps_meas_sv = dict_unpacker(gps_measurement_report_sv, 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:
|
if log_type not in LOG_TYPES:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if DEBUG:
|
# if DEBUG:
|
||||||
print("%.4f: got log: %x len %d" % (time.time(), log_type, len(log_payload)))
|
# print("%.4f: got log: %x len %d" % (time.time(), log_type, len(log_payload)))
|
||||||
|
|
||||||
if log_type == LOG_GNSS_OEMDRE_MEASUREMENT_REPORT:
|
if log_type == LOG_GNSS_OEMDRE_MEASUREMENT_REPORT:
|
||||||
msg = messaging.new_message('qcomGnss', valid=True)
|
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.speed = math.sqrt(sum([x**2 for x in vNED]))
|
||||||
gps.bearingDeg = report["q_FltHeadingRad"] * 180/math.pi
|
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?
|
# 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) +
|
dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.timezone.utc) +
|
||||||
datetime.timedelta(weeks=report['w_GpsWeekNumber']) +
|
datetime.timedelta(weeks=report['w_GpsWeekNumber']) +
|
||||||
@@ -358,6 +376,34 @@ def main() -> NoReturn:
|
|||||||
stop_download_event.set()
|
stop_download_event.set()
|
||||||
pm.send('gpsLocation', msg)
|
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:
|
elif log_type == LOG_GNSS_OEMDRE_SVPOLY_REPORT:
|
||||||
msg = messaging.new_message('qcomGnss', valid=True)
|
msg = messaging.new_message('qcomGnss', valid=True)
|
||||||
dat = unpack_svpoly(log_payload)
|
dat = unpack_svpoly(log_payload)
|
||||||
@@ -452,7 +498,7 @@ def main() -> NoReturn:
|
|||||||
else:
|
else:
|
||||||
setattr(sv, k, v)
|
setattr(sv, k, v)
|
||||||
|
|
||||||
pm.send('qcomGnss', msg)
|
pm.send('qcomGnss', msg) # possible fail here?
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user