Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
94a5e09
body FPv2
briskspirit Mar 15, 2022
b249aec
..
briskspirit Mar 15, 2022
65df954
..
briskspirit Mar 16, 2022
076fbec
..
briskspirit Mar 16, 2022
3fcedc7
Temp, REVERT!
briskspirit Mar 16, 2022
14e9c18
more cleanup
briskspirit Mar 16, 2022
2ece98f
typo
briskspirit Mar 16, 2022
e6ec7b4
..
briskspirit Mar 16, 2022
8d0c0a5
del eyes
briskspirit Mar 16, 2022
69b8f56
should work?
briskspirit Mar 16, 2022
fd3857c
fix
briskspirit Mar 16, 2022
34a5df5
new dbc
briskspirit Mar 17, 2022
f89dee6
..
briskspirit Mar 17, 2022
09810b7
fixes
briskspirit Mar 17, 2022
d274afa
static analysis
briskspirit Mar 17, 2022
5a9bf85
cln balancing code
briskspirit Mar 17, 2022
e45b441
no test route
briskspirit Mar 17, 2022
9b76c40
excluded_interfaces
briskspirit Mar 17, 2022
2b9ad9e
THE DOCS!
briskspirit Mar 18, 2022
b2f035d
comments on steer/speed mixin
briskspirit Mar 18, 2022
d6fd387
switch to bus 0
briskspirit Mar 22, 2022
f63b1ae
less UDS
briskspirit Mar 22, 2022
559e0f3
FAKE bus 0 vin and fingerprint
briskspirit Mar 22, 2022
cde89a6
FAKE locationd
briskspirit Mar 22, 2022
22e1ccf
Keep steady and remove handcoded offset
Mar 24, 2022
09836a7
Improve startup sequence, get closer to stock openpilot
Mar 25, 2022
6c9b98d
Forgot to define angle
Mar 25, 2022
50f1b10
lowercase
adeebshihadeh Mar 30, 2022
896f1e4
revert that
adeebshihadeh Mar 30, 2022
5838a19
little cleanup
adeebshihadeh Mar 30, 2022
c2b9964
change safety model
briskspirit Mar 31, 2022
a100640
update refs
briskspirit Mar 31, 2022
2e5c065
body is gold
adeebshihadeh Mar 31, 2022
63374f8
handle no llk
adeebshihadeh Mar 31, 2022
6c72ebf
oops
adeebshihadeh Mar 31, 2022
bd80285
litte more
adeebshihadeh Mar 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ How We Rate The Cars
|Toyota|Prius Prime 2021-22|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Toyota|RAV4 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|Toyota|RAV4 Hybrid 2019-21|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|
|comma|body|All|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|<a href="#"><img valign="top" src="assets/icon-star-full.svg" width="22" /></a>|

## Silver Cars

Expand Down
2 changes: 1 addition & 1 deletion panda
Empty file added selfdrive/car/body/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions selfdrive/car/body/bodycan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def create_control(packer, torque_l, torque_r):
can_bus = 0

values = {
"TORQUE_L": torque_l,
"TORQUE_R": torque_r,
}
return packer.make_can_msg("TORQUE_CMD", can_bus, values)
101 changes: 101 additions & 0 deletions selfdrive/car/body/carcontroller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import numpy as np

from selfdrive.car.body import bodycan
from opendbc.can.packer import CANPacker

MAX_TORQUE = 500
MAX_TORQUE_RATE = 50
MAX_ANGLE_ERROR = 7

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put these in a CarControllerParams in values.py


class CarController():
def __init__(self, dbc_name, CP, VM):
self.packer = CANPacker(dbc_name)

self.i_speed = 0

self.i_balance = 0
self.d_balance = 0

self.i_torque = 0

self.speed_measured = 0.
self.speed_desired = 0.

self.torque_r_filtered = 0.
self.torque_l_filtered = 0.

@staticmethod
def deadband_filter(torque, deadband):
if torque > 0:
torque += deadband
else:
torque -= deadband
return torque

def update(self, CC, CS):
if len(CC.orientationNED) == 0 or len(CC.angularVelocity) == 0:
return [], CC.actuators.copy()

# ///////////////////////////////////////
# Steer and accel mixin. Speed should be used as a target? (speed should be in m/s! now it is in RPM)
# Mix steer into torque_diff
# self.steerRatio = 0.5
# torque_r = int(np.clip((CC.actuators.accel*1000) - (CC.actuators.steer*1000) * self.steerRatio, -1000, 1000))
# torque_l = int(np.clip((CC.actuators.accel*1000) + (CC.actuators.steer*1000) * self.steerRatio, -1000, 1000))
# ////
# Setpoint speed PID
kp_speed = 0.001
ki_speed = 0.00001
alpha_speed = 1.0

self.speed_measured = (CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr) / 2.
self.speed_desired = (1. - alpha_speed)*self.speed_desired
p_speed = (self.speed_desired - self.speed_measured)
self.i_speed += ki_speed * p_speed
self.i_speed = np.clip(self.i_speed, -0.1, 0.1)
set_point = p_speed * kp_speed + self.i_speed

