openpilot v0.2 release

v0.2
Vehicle Researcher 2016-12-12 17:47:46 -08:00
parent a7e099c946
commit 449b482cc3
47 changed files with 1847 additions and 1355 deletions

View File

@ -0,0 +1,19 @@
FROM ubuntu:14.04
ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y build-essential screen wget bzip2 git libglib2.0-0
RUN wget -nv -O /tmp/anaconda.sh https://repo.continuum.io/archive/Anaconda2-4.2.0-Linux-x86_64.sh && \
/bin/bash /tmp/anaconda.sh -b -p /opt/conda && \
rm /tmp/anaconda.sh
ENV PATH /opt/conda/bin:$PATH
RUN conda install numpy==1.11.2 && conda install scipy==0.18.1
COPY requirements_openpilot.txt /tmp/
RUN pip install -r /tmp/requirements_openpilot.txt
ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH
COPY . /tmp/openpilot

View File

@ -42,26 +42,42 @@ Directory structure
- assets -- Fonts for ui
- boardd -- Daemon to talk to the board
- calibrationd -- Camera calibration server
- car -- Code that talks to the car and implements CarInterface
- common -- Shared C/C++ code for the daemons
- controls -- Python controls (PID loops etc) for the car
- logcatd -- Android logcat as a service
- loggerd -- Logger and uploader of car data
- radar -- Code that talks to the radar and implements RadarInterface
- sensord -- IMU / GPS interface code
- test/plant -- Car simulator running code through virtual maneuvers
- ui -- The UI
- visiond -- embedded vision pipeline
To understand how the services interact, see `common/services.py`
Testing on PC
------
There is rudimentary infrastructure to run a basic simulation and generate a report of openpilot's behavior in different scenarios.
```bash
# Requires working docker
./run_docker_tests.sh
```
The results are written to `selfdrive/test/plant/out/index.html`
More extensive testing infrastructure and simulation environments are coming soon.
Adding Car Support
------
It should be relatively easy to add support for the Honda CR-V Touring. The brake message is the same. Steering has a slightly different message with a different message id. Sniff CAN while using LKAS to find it.
The Honda Accord uses different signalling for the steering and probably requires new hardware.
The Honda Accord uses different signaling for the steering and probably requires new hardware.
Adding other manufacturers besides Honda/Acura is doable but will be more of an undertaking.
User Data / chffr Account / Crash Reporting
------

19
RELEASES.md 100644
View File

@ -0,0 +1,19 @@
Version 0.2 (2016-12-12)
=========================
* Car/Radar abstraction layers have shipped, see cereal/car.capnp
* controlsd has been refactored
* Shipped plant model and testing maneuvers
* visiond exits more gracefully now
* Hardware encoder in visiond should always init
* ui now turns off the screen after 30 seconds
* Switch to openpilot release branch for future releases
* Added preliminary Docker container to run tests on PC
Version 0.1 (2016-11-29)
=========================
* Initial release of openpilot
* Adaptive cruise control is working
* Lane keep assist is working
* Support for Acura ILX 2016 with AcuraWatch Plus
* Support for Honda Civic 2016 Touring Edition

14
TODO.md
View File

@ -1,14 +0,0 @@
TODO
======
An incomplete list of known issues and desired featues.
- TX and RX amounts on UI are wrong for a few frames at startup because we
subtract (total sent - 0). We should initialize sent bytes before displaying.
- Rewrite common/dbc.py to be faster and cleaner, potentially in C++.
- Add module and class level documentation where appropriate.
- Fix lock file cleanup so there isn't always 1 pending upload when the vehicle
shuts off.

View File

@ -2,6 +2,7 @@
//#define CAN_LOOPBACK_MODE
//#define USE_INTERNAL_OSC
//#define OLD_BOARD
//#define ENABLE_CURRENT_SENSOR
#define USB_VID 0xbbaa
#define USB_PID 0xddcc
@ -257,7 +258,11 @@ int get_health_pkt(void *dat) {
uint8_t gas_interceptor_detected;
} *health = dat;
health->voltage = adc_get(ADCCHAN_VOLTAGE);
#ifdef ENABLE_CURRENT_SENSOR
health->current = adc_get(ADCCHAN_CURRENT);
#else
health->current = 0;
#endif
health->started = (GPIOC->IDR & (1 << 13)) != 0;
health->controls_allowed = controls_allowed;
health->gas_interceptor_detected = gas_interceptor_detected;

View File

@ -4,4 +4,5 @@ capnp.remove_import_hook()
CEREAL_PATH = os.path.dirname(os.path.abspath(__file__))
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))

172
cereal/car.capnp 100644
View File

@ -0,0 +1,172 @@
using Cxx = import "c++.capnp";
$Cxx.namespace("cereal");
@0x8e2af1e708af8b8d;
# ******* main car state @ 100hz *******
# all speeds in m/s
struct CarState {
errors @0: List(Error);
# car speed
vEgo @1 :Float32; # best estimate of speed
wheelSpeeds @2 :WheelSpeeds;
# gas pedal, 0.0-1.0
gas @3 :Float32; # this is user + computer
gasPressed @4 :Bool; # this is user pedal only
# brake pedal, 0.0-1.0
brake @5 :Float32; # this is user pedal only
brakePressed @6 :Bool; # this is user pedal only
# steering wheel
steeringAngle @7 :Float32; # deg
steeringTorque @8 :Float32; # TODO: standardize units
steeringPressed @9 :Bool; # if the user is using the steering wheel
# cruise state
cruiseState @10 :CruiseState;
# button presses
buttonEvents @11 :List(ButtonEvent);
# which packets this state came from
canMonoTimes @12: List(UInt64);
struct WheelSpeeds {
# optional wheel speeds
fl @0 :Float32;
fr @1 :Float32;
rl @2 :Float32;
rr @3 :Float32;
}
struct CruiseState {
enabled @0: Bool;
speed @1: Float32;
}
enum Error {
# TODO: copy from error list
commIssue @0;
steerUnavailable @1;
brakeUnavailable @2;
gasUnavailable @3;
wrongGear @4;
doorOpen @5;
seatbeltNotLatched @6;
espDisabled @7;
wrongCarMode @8;
steerTemporarilyUnavailable @9;
reverseGear @10;
# ...
}
# send on change
struct ButtonEvent {
pressed @0: Bool;
type @1: Type;
enum Type {
unknown @0;
leftBlinker @1;
rightBlinker @2;
accelCruise @3;
decelCruise @4;
cancel @5;
altButton1 @6;
altButton2 @7;
altButton3 @8;
}
}
}
# ******* radar state @ 20hz *******
struct RadarState {
errors @0: List(Error);
points @1: List(RadarPoint);
# which packets this state came from
canMonoTimes @2: List(UInt64);
enum Error {
notValid @0;
}
# similar to LiveTracks
# is one timestamp valid for all? I think so
struct RadarPoint {
trackId @0: UInt64; # no trackId reuse
# these 3 are the minimum required
dRel @1: Float32; # m from the front bumper of the car
yRel @2: Float32; # m
vRel @3: Float32; # m/s
# these are optional and valid if they are not NaN
aRel @4: Float32; # m/s^2
yvRel @5: Float32; # m/s
}
}
# ******* car controls @ 100hz *******
struct CarControl {
# must be true for any actuator commands to work
enabled @0: Bool;
# range from 0.0 - 1.0
gas @1: Float32;
brake @2: Float32;
# range from -1.0 - 1.0
steeringTorque @3 :Float32;
cruiseControl @4: CruiseControl;
hudControl @5: HUDControl;
struct CruiseControl {
cancel @0: Bool;
override @1: Bool;
speedOverride @2: Float32;
accelOverride @3: Float32;
}
struct HUDControl {
speedVisible @0: Bool;
setSpeed @1: Float32;
lanesVisible @2: Bool;
leadVisible @3: Bool;
visualAlert @4: VisualAlert;
audibleAlert @5: AudibleAlert;
enum VisualAlert {
# these are the choices from the Honda
# map as good as you can for your car
none @0;
fcw @1;
steerRequired @2;
brakePressed @3;
wrongGear @4;
seatbeltUnbuckled @5;
speedTooHigh @6;
}
enum AudibleAlert {
# these are the choices from the Honda
# map as good as you can for your car
none @0;
beepSingle @1;
beepTriple @2;
beepRepeated @3;
chimeSingle @4;
chimeDouble @5;
chimeRepeated @6;
chimeContinuous @7;
}
}
}

View File

