Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ce1ec4e
add dynamic gas for non-pedal cars, up acceleration limits
sshane Dec 18, 2019
c98ff59
enable dynamic follow
sshane Dec 18, 2019
3e68542
add dynamic lane speed
sshane Dec 18, 2019
49a6236
debugging
sshane Dec 18, 2019
9839fed
todo
sshane Dec 18, 2019
b741e4f
ehh why not
sshane Dec 18, 2019
2aee53e
test 15 mph
sshane Dec 18, 2019
0aedd1d
maybe this will work?
sshane Dec 18, 2019
d002832
disable steer offset when lane change is occurring in direction of hug
sshane Dec 18, 2019
282d942
is this required?
sshane Dec 18, 2019
047ad3a
remove lint tests
sshane Dec 18, 2019
26087be
fix for detecting lane change
sshane Dec 19, 2019
ffb9adb
dynamic lane speed tuning, alter a_target as well. allow it to work w…
sshane Dec 19, 2019
78ed689
make minimum dynamic lane speed controller speed adjustable
sshane Dec 19, 2019
c6b7d49
refactor
sshane Dec 19, 2019
2c699f7
lead data is working as expected
sshane Dec 19, 2019
ebe0084
slight tuning
sshane Dec 19, 2019
762318e
wrong side of the list for the deceleration detection, we want past v…
sshane Dec 19, 2019
1e6c989
slightly higher TR below 50 mph
sshane Dec 19, 2019
e767264
reduce relative velocity tuning with positive vRel
sshane Dec 19, 2019
03c08c2
reduce positive lead acceleration tuning
sshane Dec 19, 2019
503a88b
better handling of passable if travis, or if live_tracks not updated.…
sshane Dec 19, 2019
8ec6212
allow dynamic lane speed to be toggleable
sshane Dec 19, 2019
9b0087b
add travis check for accel limits
sshane Dec 19, 2019
6e0a3ba
debug
sshane Dec 19, 2019
b937b5c
tuning
sshane Dec 19, 2019
569ed2a
change sleep time
sshane Dec 19, 2019
37f0d0e
tuning for dynamic lane speed controller
sshane Dec 19, 2019
4f8b244
let us use gas pedal without disengaging
sshane Dec 19, 2019
299db1c
reset longcontrol when gas pressed
sshane Dec 19, 2019
24b66ee
add tuning for corolla pedal, might need to test to see if this is a …
sshane Dec 19, 2019
5c41aa6
Update interface.py
sshane Dec 19, 2019
5f7a5b3
Corolla tuning
sshane Dec 19, 2019
5984d9d
Debug
sshane Dec 19, 2019
0bbba3d
tuning
sshane Dec 20, 2019
0aac3a3
Merge remote-tracking branch 'origin/dynamic_lane_speed' into dynamic…
sshane Dec 20, 2019
be58c12
don't reset tracks before next update, duh!
sshane Dec 20, 2019
3e9e484
dynamic speed margins based on v_ego
sshane Dec 20, 2019
8903c13
this works
sshane Dec 21, 2019
38daf0f
remove temp
sshane Dec 21, 2019
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
35 changes: 3 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,6 @@
Shane's Stock Additions (0.7)
Dynamic Lane Speed (0.7)
=====

This branch is simply stock openpilot with some additions to help it drive as smooth as possible on my 2017 Toyota Corolla.
This is an experimental branch exploring a possibility of an adaptive/dynamic set speed that will reduce your speed when cars in other lanes are going significantly slower than you, if you don't currently have a lead to slow you down


Highlight Features
====