# Balancing PID
kp_balance = 1300
ki_balance = 0
kd_balance = 280
alpha_d_balance = 1.0

# Clip angle error, this is enough to get up from stands
p_balance = np.clip((-CC.orientationNED[1]) - set_point, np.radians(-MAX_ANGLE_ERROR), np.radians(MAX_ANGLE_ERROR))
self.i_balance += CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr
self.d_balance = np.clip(((1. - alpha_d_balance) * self.d_balance + alpha_d_balance * -CC.angularVelocity[1]), -1., 1.)
torque = int(np.clip((p_balance*kp_balance + self.i_balance*ki_balance + self.d_balance*kd_balance), -1000, 1000))

# Positional recovery PID
kp_torque = 0.95
ki_torque = 0.1

p_torque = (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr)
self.i_torque += (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr)
torque_diff = int(np.clip(p_torque*kp_torque + self.i_torque*ki_torque, -100, 100))

# Combine 2 PIDs outputs
torque_r = torque + torque_diff
torque_l = torque - torque_diff

# Torque rate limits
self.torque_r_filtered = np.clip(self.deadband_filter(torque_r, 10) ,
self.torque_r_filtered - MAX_TORQUE_RATE,
self.torque_r_filtered + MAX_TORQUE_RATE)
self.torque_l_filtered = np.clip(self.deadband_filter(torque_l, 10),
self.torque_l_filtered - MAX_TORQUE_RATE,
self.torque_l_filtered + MAX_TORQUE_RATE)
torque_r = int(np.clip(self.torque_r_filtered, -MAX_TORQUE, MAX_TORQUE))
torque_l = int(np.clip(self.torque_l_filtered, -MAX_TORQUE, MAX_TORQUE))

# ///////////////////////////////////////

can_sends = []
can_sends.append(bodycan.create_control(self.packer, torque_l, torque_r))

new_actuators = CC.actuators.copy()
new_actuators.accel = torque_l
new_actuators.steer = torque_r

return new_actuators, can_sends
54 changes: 54 additions & 0 deletions selfdrive/car/body/carstate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from cereal import car
from opendbc.can.parser import CANParser
from selfdrive.car.interfaces import CarStateBase
from selfdrive.car.body.values import DBC


class CarState(CarStateBase):
def update(self, cp):
ret = car.CarState.new_message()

ret.wheelSpeeds.fl = cp.vl['MOTORS_DATA']['SPEED_L']
ret.wheelSpeeds.fr = cp.vl['MOTORS_DATA']['SPEED_R']

ret.vEgoRaw = ((ret.wheelSpeeds.fl + ret.wheelSpeeds.fr) / 2.) * self.CP.wheelSpeedFactor

ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
ret.standstill = abs(ret.vEgo) < 1

# irrelevant for non-car
ret.doorOpen = False
ret.seatbeltUnlatched = False
ret.gearShifter = car.CarState.GearShifter.drive
ret.steeringTorque = 0
ret.steeringAngleDeg = 0
ret.steeringPressed = False
ret.cruiseState.enabled = True
ret.cruiseState.available = True
ret.cruiseState.speed = 0

return ret

@staticmethod
def get_can_parser(CP):
signals = [
# sig_name, sig_address
("SPEED_L", "MOTORS_DATA"),
("SPEED_R", "MOTORS_DATA"),
("ELEC_ANGLE_L", "MOTORS_DATA"),
("ELEC_ANGLE_R", "MOTORS_DATA"),
("MOTOR_ERR_L", "MOTORS_DATA"),
("MOTOR_ERR_R", "MOTORS_DATA"),
("IGNITION", "VAR_VALUES"),
("ENABLE_MOTORS", "VAR_VALUES"),
("MCU_TEMP", "BODY_DATA"),
("BATT_VOLTAGE", "BODY_DATA"),
]

checks = [
("MOTORS_DATA", 100),
("VAR_VALUES", 10),
("BODY_DATA", 1),
]

return CANParser(DBC[CP.carFingerprint]["pt"], signals, checks, 0)
46 changes: 46 additions & 0 deletions selfdrive/car/body/interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
from cereal import car
from selfdrive.car import scale_rot_inertia, scale_tire_stiffness, get_safety_config
from selfdrive.car.interfaces import CarInterfaceBase

class CarInterface(CarInterfaceBase):
@staticmethod
def get_params(candidate, fingerprint=None, car_fw=None, disable_radar=False):

ret = CarInterfaceBase.get_std_params(candidate, fingerprint)

ret.carName = "body"
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.body)]

ret.steerRatio = 0.5
ret.steerRateCost = 0.5
ret.steerLimitTimer = 1.0
ret.steerActuatorDelay = 0.

ret.mass = 9
ret.wheelbase = 0.406
ret.wheelSpeedFactor = 0.008587
ret.centerToFront = ret.wheelbase * 0.44

ret.radarOffCan = True
ret.openpilotLongitudinalControl = True
ret.steerControlType = car.CarParams.SteerControlType.angle

ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase)

ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront)

return ret

def update(self, c, can_strings):
self.cp.update_strings(can_strings)