@ -85,11 +85,11 @@ struct Live20Data {
ftMonoTime @7 :UInt64;
# all deprecated
warpMatrix @0 :List(Float32);
angleOffset @1 :Float32;
calStatus @2 :Int8;
calCycle @8 :Int32;
calPerc @9 :Int8;
warpMatrixDEPRECATED @0 :List(Float32);
angleOffsetDEPRECATED @1 :Float32;
calStatusDEPRECATED @2 :Int8;
calCycleDEPRECATED @8 :Int32;
calPercDEPRECATED @9 :Int8;
leadOne @3 :LeadData;
leadTwo @4 :LeadData;
@ -138,7 +138,7 @@ struct Live100Data {
mdMonoTime @18 :UInt64;
vEgo @0 :Float32;
aEgo @1 :Float32;
aEgoDEPRECATED @1 :Float32;
vPid @2 :Float32;
vTargetLead @3 :Float32;
upAccelCmd @4 :Float32;
@ -151,7 +151,7 @@ struct Live100Data {
aTargetMax @11 :Float32;
jerkFactor @12 :Float32;
angleSteers @13 :Float32;
hudLead @14 :Int32;
hudLeadDEPRECATED @14 :Int32;
cumLagMs @15 :Float32;
enabled @19: Bool;

View File

@ -3,6 +3,6 @@ import requests
def api_get(endpoint, method='GET', timeout=None, **params):
backend = "https://api.commadotai.com/"
params['_version'] = "OPENPILOTv0.0"
params['_version'] = "OPENPILOTv0.2"
return requests.request(method, backend+endpoint, timeout=timeout, params=params)

View File

@ -5,6 +5,8 @@ import sys
if os.getenv("NOLOG"):
def capture_exception(*exc_info):
pass
def bind_user(**kwargs):
pass
def install():
pass
else:
@ -16,6 +18,9 @@ else:
capture_exception = client.captureException
def bind_user(**kwargs):
client.user_context(kwargs)
def install():
# installs a sys.excepthook
__excepthook__ = sys.excepthook

View File

@ -57,7 +57,7 @@ def set_realtime_priority(level):
raise NotImplementedError
tid = libc.syscall(NR_gettid)
subprocess.check_call(['chrt', '-f', '-p', str(level), str(tid)])
return subprocess.call(['chrt', '-f', '-p', str(level), str(tid)])
class Ratekeeper(object):

View File

@ -39,14 +39,21 @@ service_list = {
# subscribes: health
# publishes: thermal
# **** processes that communicate with the outside world ****
# boardd -- communicates with the car
# subscribes: sendcan
# publishes: can, health
# sensord -- publishes the IMU and GPS
# publishes: sensorEvents, gpsNMEA
# visiond -- talks to the cameras, runs the model, saves the videos
# subscribes: liveCalibration, sensorEvents
# publishes: frame, encodeIdx, model, features
# **** stateful data transformers ****
# controlsd -- actually drives the car
# subscribes: can, thermal, model, live20
# publishes: sendcan, live100
@ -55,9 +62,6 @@ service_list = {
# subscribes: can, live100, model
# publishes: live20, liveTracks
# sensord -- publishes the IMU and GPS
# publishes: sensorEvents, gpsNMEA
# calibrationd -- places the camera box
# subscribes: features, live100
# publishes: liveCalibration
@ -80,3 +84,4 @@ service_list = {
# logcatd -- fetches logcat info from android
# publishes: androidLog

View File

@ -1,748 +0,0 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: PDSC PDS_HMI PDS_Slave PDS_Master EPAS TPEC MAB BPEC
VAL_TABLE_ aaaaaaaaaa 3 "EPAS" 2 "TPEC" 1 "BPEC" ;
BO_ 127 Version: 8 BPEC
SG_ MODULE : 0|8@1+ (1,0) [0|0] "" MAB
SG_ BUILD : 48|16@1+ (1,0) [0|0] "" MAB
SG_ MINOR : 32|16@1+ (1,0) [0|0] "" MAB
SG_ MAJOR : 16|16@1+ (1,0) [0|0] "" MAB
BO_ 117 ThrottleInfo_Report: 8 EPAS
SG_ APEDRATE : 32|8@1- (0.04,0) [-5.12|5.08] "%/ms" MAB
SG_ APEDPC : 16|10@1+ (0.1,0) [0|99.9] "%" MAB
SG_ RPM : 0|16@1+ (0.25,0) [0|0] "RPM" MAB
BO_ 1085 PDS_Status2_Slave: 4 PDS_Slave
SG_ VOLTAGE : 16|12@1+ (0.01,0) [0|0] "V" PDS_HMI
SG_ THERMOCOUPLE : 8|8@1- (0.5,-44) [-20|107.5] "°C" PDS_HMI
SG_ BOARDTEMP : 0|8@1- (0.5,-44) [-20|107.5] "°C" PDS_HMI
BO_ 1084 PDS_Status2_Master: 4 PDS_Master
SG_ VOLTAGE : 16|12@1+ (0.01,0) [0|0] "V" PDS_HMI
SG_ THERMOCOUPLE : 8|8@1- (0.5,-44) [-20|107.5] "°C" PDS_HMI
SG_ BOARDTEMP : 0|8@1- (0.5,-44) [-20|107.5] "°C" PDS_HMI
BO_ 116 BrakeInfo_Report: 8 EPAS
SG_ TRACE : 63|1@1+ (1,0) [0|0] "" MAB
SG_ TRACA : 62|1@1+ (1,0) [0|0] "" MAB
SG_ STABE : 61|1@1+ (1,0) [0|0] "" MAB
SG_ STABA : 60|1@1+ (1,0) [0|0] "" MAB
SG_ AOG : 48|10@1- (0.035,0) [-17.92|17.885] "m/s^2" MAB
SG_ ABSE : 59|1@1+ (1,0) [0|0] "" MAB
SG_ ABSA : 58|1@1+ (1,0) [0|0] "" MAB
SG_ WHLTRQ : 32|14@1- (4,0) [-32768|32764] "Nm" MAB
SG_ PBRAKE : 30|2@1+ (1,0) [0|0] "" MAB
SG_ STATNRY : 15|1@1+ (1,0) [0|0] "" MAB
SG_ HSASTAT : 12|3@1+ (1,0) [0|0] "" MAB
SG_ HSAMODE : 28|2@1+ (1,0) [0|0] "" MAB
SG_ BRKTRQR : 0|12@1+ (4,0) [0|16380] "Nm" MAB
SG_ BRKTRQA : 16|12@1+ (4,0) [0|16380] "Nm" MAB
BO_ 115 Surround_Report: 8 EPAS
SG_ ENSNR : 62|1@1+ (1,0) [0|0] "" MAB
SG_ FLTSNR : 63|1@1+ (1,0) [0|0] "" MAB
SG_ SONAR11 : 52|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR10 : 48|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR09 : 44|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR08 : 40|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR07 : 36|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR06 : 32|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR05 : 28|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR04 : 24|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR03 : 20|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR02 : 16|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR01 : 12|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ SONAR00 : 8|4@1+ (0.15,0.15) [0.3|2.4] "m" MAB
SG_ BLISRE : 7|1@1+ (1,0) [0|0] "" MAB
SG_ BLISRA : 6|1@1+ (1,0) [0|0] "" MAB
SG_ BLISLE : 3|1@1+ (1,0) [0|0] "" MAB
SG_ BLISLA : 2|1@1+ (1,0) [0|0] "" MAB
SG_ CTARE : 5|1@1+ (1,0) [0|0] "" MAB
SG_ CTARA : 4|1@1+ (1,0) [0|0] "" MAB
SG_ CTALE : 1|1@1+ (1,0) [0|0] "" MAB
SG_ CTALA : 0|1@1+ (1,0) [0|0] "" MAB
BO_ 114 FuelLevel_Report: 2 EPAS
SG_ FUEL : 0|16@1- (0.108696,0) [0|0] "%" MAB
BO_ 113 TirePressure_Report: 8 EPAS
SG_ RR : 48|16@1+ (1,0) [0|0] "kPa" MAB
SG_ RL : 32|16@1+ (1,0) [0|0] "kPa" MAB
SG_ FR : 16|16@1+ (1,0) [0|0] "kPa" MAB
SG_ FL : 0|16@1+ (1,0) [0|0] "kPa" MAB
BO_ 112 Suspension_Report: 8 EPAS
SG_ RR : 48|16@1- (0.3913895,0) [0|0] "mm" MAB
SG_ RL : 32|16@1- (0.3913895,0) [0|0] "mm" MAB
SG_ FR : 16|16@1- (0.3913895,0) [0|0] "mm" MAB
SG_ FL : 0|16@1- (0.3913895,0) [0|0] "mm" MAB
BO_ 111 GPS_3_Report: 8 EPAS
SG_ NUMSAT : 59|5@1+ (1,0) [0|0] "" MAB
SG_ QUALITY : 56|3@1+ (1,0) [0|0] "" MAB
SG_ VDOP : 48|5@1+ (0.2,0) [0|0] "" MAB
SG_ HDOP : 40|5@1+ (0.2,0) [0|0] "" MAB
SG_ SPEED : 32|8@1+ (1,0) [0|0] "mph" MAB
SG_ HEADING : 16|16@1+ (0.01,0) [0|0] "degrees" MAB
SG_ ALTITUDE : 0|16@1- (0.25,0) [0|0] "m" MAB
BO_ 110 GPS_2_Report: 8 EPAS
SG_ INF : 62|1@1+ (1,0) [0|0] "" MAB
SG_ FLTGPS : 61|1@1+ (1,0) [0|0] "" MAB
SG_ PDOP : 56|5@1+ (0.2,0) [0|0] "" MAB
SG_ COMPASS : 48|4@1+ (45,0) [0|315] "degrees" MAB
SG_ SECONDS : 40|6@1+ (1,0) [0|59] "seconds" MAB
SG_ MINUTES : 32|6@1+ (1,0) [0|59] "minutes" MAB
SG_ HOURS : 24|5@1+ (1,0) [0|23] "hours" MAB
SG_ DAY : 16|5@1+ (1,0) [1|31] "days" MAB
SG_ MONTH : 8|4@1+ (1,0) [1|12] "months" MAB
SG_ YEAR : 0|7@1+ (1,0) [0|99] "years" MAB
BO_ 109 GPS_1_Report: 8 EPAS
SG_ VALID : 63|1@1+ (1,0) [0|0] "" MAB
SG_ LONGITUDE : 32|31@1- (3.3333333E-007,0) [0|0] "degrees" MAB
SG_ LATITUDE : 0|31@1- (3.3333333E-007,0) [0|0] "degrees" MAB
BO_ 1069 PDS_Current3Slave: 8 PDS_Slave
SG_ CURRENT24 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT23 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT22 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT21 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1065 PDS_Current2Slave: 8 PDS_Slave
SG_ CURRENT20 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT19 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT18 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT17 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1061 PDS_Current1Slave: 8 PDS_Slave
SG_ CURRENT16 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT15 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT14 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT13 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1068 PDS_Current3Master: 8 PDS_Master
SG_ CURRENT9 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT12 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT11 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT10 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1064 PDS_Current2Master: 8 PDS_Master
SG_ CURRENT8 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT7 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT6 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT5 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1060 PDS_Current1Master: 8 PDS_Master
SG_ CURRENT4 : 48|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT3 : 32|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT2 : 16|16@1- (0.001,0) [0|0] "A" PDS_HMI
SG_ CURRENT1 : 0|16@1- (0.001,0) [0|0] "A" PDS_HMI
BO_ 1057 PDS_StatusSlave: 8 PDS_Slave
SG_ STATUS_INV2 : 4|4@1+ (1,0) [0|0] "" Vector__XXX
SG_ STATUS24 : 60|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS23 : 56|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS22 : 52|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS21 : 48|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS20 : 44|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS19 : 40|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS18 : 36|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS17 : 32|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS16 : 28|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS15 : 24|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS14 : 20|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS13 : 16|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ SCRIPT : 12|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ MODE : 8|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
BO_ 1056 PDS_StatusMaster: 8 PDS_Master
SG_ STATUS_INV1 : 4|4@1+ (1,0) [0|0] "" Vector__XXX
SG_ STATUS9 : 48|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS8 : 44|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS7 : 40|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS6 : 36|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS5 : 32|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS4 : 28|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS3 : 24|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS2 : 20|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS12 : 60|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS11 : 56|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS10 : 52|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ STATUS1 : 16|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ SCRIPT : 12|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
SG_ MODE : 8|4@1+ (1,0) [0|0] "" PDSC,PDS_HMI
BO_ 1072 PDS_Reserved2: 6 PDS_Master
SG_ RESERVED2 : 7|48@0+ (1,0) [0|0] "" PDSC
BO_ 1074 PDS_Reserved4: 4 PDS_Master
SG_ RESERVED4 : 7|32@0+ (1,0) [0|0] "" PDS_HMI
BO_ 1073 PDS_Reserved3: 8 PDS_Master
SG_ RESERVED3 : 7|64@0+ (1,0) [0|0] "" PDS_HMI
BO_ 1043 PDS_Reserved1: 1 PDS_HMI
SG_ RESERVED1 : 7|8@0+ (1,0) [0|0] "" PDS_Slave,PDS_Master
BO_ 1042 PDS_ScriptRequest: 1 PDSC
SG_ SCRIPT : 0|8@1+ (1,0) [0|0] "" PDS_Slave,PDS_Master
BO_ 1041 PDS_ModeRequest: 1 PDSC
SG_ MODE : 0|8@1+ (1,0) [0|0] "" PDS_Slave,PDS_Master
BO_ 1040 PDS_RelayRequest: 2 PDSC
SG_ REQUEST : 8|8@1+ (1,0) [0|0] "" PDS_Slave,PDS_Master
SG_ CHANNEL : 0|8@1+ (1,0) [0|23] "" PDS_Slave,PDS_Master
BO_ 108 Gyro_Report: 4 EPAS
SG_ YAW : 16|16@1- (0.0002,0) [0|0] "rad/s" MAB
SG_ ROLL : 0|16@1- (0.0002,0) [0|0] "rad/s" MAB
BO_ 107 Accel_Report: 6 EPAS
SG_ VERT : 32|16@1- (0.01,0) [0|0] "m/s^2" MAB
SG_ LONG : 16|16@1- (0.01,0) [0|0] "m/s^2" MAB
SG_ LAT : 0|16@1- (0.01,0) [0|0] "m/s^2" MAB
BO_ 106 WheelSpeed_Report: 8 EPAS
SG_ RR : 48|16@1- (0.01,0) [0|0] "rad/s" MAB
SG_ RL : 32|16@1- (0.01,0) [0|0] "rad/s" MAB
SG_ FR : 16|16@1- (0.01,0) [0|0] "rad/s" MAB
SG_ FL : 0|16@1- (0.01,0) [0|0] "rad/s" MAB
BO_ 105 Misc_Report: 5 EPAS
SG_ CNCL : 14|1@1+ (1,0) [0|0] "" MAB
SG_ RES : 13|1@1+ (1,0) [0|0] "" MAB
SG_ ON : 11|1@1+ (1,0) [0|0] "" MAB
SG_ OFF : 12|1@1+ (1,0) [0|0] "" MAB
SG_ BELTP : 33|1@1+ (1,0) [0|0] "" MAB
SG_ BELTD : 32|1@1+ (1,0) [0|0] "" MAB
SG_ PABAG : 31|1@1+ (1,0) [0|0] "" MAB
SG_ PDECT : 30|1@1+ (1,0) [0|0] "" MAB
SG_ TRUNK : 29|1@1+ (1,0) [0|0] "" MAB
SG_ HOOD : 28|1@1+ (1,0) [0|0] "" MAB
SG_ DOORR : 27|1@1+ (1,0) [0|0] "" MAB
SG_ DOORP : 25|1@1+ (1,0) [0|0] "" MAB
SG_ DOORL : 26|1@1+ (1,0) [0|0] "" MAB
SG_ DOORD : 24|1@1+ (1,0) [0|0] "" MAB
SG_ WIPER : 4|4@1+ (1,0) [0|0] "" MAB
SG_ TRNSTAT : 0|2@1+ (1,0) [0|0] "" MAB
SG_ SINC : 18|1@1+ (1,0) [0|0] "" MAB
SG_ SDEC : 19|1@1+ (1,0) [0|0] "" MAB
SG_ ONOFF : 16|1@1+ (1,0) [0|0] "" MAB
SG_ LKAEN : 22|1@1+ (1,0) [0|0] "" MAB
SG_ HIBEAM : 2|2@1+ (1,0) [0|0] "" MAB
SG_ GINC : 20|1@1+ (1,0) [0|0] "" MAB
SG_ GDEC : 21|1@1+ (1,0) [0|0] "" MAB
SG_ FLTBUS : 23|1@1+ (1,0) [0|0] "" MAB
SG_ RESCNCL : 17|1@1+ (1,0) [0|0] "" MAB
SG_ AMBIENT : 8|3@1+ (1,0) [0|0] "" MAB
BO_ 104 TurnSignal_Command: 1 MAB
SG_ TRNCMD : 0|2@1+ (1,0) [0|0] "" EPAS
BO_ 103 Gear_Report: 1 EPAS
SG_ STATE : 0|3@1+ (1,0) [0|0] "" MAB
SG_ FLTBUS : 7|1@1+ (1,0) [0|0] "" MAB
SG_ DRIVER : 3|1@1+ (1,0) [0|0] "" MAB
SG_ CMD : 4|3@1+ (1,0) [0|0] "" MAB
BO_ 102 Gear_Command: 1 MAB
SG_ GCMD : 0|3@1+ (1,0) [0|0] "" EPAS
SG_ CLEAR : 7|1@1+ (1,0) [0|0] "" EPAS
BO_ 101 Steering_Report: 8 EPAS
SG_ DRIVER : 58|1@1+ (1,0) [0|0] "" MAB
SG_ FLTWDC : 59|1@1+ (1,0) [0|0] "" MAB
SG_ FLTCAL : 62|1@1+ (1,0) [0|0] "" MAB
SG_ FLTCON : 63|1@1+ (1,0) [0|0] "" MAB
SG_ TORQUE : 48|8@1- (0.0625,0) [0|0] "Nm" MAB
SG_ SPEED : 32|16@1+ (0.01,0) [0|0] "kph" MAB
SG_ FLT2 : 61|1@1+ (1,0) [0|0] "" MAB
SG_ FLT1 : 60|1@1+ (1,0) [0|0] "" MAB
SG_ EN : 56|1@1+ (1,0) [0|0] "" MAB
SG_ OVERRIDE : 57|1@1+ (1,0) [0|0] "" MAB
SG_ CMD : 16|16@1- (0.1,0) [-470|470] "degrees" MAB
SG_ ANGLE : 0|16@1- (0.1,0) [-470|470] "degrees" MAB
BO_ 100 Steering_Command: 8 MAB
SG_ QUIET : 20|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ COUNT : 56|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ IGNORE : 18|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ SVEL : 24|8@1+ (2,0) [0|500] "degrees/s" Vector__XXX
SG_ CLEAR : 17|1@1+ (1,0) [0|0] "" EPAS
SG_ EN : 16|1@1+ (1,0) [0|0] "" EPAS
SG_ SCMD : 0|16@1- (0.1,0) [-470|470] "degrees" EPAS
BO_ 99 Throttle_Report: 8 TPEC
SG_ WDCSRC : 52|4@1+ (1,0) [0|0] "" MAB
SG_ DRIVER : 58|1@1+ (1,0) [0|0] "" MAB
SG_ FLTWDC : 59|1@1+ (1,0) [0|0] "" MAB
SG_ PO : 32|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ PI : 0|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ PC : 16|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ FLTCON : 63|1@1+ (1,0) [0|0] "" MAB
SG_ FLT2 : 61|1@1+ (1,0) [0|0] "" MAB
SG_ FLT1 : 60|1@1+ (1,0) [0|0] "" MAB
SG_ EN : 56|1@1+ (1,0) [0|0] "" MAB
SG_ OVERRIDE : 57|1@1+ (1,0) [0|0] "" MAB
BO_ 98 Throttle_Command: 8 MAB
SG_ COUNT : 56|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ IGNORE : 26|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CLEAR : 25|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ PCMD : 0|16@1+ (1.52590218966964E-005,0) [0|1] "%" TPEC
SG_ EN : 24|1@1+ (1,0) [0|0] "" TPEC
BO_ 97 Brake_Report: 8 BPEC
SG_ WDCSRC : 52|4@1+ (1,0) [0|0] "" MAB
SG_ WDCBRK : 51|1@1+ (1,0) [0|0] "" MAB
SG_ DRIVER : 58|1@1+ (1,0) [0|0] "" MAB
SG_ FLTWDC : 59|1@1+ (1,0) [0|0] "" MAB
SG_ PO : 32|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ PI : 0|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ PC : 16|16@1+ (1.52590218966964E-005,0) [0|1] "%" MAB
SG_ FLTCON : 63|1@1+ (1,0) [0|0] "" MAB
SG_ FLTBOO : 62|1@1+ (1,0) [0|0] "" MAB
SG_ FLT2 : 61|1@1+ (1,0) [0|0] "" MAB
SG_ FLT1 : 60|1@1+ (1,0) [0|0] "" MAB
SG_ EN : 56|1@1+ (1,0) [0|0] "" MAB
SG_ OVERRIDE : 57|1@1+ (1,0) [0|0] "" MAB
SG_ BO : 48|1@1+ (1,0) [0|0] "" MAB
SG_ BI : 50|1@1+ (1,0) [0|0] "" MAB
SG_ BC : 49|1@1+ (1,0) [0|0] "" MAB
BO_ 96 Brake_Command: 8 MAB
SG_ COUNT : 56|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ IGNORE : 26|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ CLEAR : 25|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ PCMD : 0|16@1+ (1.52590218966964E-005,0) [0|1] "%" BPEC
SG_ EN : 24|1@1+ (1,0) [0|0] "" BPEC
SG_ BCMD : 16|1@1+ (1,0) [0|0] "" BPEC
BO_TX_BU_ 127 : EPAS,TPEC,BPEC;
BO_TX_BU_ 1073 : PDS_Slave,PDS_Master;
BO_TX_BU_ 1042 : PDS_HMI,PDSC;
BO_TX_BU_ 1041 : PDS_HMI,PDSC;
BO_TX_BU_ 1040 : PDS_HMI,PDSC;
CM_ BU_ PDSC "Power Distribution System Controller (Switch Panel)";
CM_ BU_ PDS_HMI "Power Distribution System HMI (Touchscreen)";
CM_ BU_ PDS_Slave "Power Distribution System (Slave)";
CM_ BU_ PDS_Master "Power Distribution System (Master)";
CM_ BU_ EPAS "Electric Power-Assisted Steering (Steering, Shifting, and misc CAN messages)";
CM_ BU_ TPEC "Throttle Pedal Emulator Combo";
CM_ BU_ MAB "MicroAutoBox";
CM_ BU_ BPEC "Brake Pedal Emulator Combo";
CM_ SG_ 127 BUILD "Firmware version build";
CM_ SG_ 127 MINOR "Firmware version minor";
CM_ SG_ 127 MAJOR "Firmware version major";
CM_ SG_ 117 APEDRATE "Accelerator Pedal Rate";
CM_ SG_ 117 APEDPC "Accelerator Pedal Percent";
CM_ SG_ 117 RPM "Engine RPM";
CM_ SG_ 1085 VOLTAGE "Input Voltage";
CM_ SG_ 1085 THERMOCOUPLE "External Thermocouple";
CM_ SG_ 1085 BOARDTEMP "Internal Board Temperature";
CM_ SG_ 1084 VOLTAGE "Input Voltage";
CM_ SG_ 1084 THERMOCOUPLE "External Thermocouple";
CM_ SG_ 1084 BOARDTEMP "Internal Board Temperature";
CM_ SG_ 116 TRACE "Traction Control Enabled";
CM_ SG_ 116 TRACA "Traction Control Active";
CM_ SG_ 116 STABE "Stability Control Enabled";
CM_ SG_ 116 STABA "Stability Control Active";
CM_ SG_ 116 AOG "Acceleration Over Ground Estimated";
CM_ SG_ 116 ABSE "ABS Enabled";
CM_ SG_ 116 ABSA "ABS Active";
CM_ SG_ 116 WHLTRQ "Wheel Torque";
CM_ SG_ 116 PBRAKE "Parking Brake Status";
CM_ SG_ 116 STATNRY "Vehicle Stationary";
CM_ SG_ 116 HSASTAT "Hill Start Assist Status";
CM_ SG_ 116 HSAMODE "Hill Start Assist Mode";
CM_ SG_ 116 BRKTRQR "Braking Torque Request";
CM_ SG_ 116 BRKTRQA "Braking Torque Actual";
CM_ SG_ 115 ENSNR "Sonar Enabled";
CM_ SG_ 115 FLTSNR "Fault Sonar Sensors";
CM_ SG_ 115 SONAR11 "Sonar Rear Right Side";
CM_ SG_ 115 SONAR10 "Sonar Rear Right Corner";
CM_ SG_ 115 SONAR09 "Sonar Rear Right Center";
CM_ SG_ 115 SONAR08 "Sonar Rear Left Center";
CM_ SG_ 115 SONAR07 "Sonar Rear Left Corner";
CM_ SG_ 115 SONAR06 "Sonar Rear Left Side";
CM_ SG_ 115 SONAR05 "Sonar Front Right Side";
CM_ SG_ 115 SONAR04 "Sonar Front Right Corner";
CM_ SG_ 115 SONAR03 "Sonar Front Right Center";
CM_ SG_ 115 SONAR02 "Sonar Front Left Center";
CM_ SG_ 115 SONAR01 "Sonar Front Left Corner";
CM_ SG_ 115 SONAR00 "Sonar Front Left Side";
CM_ SG_ 115 BLISRE "Blind Spot Information System Right Enabled";
CM_ SG_ 115 BLISRA "Blind Spot Information System Right Alert";
CM_ SG_ 115 BLISLE "Blind Spot Information System Left Enabled";
CM_ SG_ 115 BLISLA "Blind Spot Information System Left Alert";
CM_ SG_ 115 CTARE "Cross Traffic Alert Right Enabled";
CM_ SG_ 115 CTARA "Cross Traffic Alert Right Alert";
CM_ SG_ 115 CTALE "Cross Traffic Alert Left Enabled";
CM_ SG_ 115 CTALA "Cross Traffic Alert Left Alert";
CM_ SG_ 114 FUEL "Fuel Tank Level";
CM_ SG_ 113 RR "Tire Pressure Rear Right";
CM_ SG_ 113 RL "Tire Pressure Rear Left";
CM_ SG_ 113 FR "Tire Pressure Front Right";
CM_ SG_ 113 FL "Tire Pressure Front Left";
CM_ SG_ 112 RR "UNKNOWN";
CM_ SG_ 112 RL "UNKNOWN";
CM_ SG_ 112 FR "UNKNOWN";
CM_ SG_ 112 FL "UNKNOWN";
CM_ SG_ 111 NUMSAT "GPS Number Of satellites";
CM_ SG_ 111 QUALITY "GPS Fix Quality";
CM_ SG_ 111 VDOP "GPS Vertical Dilution Of Precision";
CM_ SG_ 111 HDOP "GPS Horizontal Dilution Of Precision";
CM_ SG_ 111 SPEED "GPS Vehicle Speed";
CM_ SG_ 111 HEADING "GPS Heading";
CM_ SG_ 111 ALTITUDE "GPS Altitude";
CM_ SG_ 110 INF "GPS Position Inferred";
CM_ SG_ 110 FLTGPS "Fault GPS";
CM_ SG_ 110 PDOP "GPS Position Dilution Of Precision";
CM_ SG_ 110 COMPASS "Compass Heading";
CM_ SG_ 110 SECONDS "GPS UTC Seconds";
CM_ SG_ 110 MINUTES "GPS UTC Minutes";
CM_ SG_ 110 HOURS "GPS UTC Hours";
CM_ SG_ 110 DAY "GPS UTC Day";
CM_ SG_ 110 MONTH "GPS UTC Month";
CM_ SG_ 110 YEAR "GPS UTC Year";
CM_ SG_ 109 VALID "GPS Valid";
CM_ SG_ 109 LONGITUDE "GPS Longitude";
CM_ SG_ 109 LATITUDE "GPS Latitude";
CM_ SG_ 1069 CURRENT24 "PDS Channel 24 Current";
CM_ SG_ 1069 CURRENT23 "PDS Channel 23 Current";
CM_ SG_ 1069 CURRENT22 "PDS Channel 22 Current";
CM_ SG_ 1069 CURRENT21 "PDS Channel 21 Current";
CM_ SG_ 1065 CURRENT20 "PDS Channel 20 Current";
CM_ SG_ 1065 CURRENT19 "PDS Channel 19 Current";
CM_ SG_ 1065 CURRENT18 "PDS Channel 18 Current";
CM_ SG_ 1065 CURRENT17 "PDS Channel 17 Current";
CM_ SG_ 1061 CURRENT16 "PDS Channel 16 Current";
CM_ SG_ 1061 CURRENT15 "PDS Channel 15 Current";
CM_ SG_ 1061 CURRENT14 "PDS Channel 14 Current";
CM_ SG_ 1061 CURRENT13 "PDS Channel 13 Current";
CM_ SG_ 1068 CURRENT9 "PDS Channel 9 Current";
CM_ SG_ 1068 CURRENT12 "PDS Channel 12 Current";
CM_ SG_ 1068 CURRENT11 "PDS Channel 11 Current";
CM_ SG_ 1068 CURRENT10 "PDS Channel 10 Current";
CM_ SG_ 1064 CURRENT8 "PDS Channel 8 Current";
CM_ SG_ 1064 CURRENT7 "PDS Channel 7 Current";
CM_ SG_ 1064 CURRENT6 "PDS Channel 6 Current";
CM_ SG_ 1064 CURRENT5 "PDS Channel 5 Current";
CM_ SG_ 1060 CURRENT4 "PDS Channel 4 Current";
CM_ SG_ 1060 CURRENT3 "PDS Channel 3 Current";
CM_ SG_ 1060 CURRENT2 "PDS Channel 2 Current";
CM_ SG_ 1060 CURRENT1 "PDS Channel 1 Current";
CM_ SG_ 1057 STATUS_INV2 "PDS Channel Inverter Slave Status";
CM_ SG_ 1057 STATUS24 "PDS Channel 24 Status";
CM_ SG_ 1057 STATUS23 "PDS Channel 23 Status";
CM_ SG_ 1057 STATUS22 "PDS Channel 22 Status";
CM_ SG_ 1057 STATUS21 "PDS Channel 21 Status";
CM_ SG_ 1057 STATUS20 "PDS Channel 20 Status";
CM_ SG_ 1057 STATUS19 "PDS Channel 19 Status";
CM_ SG_ 1057 STATUS18 "PDS Channel 18 Status";
CM_ SG_ 1057 STATUS17 "PDS Channel 17 Status";
CM_ SG_ 1057 STATUS16 "PDS Channel 16 Status";
CM_ SG_ 1057 STATUS15 "PDS Channel 15 Status";
CM_ SG_ 1057 STATUS14 "PDS Channel 14 Status";
CM_ SG_ 1057 STATUS13 "PDS Channel 13 Status";
CM_ SG_ 1057 SCRIPT "PDS Script Slave";
CM_ SG_ 1057 MODE "PDS Mode Slave";
CM_ SG_ 1056 STATUS_INV1 "PDS Channel Inverter Master Status";
CM_ SG_ 1056 STATUS9 "PDS Channel 9 Status";
CM_ SG_ 1056 STATUS8 "PDS Channel 8 Status";
CM_ SG_ 1056 STATUS7 "PDS Channel 7 Status";
CM_ SG_ 1056 STATUS6 "PDS Channel 6 Status";
CM_ SG_ 1056 STATUS5 "PDS Channel 5 Status";
CM_ SG_ 1056 STATUS4 "PDS Channel 4 Status";
CM_ SG_ 1056 STATUS3 "PDS Channel 3 Status";
CM_ SG_ 1056 STATUS2 "PDS Channel 2 Status";
CM_ SG_ 1056 STATUS12 "PDS Channel 12 Status";
CM_ SG_ 1056 STATUS11 "PDS Channel 11 Status";
CM_ SG_ 1056 STATUS10 "PDS Channel 10 Status";
CM_ SG_ 1056 STATUS1 "PDS Channel 1 Status";
CM_ SG_ 1056 SCRIPT "PDS Script Master";
CM_ SG_ 1056 MODE "PDS Mode Master";
CM_ SG_ 1042 SCRIPT "PDS Script Request";
CM_ SG_ 1041 MODE "PDS Mode Request";
CM_ SG_ 1040 REQUEST "PDS Relay Request";
CM_ SG_ 1040 CHANNEL "PDS Relay Request Channel";
CM_ SG_ 108 YAW "Yaw Rate";
CM_ SG_ 108 ROLL "Roll Rate";
CM_ SG_ 107 VERT "Vertical Acceleration";
CM_ SG_ 107 LONG "Longitudinal Acceleration";
CM_ SG_ 107 LAT "Lateral Acceleration";
CM_ SG_ 106 RR "Wheel Speed Rear Right";
CM_ SG_ 106 RL "Wheel Speed Rear Left";
CM_ SG_ 106 FR "Wheel Speed Front Right";
CM_ SG_ 106 FL "Wheel Speed Front Left";
CM_ SG_ 105 CNCL "Button Cruise Control CANCEL";
CM_ SG_ 105 RES "Button Cruise Control RESUME";
CM_ SG_ 105 ON "Button Cruise Control ON";
CM_ SG_ 105 OFF "Button Cruise Control OFF";
CM_ SG_ 105 BELTP "Passenger Seat Belt Buckle";
CM_ SG_ 105 BELTD "Driver Seat Belt Buckle";
CM_ SG_ 105 PABAG "Passenger Airbag";
CM_ SG_ 105 PDECT "Passenger Detect";
CM_ SG_ 105 TRUNK "Trunk Open";
CM_ SG_ 105 HOOD "Hood Open";
CM_ SG_ 105 DOORR "Rear Right Door";
CM_ SG_ 105 DOORP "Passenger Door";
CM_ SG_ 105 DOORL "Rear Left Door";
CM_ SG_ 105 DOORD "Driver Door";
CM_ SG_ 105 WIPER "Windshield Wiper Status";
CM_ SG_ 105 TRNSTAT "Turn Signal Status";
CM_ SG_ 105 SINC "Button ACC SET+";
CM_ SG_ 105 SDEC "Button ACC SET-";
CM_ SG_ 105 ONOFF "Button ACC On/Off Toggle";
CM_ SG_ 105 LKAEN "Button LKA On/Off Toggle";
CM_ SG_ 105 HIBEAM "High Beam Headlights";
CM_ SG_ 105 GINC "Button ACC GAP+";
CM_ SG_ 105 GDEC "Button ACC GAP-";
CM_ SG_ 105 FLTBUS "Fault CAN Bus (misc)";
CM_ SG_ 105 RESCNCL "Button ACC Resume/Cancel";
CM_ SG_ 105 AMBIENT "Ambient Light Level";
CM_ SG_ 104 TRNCMD "Turn Signal Command";
CM_ SG_ 103 STATE "Gear State";
CM_ SG_ 103 FLTBUS "Fault CAN Bus (gear)";
CM_ SG_ 103 DRIVER "Driver Override (gear)";
CM_ SG_ 103 CMD "Gear Command (reported)";
CM_ SG_ 102 GCMD "Gear Command";
CM_ SG_ 102 CLEAR "Clear Override (gear)";
CM_ SG_ 101 DRIVER "Driver Activity (steering)";
CM_ SG_ 101 FLTWDC "Fault Watchdog Counter (steering)";
CM_ SG_ 101 FLTCAL "Fault Steering Calibration";
CM_ SG_ 101 FLTCON "Fault Connector (steering)";
CM_ SG_ 101 TORQUE "Steering Column Torque";
CM_ SG_ 101 SPEED "Vehicle Speed";
CM_ SG_ 101 FLT2 "Fault CAN Bus 2 (steering)";
CM_ SG_ 101 FLT1 "Fault CAN Bus 1 (steering)";
CM_ SG_ 101 EN "Steering Enabled";
CM_ SG_ 101 OVERRIDE "Driver Override (steering)";
CM_ SG_ 101 CMD "Steering Command (reported)";
CM_ SG_ 101 ANGLE "Steering Wheel Angle";
CM_ SG_ 100 QUIET "Disable the driver override audible warning";
CM_ SG_ 100 COUNT "Optional Watchdog Counter (steering)";
CM_ SG_ 100 IGNORE "Ignore override (steering)";
CM_ SG_ 100 SVEL "Steering Command Rate Limit";
CM_ SG_ 100 CLEAR "Clear Override (steering)";
CM_ SG_ 100 EN "Steering Enable";
CM_ SG_ 100 SCMD "Steering Command";
CM_ SG_ 99 WDCSRC "Watchdog Counter Source (throttle)";
CM_ SG_ 99 DRIVER "Driver Activity (throttle)";
CM_ SG_ 99 FLTWDC "Fault Watchdog Counter (throttle)";
CM_ SG_ 99 PO "Throttle Pedal Output";
CM_ SG_ 99 PI "Throttle Pedal Input";
CM_ SG_ 99 PC "Throttle Pedal Command (reported)";
CM_ SG_ 99 FLTCON "Fault Connector (throttle)";
CM_ SG_ 99 FLT2 "Fault CH2 (throttle)";
CM_ SG_ 99 FLT1 "Fault CH1 (throttle)";
CM_ SG_ 99 EN "Throttle Enabled";
CM_ SG_ 99 OVERRIDE "Driver Override (throttle)";
CM_ SG_ 98 COUNT "Optional Watchdog Counter (throttle)";
CM_ SG_ 98 IGNORE "Ignore pedal override (throttle)";
CM_ SG_ 98 CLEAR "Clear Override (throttle)";
CM_ SG_ 98 PCMD "Throttle Pedal Command";
CM_ SG_ 98 EN "Throttle Enable";
CM_ SG_ 97 WDCSRC "Watchdog Counter Source (brakes)";
CM_ SG_ 97 WDCBRK "Watchdog Counter braking status";
CM_ SG_ 97 DRIVER "Driver Activity (brakes)";
CM_ SG_ 97 FLTWDC "Fault Watchdog Counter (brakes)";
CM_ SG_ 97 PO "Brake Pedal Output";
CM_ SG_ 97 PI "Brake Pedal Input";
CM_ SG_ 97 PC "Brake Pedal Command (reported)";
CM_ SG_ 97 FLTCON "Fault Connector (brakes)";
CM_ SG_ 97 FLTBOO "Fault BOO";
CM_ SG_ 97 FLT2 "Fault CH2 (brakes)";
CM_ SG_ 97 FLT1 "Fault CH1 (brakes)";
CM_ SG_ 97 EN "Brakes Enabled";
CM_ SG_ 97 OVERRIDE "Driver Override (brakes)";
CM_ SG_ 97 BO "BOO Output";
CM_ SG_ 97 BI "BOO Input";
CM_ SG_ 97 BC "BOO Command";
CM_ SG_ 96 COUNT "Optional Watchdog Counter (brakes)";
CM_ SG_ 96 IGNORE "Ignore pedal override (brakes)";
CM_ SG_ 96 CLEAR "Clear Override (brakes)";
CM_ SG_ 96 PCMD "Brake Pedal Command";
CM_ SG_ 96 EN "Brakes Enable";
CM_ SG_ 96 BCMD "BOO Command";
BA_DEF_ "NetworkSpeed" ENUM "500kBits/s";
BA_DEF_ "BusType" STRING ;
BA_DEF_DEF_ "NetworkSpeed" "500kBits/s";
BA_DEF_DEF_ "BusType" "CAN";
VAL_ 127 MODULE 3 "EPAS (steering/shifter)" 2 "TPEC (throttle)" 1 "BPEC (brake)" ;
VAL_ 116 TRACE 1 "Enabled" 0 "Disabled" ;
VAL_ 116 TRACA 1 "Active" 0 "Inactive" ;
VAL_ 116 STABE 1 "Enabled" 0 "Disabled" ;
VAL_ 116 STABA 1 "Active" 0 "Inactive" ;
VAL_ 116 ABSE 1 "Enabled" 0 "Disabled" ;
VAL_ 116 ABSA 1 "Active" 0 "Inactive" ;
VAL_ 116 PBRAKE 3 "Fault" 2 "On" 1 "Transition" 0 "Off" ;
VAL_ 116 STATNRY 1 "Stationary" 0 "Moving" ;
VAL_ 116 HSASTAT 7 "Undefined" 6 "Failed" 5 "Slow Release" 4 "Fast Release" 3 "Active Released" 2 "Active Pressed" 1 "Finding Gradient" 0 "Inactive" ;
VAL_ 116 HSAMODE 3 "Undefined" 2 "Manual" 1 "Auto" 0 "Off" ;
VAL_ 115 ENSNR 1 "Enabled" 0 "Disabled" ;
VAL_ 115 FLTSNR 1 "Fault" 0 "No Fault" ;
VAL_ 115 SONAR11 0 "No Detection" ;
VAL_ 115 SONAR10 0 "No Detection" ;
VAL_ 115 SONAR09 0 "No Detection" ;
VAL_ 115 SONAR08 0 "No Detection" ;
VAL_ 115 SONAR07 0 "No Detection" ;
VAL_ 115 SONAR06 0 "No Detection" ;
VAL_ 115 SONAR05 0 "No Detection" ;
VAL_ 115 SONAR04 0 "No Detection" ;
VAL_ 115 SONAR03 0 "No Detection" ;
VAL_ 115 SONAR02 0 "No Detection" ;
VAL_ 115 SONAR01 0 "No Detection" ;
VAL_ 115 SONAR00 0 "No Detection" ;
VAL_ 115 BLISRE 1 "Enabled" 0 "Disabled" ;
VAL_ 115 BLISRA 1 "Alert" 0 "No Alert" ;
VAL_ 115 BLISLE 1 "Enabled" 0 "Disabled" ;
VAL_ 115 BLISLA 1 "Alert" 0 "No Alert" ;
VAL_ 115 CTARE 1 "Enabled" 0 "Disabled" ;
VAL_ 115 CTARA 1 "Alert" 0 "No Alert" ;
VAL_ 115 CTALE 1 "Enabled" 0 "Disabled" ;
VAL_ 115 CTALA 1 "Alert" 0 "No Alert" ;
VAL_ 111 QUALITY 2 "3D Fix" 1 "2D Fix" 0 "No Fix" ;
VAL_ 110 INF 1 "Inferred Position" 0 "Actual Position" ;
VAL_ 110 FLTGPS 1 "Fault" 0 "No Fault" ;
VAL_ 109 VALID 1 "Valid" 0 "Invalid" ;
VAL_ 1057 STATUS_INV2 1 "On" 0 "Off" ;
VAL_ 1057 STATUS24 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS23 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS22 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS21 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS20 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS19 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS18 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS17 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS16 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS15 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS14 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 STATUS13 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1057 SCRIPT 4 "Valet Shutdown" 3 "Valet Startup" 2 "Shutdown" 1 "Startup" 0 "None" ;
VAL_ 1057 MODE 2 "Valet" 1 "Manual" 0 "Auto" ;
VAL_ 1056 STATUS_INV1 1 "On" 0 "Off" ;
VAL_ 1056 STATUS9 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS8 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS7 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS6 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS5 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS4 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS3 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS2 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS12 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS11 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS10 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 STATUS1 5 "Over current" 4 "Bad fuse" 3 "Bad relay" 2 "No load" 1 "On" 0 "Off" ;
VAL_ 1056 SCRIPT 4 "Valet Shutdown" 3 "Valet Startup" 2 "Shutdown" 1 "Startup" 0 "None" ;
VAL_ 1056 MODE 2 "Valet" 1 "Manual" 0 "Auto" ;
VAL_ 1042 SCRIPT 4 "Valet Shutdown" 3 "Valet Startup" 2 "Shutdown" 1 "Startup" 0 "None" ;
VAL_ 1041 MODE 2 "Valet" 1 "Manual" 0 "Auto" ;
VAL_ 1040 REQUEST 2 "Toggle" 1 "On" 0 "Off" ;
VAL_ 1040 CHANNEL 51 "INVERTER 4" 50 "INVERTER 3" 49 "INVERTER 2" 48 "INVERTER 1" 23 "CH24" 22 "CH23" 21 "CH22" 20 "CH21" 19 "CH20" 18 "CH19" 17 "CH18" 16 "CH17" 15 "CH16" 14 "CH15" 13 "CH14" 12 "CH13" 11 "CH12" 10 "CH11" 9 "CH10" 8 "CH09" 7 "CH08" 6 "CH07" 5 "CH06" 4 "CH05" 3 "CH04" 2 "CH03" 1 "CH02" 0 "CH01" ;
VAL_ 105 CNCL 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 RES 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 ON 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 OFF 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 BELTP 1 "Buckled" 0 "Unbuckled" ;
VAL_ 105 BELTD 1 "Buckled" 0 "Unbuckled" ;
VAL_ 105 PABAG 1 "Enabled" 0 "Disabled" ;
VAL_ 105 PDECT 1 "Passenger" 0 "No Passenger" ;
VAL_ 105 TRUNK 1 "Open" 0 "Closed" ;
VAL_ 105 HOOD 1 "Open" 0 "Closed" ;
VAL_ 105 DOORR 1 "Open" 0 "Closed" ;
VAL_ 105 DOORP 1 "Open" 0 "Closed" ;
VAL_ 105 DOORL 1 "Open" 0 "Closed" ;
VAL_ 105 DOORD 1 "Open" 0 "Closed" ;
VAL_ 105 WIPER 15 "NO_DATA" 14 "STALLED" 13 "RESERVED" 12 "AUTO_ADJUST" 11 "COURTESY_WIPE" 10 "AUTO_HIGH" 9 "AUTO_LOW" 8 "WASH" 7 "MIST_FLICK" 6 "MANUAL_HIGH" 5 "MANUAL_LOW" 4 "MANUAL_ON" 3 "MANUAL_OFF" 2 "OFF_MOVING" 1 "AUTO_OFF" 0 "OFF" ;
VAL_ 105 TRNSTAT 2 "Right" 1 "Left" 0 "None" ;
VAL_ 105 SINC 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 SDEC 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 ONOFF 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 LKAEN 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 HIBEAM 2 "HIGH" 1 "FLASH_TO_PASS" 0 "NULL" ;
VAL_ 105 GINC 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 GDEC 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 FLTBUS 1 "Fault" 0 "No Fault" ;
VAL_ 105 RESCNCL 1 "Pressed" 0 "Not Pressed" ;
VAL_ 105 AMBIENT 7 "NO_DATA" 4 "TUNNEL_OFF" 3 "TUNNEL_ON" 2 "TWILIGHT" 1 "LIGHT" 0 "DARK" ;
VAL_ 104 TRNCMD 2 "Right" 1 "Left" 0 "None" ;
VAL_ 103 STATE 5 "Low" 4 "Drive" 3 "Neutral" 0 "None" 2 "Reverse" 1 "Park" ;
VAL_ 103 FLTBUS 1 "Fault" 0 "No Fault" ;
VAL_ 103 DRIVER 1 "Last shift requested by driver" 0 "Last shift requested by-wire" ;
VAL_ 103 CMD 5 "Low" 4 "Drive" 3 "Neutral" 0 "None" 2 "Reverse" 1 "Park" ;
VAL_ 102 GCMD 5 "Low" 4 "Drive" 3 "Neutral" 0 "None" 2 "Reverse" 1 "Park" ;
VAL_ 101 DRIVER 1 "Driver Activity" 0 "No Activity" ;
VAL_ 101 FLTWDC 1 "Fault" 0 "No Fault" ;
VAL_ 101 FLTCAL 1 "Fault" 0 "No Fault" ;
VAL_ 101 FLTCON 1 "Fault" 0 "No Fault" ;
VAL_ 101 FLT2 1 "Fault" 0 "No Fault" ;
VAL_ 101 FLT1 1 "Fault" 0 "No Fault" ;
VAL_ 101 EN 1 "Enabled" 0 "Disabled" ;
VAL_ 101 OVERRIDE 1 "Driver Override" 0 "No Override" ;
VAL_ 100 EN 1 "Enabled" 0 "Disable" ;
VAL_ 99 WDCSRC 15 "STEERING_REPORT" 14 "STEERING_COMMAND" 13 "STEERING_DISABLED" 12 "STEERING_COUNTER" 11 "THROTTLE_REPORT" 10 "THROTTLE_COMMAND" 9 "THROTTLE_DISABLED" 8 "THROTTLE_COUNTER" 7 "BRAKE_REPORT" 6 "BRAKE_COMMAND" 5 "BRAKE_DISABLED" 4 "BRAKE_COUNTER" 3 "OTHER_STEERING" 2 "OTHER_THROTTLE" 1 "OTHER_BRAKE" 0 "NONE" ;
VAL_ 99 DRIVER 1 "Driver Activity" 0 "No Activity" ;
VAL_ 99 FLTWDC 1 "Fault" 0 "No Fault" ;
VAL_ 99 FLTCON 1 "Fault" 0 "No Fault" ;
VAL_ 99 FLT2 1 "Fault" 0 "No Fault" ;
VAL_ 99 FLT1 1 "Fault" 0 "No Fault" ;
VAL_ 99 EN 1 "Enabled" 0 "Disabled" ;
VAL_ 99 OVERRIDE 1 "Driver Override" 0 "No Override" ;
VAL_ 98 EN 1 "Enabled" 0 "Disable" ;
VAL_ 97 WDCSRC 15 "STEERING_REPORT" 14 "STEERING_COMMAND" 13 "STEERING_DISABLED" 12 "STEERING_COUNTER" 11 "THROTTLE_REPORT" 10 "THROTTLE_COMMAND" 9 "THROTTLE_DISABLED" 8 "THROTTLE_COUNTER" 7 "BRAKE_REPORT" 6 "BRAKE_COMMAND" 5 "BRAKE_DISABLED" 4 "BRAKE_COUNTER" 3 "OTHER_STEERING" 2 "OTHER_THROTTLE" 1 "OTHER_BRAKE" 0 "NONE" ;
VAL_ 97 WDCBRK 1 "WDC applying brakes" 0 "Normal" ;
VAL_ 97 DRIVER 1 "Driver Activity" 0 "No Activity" ;
VAL_ 97 FLTWDC 1 "Fault" 0 "No Fault" ;
VAL_ 97 FLTCON 1 "Fault" 0 "No Fault" ;
VAL_ 97 FLTBOO 1 "Fault" 0 "No Fault" ;
VAL_ 97 FLT2 1 "Fault" 0 "No Fault" ;
VAL_ 97 FLT1 1 "Fault" 0 "No Fault" ;
VAL_ 97 EN 1 "Enabled" 0 "Disabled" ;
VAL_ 97 OVERRIDE 1 "Driver Override" 0 "No Override" ;
VAL_ 97 BO 1 "On" 0 "Off" ;
VAL_ 97 BI 1 "On" 0 "Off" ;
VAL_ 97 BC 1 "On" 0 "Off" ;
VAL_ 96 EN 1 "Enabled" 0 "Disable" ;
VAL_ 96 BCMD 1 "On" 0 "Off" ;

View File

@ -7,16 +7,17 @@
export GIT_SSH_COMMAND="ssh -i /data/data/com.termux/files/id_rsa_openpilot_ro"
# check out the openpilot repo
# TODO: release branch only
if [ ! -d /data/openpilot ]; then
cd /tmp
git clone git@github.com:commaai/openpilot.git
git clone git@github.com:commaai/openpilot.git -b release
mv /tmp/openpilot /data/openpilot
fi
# update the openpilot repo
# enter openpilot directory
cd /data/openpilot
git pull
# removed automatic update from openpilot
#git pull
# start manager
cd selfdrive

View File

@ -0,0 +1,12 @@
Cython==0.24.1
bitstring==3.1.5
fastcluster==1.1.21
h5py==2.6.0
libusb1==1.5.0
pycapnp==0.5.9
pyzmq==15.4.0
raven==5.23.0
requests==2.10.0
setproctitle==1.1.10
simplejson==3.8.2
-e git+https://github.com/commaai/le_python.git#egg=Logentries

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -e
docker build -t tmppilot -f Dockerfile.openpilot .
docker run --rm \
-v "$(pwd)"/selfdrive/test/plant/out:/tmp/openpilot/selfdrive/test/plant/out \
tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/plant && ./runtest.sh'

View File

@ -27,6 +27,8 @@ libusb_context *ctx = NULL;
libusb_device_handle *dev_handle;
pthread_mutex_t usb_lock;
bool spoofing_started = false;
// double the FIFO size
#define RECV_SIZE (0x1000)
#define TIMEOUT 0
@ -147,7 +149,11 @@ void can_health(void *s) {
// set fields
healthData.setVoltage(health.voltage);
healthData.setCurrent(health.current);
healthData.setStarted(health.started);
if (spoofing_started) {
healthData.setStarted(1);
} else {
healthData.setStarted(health.started);
}
healthData.setControlsAllowed(health.controls_allowed);
healthData.setGasInterceptorDetected(health.gas_interceptor_detected);
@ -177,7 +183,7 @@ void can_send(void *s) {
memset(send, 0, msg_count*0x10);
for (int i = 0; i < msg_count; i++) {
auto cmsg = event.getCan()[i];
auto cmsg = event.getSendcan()[i];
if (cmsg.getAddress() >= 0x800) {
// extended
send[i*4] = (cmsg.getAddress() << 3) | 5;
@ -270,6 +276,11 @@ int main() {
err = setpriority(PRIO_PROCESS, 0, -4);
printf("boardd: setpriority returns %d\n", err);
// check the environment
if (getenv("STARTED")) {
spoofing_started = true;
}
// connect to the board
err = libusb_init(&ctx);
assert(err == 0);

View File

@ -18,19 +18,23 @@ except Exception:
# TODO: rewrite in C to save CPU
# *** serialization functions ***
def can_list_to_can_capnp(can_msgs):
def can_list_to_can_capnp(can_msgs, msgtype='can'):
dat = messaging.new_message()
dat.init('can', len(can_msgs))
dat.init(msgtype, len(can_msgs))
for i, can_msg in enumerate(can_msgs):
dat.can[i].address = can_msg[0]
dat.can[i].busTime = can_msg[1]
dat.can[i].dat = can_msg[2]
dat.can[i].src = can_msg[3]
if msgtype == 'sendcan':
cc = dat.sendcan[i]
else:
cc = dat.can[i]
cc.address = can_msg[0]
cc.busTime = can_msg[1]
cc.dat = can_msg[2]
cc.src = can_msg[3]
return dat
def can_capnp_to_can_list_old(dat, src_filter=[]):
ret = []
for msg in dat.can:
for msg in dat:
if msg.src in src_filter:
ret.append([msg.address, msg.busTime, msg.dat.encode("hex")])
return ret

View File

View File

@ -1,8 +1,12 @@
fingerprints = {
"ACURA ILX 2016 ACURAWATCH PLUS": {
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 929L: 4, 1057L: 5, 777L: 8, 1034L: 5, 1036L: 8, 398L: 3, 399L: 7, 145L: 8, 660L: 8, 985L: 3, 923L: 2, 542L: 7, 773L: 7, 800L: 8, 432L: 7, 419L: 8, 420L: 8, 1030L: 5, 422L: 8, 808L: 8, 428L: 8, 304L: 8, 819L: 7, 821L: 5, 57L: 3, 316L: 8, 545L: 4, 464L: 8, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 344L: 8, 804L: 8, 1039L: 8, 476L: 4, 892L: 8, 490L: 8, 1064L: 7, 882L: 2, 884L: 7, 887L: 8, 888L: 8, 380L: 8, 1365L: 5
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 929L: 4, 1057L: 5, 777L: 8, 1034L: 5, 1036L: 8, 398L: 3, 399L: 7, 145L: 8, 660L: 8, 985L: 3, 923L: 2, 542L: 7, 773L: 7, 800L: 8, 432L: 7, 419L: 8, 420L: 8, 1030L: 5, 422L: 8, 808L: 8, 428L: 8, 304L: 8, 819L: 7, 821L: 5, 57L: 3, 316L: 8, 545L: 4, 464L: 8, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 344L: 8, 804L: 8, 1039L: 8, 476L: 4, 892L: 8, 490L: 8, 1064L: 7, 882L: 2, 884L: 7, 887L: 8, 888L: 8, 380L: 8, 1365L: 5,
# sent messages
0xe4: 5, 0x1fa: 8, 0x200: 3, 0x30c: 8, 0x33d: 4,
},
"HONDA CIVIC 2016 TOURING": {
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 777L: 8, 1036L: 8, 1039L: 8, 1424L: 5, 401L: 8, 148L: 8, 662L: 4, 985L: 3, 795L: 8, 773L: 7, 800L: 8, 545L: 6, 420L: 8, 806L: 8, 808L: 8, 1322L: 5, 427L: 3, 428L: 8, 304L: 8, 432L: 7, 57L: 3, 450L: 8, 929L: 8, 330L: 8, 1302L: 8, 464L: 8, 1361L: 5, 1108L: 8, 597L: 8, 470L: 2, 344L: 8, 804L: 8, 399L: 7, 476L: 7, 1633L: 8, 487L: 4, 892L: 8, 490L: 8, 493L: 5, 884L: 8, 891L: 8, 380L: 8, 1365L: 5
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 777L: 8, 1036L: 8, 1039L: 8, 1424L: 5, 401L: 8, 148L: 8, 662L: 4, 985L: 3, 795L: 8, 773L: 7, 800L: 8, 545L: 6, 420L: 8, 806L: 8, 808L: 8, 1322L: 5, 427L: 3, 428L: 8, 304L: 8, 432L: 7, 57L: 3, 450L: 8, 929L: 8, 330L: 8, 1302L: 8, 464L: 8, 1361L: 5, 1108L: 8, 597L: 8, 470L: 2, 344L: 8, 804L: 8, 399L: 7, 476L: 7, 1633L: 8, 487L: 4, 892L: 8, 490L: 8, 493L: 5, 884L: 8, 891L: 8, 380L: 8, 1365L: 5,
# sent messages
0xe4: 5, 0x1fa: 8, 0x200: 3, 0x30c: 8, 0x33d: 5, 0x35e: 8, 0x39f: 8,
}
}

View File

View File

@ -2,7 +2,7 @@ import os
import dbcs
from collections import defaultdict
from selfdrive.controls.lib.hondacan import fix
from selfdrive.car.honda.hondacan import fix
from common.realtime import sec_since_boot
from common.dbc import dbc
@ -112,7 +112,7 @@ class CANParser(object):
# assess overall can validity: if there is one relevant message invalid, then set can validity flag to False
self.can_valid = True
if False in self.ok.values():
print "CAN INVALID!"
#print "CAN INVALID!"
self.can_valid = False
def _check_dead_msgs(self):

View File

@ -1,25 +1,54 @@
from collections import namedtuple
import common.numpy_fast as np
import selfdrive.controls.lib.hondacan as hondacan
from common.realtime import sec_since_boot
from selfdrive.config import CruiseButtons
from selfdrive.boardd.boardd import can_list_to_can_capnp
from selfdrive.controls.lib.alert_database import process_hud_alert
from selfdrive.controls.lib.drive_helpers import actuator_hystereses, rate_limit
class AH:
#[alert_idx, value]
# See dbc files for info on values"
NONE = [0, 0]
FCW = [1, 0x8]
STEER = [2, 1]
BRAKE_PRESSED = [3, 10]
GEAR_NOT_D = [4, 6]
SEATBELT = [5, 5]
SPEED_TOO_HIGH = [6, 8]
def process_hud_alert(hud_alert):
# initialize to no alert
fcw_display = 0
steer_required = 0
acc_alert = 0
if hud_alert == AH.NONE: # no alert
pass
elif hud_alert == AH.FCW: # FCW
fcw_display = hud_alert[1]
elif hud_alert == AH.STEER: # STEER
steer_required = hud_alert[1]
else: # any other ACC alert
acc_alert = hud_alert[1]
return fcw_display, steer_required, acc_alert
import selfdrive.car.honda.hondacan as hondacan
HUDData = namedtuple("HUDData",
["pcm_accel", "v_cruise", "X2", "car", "X4", "X5",
"lanes", "beep", "X8", "chime", "acc_alert"])
class CarController(object):
def __init__(self):
self.controls_allowed = False
self.mismatch_start, self.pcm_mismatch_start = 0, 0
self.braking = False
self.brake_steady = 0.
self.final_brake_last = 0.
# redundant safety check with the board
self.controls_allowed = False
def update(self, sendcan, enabled, CS, frame, final_gas, final_brake, final_steer, \
pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel, \
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert, \
@ -61,9 +90,9 @@ class CarController(object):
#print chime, alert_id, hud_alert
fcw_display, steer_required, acc_alert = process_hud_alert(hud_alert)
hud = HUDData(pcm_accel, hud_v_cruise, 0x41, hud_car,
hud = HUDData(int(pcm_accel), int(hud_v_cruise), 0x41, hud_car,
0xc1, 0x41, hud_lanes + steer_required,
snd_beep, 0x48, (snd_chime << 5) + fcw_display, acc_alert)
int(snd_beep), 0x48, (snd_chime << 5) + fcw_display, acc_alert)
if not all(isinstance(x, int) and 0 <= x < 256 for x in hud):
print "INVALID HUD", hud
@ -71,14 +100,11 @@ class CarController(object):
# **** process the car messages ****
user_brake_ctrl = CS.user_brake/0.015625 # FIXME: factor needed to convert to old scale
# *** compute control surfaces ***
tt = sec_since_boot()
GAS_MAX = 1004
BRAKE_MAX = 1024/4
#STEER_MAX = 0xF00 if not CS.torque_mod else 0xF00/4 # ilx has 8x steering torque limit, used as a 2x
STEER_MAX = 0xF00 # ilx has 8x steering torque limit, used as a 2x
STEER_MAX = 0xF00
GAS_OFFSET = 328
# steer torque is converted back to CAN reference (positive when steering right)
@ -87,51 +113,37 @@ class CarController(object):
apply_steer = int(np.clip(-final_steer*STEER_MAX, -STEER_MAX, STEER_MAX))
# no gas if you are hitting the brake or the user is
if apply_gas > 0 and (apply_brake != 0 or user_brake_ctrl > 10):
print "CANCELLING GAS", apply_brake, user_brake_ctrl
if apply_gas > 0 and (apply_brake != 0 or CS.brake_pressed):
print "CANCELLING GAS", apply_brake
apply_gas = 0
# no computer brake if the user is hitting the gas
# if the computer is trying to brake, it can't be hitting the gas
# TODO: car_gas can override brakes without canceling... this is bad
# no computer brake if the gas is being pressed
if CS.car_gas > 0 and apply_brake != 0:
print "CANCELLING BRAKE"
apply_brake = 0
# any other cp.vl[0x18F]['STEER_STATUS'] is common and can happen during user override. sending 0 torque to avoid EPS sending error 5
if CS.steer_not_allowed:
print "STEER ALERT, TORQUE INHIBITED"
apply_steer = 0
# *** entry into controls state ***
if (CS.prev_cruise_buttons == CruiseButtons.DECEL_SET or CS.prev_cruise_buttons == CruiseButtons.RES_ACCEL) and \
CS.cruise_buttons == 0 and not self.controls_allowed:
print "CONTROLS ARE LIVE"
self.controls_allowed = True
# to avoid race conditions, check if control has been disabled for at least 0.2s
# keep resetting start timer if mismatch isn't true
if not (self.controls_allowed and not enabled):
self.mismatch_start = tt
# to avoid race conditions, check if control is disabled but pcm control is on for at least 0.2s
if not (not self.controls_allowed and CS.pcm_acc_status):
self.pcm_mismatch_start = tt
# something is very wrong, since pcm control is active but controls should not be allowed; TODO: send pcm fault cmd?
if (tt - self.pcm_mismatch_start) > 0.2:
pcm_cancel_cmd = True
# TODO: clean up gear condition, ideally only D (and P for debug) shall be valid gears
# *** exit from controls state on cancel, gas, or brake ***
if (CS.cruise_buttons == CruiseButtons.CANCEL or CS.brake_pressed or
CS.user_gas_pressed or (tt - self.mismatch_start) > 0.2 or
not CS.main_on or not CS.gear_shifter_valid or
(CS.pedal_gas > 0 and CS.brake_only)) and self.controls_allowed:
CS.user_gas_pressed or (CS.pedal_gas > 0 and CS.brake_only)) and self.controls_allowed:
print "CONTROLS ARE DEAD"
self.controls_allowed = False
# 5 is a permanent fault, no torque request will be fullfilled
# *** controls fail on steer error, brake error, or invalid can ***
if CS.steer_error:
print "STEER ERROR"
self.controls_allowed = False
# any other cp.vl[0x18F]['STEER_STATUS'] is common and can happen during user override. sending 0 torque to avoid EPS sending error 5
elif CS.steer_not_allowed:
print "STEER ALERT, TORQUE INHIBITED"
apply_steer = 0
if CS.brake_error:
print "BRAKE ERROR"
self.controls_allowed = False
@ -140,13 +152,6 @@ class CarController(object):
print "CAN INVALID"
self.controls_allowed = False
if not self.controls_allowed:
apply_steer = 0
apply_gas = 0
apply_brake = 0
pcm_speed = 0 # make sure you send 0 target speed to pcm
#pcm_cancel_cmd = 1 # prevent pcm control from turning on. FIXME: we can't just do this
# Send CAN commands.
can_sends = []
@ -160,7 +165,6 @@ class CarController(object):
can_sends.append(
hondacan.create_brake_command(apply_brake, pcm_override,
pcm_cancel_cmd, hud.chime, idx))
if not CS.brake_only:
# send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
# This prevents unexpected pedal range rescaling
@ -182,4 +186,5 @@ class CarController(object):
idx = (frame/radar_send_step) % 4
can_sends.extend(hondacan.create_radar_commands(CS.v_ego, CS.civic, idx))
sendcan.send(can_list_to_can_capnp(can_sends).to_bytes())
sendcan.send(can_list_to_can_capnp(can_sends, msgtype='sendcan').to_bytes())

View File

@ -2,11 +2,11 @@ import numpy as np
import selfdrive.messaging as messaging
from selfdrive.boardd.boardd import can_capnp_to_can_list_old, can_capnp_to_can_list
from selfdrive.controls.lib.can_parser import CANParser
from selfdrive.controls.lib.fingerprints import fingerprints
from selfdrive.config import VehicleParams
from common.realtime import sec_since_boot
from selfdrive.car.fingerprints import fingerprints
from selfdrive.car.honda.can_parser import CANParser
def get_can_parser(civic, brake_only):
# this function generates lists for signal, messages and initial values
@ -46,6 +46,7 @@ def get_can_parser(civic, brake_only):
("LEFT_BLINKER", 0x326, 0),
("RIGHT_BLINKER", 0x326, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x14a, 100),
@ -97,6 +98,7 @@ def get_can_parser(civic, brake_only):
("LEFT_BLINKER", 0x294, 0),
("RIGHT_BLINKER", 0x294, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x156, 100),
@ -153,6 +155,7 @@ def fingerprint(logcan):
if len(possible_cars) == 1 and st is not None and (sec_since_boot()-st) > 0.1:
break
elif len(possible_cars) == 0:
print finger
raise Exception("car doesn't match any fingerprints")
print "fingerprinted", possible_cars[0]
@ -183,6 +186,9 @@ class CarState(object):
self.cruise_setting = 0
self.blinker_on = 0
self.left_blinker_on = 0
self.right_blinker_on = 0
# TODO: actually make this work
self.a_ego = 0.
@ -190,16 +196,9 @@ class CarState(object):
self.ui_speed_fudge = 1.01 if self.civic else 1.025
# load vehicle params
self.VP = VehicleParams(self.civic)
def update(self, logcan):
# ******************* do can recv *******************
can_pub_main = []
canMonoTimes = []
for a in messaging.drain_sock(logcan):
canMonoTimes.append(a.logMonoTime)
can_pub_main.extend(can_capnp_to_can_list_old(a, [0,2]))
self.VP = VehicleParams(self.civic, self.brake_only, self.torque_mod)
def update(self, can_pub_main):
cp = self.cp
cp.update_can(can_pub_main)
@ -215,6 +214,11 @@ class CarState(object):
self.prev_cruise_setting = self.cruise_setting
self.prev_blinker_on = self.blinker_on
self.prev_left_blinker_on = self.left_blinker_on
self.prev_right_blinker_on = self.right_blinker_on
self.rpm = cp.vl[0x17C]['ENGINE_RPM']
# ******************* parse out can *******************
self.door_all_closed = not any([cp.vl[0x405]['DOOR_OPEN_FL'], cp.vl[0x405]['DOOR_OPEN_FR'],
cp.vl[0x405]['DOOR_OPEN_RL'], cp.vl[0x405]['DOOR_OPEN_RR']])
@ -252,6 +256,8 @@ class CarState(object):
self.main_on = cp.vl[0x326]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,8] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x326]['LEFT_BLINKER'] or cp.vl[0x326]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x326]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x326]['RIGHT_BLINKER']
else:
self.gear_shifter = cp.vl[0x1A3]['GEAR_SHIFTER']
self.angle_steers = cp.vl[0x156]['STEER_ANGLE']
@ -261,6 +267,8 @@ class CarState(object):
self.main_on = cp.vl[0x1A6]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,4] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x294]['LEFT_BLINKER'] or cp.vl[0x294]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x294]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x294]['RIGHT_BLINKER']
self.car_gas = cp.vl[0x130]['CAR_GAS']
self.brake_pressed = cp.vl[0x17C]['BRAKE_PRESSED']
self.user_brake = cp.vl[0x1A4]['USER_BRAKE']
@ -272,4 +280,3 @@ class CarState(object):
self.hud_lead = cp.vl[0x30C]['HUD_LEAD']
self.counter_pcm = cp.vl[0x324]['COUNTER']
return canMonoTimes

View File

@ -0,0 +1,233 @@
#!/usr/bin/env python
import time
import numpy as np
from selfdrive.config import Conversions as CV
from selfdrive.car.honda.carstate import CarState
from selfdrive.car.honda.carcontroller import CarController, AH
from selfdrive.boardd.boardd import can_capnp_to_can_list_old
from cereal import car
import zmq
from common.services import service_list
import selfdrive.messaging as messaging
# Car button codes
class CruiseButtons:
RES_ACCEL = 4
DECEL_SET = 3
CANCEL = 2
MAIN = 1
#car chimes: enumeration from dbc file. Chimes are for alerts and warnings
class CM:
MUTE = 0
SINGLE = 3
DOUBLE = 4
REPEATED = 1
CONTINUOUS = 2
#car beepss: enumeration from dbc file. Beeps are for activ and deactiv
class BP:
MUTE = 0
SINGLE = 3
TRIPLE = 2
REPEATED = 1
class CarInterface(object):
def __init__(self, read_only=False):
context = zmq.Context()
self.logcan = messaging.sub_sock(context, service_list['can'].port)
self.frame = 0
# *** init the major players ***
self.CS = CarState(self.logcan)
# sending if read only is False
if not read_only:
self.sendcan = messaging.pub_sock(context, service_list['sendcan'].port)
self.CC = CarController()
def getVehicleParams(self):
return self.CS.VP
# returns a car.CarState
def update(self):
# ******************* do can recv *******************
can_pub_main = []
canMonoTimes = []
for a in messaging.drain_sock(self.logcan):
canMonoTimes.append(a.logMonoTime)
can_pub_main.extend(can_capnp_to_can_list_old(a.can, [0,2]))
self.CS.update(can_pub_main)
# create message
ret = car.CarState.new_message()
# speeds
ret.vEgo = self.CS.v_ego
ret.wheelSpeeds.fl = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_FL']
ret.wheelSpeeds.fr = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_FR']
ret.wheelSpeeds.rl = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_RL']
ret.wheelSpeeds.rr = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_RR']
# gas pedal
ret.gas = self.CS.car_gas / 256.0
if self.CS.VP.brake_only:
ret.gasPressed = self.CS.pedal_gas > 0
else:
ret.gasPressed = self.CS.user_gas_pressed
# brake pedal
ret.brake = self.CS.user_brake
ret.brakePressed = self.CS.brake_pressed != 0
# steering wheel
# TODO: units
ret.steeringAngle = self.CS.angle_steers
ret.steeringTorque = self.CS.cp.vl[0x18F]['STEER_TORQUE_SENSOR']
ret.steeringPressed = self.CS.steer_override
# cruise state
ret.cruiseState.enabled = self.CS.pcm_acc_status != 0
ret.cruiseState.speed = self.CS.v_cruise_pcm * CV.KPH_TO_MS
# TODO: button presses
buttonEvents = []
if self.CS.left_blinker_on != self.CS.prev_left_blinker_on:
be = car.CarState.ButtonEvent.new_message()
be.type = 'leftBlinker'
be.pressed = self.CS.left_blinker_on != 0
buttonEvents.append(be)
if self.CS.right_blinker_on != self.CS.prev_right_blinker_on:
be = car.CarState.ButtonEvent.new_message()
be.type = 'rightBlinker'
be.pressed = self.CS.right_blinker_on != 0
buttonEvents.append(be)
if self.CS.cruise_buttons != self.CS.prev_cruise_buttons:
be = car.CarState.ButtonEvent.new_message()
be.type = 'unknown'
if self.CS.cruise_buttons != 0:
be.pressed = True
but = self.CS.cruise_buttons
else:
be.pressed = False
but = self.CS.prev_cruise_buttons
if but == CruiseButtons.RES_ACCEL:
be.type = 'accelCruise'
elif but == CruiseButtons.DECEL_SET:
be.type = 'decelCruise'
elif but == CruiseButtons.CANCEL:
be.type = 'cancel'
elif but == CruiseButtons.MAIN:
be.type = 'altButton3'
buttonEvents.append(be)
if self.CS.cruise_setting != self.CS.prev_cruise_setting:
be = car.CarState.ButtonEvent.new_message()
be.type = 'unknown'
if self.CS.cruise_setting != 0:
be.pressed = True
but = self.CS.cruise_setting
else:
be.pressed = False
but = self.CS.prev_cruise_setting
if but == 1:
be.type = 'altButton1'
# TODO: more buttons?
buttonEvents.append(be)
ret.buttonEvents = buttonEvents
# errors
# TODO: I don't like the way capnp does enums
# These strings aren't checked at compile time
errors = []
if not self.CS.can_valid:
errors.append('commIssue')
if self.CS.steer_error:
errors.append('steerUnavailable')
elif self.CS.steer_not_allowed:
errors.append('steerTemporarilyUnavailable')
if self.CS.brake_error:
errors.append('brakeUnavailable')
if not self.CS.gear_shifter_valid:
errors.append('wrongGear')
if not self.CS.door_all_closed:
errors.append('doorOpen')
if not self.CS.seatbelt:
errors.append('seatbeltNotLatched')
if self.CS.esp_disabled:
errors.append('espDisabled')
if not self.CS.main_on:
errors.append('wrongCarMode')
if self.CS.gear_shifter == 2:
errors.append('reverseGear')
ret.errors = errors
ret.canMonoTimes = canMonoTimes
# cast to reader so it can't be modified
#print ret
return ret.as_reader()
# pass in a car.CarControl
# to be called @ 100hz
def apply(self, c):
#print c
if c.hudControl.speedVisible:
hud_v_cruise = c.hudControl.setSpeed * CV.MS_TO_KPH
else:
hud_v_cruise = 255
hud_alert = {
"none": AH.NONE,
"fcw": AH.FCW,
"steerRequired": AH.STEER,
"brakePressed": AH.BRAKE_PRESSED,
"wrongGear": AH.GEAR_NOT_D,
"seatbeltUnbuckled": AH.SEATBELT,
"speedTooHigh": AH.SPEED_TOO_HIGH}[str(c.hudControl.visualAlert)]
snd_beep, snd_chime = {
"none": (BP.MUTE, CM.MUTE),
"beepSingle": (BP.SINGLE, CM.MUTE),
"beepTriple": (BP.TRIPLE, CM.MUTE),
"beepRepeated": (BP.REPEATED, CM.MUTE),
"chimeSingle": (BP.MUTE, CM.SINGLE),
"chimeDouble": (BP.MUTE, CM.DOUBLE),
"chimeRepeated": (BP.MUTE, CM.REPEATED),
"chimeContinuous": (BP.MUTE, CM.CONTINUOUS)}[str(c.hudControl.audibleAlert)]
pcm_accel = int(np.clip(c.cruiseControl.accelOverride/1.4,0,1)*0xc6)
self.CC.update(self.sendcan, c.enabled, self.CS, self.frame, \
c.gas, c.brake, c.steeringTorque, \
c.cruiseControl.speedOverride, \
c.cruiseControl.override, \
c.cruiseControl.cancel, \
pcm_accel, \
hud_v_cruise, c.hudControl.lanesVisible, \
hud_show_car = c.hudControl.leadVisible, \
hud_alert = hud_alert, \
snd_beep = snd_beep, \
snd_chime = snd_chime)
self.frame += 1
return not (c.enabled and not self.CC.controls_allowed)
if __name__ == "__main__":
CI = CarInterface(read_only=True)
while 1:
cs = CI.update()
print(chr(27) + "[2J")
print cs
time.sleep(0.1)

View File

@ -57,12 +57,18 @@ class UIParams:
car_color = 110
class VehicleParams:
def __init__(self, civic):
def __init__(self, civic, brake_only=False, torque_mod=False):
if civic:
self.wheelbase = 2.67
self.steer_ratio = 15.3
self.slip_factor = 0.0014
self.civic = True
else:
self.wheelbase = 2.67 # from http://www.edmunds.com/acura/ilx/2016/sedan/features-specs/
self.steer_ratio = 15.3 # from http://www.edmunds.com/acura/ilx/2016/road-test-specs/
self.slip_factor = 0.0014
self.civic = False
self.brake_only = brake_only
self.torque_mod = torque_mod
self.ui_speed_fudge = 1.01 if self.civic else 1.025

View File

@ -1,85 +1,75 @@
#!/usr/bin/env python
import os
import zmq
import numpy as np
import selfdrive.messaging as messaging
from cereal import car
from selfdrive.config import Conversions as CV
from common.services import service_list
from common.realtime import sec_since_boot, set_realtime_priority, Ratekeeper
from selfdrive.config import CruiseButtons
from selfdrive.config import Conversions as CV
from selfdrive.controls.lib.drive_helpers import learn_angle_offset
from selfdrive.controls.lib.alert_database import process_alert, AI
import selfdrive.messaging as messaging
from selfdrive.controls.lib.carstate import CarState
from selfdrive.controls.lib.carcontroller import CarController
from selfdrive.controls.lib.longcontrol import LongControl
from selfdrive.controls.lib.latcontrol import LatControl
from selfdrive.controls.lib.pathplanner import PathPlanner
from selfdrive.controls.lib.adaptivecruise import AdaptiveCruise
from selfdrive.controls.lib.alertmanager import AlertManager
car_type = os.getenv("CAR")
if car_type is not None:
exec('from selfdrive.car.'+car_type+'.interface import CarInterface')
else:
from selfdrive.car.honda.interface import CarInterface
V_CRUISE_MAX = 144
V_CRUISE_MIN = 8
V_CRUISE_DELTA = 8
V_CRUISE_ENABLE_MIN = 40
def controlsd_thread(gctx, rate=100): #rate in Hz
# *** log ***
context = zmq.Context()
live100 = messaging.pub_sock(context, service_list['live100'].port)
thermal = messaging.sub_sock(context, service_list['thermal'].port)
live20 = messaging.sub_sock(context, service_list['live20'].port)
model = messaging.sub_sock(context, service_list['model'].port)
health = messaging.sub_sock(context, service_list['health'].port)
logcan = messaging.sub_sock(context, service_list['can'].port)
sendcan = messaging.pub_sock(context, service_list['sendcan'].port)
# *** init the major players ***
CS = CarState(logcan)
CC = CarController()
# connects to can and sendcan
CI = CarInterface()
VP = CI.getVehicleParams()
PP = PathPlanner(model)
AC = AdaptiveCruise(live20)
AM = AlertManager()
LoC = LongControl()
LaC = LatControl()
# *** control initial values ***
apply_brake = 0
# controls enabled state
enabled = False
last_enable_request = 0
# *** time values ***
last_enable_pressed = 0
# *** controls initial values ***
# *** display stuff
soft_disable_start = 0
sounding = False
no_mismatch_pcm_last, no_mismatch_ctrl_last = 0, 0
# car state
alert, sound_exp, hud_exp, text_exp, alert_p = None, 0, 0, 0, 0
rear_view_cam, rear_view_toggle = False, False
v_cruise = 255 # this means no display
v_cruise_max = 144
v_cruise_min = 8
v_cruise_delta = 8
# on activation target at least 25mph. With 5mph you need too much tapping
v_cruise_enable_min = 40
hud_v_cruise = 255
# learned angle offset
angle_offset = 0
max_enable_speed = 57. # ~91 mph
# rear view camera state
rear_view_toggle = False
pcm_threshold = 25.*CV.MPH_TO_MS # below this speed pcm cancels
overtemp = True
v_cruise_kph = 255
# 0.0 - 1.0
awareness_status = 0.0
soft_disable_timer = None
# start the loop
set_realtime_priority(2)
@ -88,14 +78,54 @@ def controlsd_thread(gctx, rate=100): #rate in Hz
cur_time = sec_since_boot()
# read CAN
canMonoTimes = CS.update(logcan)
CS = CI.update()
# **** rearview mirror management ***
if CS.cruise_setting == 1 and CS.prev_cruise_setting == 0:
rear_view_toggle = not rear_view_toggle
# did it request to enable?
enable_request, enable_condition = False, False
# show rear view camera on phone if in reverse gear or when lkas button is pressed
rear_view_cam = (CS.gear_shifter == 2) or rear_view_toggle or CS.blinker_on
if enabled:
# gives the user 6 minutes
awareness_status -= 1.0/(100*60*6)
if awareness_status <= 0.:
AM.add("driverDistracted", enabled)
# handle button presses
for b in CS.buttonEvents:
print b
# reset awareness on any user action
awareness_status = 1.0
# button presses for rear view
if b.type == "leftBlinker" or b.type == "rightBlinker":
if b.pressed:
rear_view_toggle = True
else:
rear_view_toggle = False
if b.type == "altButton1" and b.pressed:
rear_view_toggle = not rear_view_toggle
if not VP.brake_only and enabled and not b.pressed:
if b.type == "accelCruise":
v_cruise_kph = v_cruise_kph - (v_cruise_kph % V_CRUISE_DELTA) + V_CRUISE_DELTA
elif b.type == "decelCruise":
v_cruise_kph = v_cruise_kph - (v_cruise_kph % V_CRUISE_DELTA) - V_CRUISE_DELTA
v_cruise_kph = np.clip(v_cruise_kph, V_CRUISE_MIN, V_CRUISE_MAX)
if not enabled and b.type in ["accelCruise", "decelCruise"] and not b.pressed:
enable_request = True
# do disable on button down
if b.type == "cancel" and b.pressed:
AM.add("disable", enabled)
# *** health checking logic ***
hh = messaging.recv_sock(health)
if hh is not None:
# if the board isn't allowing controls but somehow we are enabled!
if not hh.health.controlsAllowed and enabled:
AM.add("controlsMismatch", enabled)
# *** thermal checking logic ***
@ -105,130 +135,57 @@ def controlsd_thread(gctx, rate=100): #rate in Hz
cpu_temps = [td.thermal.cpu0, td.thermal.cpu1, td.thermal.cpu2,
td.thermal.cpu3, td.thermal.mem, td.thermal.gpu]
# check overtemp
overtemp = any(t > 950 for t in cpu_temps)
if any(t > 950 for t in cpu_temps):
AM.add("overheat", enabled)
# *** getting model logic ***
PP.update(cur_time, CS.v_ego)
PP.update(cur_time, CS.vEgo)
if rk.frame % 5 == 2:
# *** run this at 20hz again ***
angle_offset = learn_angle_offset(enabled, CS.v_ego, angle_offset, np.asarray(PP.d_poly), LaC.y_des, CS.steer_override)
angle_offset = learn_angle_offset(enabled, CS.vEgo, angle_offset, np.asarray(PP.d_poly), LaC.y_des, CS.steeringPressed)
# to avoid race conditions, check if control has been disabled for at least 0.2s
mismatch_ctrl = not CC.controls_allowed and enabled
mismatch_pcm = (not CS.pcm_acc_status and (not apply_brake or CS.v_ego < 0.1)) and enabled
# keep resetting start timer if mismatch isn't true
if not mismatch_ctrl:
no_mismatch_ctrl_last = cur_time
if not mismatch_pcm or not CS.brake_only:
no_mismatch_pcm_last = cur_time
#*** v_cruise logic ***
if CS.brake_only:
v_cruise = int(CS.v_cruise_pcm) # TODO: why sometimes v_cruise_pcm is long type?
else:
if CS.prev_cruise_buttons == 0 and CS.cruise_buttons == CruiseButtons.RES_ACCEL and enabled:
v_cruise = v_cruise - (v_cruise % v_cruise_delta) + v_cruise_delta
elif CS.prev_cruise_buttons == 0 and CS.cruise_buttons == CruiseButtons.DECEL_SET and enabled:
v_cruise = v_cruise + (v_cruise % v_cruise_delta) - v_cruise_delta
# *** enabling/disabling logic ***
enable_pressed = (CS.prev_cruise_buttons == CruiseButtons.DECEL_SET or CS.prev_cruise_buttons == CruiseButtons.RES_ACCEL) \
and CS.cruise_buttons == 0
if enable_pressed:
print "enabled pressed at", cur_time
last_enable_pressed = cur_time
# if pcm does speed control than we need to wait on pcm to enable
if CS.brake_only:
enable_condition = (cur_time - last_enable_pressed) < 0.2 and CS.pcm_acc_status
else:
enable_condition = enable_pressed
# always clear the alert at every cycle
alert_id = []
# check for PCM not enabling
if CS.brake_only and (cur_time - last_enable_pressed) < 0.2 and not CS.pcm_acc_status:
print "waiting for PCM to enable"
# check for denied enabling
if enable_pressed and not enabled:
deny_enable = \
[(AI.SEATBELT, not CS.seatbelt),
(AI.DOOR_OPEN, not CS.door_all_closed),
(AI.ESP_OFF, CS.esp_disabled),
(AI.STEER_ERROR, CS.steer_error),
(AI.BRAKE_ERROR, CS.brake_error),
(AI.GEAR_NOT_D, not CS.gear_shifter_valid),
(AI.MAIN_OFF, not CS.main_on),
(AI.PEDAL_PRESSED, CS.user_gas_pressed or CS.brake_pressed or (CS.pedal_gas > 0 and CS.brake_only)),
(AI.HIGH_SPEED, CS.v_ego > max_enable_speed),
(AI.OVERHEAT, overtemp),
(AI.COMM_ISSUE, PP.dead or AC.dead),
(AI.CONTROLSD_LAG, rk.remaining < -0.2)]
for alertn, cond in deny_enable:
if cond:
alert_id += [alertn]
# check for soft disables
# disable if the pedals are pressed while engaged, this is a user disable
if enabled:
soft_disable = \
[(AI.SEATBELT_SD, not CS.seatbelt),
(AI.DOOR_OPEN_SD, not CS.door_all_closed),
(AI.ESP_OFF_SD, CS.esp_disabled),
(AI.OVERHEAT_SD, overtemp),
(AI.COMM_ISSUE_SD, PP.dead or AC.dead),
(AI.CONTROLSD_LAG_SD, rk.remaining < -0.2)]
sounding = False
for alertn, cond in soft_disable:
if cond:
alert_id += [alertn]
sounding = True
# soft disengagement expired, user need to take control
if (cur_time - soft_disable_start) > 3.:
enabled = False
v_cruise = 255
if not sounding:
soft_disable_start = cur_time
if CS.gasPressed or CS.brakePressed:
AM.add("disable", enabled)
# check for immediate disables
if enabled:
immediate_disable = \
[(AI.PCM_LOW_SPEED, (cur_time > no_mismatch_pcm_last > 0.2) and CS.v_ego < pcm_threshold),
(AI.STEER_ERROR_ID, CS.steer_error),
(AI.BRAKE_ERROR_ID, CS.brake_error),
(AI.CTRL_MISMATCH_ID, (cur_time - no_mismatch_ctrl_last) > 0.2),
(AI.PCM_MISMATCH_ID, (cur_time - no_mismatch_pcm_last) > 0.2)]
for alertn, cond in immediate_disable:
if cond:
alert_id += [alertn]
# immediate turn off control
enabled = False
v_cruise = 255
if enable_request:
# check for pressed pedals
if CS.gasPressed or CS.brakePressed:
AM.add("pedalPressed", enabled)
enable_request = False
else:
print "enabled pressed at", cur_time
last_enable_request = cur_time
# user disabling
if enabled and (CS.user_gas_pressed or CS.brake_pressed or not CS.gear_shifter_valid or \
(CS.cruise_buttons == CruiseButtons.CANCEL and CS.prev_cruise_buttons == 0) or \
not CS.main_on or (CS.pedal_gas > 0 and CS.brake_only)):
enabled = False
v_cruise = 255
alert_id += [AI.DISABLE]
if VP.brake_only:
enable_condition = ((cur_time - last_enable_request) < 0.2) and CS.cruiseState.enabled
else:
enable_condition = enable_request
# enabling
if enable_condition and not enabled and len(alert_id) == 0:
if enable_request or enable_condition or enabled:
# add all alerts from car
for alert in CS.errors:
AM.add(alert, enabled)
if AC.dead:
AM.add("radarCommIssue", enabled)
if PP.dead:
AM.add("modelCommIssue", enabled)
if enable_condition and not enabled and not AM.alertPresent():
print "*** enabling controls"
#enable both lateral and longitudinal controls
# beep for enabling
AM.add("enable", enabled)
# enable both lateral and longitudinal controls
enabled = True
counter_pcm_enabled = CS.counter_pcm
# on activation, let's always set v_cruise from where we are, even if PCM ACC is active
# what we want to be displayed in mph
v_cruise_mph = round(CS.v_ego * CV.MS_TO_MPH * CS.ui_speed_fudge)
# what we need to send to have that displayed
v_cruise = int(round(np.maximum(v_cruise_mph * CV.MPH_TO_KPH, v_cruise_enable_min)))
v_cruise_kph = int(round(np.maximum(CS.vEgo * CV.MS_TO_KPH * VP.ui_speed_fudge, V_CRUISE_ENABLE_MIN)))
# 6 minutes driver you're on
awareness_status = 1.0
@ -236,67 +193,69 @@ def controlsd_thread(gctx, rate=100): #rate in Hz
# reset the PID loops
LaC.reset()
# start long control at actual speed
LoC.reset(v_pid = CS.v_ego)
LoC.reset(v_pid = CS.vEgo)
alert_id += [AI.ENABLE]
if VP.brake_only and CS.cruiseState.enabled:
v_cruise_kph = CS.cruiseState.speed * CV.MS_TO_KPH
if v_cruise != 255 and not CS.brake_only:
v_cruise = np.clip(v_cruise, v_cruise_min, v_cruise_max)
# *** put the adaptive in adaptive cruise control ***
AC.update(cur_time, CS.vEgo, CS.steeringAngle, LoC.v_pid, awareness_status, VP)
# **** awareness status manager ****
if enabled:
# gives the user 6 minutes
awareness_status -= 1.0/(100*60*6)
# reset on steering, blinker, or cruise buttons
if CS.steer_override or CS.blinker_on or CS.cruise_buttons or CS.cruise_setting:
awareness_status = 1.0
if awareness_status <= 0.:
alert_id += [AI.DRIVER_DISTRACTED]
# ****** initial actuators commands ***
# *** gas/brake PID loop ***
AC.update(cur_time, CS.v_ego, CS.angle_steers, LoC.v_pid, awareness_status, CS.VP)
final_gas, final_brake = LoC.update(enabled, CS, v_cruise, AC.v_target_lead, AC.a_target, AC.jerk_factor)
pcm_accel = int(np.clip(AC.a_pcm/1.4,0,1)*0xc6) # TODO: perc of max accel in ACC?
final_gas, final_brake = LoC.update(enabled, CS.vEgo, v_cruise_kph, AC.v_target_lead, AC.a_target, AC.jerk_factor, VP)
# *** steering PID loop ***
final_steer, sat_flag = LaC.update(enabled, CS, PP.d_poly, angle_offset)
# this needs to stay before hysteresis logic to avoid pcm staying on control during brake hysteresis
pcm_override = True # this is always True
pcm_cancel_cmd = False
if CS.brake_only and final_brake == 0.:
pcm_speed = LoC.v_pid - .3 # FIXME: just for exp
else:
pcm_speed = 0
final_steer, sat_flag = LaC.update(enabled, CS.vEgo, CS.steeringAngle, CS.steeringPressed, PP.d_poly, angle_offset, VP)
# ***** handle alerts ****
# send a "steering required alert" if saturation count has reached the limit
if sat_flag:
alert_id += [AI.STEER_SATURATED]
AM.add("steerSaturated", enabled)
# process the alert, based on id
alert, chime, beep, hud_alert, alert_text, sound_exp, hud_exp, text_exp, alert_p = \
process_alert(alert_id, alert, cur_time, sound_exp, hud_exp, text_exp, alert_p)
if enabled and AM.alertShouldDisable():
print "DISABLING IMMEDIATELY ON ALERT"
enabled = False
# alerts pub
if len(alert_id) != 0:
print alert_id, alert_text
# *** process for hud display ***
if not enabled or (hud_v_cruise == 255 and CS.counter_pcm == counter_pcm_enabled):
hud_v_cruise = 255
if enabled and AM.alertShouldSoftDisable():
if soft_disable_timer is None:
soft_disable_timer = 3 * rate
elif soft_disable_timer == 0:
print "SOFT DISABLING ON ALERT"
enabled = False
else:
soft_disable_timer -= 1
else:
hud_v_cruise = v_cruise
soft_disable_timer = None
# *** actually do can sends ***
CC.update(sendcan, enabled, CS, rk.frame, \
final_gas, final_brake, final_steer, \
pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel, \
hud_v_cruise, hud_show_lanes = enabled, \
hud_show_car = AC.has_lead, \
hud_alert = hud_alert, \
snd_beep = beep, snd_chime = chime)
# *** push the alerts to current ***
alert_text_1, alert_text_2, visual_alert, audible_alert = AM.process_alerts(cur_time)
# ***** control the car *****
CC = car.CarControl.new_message()
CC.enabled = enabled
CC.gas = float(final_gas)
CC.brake = float(final_brake)
CC.steeringTorque = float(final_steer)
CC.cruiseControl.override = True
CC.cruiseControl.cancel = bool((not VP.brake_only) or (not enabled and CS.cruiseState.enabled)) # always cancel if we have an interceptor
CC.cruiseControl.speedOverride = float((LoC.v_pid - .3) if (VP.brake_only and final_brake == 0.) else 0.0)
CC.cruiseControl.accelOverride = float(AC.a_pcm)
CC.hudControl.setSpeed = float(v_cruise_kph * CV.KPH_TO_MS)
CC.hudControl.speedVisible = enabled
CC.hudControl.lanesVisible = enabled
CC.hudControl.leadVisible = bool(AC.has_lead)
CC.hudControl.visualAlert = visual_alert
CC.hudControl.audibleAlert = audible_alert
# this alert will apply next controls cycle
if not CI.apply(CC):
AM.add("controlsFailed", enabled)
# ***** publish state to logger *****
@ -304,14 +263,14 @@ def controlsd_thread(gctx, rate=100): #rate in Hz
dat = messaging.new_message()
dat.init('live100')
# move liveUI into live100
dat.live100.rearViewCam = bool(rear_view_cam)
dat.live100.alertText1 = alert_text[0]
dat.live100.alertText2 = alert_text[1]
# show rear view camera on phone if in reverse gear or when button is pressed
dat.live100.rearViewCam = ('reverseGear' in CS.errors) or rear_view_toggle
dat.live100.alertText1 = alert_text_1
dat.live100.alertText2 = alert_text_2
dat.live100.awarenessStatus = max(awareness_status, 0.0) if enabled else 0.0
# what packets were used to process
dat.live100.canMonoTimes = canMonoTimes
dat.live100.canMonoTimes = list(CS.canMonoTimes)
dat.live100.mdMonoTime = PP.logMonoTime
dat.live100.l20MonoTime = AC.logMonoTime
@ -319,15 +278,13 @@ def controlsd_thread(gctx, rate=100): #rate in Hz
dat.live100.enabled = enabled
# car state
dat.live100.vEgo = float(CS.v_ego)
dat.live100.aEgo = float(CS.a_ego)
dat.live100.angleSteers = float(CS.angle_steers)
dat.live100.hudLead = CS.hud_lead
dat.live100.steerOverride = CS.steer_override
dat.live100.vEgo = CS.vEgo
dat.live100.angleSteers = CS.steeringAngle
dat.live100.steerOverride = CS.steeringPressed
# longitudinal control state
dat.live100.vPid = float(LoC.v_pid)
dat.live100.vCruise = float(v_cruise)
dat.live100.vCruise = float(v_cruise_kph)
dat.live100.upAccelCmd = float(LoC.Up_accel_cmd)
dat.live100.uiAccelCmd = float(LoC.Ui_accel_cmd)
@ -356,3 +313,4 @@ def main(gctx=None):
if __name__ == "__main__":
main()

View File

@ -1,178 +0,0 @@
alerts = []
keys = ["id",
"chime",
"beep",
"hud_alert",
"screen_chime",
"priority",
"text_line_1",
"text_line_2",
"duration_sound",
"duration_hud_alert",
"duration_text"]
#car chimes: enumeration from dbc file. Chimes are for alerts and warnings
class CM:
MUTE = 0
SINGLE = 3
DOUBLE = 4
REPEATED = 1
CONTINUOUS = 2
#car beepss: enumeration from dbc file. Beeps are for activ and deactiv
class BP:
MUTE = 0
SINGLE = 3
TRIPLE = 2
REPEATED = 1
# lert ids
class AI:
ENABLE = 0
DISABLE = 1
SEATBELT = 2
DOOR_OPEN = 3
PEDAL_PRESSED = 4
COMM_ISSUE = 5
ESP_OFF = 6
FCW = 7
STEER_ERROR = 8
BRAKE_ERROR = 9
CALIB_INCOMPLETE = 10
CALIB_INVALID = 11
GEAR_NOT_D = 12
MAIN_OFF = 13
STEER_SATURATED = 14
PCM_LOW_SPEED = 15
THERMAL_DEAD = 16
OVERHEAT = 17
HIGH_SPEED = 18
CONTROLSD_LAG = 19
STEER_ERROR_ID = 100
BRAKE_ERROR_ID = 101
PCM_MISMATCH_ID = 102
CTRL_MISMATCH_ID = 103
SEATBELT_SD = 200
DOOR_OPEN_SD = 201
COMM_ISSUE_SD = 202
ESP_OFF_SD = 203
THERMAL_DEAD_SD = 204
OVERHEAT_SD = 205
CONTROLSD_LAG_SD = 206
CALIB_INCOMPLETE_SD = 207
CALIB_INVALID_SD = 208
DRIVER_DISTRACTED = 300
class AH:
#[alert_idx, value]
# See dbc files for info on values"
NONE = [0, 0]
FCW = [1, 0x8]
STEER = [2, 1]
BRAKE_PRESSED = [3, 10]
GEAR_NOT_D = [4, 6]
SEATBELT = [5, 5]
SPEED_TOO_HIGH = [6, 8]
class ET:
ENABLE = 0
NO_ENTRY = 1
WARNING = 2
SOFT_DISABLE = 3
IMMEDIATE_DISABLE = 4
USER_DISABLE = 5
def process_alert(alert_id, alert, cur_time, sound_exp, hud_exp, text_exp, alert_p):
# INPUTS:
# alert_id is mapped to the alert properties in alert_database
# cur_time is current time
# sound_exp is when the alert beep/chime is supposed to end
# hud_exp is when the hud visual is supposed to end
# text_exp is when the alert text is supposed to disappear
# alert_p is the priority of the current alert
# CM, BP, AH are classes defined in alert_database and they respresents chimes, beeps and hud_alerts
if len(alert_id) > 0:
# take the alert with higher priority
alerts_present = filter(lambda a_id: a_id['id'] in alert_id, alerts)
alert = sorted(alerts_present, key=lambda k: k['priority'])[-1]
# check if we have a more important alert
if alert['priority'] > alert_p:
alert_p = alert['priority']
sound_exp = cur_time + alert['duration_sound']
hud_exp = cur_time + alert['duration_hud_alert']
text_exp = cur_time + alert['duration_text']
chime = CM.MUTE
beep = BP.MUTE
if cur_time < sound_exp:
chime = alert['chime']
beep = alert['beep']
hud_alert = AH.NONE
if cur_time < hud_exp:
hud_alert = alert['hud_alert']
alert_text = ["", ""]
if cur_time < text_exp:
alert_text = [alert['text_line_1'], alert['text_line_2']]
if chime == CM.MUTE and beep == BP.MUTE and hud_alert == AH.NONE: #and alert_text[0] is None and alert_text[1] is None:
alert_p = 0
return alert, chime, beep, hud_alert, alert_text, sound_exp, hud_exp, text_exp, alert_p
def process_hud_alert(hud_alert):
# initialize to no alert
fcw_display = 0
steer_required = 0
acc_alert = 0
if hud_alert == AH.NONE: # no alert
pass
elif hud_alert == AH.FCW: # FCW
fcw_display = hud_alert[1]
elif hud_alert == AH.STEER: # STEER
steer_required = hud_alert[1]
else: # any other ACC alert
acc_alert = hud_alert[1]
return fcw_display, steer_required, acc_alert
def app_alert(alert_add):
alerts.append(dict(zip(keys, alert_add)))
app_alert([AI.ENABLE, CM.MUTE, BP.SINGLE, AH.NONE, ET.ENABLE, 2, "", "", .2, 0., 0.])
app_alert([AI.DISABLE, CM.MUTE, BP.SINGLE, AH.NONE, ET.USER_DISABLE, 2, "", "", .2, 0., 0.])
app_alert([AI.SEATBELT, CM.DOUBLE, BP.MUTE, AH.SEATBELT, ET.NO_ENTRY, 1, "Comma Unavailable", "Seatbelt Unlatched", .4, 2., 3.])
app_alert([AI.DOOR_OPEN, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Door Open", .4, 0., 3.])
app_alert([AI.PEDAL_PRESSED, CM.DOUBLE, BP.MUTE, AH.BRAKE_PRESSED, ET.NO_ENTRY, 1, "Comma Unavailable", "Pedal Pressed", .4, 2., 3.])
app_alert([AI.COMM_ISSUE, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Communcation Issues", .4, 0., 3.])
app_alert([AI.ESP_OFF, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "ESP Off", .4, 0., 3.])
app_alert([AI.FCW, CM.REPEATED, BP.MUTE, AH.FCW, ET.WARNING, 3, "Risk of Collision", "", 1., 2., 3.])
app_alert([AI.STEER_ERROR, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Steer Error", .4, 0., 3.])
app_alert([AI.BRAKE_ERROR, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Brake Error", .4, 0., 3.])
app_alert([AI.CALIB_INCOMPLETE, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Calibration in Progress", .4, 0., 3.])
app_alert([AI.CALIB_INVALID, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Calibration Error", .4, 0., 3.])
app_alert([AI.GEAR_NOT_D, CM.DOUBLE, BP.MUTE, AH.GEAR_NOT_D, ET.NO_ENTRY, 1, "Comma Unavailable", "Gear not in D", .4, 2., 3.])
app_alert([AI.MAIN_OFF, CM.MUTE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Main Switch Off", .4, 0., 3.])
app_alert([AI.STEER_SATURATED, CM.SINGLE, BP.MUTE, AH.STEER, ET.WARNING, 2, "Take Control", "Steer Control Saturated", 1., 2., 3.])
app_alert([AI.PCM_LOW_SPEED, CM.MUTE, BP.SINGLE, AH.STEER, ET.WARNING, 2, "Comma disengaged", "Speed too low", .2, 2., 3.])
app_alert([AI.THERMAL_DEAD, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Thermal Unavailable", .4, 0., 3.])
app_alert([AI.OVERHEAT, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "System Overheated", .4, 0., 3.])
app_alert([AI.HIGH_SPEED, CM.DOUBLE, BP.MUTE, AH.SPEED_TOO_HIGH, ET.NO_ENTRY, 1, "Comma Unavailable", "Speed Too High", .4, 2., 3.])
app_alert([AI.CONTROLSD_LAG, CM.DOUBLE, BP.MUTE, AH.NONE, ET.NO_ENTRY, 1, "Comma Unavailable", "Controls Lagging", .4, 0., 3.])
app_alert([AI.STEER_ERROR_ID, CM.REPEATED, BP.MUTE, AH.STEER, ET.IMMEDIATE_DISABLE, 3, "Take Control Immediately", "Steer Error", 1., 3., 3.])
app_alert([AI.BRAKE_ERROR_ID, CM.REPEATED, BP.MUTE, AH.STEER, ET.IMMEDIATE_DISABLE, 3, "Take Control Immediately", "Brake Error", 1., 3., 3.])
app_alert([AI.PCM_MISMATCH_ID, CM.REPEATED, BP.MUTE, AH.STEER, ET.IMMEDIATE_DISABLE, 3, "Take Control Immediately", "Pcm Mismatch", 1., 3., 3.])
app_alert([AI.CTRL_MISMATCH_ID, CM.REPEATED, BP.MUTE, AH.STEER, ET.IMMEDIATE_DISABLE, 3, "Take Control Immediately", "Ctrl Mismatch", 1., 3., 3.])
app_alert([AI.SEATBELT_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Seatbelt Unlatched", 1., 3., 3.])
app_alert([AI.DOOR_OPEN_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Door Open", 1., 3., 3.])
app_alert([AI.COMM_ISSUE_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Technical Issues", 1., 3., 3.])
app_alert([AI.ESP_OFF_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "ESP Off", 1., 3., 3.])
app_alert([AI.THERMAL_DEAD_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Thermal Unavailable", 1., 3., 3.])
app_alert([AI.OVERHEAT_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "System Overheated", 1., 3., 3.])
app_alert([AI.CONTROLSD_LAG_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Controls Lagging", 1., 3., 3.])
app_alert([AI.CALIB_INCOMPLETE_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Calibration in Progress", 1., 3., 3.])
app_alert([AI.CALIB_INVALID_SD, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 3, "Take Control Immediately", "Calibration Error", 1., 3., 3.])
app_alert([AI.DRIVER_DISTRACTED, CM.REPEATED, BP.MUTE, AH.STEER, ET.SOFT_DISABLE, 2, "Take Control to Regain Speed", "User Distracted", 1., 1., 1.])

View File

@ -0,0 +1,113 @@
from cereal import car
class ET:
ENABLE = 0
NO_ENTRY = 1
WARNING = 2
SOFT_DISABLE = 3
IMMEDIATE_DISABLE = 4
USER_DISABLE = 5
class alert(object):
def __init__(self, alert_text_1, alert_text_2, alert_type, visual_alert, audible_alert, duration_sound, duration_hud_alert, duration_text):
self.alert_text_1 = alert_text_1
self.alert_text_2 = alert_text_2
self.alert_type = alert_type
self.visual_alert = visual_alert if visual_alert is not None else "none"
self.audible_alert = audible_alert if audible_alert is not None else "none"
self.duration_sound = duration_sound
self.duration_hud_alert = duration_hud_alert
self.duration_text = duration_text
# typecheck that enums are valid on startup
tst = car.CarControl.new_message()
tst.hudControl.visualAlert = self.visual_alert
tst.hudControl.audibleAlert = self.audible_alert
def __str__(self):
return self.alert_text_1 + "/" + self.alert_text_2 + " " + str(self.alert_type) + " " + str(self.visual_alert) + " " + str(self.audible_alert)
def __gt__(self, alert2):
return self.alert_type > alert2.alert_type
class AlertManager(object):
alerts = {
"enable": alert("", "", ET.ENABLE, None, "beepSingle", .2, 0., 0.),
"disable": alert("", "", ET.USER_DISABLE, None, "beepSingle", .2, 0., 0.),
"pedalPressed": alert("Comma Unavailable", "Pedal Pressed", ET.NO_ENTRY, "brakePressed", "chimeDouble", .4, 2., 3.),
"driverDistracted": alert("Take Control to Regain Speed", "User Distracted", ET.WARNING, "steerRequired", "chimeRepeated", 1., 1., 1.),
"steerSaturated": alert("Take Control", "Steer Control Saturated", ET.WARNING, "steerRequired", "chimeSingle", 1., 2., 3.),
"overheat": alert("Take Control Immediately", "System Overheated", ET.SOFT_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"controlsMismatch": alert("Take Control Immediately", "Controls Mismatch", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"radarCommIssue": alert("Take Control Immediately", "Radar Comm Issue", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"modelCommIssue": alert("Take Control Immediately", "Model Comm Issue", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"controlsFailed": alert("Take Control Immediately", "Controls Failed", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
# car errors
"commIssue": alert("Take Control Immediately","Communication Issues", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"steerUnavailable": alert("Take Control Immediately","Steer Error", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"steerTemporarilyUnavailable": alert("Take Control", "Steer Temporarily Unavailable", ET.WARNING, "steerRequired", "chimeRepeated", 1., 2., 3.),
"brakeUnavailable": alert("Take Control Immediately","Brake Error", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"gasUnavailable": alert("Take Control Immediately","Gas Error", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"wrongGear": alert("Take Control Immediately","Gear not D", ET.SOFT_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"reverseGear": alert("Take Control Immediately","Car in Reverse", ET.IMMEDIATE_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"doorOpen": alert("Take Control Immediately","Door Open", ET.SOFT_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"seatbeltNotLatched": alert("Take Control Immediately","Seatbelt Unlatched", ET.SOFT_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"espDisabled": alert("Take Control Immediately","ESP Off", ET.SOFT_DISABLE, "steerRequired", "chimeRepeated", 1., 3., 3.),
"wrongCarMode": alert("Comma Unavailable","Main Switch Off", ET.NO_ENTRY, None, None, .4, 0., 3.),
}
def __init__(self):
self.activealerts = []
self.current_alert = None
def alertPresent(self):
return len(self.activealerts) > 0
def alertShouldSoftDisable(self):
return len(self.activealerts) > 0 and self.activealerts[0].alert_type == ET.SOFT_DISABLE
def alertShouldDisable(self):
return len(self.activealerts) > 0 and self.activealerts[0].alert_type >= ET.IMMEDIATE_DISABLE
def add(self, alert_type, enabled = True):
this_alert = self.alerts[str(alert_type)]
# downgrade the alert if we aren't enabled
if not enabled and this_alert.alert_type > ET.NO_ENTRY:
this_alert = alert("Comma Unavailable" if this_alert.alert_text_1 != "" else "", this_alert.alert_text_2, ET.NO_ENTRY, None, "chimeDouble", .4, 0., 3.)
# ignore no entries if we are enabled
if enabled and this_alert.alert_type < ET.WARNING:
return
self.activealerts.append(this_alert)
self.activealerts.sort()
def process_alerts(self, cur_time):
if self.alertPresent():
self.alert_start_time = cur_time
self.current_alert = self.activealerts[0]
print self.current_alert
alert_text_1 = ""
alert_text_2 = ""
visual_alert = "none"
audible_alert = "none"
if self.current_alert is not None:
# ewwwww
if self.alert_start_time + self.current_alert.duration_sound > cur_time:
audible_alert = self.current_alert.audible_alert
if self.alert_start_time + self.current_alert.duration_hud_alert > cur_time:
visual_alert = self.current_alert.visual_alert
if self.alert_start_time + self.current_alert.duration_text > cur_time:
alert_text_1 = self.current_alert.alert_text_1
alert_text_2 = self.current_alert.alert_text_2
# reset
self.activealerts = []
return alert_text_1, alert_text_2, visual_alert, audible_alert

View File

@ -97,24 +97,24 @@ class LatControl(object):
def reset(self):
self.Ui_steer = 0.
def update(self, enabled, CS, d_poly, angle_offset):
def update(self, enabled, v_ego, angle_steers, steer_override, d_poly, angle_offset, VP):
rate = 100
steer_max = 1.0
# how far we look ahead is function of speed
d_lookahead = calc_d_lookahead(CS.v_ego)
d_lookahead = calc_d_lookahead(v_ego)
# calculate actual offset at the lookahead point
self.y_actual, _ = calc_lookahead_offset(CS.v_ego, CS.angle_steers,
d_lookahead, CS.VP, angle_offset)
self.y_actual, _ = calc_lookahead_offset(v_ego, angle_steers,
d_lookahead, VP, angle_offset)
# desired lookahead offset
self.y_des = np.polyval(d_poly, d_lookahead)
output_steer, self.Up_steer, self.Ui_steer, self.lateral_control_sat, self.sat_count, sat_flag = pid_lateral_control(
CS.v_ego, self.y_actual, self.y_des, self.Ui_steer, steer_max,
CS.steer_override, self.sat_count, enabled, CS.torque_mod, rate)
v_ego, self.y_actual, self.y_des, self.Ui_steer, steer_max,
steer_override, self.sat_count, enabled, VP.torque_mod, rate)
final_steer = np.clip(output_steer, -steer_max, steer_max)
return final_steer, sat_flag

View File

@ -107,7 +107,7 @@ def pid_long_control(v_ego, v_pid, Ui_accel_cmd, gas_max, brake_max, jerk_factor
accel_cmd_new = Ui_accel_cmd_new + Up_accel_cmd
output_gb_new = compute_gb([accel_cmd_new, v_ego])
# Anti-wind up for integrator: only update integrator if we not against the thottle and brake limits
# Anti-wind up for integrator: only update integrator if we not against the throttle and brake limits
# do not wind up if we are changing gear and we are on the gas pedal
if (((v_error >= 0. and (output_gb_new < gas_max or Ui_accel_cmd < 0)) or
(v_error <= 0. and (output_gb_new > - brake_max or Ui_accel_cmd > 0))) and
@ -151,9 +151,9 @@ class LongControl(object):
self.Ui_accel_cmd = 0.
self.v_pid = v_pid
def update(self, enabled, CS, v_cruise, v_target_lead, a_target, jerk_factor):
def update(self, enabled, v_ego, v_cruise, v_target_lead, a_target, jerk_factor, VP):
# TODO: not every time
if CS.brake_only:
if VP.brake_only:
gas_max_v = [0, 0] # values
else:
gas_max_v = [0.6, 0.6] # values
@ -162,8 +162,8 @@ class LongControl(object):
brake_max_bp = [0., 5., 20., 100.] # speeds
# brake and gas limits
brake_max = np.interp(CS.v_ego, brake_max_bp, brake_max_v)
gas_max = np.interp(CS.v_ego, gas_max_bp, gas_max_v)
brake_max = np.interp(v_ego, brake_max_bp, brake_max_v)
gas_max = np.interp(v_ego, gas_max_bp, gas_max_v)
overshoot_allowance = 2.0 # overshoot allowed when changing accel sign
@ -172,30 +172,30 @@ class LongControl(object):
# limit max target speed based on cruise setting:
v_cruise_mph = round(v_cruise * CV.KPH_TO_MPH) # what's displayed in mph on the IC
v_target = np.minimum(v_target_lead, v_cruise_mph * CV.MPH_TO_MS / CS.ui_speed_fudge)
v_target = np.minimum(v_target_lead, v_cruise_mph * CV.MPH_TO_MS / VP.ui_speed_fudge)
max_speed_delta_up = a_target[1]*1.0/rate
max_speed_delta_down = a_target[0]*1.0/rate
# *** long control substate transitions
self.long_control_state = long_control_state_trans(enabled, self.long_control_state, CS.v_ego, v_target, self.v_pid, output_gb)
self.long_control_state = long_control_state_trans(enabled, self.long_control_state, v_ego, v_target, self.v_pid, output_gb)
# *** long control behavior based on state
# TODO: move this to drive_helpers
# disabled
if self.long_control_state == LongCtrlState.off:
self.v_pid = CS.v_ego # do nothing
self.v_pid = v_ego # do nothing
output_gb = 0.
self.Ui_accel_cmd = 0.
# tracking objects and driving
elif self.long_control_state == LongCtrlState.pid:
#reset v_pid close to v_ego if it was too far and new v_target is closer to v_ego
if ((self.v_pid > CS.v_ego + overshoot_allowance) and
if ((self.v_pid > v_ego + overshoot_allowance) and
(v_target < self.v_pid)):
self.v_pid = np.maximum(v_target, CS.v_ego + overshoot_allowance)
elif ((self.v_pid < CS.v_ego - overshoot_allowance) and
self.v_pid = np.maximum(v_target, v_ego + overshoot_allowance)
elif ((self.v_pid < v_ego - overshoot_allowance) and
(v_target > self.v_pid)):
self.v_pid = np.minimum(v_target, CS.v_ego - overshoot_allowance)
self.v_pid = np.minimum(v_target, v_ego - overshoot_allowance)
# move v_pid no faster than allowed accel limits
if (v_target > self.v_pid + max_speed_delta_up):
@ -206,27 +206,29 @@ class LongControl(object):
self.v_pid = v_target
# to avoid too much wind up on acceleration, limit positive speed error
if not CS.brake_only:
max_speed_error = np.interp(CS.v_ego, max_speed_error_bp, max_speed_error_v)
self.v_pid = np.minimum(self.v_pid, CS.v_ego + max_speed_error)
if not VP.brake_only:
max_speed_error = np.interp(v_ego, max_speed_error_bp, max_speed_error_v)
self.v_pid = np.minimum(self.v_pid, v_ego + max_speed_error)
output_gb, self.Up_accel_cmd, self.Ui_accel_cmd, self.long_control_sat = pid_long_control(CS.v_ego, self.v_pid, \
self.Ui_accel_cmd, gas_max, brake_max, jerk_factor, CS.gear, rate)
# TODO: removed anti windup on gear change, does it matter?
output_gb, self.Up_accel_cmd, self.Ui_accel_cmd, self.long_control_sat = pid_long_control(v_ego, self.v_pid, \
self.Ui_accel_cmd, gas_max, brake_max, jerk_factor, 0, rate)
# intention is to stop, switch to a different brake control until we stop
elif self.long_control_state == LongCtrlState.stopping:
if CS.v_ego > 0. or output_gb > -brake_stopping_target or not CS.standstill:
if v_ego > 0. or output_gb > -brake_stopping_target:
output_gb -= stopping_brake_rate/rate
output_gb = np.clip(output_gb, -brake_max, gas_max)
self.v_pid = CS.v_ego
self.v_pid = v_ego
self.Ui_accel_cmd = 0.
# intention is to move again, release brake fast before handling control to PID
elif self.long_control_state == LongCtrlState.starting:
if output_gb < -0.2:
output_gb += starting_brake_rate/rate
self.v_pid = CS.v_ego
self.v_pid = v_ego
self.Ui_accel_cmd = starting_Ui
self.last_output_gb = output_gb
final_gas = np.clip(output_gb, 0., gas_max)
final_brake = -np.clip(output_gb, -brake_max, 0.)
return final_gas, final_brake

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python
import os
import zmq
import numpy as np
import numpy.matlib
@ -9,7 +10,6 @@ from fastcluster import linkage_vector
import selfdrive.messaging as messaging
from selfdrive.boardd.boardd import can_capnp_to_can_list_old
from selfdrive.controls.lib.latcontrol import calc_lookahead_offset
from selfdrive.controls.lib.can_parser import CANParser
from selfdrive.controls.lib.pathplanner import PathPlanner
from selfdrive.config import VehicleParams
from selfdrive.controls.lib.radar_helpers import Track, Cluster, fcluster, RDR_TO_LDR
@ -18,10 +18,16 @@ from common.services import service_list
from common.realtime import sec_since_boot, set_realtime_priority, Ratekeeper
from common.kalman.ekf import EKF, SimpleSensor
radar_type = os.getenv("RADAR")
if radar_type is not None:
exec('from selfdrive.radar.'+car_type+'.interface import RadarInterface')
else:
from selfdrive.radar.nidec.interface import RadarInterface
#vision point
DIMSV = 2
XV, SPEEDV = 0, 1
VISION_POINT = 1
VISION_POINT = -1
class EKFV1D(EKF):
def __init__(self):
@ -41,30 +47,6 @@ class EKFV1D(EKF):
return tf, tfj
# nidec radar decoding
def nidec_decode(cp, ar_pts):
for ii in cp.msgs_upd:
# filter points with very big distance, as fff (~255) is invalid. FIXME: use VAL tables from dbc
if cp.vl[ii]['LONG_DIST'] < 255:
ar_pts[ii] = [cp.vl[ii]['LONG_DIST'] + RDR_TO_LDR,
-cp.vl[ii]['LAT_DIST'], cp.vl[ii]['REL_SPEED'], np.nan,
cp.ts[ii], cp.vl[ii]['NEW_TRACK'], cp.ct[ii]]
elif ii in ar_pts:
del ar_pts[ii]
return ar_pts
def _create_radard_can_parser():
dbc_f = 'acura_ilx_2016_nidec.dbc'
radar_messages = range(0x430, 0x43A) + range(0x440, 0x446)
signals = zip(['LONG_DIST'] * 16 + ['NEW_TRACK'] * 16 + ['LAT_DIST'] * 16 +
['REL_SPEED'] * 16, radar_messages * 4,
[255] * 16 + [1] * 16 + [0] * 16 + [0] * 16)
checks = zip(radar_messages, [20]*16)
return CANParser(dbc_f, signals, checks)
# fuses camera and radar data for best lead detection
def radard_thread(gctx=None):
set_realtime_priority(1)
@ -73,10 +55,10 @@ def radard_thread(gctx=None):
# *** subscribe to features and model from visiond
model = messaging.sub_sock(context, service_list['model'].port)
logcan = messaging.sub_sock(context, service_list['can'].port)
live100 = messaging.sub_sock(context, service_list['live100'].port)
PP = PathPlanner(model)
RI = RadarInterface()
# *** publish live20 and liveTracks
live20 = messaging.pub_sock(context, service_list['live20'].port)
@ -84,9 +66,8 @@ def radard_thread(gctx=None):
# subscribe to stats about the car
# TODO: move this to new style packet
VP = VehicleParams(False) # same for ILX and civic
VP = VehicleParams(False, False) # same for ILX and civic
ar_pts = {}
path_x = np.arange(0.0, 140.0, 0.1) # 140 meters is max
# Time-alignment
@ -100,9 +81,6 @@ def radard_thread(gctx=None):
tracks = defaultdict(dict)
# Nidec
cp = _create_radard_can_parser()
# Kalman filter stuff:
ekfv = EKFV1D()
speedSensorV = SimpleSensor(XV, 1, 2)
@ -114,23 +92,11 @@ def radard_thread(gctx=None):
rk = Ratekeeper(rate, print_delay_threshold=np.inf)
while 1:
canMonoTimes = []
can_pub_radar = []
for a in messaging.drain_sock(logcan, wait_for_one=True):
canMonoTimes.append(a.logMonoTime)
can_pub_radar.extend(can_capnp_to_can_list_old(a, [1, 3]))
rr = RI.update()
# only run on the 0x445 packets, used for timing
if not any(x[0] == 0x445 for x in can_pub_radar):
continue
cp.update_can(can_pub_radar)
if not cp.can_valid:
# TODO: handle this
pass
ar_pts = nidec_decode(cp, ar_pts)
ar_pts = {}
for pt in rr.points:
ar_pts[pt.trackId] = [pt.dRel + RDR_TO_LDR, pt.yRel, pt.vRel, pt.aRel, None, False, None]
# receive the live100s
l100 = messaging.recv_sock(live100)
@ -184,7 +150,7 @@ def radard_thread(gctx=None):
v_ego_t_aligned = np.interp(cur_time - rdr_delay, v_ego_array[1], v_ego_array[0])
d_path = np.sqrt(np.amin((path_x - rpt[0]) ** 2 + (path_y - rpt[1]) ** 2))
# create the track
# create the track if it doesn't exist or it's a new track
if ids not in tracks or rpt[5] == 1:
tracks[ids] = Track()
tracks[ids].update(rpt[0], rpt[1], rpt[2], d_path, v_ego_t_aligned)
@ -246,7 +212,7 @@ def radard_thread(gctx=None):
dat = messaging.new_message()
dat.init('live20')
dat.live20.mdMonoTime = PP.logMonoTime
dat.live20.canMonoTimes = canMonoTimes
dat.live20.canMonoTimes = list(rr.canMonoTimes)
if lead_len > 0:
lead_clusters[0].toLive20(dat.live20.leadOne)
if lead2_len > 0:

View File

@ -84,6 +84,8 @@ class Uploader(object):
cloudlog.exception("clean_dirs failed")
def gen_upload_files(self):
if not os.path.isdir(self.root):
return
for logname in listdir_by_creation_date(self.root):
path = os.path.join(self.root, logname)
names = os.listdir(path)

View File

@ -29,7 +29,6 @@ managed_processes = {
"calibrationd": "selfdrive.calibrationd.calibrationd",
"loggerd": "selfdrive.loggerd.loggerd",
"logmessaged": "selfdrive.logmessaged",
#"boardd": "selfdrive.boardd.boardd",
"logcatd": ("logcatd", ["./logcatd"]),
"boardd": ("boardd", ["./boardd"]), # switch to c++ boardd
"ui": ("ui", ["./ui"]),
@ -38,7 +37,13 @@ managed_processes = {
running = {}
car_started_processes = ['controlsd', 'loggerd', 'visiond', 'sensord', 'radard', 'calibrationd']
# due to qualcomm kernel bugs SIGKILLing visiond sometimes causes page table corruption
unkillable_processes = ['visiond']
# processes to end with SIGINT instead of SIGTERM
interrupt_processes = ['loggerd']
car_started_processes = ['controlsd', 'loggerd', 'sensord', 'radard', 'calibrationd', 'visiond']
# ****************** process management functions ******************
@ -91,15 +96,30 @@ def kill_managed_process(name):
if name not in running or name not in managed_processes:
return
cloudlog.info("killing %s" % name)
running[name].terminate()
if name in interrupt_processes:
os.kill(running[name].pid, signal.SIGINT)
else:
running[name].terminate()
# give it 5 seconds to die
running[name].join(5.0)
if running[name].exitcode is None:
cloudlog.info("killing %s with SIGKILL" % name)
os.kill(running[name].pid, signal.SIGKILL)
running[name].join()
cloudlog.info("%s is finally dead" % name)
else:
cloudlog.info("%s is dead with %d" % (name, running[name].exitcode))
if name in unkillable_processes:
cloudlog.critical("unkillable process %s failed to exit! rebooting in 15 if it doesn't die" % name)
running[name].join(15.0)
if running[name].exitcode is None:
cloudlog.critical("FORCE REBOOTING PHONE!")
os.system("date > /sdcard/unkillable_reboot")
os.system("reboot")
raise RuntimeError
else:
cloudlog.info("killing %s with SIGKILL" % name)
os.kill(running[name].pid, signal.SIGKILL)
running[name].join()
cloudlog.info("%s is dead with %d" % (name, running[name].exitcode))
del running[name]
def cleanup_all_processes(signal, frame):
@ -125,6 +145,7 @@ def manager_init():
os.environ['DONGLE_SECRET'] = dongle_secret
cloudlog.bind_global(dongle_id=dongle_id)
common.crash.bind_user(dongle_id=dongle_id)
# set gctx
gctx = {
@ -152,8 +173,9 @@ def manager_thread():
start_managed_process("uploader")
start_managed_process("ui")
# *** wait for the board ***
wait_for_device()
if os.getenv("NOBOARD") is None:
# *** wait for the board ***
wait_for_device()
# flash the device
if os.getenv("NOPROG") is None:
@ -188,12 +210,13 @@ def manager_thread():
start_managed_process("uploader")
# start constellation of processes when the car starts
if td.health.started:
for p in car_started_processes:
start_managed_process(p)
else:
for p in car_started_processes:
kill_managed_process(p)
if not os.getenv("STARTALL"):
if td.health.started:
for p in car_started_processes:
start_managed_process(p)
else:
for p in car_started_processes:
kill_managed_process(p)
# check the status of all processes, did any of them die?
for p in running:
@ -257,6 +280,8 @@ def wait_for_device():
def main():
if os.getenv("NOLOG") is not None:
del managed_processes['loggerd']
if os.getenv("NOUPLOAD") is not None:
del managed_processes['uploader']
if os.getenv("NOBOARD") is not None:
del managed_processes['boardd']

View File

View File

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
import numpy as np
from selfdrive.car.honda.can_parser import CANParser
from selfdrive.boardd.boardd import can_capnp_to_can_list_old
from cereal import car
import zmq
from common.services import service_list
import selfdrive.messaging as messaging
def _create_radard_can_parser():
dbc_f = 'acura_ilx_2016_nidec.dbc'
radar_messages = range(0x430, 0x43A) + range(0x440, 0x446)
signals = zip(['LONG_DIST'] * 16 + ['NEW_TRACK'] * 16 + ['LAT_DIST'] * 16 +
['REL_SPEED'] * 16, radar_messages * 4,
[255] * 16 + [1] * 16 + [0] * 16 + [0] * 16)
checks = zip(radar_messages, [20]*16)
return CANParser(dbc_f, signals, checks)
class RadarInterface(object):
def __init__(self):
# radar
self.pts = {}
self.track_id = 0
# Nidec
self.rcp = _create_radard_can_parser()
context = zmq.Context()
self.logcan = messaging.sub_sock(context, service_list['can'].port)
def update(self):
canMonoTimes = []
can_pub_radar = []
# TODO: can hang if no packets show up
while 1:
for a in messaging.drain_sock(self.logcan, wait_for_one=True):
canMonoTimes.append(a.logMonoTime)
can_pub_radar.extend(can_capnp_to_can_list_old(a.can, [1, 3]))
# only run on the 0x445 packets, used for timing
if any(x[0] == 0x445 for x in can_pub_radar):
break
self.rcp.update_can(can_pub_radar)
ret = car.RadarState.new_message()
errors = []
if not self.rcp.can_valid:
errors.append("notValid")
ret.errors = errors
ret.canMonoTimes = canMonoTimes
for ii in self.rcp.msgs_upd:
cpt = self.rcp.vl[ii]
if cpt['LONG_DIST'] < 255:
if ii not in self.pts or cpt['NEW_TRACK']:
self.pts[ii] = car.RadarState.RadarPoint.new_message()
self.pts[ii].trackId = self.track_id
self.track_id += 1
self.pts[ii].dRel = cpt['LONG_DIST'] # from front of car
self.pts[ii].yRel = -cpt['LAT_DIST'] # in car frame's y axis, left is positive
self.pts[ii].vRel = cpt['REL_SPEED']
self.pts[ii].aRel = float('nan')
self.pts[ii].yvRel = float('nan')
else:
if ii in self.pts:
del self.pts[ii]
ret.points = self.pts.values()
return ret
if __name__ == "__main__":
RI = RadarInterface()
while 1:
ret = RI.update()
print(chr(27) + "[2J")
print ret

View File

View File

View File

@ -0,0 +1,71 @@
import os
from enum import Enum
from maneuverplots import ManeuverPlot
from plant import Plant
import numpy as np
class Maneuver(object):
def __init__(self, title, duration, **kwargs):
# Was tempted to make a builder class
self.distance_lead = kwargs.get("initial_distance_lead", 200.0)
self.speed = kwargs.get("initial_speed", 0.0)
self.lead_relevancy = kwargs.get("lead_relevancy", 0)
self.grade_values = kwargs.get("grade_values", [0.0, 0.0])
self.grade_breakpoints = kwargs.get("grade_breakpoints", [0.0, duration])
self.speed_lead_values = kwargs.get("speed_lead_values", [0.0, 0.0])
self.speed_lead_breakpoints = kwargs.get("speed_lead_values", [0.0, duration])
self.cruise_button_presses = kwargs.get("cruise_button_presses", [])
self.duration = duration
self.title = title
def evaluate(self):
"""runs the plant sim and returns (score, run_data)"""
plant = Plant(
lead_relevancy = self.lead_relevancy,
speed = self.speed,
distance_lead = self.distance_lead
)
last_live100 = None
event_queue = sorted(self.cruise_button_presses, key=lambda a: a[1])[::-1]
plot = ManeuverPlot(self.title)
buttons_sorted = sorted(self.cruise_button_presses, key=lambda a: a[1])
current_button = 0
while plant.current_time() < self.duration:
while buttons_sorted and plant.current_time() >= buttons_sorted[0][1]:
current_button = buttons_sorted[0][0]
buttons_sorted = buttons_sorted[1:]
print "current button changed to", current_button
grade = np.interp(plant.current_time(), self.grade_breakpoints, self.grade_values)
speed_lead = np.interp(plant.current_time(), self.speed_lead_breakpoints, self.speed_lead_values)
distance, speed, acceleration, distance_lead, brake, gas, steer_torque, live100 = plant.step(speed_lead, current_button, grade)
if live100:
last_live100 = live100[-1]
d_rel = distance_lead - distance if self.lead_relevancy else 200.
v_rel = speed_lead - speed if self.lead_relevancy else 0.
if last_live100:
# print last_live100
#develop plots
plot.add_data(
time=plant.current_time(),
gas=gas, brake=brake, steer_torque=steer_torque,
distance=distance, speed=speed, acceleration=acceleration,
up_accel_cmd=last_live100.upAccelCmd, ui_accel_cmd=last_live100.uiAccelCmd,
d_rel=d_rel, v_rel=v_rel, v_lead=speed_lead,
v_target_lead=last_live100.vTargetLead, pid_speed=last_live100.vPid,
cruise_speed=last_live100.vCruise,
jerk_factor=last_live100.jerkFactor,
a_target_min=last_live100.aTargetMin, a_target_max=last_live100.aTargetMax)
return (None, plot)

View File

@ -0,0 +1,139 @@
import os
import numpy as np
import matplotlib.pyplot as plt
import pylab
from selfdrive.config import Conversions as CV
class ManeuverPlot(object):
def __init__(self, title = None):
self.time_array = []
self.gas_array = []
self.brake_array = []
self.steer_torque_array = []
self.distance_array = []
self.speed_array = []
self.acceleration_array = []
self.up_accel_cmd_array = []
self.ui_accel_cmd_array = []
self.d_rel_array = []
self.v_rel_array = []
self.v_lead_array = []
self.v_target_lead_array = []
self.pid_speed_array = []
self.cruise_speed_array = []
self.jerk_factor_array = []
self.a_target_min_array = []
self.a_target_max_array = []
self.v_target_array = []
self.title = title
def add_data(self, time, gas, brake, steer_torque, distance, speed,
acceleration, up_accel_cmd, ui_accel_cmd, d_rel, v_rel, v_lead,
v_target_lead, pid_speed, cruise_speed, jerk_factor, a_target_min,
a_target_max):
self.time_array.append(time)
self.gas_array.append(gas)
self.brake_array.append(brake)
self.steer_torque_array.append(steer_torque)
self.distance_array.append(distance)
self.speed_array.append(speed)
self.acceleration_array.append(acceleration)
self.up_accel_cmd_array.append(up_accel_cmd)
self.ui_accel_cmd_array.append(ui_accel_cmd)
self.d_rel_array.append(d_rel)
self.v_rel_array.append(v_rel)
self.v_lead_array.append(v_lead)
self.v_target_lead_array.append(v_target_lead)
self.pid_speed_array.append(pid_speed)
self.cruise_speed_array.append(cruise_speed)
self.jerk_factor_array.append(jerk_factor)
self.a_target_min_array.append(a_target_min)
self.a_target_max_array.append(a_target_max)
def write_plot(self, path, maneuver_name):
title = self.title or maneuver_name
# TODO: Missing plots from the old one:
# long_control_state
# proportional_gb, intergral_gb
if not os.path.exists(path + "/" + maneuver_name):
os.makedirs(path + "/" + maneuver_name)
plt_num = 0
# speed chart ===================
plt_num += 1
plt.figure(plt_num)
plt.plot(
np.array(self.time_array), np.array(self.speed_array) * CV.MS_TO_MPH, 'r',
np.array(self.time_array), np.array(self.pid_speed_array) * CV.MS_TO_MPH, 'y--',
np.array(self.time_array), np.array(self.v_target_lead_array) * CV.MS_TO_MPH, 'b',
np.array(self.time_array), np.array(self.cruise_speed_array) * CV.KPH_TO_MPH, 'k',
np.array(self.time_array), np.array(self.v_lead_array) * CV.MS_TO_MPH, 'm'
)
plt.xlabel('Time [s]')
plt.ylabel('Speed [mph]')
plt.legend(['speed', 'pid speed', 'Target (lead) speed', 'Cruise speed', 'Lead speed'], loc=0)
plt.grid()
pylab.savefig("/".join([path, maneuver_name, 'speeds.svg']), dpi=1000)
# acceleration chart ============
plt_num += 1
plt.figure(plt_num)
plt.plot(
np.array(self.time_array), np.array(self.acceleration_array), 'g',
np.array(self.time_array), np.array(self.a_target_min_array), 'k--',
np.array(self.time_array), np.array(self.a_target_max_array), 'k--',
)
plt.xlabel('Time [s]')
plt.ylabel('Acceleration [m/s^2]')
plt.legend(['accel', 'max', 'min'], loc=0)
plt.grid()
pylab.savefig("/".join([path, maneuver_name, 'acceleration.svg']), dpi=1000)
# pedal chart ===================
plt_num += 1
plt.figure(plt_num)
plt.plot(
np.array(self.time_array), np.array(self.gas_array), 'g',
np.array(self.time_array), np.array(self.brake_array), 'r',
)
plt.xlabel('Time [s]')
plt.ylabel('Pedal []')
plt.legend(['Gas pedal', 'Brake pedal'], loc=0)
plt.grid()
pylab.savefig("/".join([path, maneuver_name, 'pedals.svg']), dpi=1000)
# pid chart ======================
plt_num += 1
plt.figure(plt_num)
plt.plot(
np.array(self.time_array), np.array(self.up_accel_cmd_array), 'g',
np.array(self.time_array), np.array(self.ui_accel_cmd_array), 'b'
)
plt.xlabel("Time, [s]")
plt.ylabel("Accel Cmd [m/s^2]")
plt.grid()
plt.legend(["Proportional", "Integral"], loc=0)
pylab.savefig("/".join([path, maneuver_name, "pid.svg"]), dpi=1000)
# relative distances chart =======
plt_num += 1
plt.figure(plt_num)
plt.plot(
np.array(self.time_array), np.array(self.d_rel_array), 'g',
)
plt.xlabel('Time [s]')
plt.ylabel('Relative Distance [m]')
plt.grid()
pylab.savefig("/".join([path, maneuver_name, 'distance.svg']), dpi=1000)
plt.close("all")

View File

@ -0,0 +1,275 @@
#!/usr/bin/env python
import os
import struct
import zmq
import numpy as np
from dbcs import DBC_PATH
from common.realtime import Ratekeeper
from common.services import service_list
import selfdrive.messaging as messaging
from selfdrive.config import CruiseButtons
from selfdrive.car.honda.hondacan import fix
from selfdrive.car.honda.carstate import get_can_parser
from selfdrive.boardd.boardd import can_capnp_to_can_list_old, can_capnp_to_can_list, can_list_to_can_capnp
from selfdrive.car.honda.can_parser import CANParser
from common.dbc import dbc
acura = dbc(os.path.join(DBC_PATH, "acura_ilx_2016_can.dbc"))
def car_plant(pos, speed, grade, gas, brake):
# vehicle parameters
mass = 1700
aero_cd = 0.3
force_peak = mass*3.
force_brake_peak = -mass*10. #1g
power_peak = 100000 # 100kW
speed_base = power_peak/force_peak
rolling_res = 0.01
g = 9.81
wheel_r = 0.31
frontal_area = 2.2
air_density = 1.225
gas_to_peak_linear_slope = 3.33
brake_to_peak_linear_slope = 0.2
creep_accel_v = [1., 0.]
creep_accel_bp = [0., 1.5]
#*** longitudinal model ***
# find speed where peak torque meets peak power
force_brake = brake * force_brake_peak * brake_to_peak_linear_slope
if speed < speed_base: # torque control
force_gas = gas * force_peak * gas_to_peak_linear_slope
else: # power control
force_gas = gas * power_peak / speed * gas_to_peak_linear_slope
force_grade = - grade * mass # positive grade means uphill
creep_accel = np.interp(speed, creep_accel_bp, creep_accel_v)
force_creep = creep_accel * mass
force_resistance = -(rolling_res * mass * g + 0.5 * speed**2 * aero_cd * air_density)
force = force_gas + force_brake + force_resistance + force_grade + force_creep
acceleration = force / mass
# TODO: lateral model
return speed, acceleration
def get_car_can_parser():
dbc_f = 'acura_ilx_2016_can.dbc'
signals = [
("STEER_TORQUE", 0xe4, 0),
("STEER_TORQUE_REQUEST", 0xe4, 0),
("COMPUTER_BRAKE", 0x1fa, 0),
("COMPUTER_BRAKE_REQUEST", 0x1fa, 0),
("GAS_COMMAND", 0x200, 0),
]
checks = [
(0xe4, 100),
(0x1fa, 50),
(0x200, 50),
]
return CANParser(dbc_f, signals, checks)
class Plant(object):
messaging_initialized = False
def __init__(self, lead_relevancy=False, rate=100, speed=0.0, distance_lead=2.0):
self.rate = rate
self.civic = False
self.brake_only = False
if not Plant.messaging_initialized:
context = zmq.Context()
Plant.logcan = messaging.pub_sock(context, service_list['can'].port)
Plant.sendcan = messaging.sub_sock(context, service_list['sendcan'].port)
Plant.model = messaging.pub_sock(context, service_list['model'].port)
Plant.live100 = messaging.sub_sock(context, service_list['live100'].port)
Plant.messaging_initialized = True
self.angle_steer = 0.
self.gear_choice = 0
self.speed, self.speed_prev = 0., 0.
self.esp_disabled = 0
self.main_on = 1
self.user_gas = 0
self.computer_brake,self.user_brake = 0,0
self.brake_pressed = 0
self.distance, self.distance_prev = 0., 0.
self.speed, self.speed_prev = speed, speed
self.steer_error, self.brake_error, self.steer_not_allowed = 0, 0, 0
self.gear_shifter = 4 # D gear
self.pedal_gas = 0
self.cruise_setting = 0
self.seatbelt, self.door_all_closed = True, True
self.steer_torque, self.v_cruise, self.acc_status = 0, 0, 0 # v_cruise is reported from can, not the one used for controls
self.lead_relevancy = lead_relevancy
# lead car
self.distance_lead, self.distance_lead_prev = distance_lead , distance_lead
self.rk = Ratekeeper(rate, print_delay_threshold=100)
self.ts = 1./rate
self.cp = get_car_can_parser()
def speed_sensor(self, speed):
if speed<0.3:
return 0
else:
return speed
def current_time(self):
return float(self.rk.frame) / self.rate
def step(self, v_lead=0.0, cruise_buttons=None, grade=0.0):
# dbc_f, sgs, ivs, msgs, cks_msgs, frqs = initialize_can_struct(self.civic, self.brake_only)
cp2 = get_can_parser(self.civic, self.brake_only)
sgs = cp2._sgs
msgs = cp2._msgs
cks_msgs = cp2.msgs_ck
# ******** get messages sent to the car ********
can_msgs = []
for a in messaging.drain_sock(Plant.sendcan):
can_msgs += can_capnp_to_can_list_old(a.sendcan, [0,2])
#print can_msgs
self.cp.update_can(can_msgs)
# ******** get live100 messages for plotting ***
live_msgs = []
for a in messaging.drain_sock(Plant.live100):
live_msgs.append(a.live100)
if self.cp.vl[0x1fa]['COMPUTER_BRAKE_REQUEST']:
brake = self.cp.vl[0x1fa]['COMPUTER_BRAKE']
else:
brake = 0.0
if self.cp.vl[0x200]['GAS_COMMAND'] > 0:
gas = self.cp.vl[0x200]['GAS_COMMAND'] / 256.0
else:
gas = 0.0
if self.cp.vl[0xe4]['STEER_TORQUE_REQUEST']:
steer_torque = self.cp.vl[0xe4]['STEER_TORQUE']*1.0/0xf00
else:
steer_torque = 0.0
distance_lead = self.distance_lead_prev + v_lead * self.ts
# ******** run the car ********
speed, acceleration = car_plant(self.distance_prev, self.speed_prev, grade, gas, brake)
standstill = (speed == 0)
distance = self.distance_prev + speed * self.ts
speed = self.speed_prev + self.ts * acceleration
if speed <= 0:
speed = 0
acceleration = 0
# ******** lateral ********
self.angle_steer -= steer_torque
# *** radar model ***
if self.lead_relevancy:
d_rel = np.maximum(0., self.distance_lead - distance)
v_rel = v_lead - speed
else:
d_rel = 200.
v_rel = 0.
a_rel = 0
lateral_pos_rel = 0.
# print at 5hz
if (self.rk.frame%(self.rate/5)) == 0:
print "%6.2f m %6.2f m/s %6.2f m/s2 %.2f ang gas: %.2f brake: %.2f steer: %5.2f lead_rel: %6.2f m %6.2f m/s" % (distance, speed, acceleration, self.angle_steer, gas, brake, steer_torque, d_rel, v_rel)
# ******** publish the car ********
vls = [self.speed_sensor(speed), self.speed_sensor(speed), self.speed_sensor(speed), self.speed_sensor(speed),
self.angle_steer, 0, self.gear_choice, speed!=0,
0, 0, 0, 0,
self.v_cruise, not self.seatbelt, self.seatbelt, self.brake_pressed,
self.user_gas, cruise_buttons, self.esp_disabled, 0,
self.user_brake, self.steer_error, self.speed_sensor(speed), self.brake_error,
self.brake_error, self.gear_shifter, self.main_on, self.acc_status,
self.pedal_gas, self.cruise_setting,
# left_blinker, right_blinker, counter
0,0,0,
# interceptor_gas
0,0]
# TODO: publish each message at proper frequency
can_msgs = []
for msg in set(msgs):
msg_struct = {}
indxs = [i for i, x in enumerate(msgs) if msg == msgs[i]]
for i in indxs:
msg_struct[sgs[i]] = vls[i]
if msg in cks_msgs:
msg_struct["COUNTER"] = self.rk.frame % 4
msg_data = acura.encode(msg, msg_struct)
if msg in cks_msgs:
msg_data = fix(msg_data, msg)
can_msgs.append([msg, 0, msg_data, 0])
# add the radar message
# TODO: use the DBC
def to_3_byte(x):
return struct.pack("!H", int(x)).encode("hex")[1:]
def to_3s_byte(x):
return struct.pack("!h", int(x)).encode("hex")[1:]
radar_msg = to_3_byte(d_rel*16.0) + \
to_3_byte(int(lateral_pos_rel*16.0)&0x3ff) + \
to_3s_byte(int(v_rel*32.0)) + \
"0f00000"
can_msgs.append([0x445, 0, radar_msg.decode("hex"), 1])
Plant.logcan.send(can_list_to_can_capnp(can_msgs).to_bytes())
# ******** publish a fake model going straight ********
md = messaging.new_message()
md.init('model')
md.model.frameId = 0
for x in [md.model.path, md.model.leftLane, md.model.rightLane]:
x.points = [0.0]*50
x.prob = 1.0
x.std = 1.0
# fake values?
Plant.model.send(md.to_bytes())
# ******** update prevs ********
self.speed_prev = speed
self.distance_prev = distance
self.distance_lead_prev = distance_lead
self.rk.keep_time()
return (distance, speed, acceleration, distance_lead, brake, gas, steer_torque, live_msgs)
# simple engage in standalone mode
def plant_thread(rate=100):
plant = Plant(rate)
while 1:
if plant.rk.frame%100 >= 20 and plant.rk.frame%100 <= 25:
cruise_buttons = CruiseButtons.RES_ACCEL
else:
cruise_buttons = 0
plant.step()
if __name__ == "__main__":
plant_thread()

View File

@ -0,0 +1,10 @@
#!/bin/bash
pushd ../../controls
./controlsd.py &
pid1=$!
./radard.py &
pid2=$!
trap "trap - SIGTERM && kill $pid1 && kill $pid2" SIGINT SIGTERM EXIT
popd
mkdir -p out
MPLBACKEND=svg ./runtracks.py out

View File

@ -0,0 +1,207 @@
#!/usr/bin/env python
import sys
import time, json
from selfdrive.test.plant import plant
from selfdrive.config import Conversions as CV, CruiseButtons as CB
from maneuver import *
maneuvers = [
Maneuver(
'while cruising at 40 mph, change cruise speed to 50mph',
duration=30.,
initial_speed = 40. * CV.MPH_TO_MS,
cruise_button_presses = [(CB.DECEL_SET, 2.), (0, 2.3),
(CB.RES_ACCEL, 10.), (0, 10.1),
(CB.RES_ACCEL, 10.2), (0, 10.3)]
),
Maneuver(
'while cruising at 60 mph, change cruise speed to 50mph',
duration=30.,
initial_speed=60. * CV.MPH_TO_MS,
cruise_button_presses = [(CB.DECEL_SET, 2.), (0, 2.3),
(CB.DECEL_SET, 10.), (0, 10.1),
(CB.DECEL_SET, 10.2), (0, 10.3)]
),
Maneuver(
'while cruising at 20mph, grade change +10%',
duration=25.,
initial_speed=20. * CV.MPH_TO_MS,
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)],
grade_values = [0., 0., 1.0],
grade_breakpoints = [0., 10., 11.]
),
Maneuver(
'while cruising at 20mph, grade change -10%',
duration=25.,
initial_speed=20. * CV.MPH_TO_MS,
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)],
grade_values = [0., 0., -1.0],
grade_breakpoints = [0., 10., 11.]
),
Maneuver(
'approaching a 40mph car while cruising at 60mph from 100m away',
duration=30.,
initial_speed = 60. * CV.MPH_TO_MS,
lead_relevancy=True,
initial_distance_lead=100.,
speed_lead_values = [40.*CV.MPH_TO_MS, 40.*CV.MPH_TO_MS],
speed_lead_breakpoints = [0., 100.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)]
),
Maneuver(
'approaching a 0mph car while cruising at 40mph from 150m away',
duration=30.,
initial_speed = 40. * CV.MPH_TO_MS,
lead_relevancy=True,
initial_distance_lead=150.,
speed_lead_values = [0.*CV.MPH_TO_MS, 0.*CV.MPH_TO_MS],
speed_lead_breakpoints = [0., 100.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)]
),
Maneuver(
'steady state following a car at 20m/s, then lead decel to 0mph at 1m/s^2',
duration=50.,
initial_speed = 20.,
lead_relevancy=True,
initial_distance_lead=35.,
speed_lead_values = [20.*CV.MPH_TO_MS, 20.*CV.MPH_TO_MS, 0.*CV.MPH_TO_MS],
speed_lead_breakpoints = [0., 15., 35.0],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)]
),
Maneuver(
'steady state following a car at 20m/s, then lead decel to 0mph at 2m/s^2',
duration=50.,
initial_speed = 20.,
lead_relevancy=True,
initial_distance_lead=35.,
speed_lead_values = [20.*CV.MPH_TO_MS, 20.*CV.MPH_TO_MS, 0.*CV.MPH_TO_MS],
speed_lead_breakpoints = [0., 15., 25.0],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3)]
),
Maneuver(
'starting at 0mph, approaching a stopped car 100m away',
duration=30.,
initial_speed = 0.,
lead_relevancy=True,
initial_distance_lead=100.,
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7),
(CB.RES_ACCEL, 1.8), (0.0, 1.9)]
),
Maneuver(
"following a car at 60mph, lead accel and decel at 0.5m/s^2 every 2s",
duration=25.,
initial_speed=30.,
lead_relevancy=True,
initial_distance_lead=49.,
speed_lead_values=[30.,30.,29.,31.,29.,31.,29.],
speed_lead_breakpoints=[0., 6., 8., 12.,16.,20.,24.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7)]
),
Maneuver(
"following a car at 10mph, stop and go at 1m/s2 lead dece1 and accel",
duration=70.,
initial_speed=10.,
lead_relevancy=True,
initial_distance_lead=20.,
speed_lead_values=[10., 0., 0., 10., 0.,10.],
speed_lead_breakpoints=[10., 20., 30., 40., 50., 60.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7)]
),
Maneuver(
"green light: stopped behind lead car, lead car accelerates at 1.5 m/s",
duration=30.,
initial_speed=0.,
lead_relevancy=True,
initial_distance_lead=4.,
speed_lead_values=[0, 0 , 45],
speed_lead_breakpoints=[0, 10., 40.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7),
(CB.RES_ACCEL, 1.8), (0.0, 1.9),
(CB.RES_ACCEL, 2.0), (0.0, 2.1),
(CB.RES_ACCEL, 2.2), (0.0, 2.3)]
),
Maneuver(
"stop and go with 1m/s2 lead decel and accel, with full stops",
duration=70.,
initial_speed=0.,
lead_relevancy=True,
initial_distance_lead=20.,
speed_lead_values=[10., 0., 0., 10., 0., 0.] ,
speed_lead_breakpoints=[10., 20., 30., 40., 50., 60.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7)]
),
Maneuver(
"accelerate from 20 while lead vehicle decelerates from 40 to 20 at 1m/s2",
duration=30.,
initial_speed=10.,
lead_relevancy=True,
initial_distance_lead=10.,
speed_lead_values=[20., 10.],
speed_lead_breakpoints=[1., 11.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7),
(CB.RES_ACCEL, 1.8), (0.0, 1.9),
(CB.RES_ACCEL, 2.0), (0.0, 2.1),
(CB.RES_ACCEL, 2.2), (0.0, 2.3)]
),
Maneuver(
"accelerate from 20 while lead vehicle decelerates from 40 to 0 at 2m/s2",
duration=30.,
initial_speed=10.,
lead_relevancy=True,
initial_distance_lead=10.,
speed_lead_values=[20., 0.],
speed_lead_breakpoints=[1., 11.],
cruise_button_presses = [(CB.DECEL_SET, 1.2), (0, 1.3),
(CB.RES_ACCEL, 1.4), (0.0, 1.5),
(CB.RES_ACCEL, 1.6), (0.0, 1.7),
(CB.RES_ACCEL, 1.8), (0.0, 1.9),
(CB.RES_ACCEL, 2.0), (0.0, 2.1),
(CB.RES_ACCEL, 2.2), (0.0, 2.3)]
)
]
css_style = """
.maneuver_title {
font-size: 24px;
text-align: center;
}
.maneuver_graph {
width: 100%;
}
"""
def main(output_dir):
view_html = "<html><head><style>%s</style></head><body><table>" % (css_style,)
for i, man in enumerate(maneuvers):
view_html += "<tr><td class='maneuver_title' colspan=5><div>%s</div></td></tr><tr>" % (man.title,)
for c in ['distance.svg', 'speeds.svg', 'acceleration.svg', 'pedals.svg', 'pid.svg']:
view_html += "<td><img class='maneuver_graph' src='%s'/></td>" % (os.path.join("maneuver" + str(i+1).zfill(2), c), )
view_html += "</tr>"
with open(os.path.join(output_dir, "index.html"), "w") as f:
f.write(view_html)
for i, man in enumerate(maneuvers):
score, plot = man.evaluate()
plot.write_plot(output_dir, "maneuver" + str(i+1).zfill(2))
if __name__ == "__main__":
if len(sys.argv) <= 1:
print "Usage:", sys.argv[0], "<output_dir>"
exit(1)
main(sys.argv[1])

View File

@ -133,10 +133,31 @@ typedef struct UIState {
GLuint frame_front_tex;
UIScene scene;
bool awake;
int awake_timeout;
} UIState;
static void set_awake(UIState *s, bool awake) {
if (awake) {
// 30 second timeout
s->awake_timeout = 30;
}
if (s->awake != awake) {
s->awake = awake;
// TODO: actually turn off the screen and not just the backlight
FILE *f = fopen("/sys/class/leds/lcd-backlight/brightness", "wb");
if (f != NULL) {
if (awake) {
fprintf(f, "205");
} else {
fprintf(f, "0");
}
fclose(f);
}
}
}
static bool activity_running() {
return system("dumpsys activity activities | grep mFocusedActivity > /dev/null") == 0;
@ -173,13 +194,13 @@ typedef struct Button {
static const Button buttons[] = {
{
.label = "wifi",
.x = 400, .y = 700, .w = 250, .h = 250,
.x = 400, .y = 730, .w = 250, .h = 250,
.pressed = wifi_pressed,
.enabled = wifi_enabled,
},
{
.label = "ap",
.x = 1300, .y = 700, .w = 250, .h = 250,
.x = 1300, .y = 730, .w = 250, .h = 250,
.pressed = ap_pressed,
.enabled = ap_enabled,
}
@ -380,6 +401,9 @@ static void ui_init(UIState *s) {
glDisable(GL_DEPTH_TEST);
assert(glGetError() == GL_NO_ERROR);
// set awake
set_awake(s, true);
}
@ -1123,7 +1147,7 @@ static void ui_update(UIState *s) {
s->scene.v_cruise = datad.vCruise;
s->scene.v_ego = datad.vEgo;
s->scene.angle_steers = datad.angleSteers;
s->scene.engaged = (datad.hudLead == 1) || (datad.hudLead == 2);
s->scene.engaged = datad.enabled;
// printf("recv %f\n", datad.vEgo);
s->scene.frontview = datad.rearViewCam;
@ -1197,6 +1221,12 @@ static void ui_update(UIState *s) {
if (rx_bytes) free(rx_bytes);
if (tx_bytes) free(tx_bytes);
// TODO: do this properly
system("git rev-parse --abbrev-ref HEAD > /tmp/git_branch");
char *git_branch = read_file("/tmp/git_branch");
system("git rev-parse --short HEAD > /tmp/git_commit");
char *git_commit = read_file("/tmp/git_commit");
int pending = pending_uploads();
// service call wifi 20 # getWifiEnabledState
@ -1210,14 +1240,29 @@ static void ui_update(UIState *s) {
s->board_connected = !system("lsusb | grep bbaa > /dev/null");
snprintf(s->base_text, sizeof(s->base_text),
"serial: %s\n dongle id: %s\n battery: %s %s\npending: %d\nrx %.1fkiB/s tx %.1fkiB/s\nboard: %s",
"version: %s (%s)\nserial: %s\n dongle id: %s\n battery: %s %s\npending: %d\nrx %.1fkiB/s tx %.1fkiB/s\nboard: %s",
git_commit, git_branch,
s->serial, s->dongle_id, bat_cap ? bat_cap : "(null)", bat_stat ? bat_stat : "(null)",
pending, rx_rate / 1024.0, tx_rate / 1024.0, s->board_connected ? "found" : "NOT FOUND");
if (bat_cap) free(bat_cap);
if (bat_stat) free(bat_stat);
if (git_branch) free(git_branch);
if (git_commit) free(git_commit);
s->last_base_update = ts;
if (s->awake_timeout > 0) {
s->awake_timeout--;
} else {
set_awake(s, false);
}
}
if (s->vision_connected) {
// always awake if vision is connected
set_awake(s, true);
}
if (!s->vision_connected) {
@ -1226,16 +1271,20 @@ static void ui_update(UIState *s) {
int touch_x = -1, touch_y = -1;
err = touch_poll(&s->touch, &touch_x, &touch_y);
if (err == 1) {
// press buttons
for (int i=0; i<ARRAYSIZE(buttons); i++) {
const Button *b = &buttons[i];
if (touch_x >= b->x && touch_x < b->x+b->w
&& touch_y >= b->y && touch_y < b->y+b->h) {
if (b->pressed && !activity_running()) {
b->pressed();
break;
if (s->awake) {
// press buttons
for (int i=0; i<ARRAYSIZE(buttons); i++) {
const Button *b = &buttons[i];
if (touch_x >= b->x && touch_x < b->x+b->w
&& touch_y >= b->y && touch_y < b->y+b->h) {
if (b->pressed && !activity_running()) {
b->pressed();
break;
}
}
}
} else {
set_awake(s, true);
}
}
}

Binary file not shown.