1. **(NOT YET ADDED) Dynamic gas**: This aims to provide a smoother driving experience in stop and go traffic by modifying the maximum gas that can be applied based on your current velocity and the relative velocity of the lead car. It'll also of course increase the maximum gas when the lead is accelerating to help you get up to speed quicker than stock. And smoother; this eliminates the jerking you get from stock openpilot with comma pedal. Better tuning will be next.
2. **Dynamic follow**: This is my dynamic follow from 0.5, where it changes your TR (following distance) dynamically based on multiple vehicle factors, as well as data from the lead vehicle. [Here's an old write up from a while ago explaining how it works exactly. Some of it might be out of date, but how it functions is the same.](https://github.com/ShaneSmiskol/openpilot/blob/dynamic-follow/README.md)
3. **(NOT YET ADDED) Two PID loops to control gas and brakes independently (new!)**: If you have a Toyota Corolla with a comma pedal, you'll love this addition. Two longitudinal PID loops are set up in `longcontrol.py` so that one is running with comma pedal tuning to control the gas, and the other is running stock non-pedal tuning for better braking control. In the car, this feels miles better than stock openpilot, and nearly as good as your stock Toyota cruise control before you pulled out your DSU! It won't accelerate up to stopped cars and brake at the last moment anymore.
3. **Custom wheel offset to reduce lane hugging**: Stock openpilot doesn't seem to be able to identify your car's true angle offset. With the `LaneHugging` module you can specify a custom angle offset to be added to your desired steering angle. Simply find the angle your wheel is at when you're driving on a straight highway. By default, this is disabled, to enable you can:
- Use the `opEdit` class in the root directory of openpilot. To use it, simply open an `ssh` shell and enter the commands below:
```python
cd /data/openpilot
python op_edit.py
```
You'll be greeted with a list of your parameters you can explore, enter the number corresponding to `lane_hug_direction`. Your options are to enter `'left'` or `'right'` for whichever direction your car has a tendency to hug toward. `None` will disable the feature.
Finally you'll need to enter your absolute angle offset (negative will be converted to positive) with the `opParams` parameter: `lane_hug_angle_offset`.
4. **Custom following distance**: Using the `following_distance` parameter in `opParams`, you can specify a custom TR value to always be used. Afraid of technology and want to give yourself the highest following distance out there? Try out 2.7s! Are you daredevil and don't care about pissing off the car you're tailgating ahead? Try 0.9s!
- Again, you can use `opEdit` to change this:
```python
cd /data/openpilot
python op_edit.py
```
Then enter the number for the `following_distance` parameter and set to a float or integer between `0.9` and `2.7`. `None` will use dynamic follow!
5. **Customize this branch (opEdit Parameter class)**: This is a handy tool to change your `opParams` parameters without diving into any json files or code. You can specify parameters to be used in any fork's operation that supports `opParams`. First, ssh in to your EON and make sure you're in `/data/openpilot`, then start `opEdit`:
```python
cd /data/openpilot
python op_edit.py
```
A list of parameters that you can change are located [here](https://github.com/ShaneSmiskol/openpilot/blob/stock_additions-07/common/op_params.py#L29).

Parameters are stored at `/data/op_params.json`
> What if we got all the radar points (up to 16 for Toyota I believe), only cared about the ones that are within a margin of our speed and if the average is lower than us by another margin, reduce speed to the average of the cars around us? Or maybe the average of the... average and our initial set speed
8 changes: 5 additions & 3 deletions common/op_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ def __init__(self):
'alca_nudge_required': {'default': True, 'allowed_types': [bool], 'description': ('Whether to wait for applied torque to the wheel (nudge) before making lane changes. '
'If False, lane change will occur IMMEDIATELY after signaling')},
'alca_min_speed': {'default': 30.0, 'allowed_types': [float, int], 'description': 'The minimum speed allowed for an automatic lane change (in MPH)'},
'min_model_speed': {'default': 20.0, 'allowed_types': [float, int], 'description': 'The minimum speed the model will be allowed to slow down for curves (in MPH)'}}
'min_model_slowdown_speed': {'default': 20.0, 'allowed_types': [float, int], 'description': 'The minimum speed the driving model will be allowed to slow you down for curves (in MPH)'},
'dynamic_lane_speed': {'default': True, 'allowed_types': [bool], 'description': 'Whether to automatically adjust your speed based on vehicles in surrounding lanes'},
'min_dynamic_lane_speed': {'default': 20.0, 'allowed_types': [float, int], 'description': 'The minimum speed the dynamic lane speed controller will be allowed to adjust your speed based on surrounding cars from the radar (in MPH)'}}

self.params = {}
self.params_file = "/data/op_params.json"
self.kegman_file = "/data/kegman.json"
self.last_read_time = time.time()
self.read_timeout = 1.0 # max frequency to read with self.get(...) (sec)
self.read_frequency = 10.0 # max frequency to read with self.get(...) (sec)
self.force_update = False # replaces values with default params if True, not just add add missing key/value pairs
self.run_init() # restores, reads, and updates params

Expand Down Expand Up @@ -103,7 +105,7 @@ def put(self, key, value):
write_params(self.params, self.params_file)

def get(self, key=None, default=None): # can specify a default value if key doesn't exist
if (time.time() - self.last_read_time) >= self.read_timeout and not travis: # make sure we aren't reading file too often
if (time.time() - self.last_read_time) >= self.read_frequency and not travis: # make sure we aren't reading file too often
self.params, read_status = read_params(self.params_file, self.format_default_params())
self.last_read_time = time.time()
if key is None: # get all
Expand Down
13 changes: 7 additions & 6 deletions op_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class opEdit: # use by running `python /data/openpilot/op_edit.py`
def __init__(self):
self.op_params = opParams()
self.params = None
self.sleep_time = 1.0
print('Welcome to the opParams command line editor!')
print('Here are your parameters:\n')
self.run_loop()
Expand Down Expand Up @@ -46,11 +47,11 @@ def parse_choice(self, choice):
return 'error', choice
else:
print('\nNot an integer!\n', flush=True)
time.sleep(1.5)
time.sleep(self.sleep_time)
return 'retry', choice
if choice not in range(1, len(self.params) + 3): # three for add/delete parameter
print('Not in range!\n', flush=True)
time.sleep(1.5)
time.sleep(self.sleep_time)
return 'continue', choice