ret = self.CS.update(self.cp)

ret.canValid = self.cp.can_valid

self.CS.out = ret.as_reader()
return self.CS.out

def apply(self, c):
return self.CC.update(c, self.CS)
5 changes: 5 additions & 0 deletions selfdrive/car/body/radar_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env python3
from selfdrive.car.interfaces import RadarInterfaceBase

class RadarInterface(RadarInterfaceBase):
pass
33 changes: 33 additions & 0 deletions selfdrive/car/body/values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from typing import Dict

from cereal import car
from selfdrive.car import dbc_dict
from selfdrive.car.docs_definitions import CarInfo
Ecu = car.CarParams.Ecu


class CarControllerParams:
ANGLE_DELTA_BP = [0., 5., 15.]
ANGLE_DELTA_V = [5., .8, .15] # windup limit
ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit
LKAS_MAX_TORQUE = 1 # A value of 1 is easy to overpower
STEER_THRESHOLD = 1.0

class CAR:
BODY = "COMMA BODY"

CAR_INFO: Dict[str, CarInfo] = {
CAR.BODY: CarInfo("comma body", package="All", good_torque=True),
}

FW_VERSIONS = {
CAR.BODY: {
(Ecu.engine, 0x720, None): [
b'02/27/2022'
],
},
}

DBC = {
CAR.BODY: dbc_dict('comma_body', None),
}
3 changes: 3 additions & 0 deletions selfdrive/car/docs_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ def init(self, CP: car.CarParams, non_tested_cars: List[str], all_footnotes: Dic
Column.MAINTAINED: CP.carFingerprint not in non_tested_cars,
}

if self.name == "comma body":
self.row[Column.LONGITUDINAL] = True

self.all_footnotes = all_footnotes
for column in StarColumns:
self.row[column] = Star.FULL if self.row[column] else Star.EMPTY
Expand Down
7 changes: 7 additions & 0 deletions selfdrive/car/fw_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ class Request:
[NISSAN_VERSION_RESPONSE_STANDARD],
rx_offset=NISSAN_RX_OFFSET,
),
# Body
Request(
"body",
[TESTER_PRESENT_REQUEST, UDS_VERSION_REQUEST],
[TESTER_PRESENT_RESPONSE, UDS_VERSION_RESPONSE],
bus=0,
),
]


Expand Down
3 changes: 3 additions & 0 deletions selfdrive/car/tests/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from selfdrive.car.toyota.values import CAR as TOYOTA
from selfdrive.car.volkswagen.values import CAR as VOLKSWAGEN
from selfdrive.car.tesla.values import CAR as TESLA
from selfdrive.car.body.values import CAR as COMMA

# TODO: add routes for these cars
non_tested_cars = [
Expand All @@ -25,6 +26,8 @@
TestRoute = namedtuple('TestRoute', ['route', 'car_fingerprint'])

routes = [
TestRoute("d6ac8ebdb47bc549|2022-03-31--13-10-06", COMMA.BODY),

TestRoute("0c94aa1e1296d7c6|2021-05-05--19-48-37", CHRYSLER.JEEP_CHEROKEE),
TestRoute("91dfedae61d7bd75|2021-05-22--20-07-52", CHRYSLER.JEEP_CHEROKEE_2019),
TestRoute("420a8e183f1aed48|2020-03-05--07-15-29", CHRYSLER.PACIFICA_2017_HYBRID),
Expand Down
1 change: 1 addition & 0 deletions selfdrive/car/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def test_car_interface(self):
# TODO: also check for checkusm and counter violations from can parser
can_invalid_cnt = 0
CC = car.CarControl.new_message()

for i, msg in enumerate(self.can_msgs):
CS = self.CI.update(CC, (msg.as_builder().to_bytes(),))
self.CI.apply(CC)
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/test/process_replay/ref_commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
98d82b2da600755b12e9ecb2744bf4a8b0942ca1
6c72ebf4ef60b895bde5f0700babf150fd97d523
6 changes: 6 additions & 0 deletions selfdrive/test/process_replay/test_processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


original_segments = [
("BODY", "d6ac8ebdb47bc549|2022-03-31--13-10-06--4"), # COMMA.BODY
("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.SONATA
("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.PRIUS (INDI)
("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.RAV4 (LQR)
Expand All @@ -30,6 +31,7 @@
]

segments = [
("BODY", "d6ac8ebdb47bc549|2022-03-31--13-10-06--4"),
("HYUNDAI", "fakedata|2022-01-20--17-49-04--0"),
("TOYOTA", "fakedata|2022-01-20--17-50-51--0"),
("TOYOTA2", "fakedata|2022-01-20--17-52-36--0"),
Expand Down Expand Up @@ -67,6 +69,10 @@ def test_process(cfg, lr, cmp_log_fn, ignore_fields=None, ignore_msgs=None):
# check to make sure openpilot is engaged in the route
if cfg.proc_name == "controlsd":
for msg in log_msgs:
if msg.which() == "carParams":
# body doesn't enable
if msg.carParams.carName == "body":
break
if msg.which() == "controlsState":
if msg.controlsState.active:
break
Expand Down