if choice == len(self.params) + 1: # add new parameter
Expand Down Expand Up @@ -87,7 +88,7 @@ def change_parameter(self, choice):

if extra_info and not any([isinstance(new_value, typ) for typ in param_allowed_types]):
print('The type of data you entered ({}) is not allowed with this parameter!\n'.format(str(type(new_value)).split("'")[1]))
time.sleep(1.5)
time.sleep(self.sleep_time)
return

print('\nOld value: {} (type: {})'.format(old_value, str(type(old_value)).split("'")[1]))
Expand All @@ -99,7 +100,7 @@ def change_parameter(self, choice):
print('\nSaved!\n')
else:
print('\nNot saved!\n', flush=True)
time.sleep(1.5)
time.sleep(self.sleep_time)

def parse_input(self, dat):
try:
Expand Down Expand Up @@ -136,7 +137,7 @@ def delete_parameter(self):
print('\nDeleted!\n')
else:
print('\nNot saved!\n', flush=True)
time.sleep(1.5)
time.sleep(self.sleep_time)

def add_parameter(self):
print('Type the name of your new parameter:')
Expand Down Expand Up @@ -169,7 +170,7 @@ def add_parameter(self):
print('\nSaved!\n')
else:
print('\nNot saved!\n', flush=True)
time.sleep(1.5)
time.sleep(self.sleep_time)


opEdit()
4 changes: 2 additions & 2 deletions run_docker_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ RUN="docker run --shm-size 1G --rm tmppilot /bin/sh -c"
docker build -t tmppilot -f Dockerfile.openpilot .

$RUN "$SETUP cd /tmp/openpilot/selfdrive/test/ && ./test_fingerprints.py"
$RUN 'cd /tmp/openpilot/ && flake8 --select=F $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda" | grep -vi "^\./tools")'
$RUN 'cd /tmp/openpilot/ && pylint --disable=R,C,W $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda" | grep -vi "^\./tools"); exit $(($? & 3))'
#$RUN 'cd /tmp/openpilot/ && flake8 --select=F $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda" | grep -vi "^\./tools")'
#$RUN 'cd /tmp/openpilot/ && pylint --disable=R,C,W $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda" | grep -vi "^\./tools"); exit $(($? & 3))'
$RUN "$SETUP python -m unittest discover common"
$RUN "$SETUP python -m unittest discover opendbc/can"
$RUN "$SETUP python -m unittest discover selfdrive/boardd"
Expand Down
12 changes: 9 additions & 3 deletions selfdrive/car/toyota/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,13 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), vin="", has_relay
tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 2860. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.05]]
ret.lateralTuning.pid.kf = 0.00003 # full torque for 20 deg at 80mph means 0.00007818594
ret.lateralTuning.pid.kf = 0.00003 * 0.8 # full torque for 20 deg at 80mph means 0.00007818594
if ret.enableGasInterceptor:
# with open('/data/gasint', 'a') as f:
# f.write('True\n')
ret.longitudinalTuning.kpV = [1.0, 0.66, 0.42]
ret.longitudinalTuning.kiV = [0.135, 0.09]


elif candidate == CAR.LEXUS_RXH:
stop_and_go = True
Expand Down Expand Up @@ -413,11 +419,11 @@ def update(self, c, can_strings):
events.append(create_event('pcmDisable', [ET.USER_DISABLE]))

# disable on pedals rising edge or when brake is pressed and speed isn't zero
if (ret.gasPressed and not self.gas_pressed_prev) or \
if (ret.gasPressed and not self.gas_pressed_prev and travis) or \
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001)):
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))

if ret.gasPressed:
if ret.gasPressed and travis:
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))

ret.events = events
Expand Down
20 changes: 10 additions & 10 deletions selfdrive/controls/controlsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ def data_sample(CI, CC, sm, can_sock, driver_status, state, mismatch_counter, pa
can_strs = messaging.drain_sock_raw(can_sock, wait_for_one=True)
CS = CI.update(CC, can_strs)

sm.update(0)

events = list(CS.events)
add_lane_change_event(events, sm['pathPlan'])
enabled = isEnabled(state)
Expand Down Expand Up @@ -239,7 +237,7 @@ def state_transition(frame, CS, CP, state, events, soft_disable_timer, v_cruise_


def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cruise_kph, v_cruise_kph_last,
AM, rk, driver_status, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, passable_state_control):
AM, rk, driver_status, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, sm):
"""Given the state, this function returns an actuators packet"""

actuators = car.CarControl.Actuators.new_message()
Expand Down Expand Up @@ -286,7 +284,12 @@ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cr
v_acc_sol = plan.vStart + dt * (a_acc_sol + plan.aStart) / 2.0

# Gas/Brake PID loop
passable_loc = {'lead_one': passable_state_control['lead_one'], 'gas_pressed': CS.gasPressed, 'has_lead': plan.hasLead}
passable_loc = {}
if not travis:
passable_loc['lead_one'] = sm['radarState'].leadOne
passable_loc['live_tracks'] = {'tracks': sm['liveTracks'], 'updated': sm.updated['liveTracks']}
passable_loc['has_lead'] = plan.hasLead
passable_loc['gas_pressed'] = CS.gasPressed
actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.brakePressed, CS.standstill, CS.cruiseState.standstill,
v_cruise_kph, v_acc_sol, plan.vTargetFuture, a_acc_sol, CP, passable_loc)
# Steering PID loop and lateral MPC
Expand Down Expand Up @@ -479,7 +482,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):

if sm is None:
sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \
'model', 'gpsLocation', 'radarState'], ignore_alive=['gpsLocation'])
'model', 'gpsLocation', 'radarState', 'liveTracks'], ignore_alive=['gpsLocation'])


if can_sock is None:
Expand Down Expand Up @@ -551,6 +554,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
prof = Profiler(False) # off by default

while True:
sm.update(0)
start_time = sec_since_boot()
prof.checkpoint("Ratekeeper", ignore=True)

Expand Down Expand Up @@ -593,13 +597,9 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
prof.checkpoint("State transition")

# Compute actuators (runs PID loops and lateral MPC)
if not travis:
passable_state_control = {'lead_one': sm['radarState'].leadOne}
else:
passable_state_control = {'lead_one': None}
actuators, v_cruise_kph, driver_status, v_acc, a_acc, lac_log, last_blinker_frame = \
state_control(sm.frame, sm.rcv_frame, sm['plan'], sm['pathPlan'], CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, AM, rk,
driver_status, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, passable_state_control)
driver_status, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, sm)

prof.checkpoint("State Control")

Expand Down
13 changes: 10 additions & 3 deletions selfdrive/controls/lane_hugging.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from common.op_params import opParams
from cereal import log

LaneChangeState = log.PathPlan.LaneChangeState
LaneChangeDirection = log.PathPlan.LaneChangeDirection

class LaneHugging:
def __init__(self):
Expand All @@ -9,11 +12,15 @@ def __init__(self):
self.direction = self.direction.lower()
self.angle_offset = abs(self.op_params.get('lane_hug_angle_offset', 0.0))

def offset_mod(self, angle_steers_des):
def offset_mod(self, path_plan):
# negative angles: right
# positive angles: left
if self.direction == 'left':
angle_steers_des = path_plan.angleSteers
lane_change_state = path_plan.laneChangeState
direction = path_plan.laneChangeDirection
starting = LaneChangeState.laneChangeStarting
if self.direction == 'left' and ((lane_change_state == starting and direction != LaneChangeDirection.left) or lane_change_state != starting):
angle_steers_des -= self.angle_offset
elif self.direction == 'right':
elif self.direction == 'right' and ((lane_change_state == starting and direction != LaneChangeDirection.right) or lane_change_state != starting):
angle_steers_des += self.angle_offset
return angle_steers_des
2 changes: 1 addition & 1 deletion selfdrive/controls/lib/latcontrol_lqr.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, ste

# Subtract offset. Zero angle should correspond to zero torque
# self.angle_steers_des = path_plan.angleSteers - path_plan.angleOffset
self.angle_steers_des = self.lane_hugging.offset_mod(path_plan.angleSteers - path_plan.angleOffset)
self.angle_steers_des = self.lane_hugging.offset_mod(path_plan) - path_plan.angleOffset
angle_steers -= path_plan.angleOffset

# Update Kalman filter
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/controls/lib/latcontrol_pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def update(self, active, v_ego, angle_steers, angle_steers_rate, eps_torque, ste
self.pid.reset()
else:
# self.angle_steers_des = path_plan.angleSteers # get from MPC/PathPlanner
self.angle_steers_des = self.lane_hugging.offset_mod(path_plan.angleSteers)
self.angle_steers_des = self.lane_hugging.offset_mod(path_plan)

steers_max = get_steer_max(CP, v_ego)
self.pid.pos_limit = steers_max
Expand Down
Loading