parent
							
								
									e883789c0e
								
							
						
					
					
						commit
						3da28d4df2
					
				
				 6 changed files with 0 additions and 441 deletions
			
			
		@ -1,19 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
import time | 
				
			||||
import cereal.messaging as messaging | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == "__main__": | 
				
			||||
  sm = messaging.SubMaster(['deviceState', 'pandaStates', 'modelV2', 'liveCalibration', 'driverMonitoringState', 'longitudinalPlan', 'lateralPlan']) | 
				
			||||
 | 
				
			||||
  i = 0 | 
				
			||||
  while True: | 
				
			||||
    sm.update(0) | 
				
			||||
 | 
				
			||||
    i += 1 | 
				
			||||
    if i % 100 == 0: | 
				
			||||
      print() | 
				
			||||
      print("alive", sm.alive) | 
				
			||||
      print("valid", sm.valid) | 
				
			||||
 | 
				
			||||
    time.sleep(0.01) | 
				
			||||
@ -1,43 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
 | 
				
			||||
import time | 
				
			||||
import statistics | 
				
			||||
import cereal.messaging as messaging | 
				
			||||
 | 
				
			||||
from typing import Dict | 
				
			||||
 | 
				
			||||
camera_states = [ | 
				
			||||
  'roadCameraState', | 
				
			||||
  'wideRoadCameraState', | 
				
			||||
  'driverCameraState' | 
				
			||||
] | 
				
			||||
 | 
				
			||||
def fmt(val): | 
				
			||||
  ref = 0.05 | 
				
			||||
  return f"{val:.6f} ({100 * val / ref:.2f}%)" | 
				
			||||
 | 
				
			||||
if __name__ == "__main__": | 
				
			||||
  sm = messaging.SubMaster(camera_states) | 
				
			||||
 | 
				
			||||
  prev_sof = {state: None for state in camera_states} | 
				
			||||
  diffs: Dict[str, list] = {state: [] for state in camera_states} | 
				
			||||
 | 
				
			||||
  st = time.monotonic() | 
				
			||||
  while True: | 
				
			||||
    sm.update() | 
				
			||||
 | 
				
			||||
    for state in camera_states: | 
				
			||||
      if sm.updated[state]: | 
				
			||||
        if prev_sof[state] is not None: | 
				
			||||
          diffs[state].append((sm[state].timestampSof - prev_sof[state]) / 1e9) | 
				
			||||
        prev_sof[state] = sm[state].timestampSof | 
				
			||||
 | 
				
			||||
    if time.monotonic() - st > 10: | 
				
			||||
      for state in camera_states: | 
				
			||||
        values = diffs[state] | 
				
			||||
        ref = 0.05 | 
				
			||||
        print(f"{state}  \tMean: {fmt(statistics.mean(values))} \t Min: {fmt(min(values))} \t Max: {fmt(max(values))} \t Std: {statistics.stdev(values):.6f} \t Num frames: {len(values)}") | 
				
			||||
        diffs[state] = [] | 
				
			||||
 | 
				
			||||
      print() | 
				
			||||
      st = time.monotonic() | 
				
			||||
@ -1,32 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
import numpy as np | 
				
			||||
import control  # pylint: disable=import-error | 
				
			||||
 | 
				
			||||
dt = 0.01 | 
				
			||||
A = np.array([[ 0.        ,  1.        ],       [-0.78823806,  1.78060701]]) | 
				
			||||
B = np.array([[-2.23399437e-05],       [ 7.58330763e-08]]) | 
				
			||||
C = np.array([[1., 0.]]) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
# Kalman tuning | 
				
			||||
Q = np.diag([1, 1]) | 
				
			||||
R = np.atleast_2d(1e5) | 
				
			||||
 | 
				
			||||
(_, _, L) = control.dare(A.T, C.T, Q, R) | 
				
			||||
L = L.T | 
				
			||||
 | 
				
			||||
# LQR tuning | 
				
			||||
Q = np.diag([2e5, 1e-5]) | 
				
			||||
R = np.atleast_2d(1) | 
				
			||||
(_, _, K) = control.dare(A, B, Q, R) | 
				
			||||
 | 
				
			||||
A_cl = (A - B.dot(K)) | 
				
			||||
sys = control.ss(A_cl, B, C, 0, dt) | 
				
			||||
dc_gain = control.dcgain(sys) | 
				
			||||
 | 
				
			||||
print(("self.A = np." + A.__repr__()).replace('\n', '')) | 
				
			||||
print(("self.B = np." + B.__repr__()).replace('\n', '')) | 
				
			||||
print(("self.C = np." + C.__repr__()).replace('\n', '')) | 
				
			||||
print(("self.K = np." + K.__repr__()).replace('\n', '')) | 
				
			||||
print(("self.L = np." + L.__repr__()).replace('\n', '')) | 
				
			||||
print("self.dc_gain = " + str(dc_gain)) | 
				
			||||
@ -1,64 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
import os | 
				
			||||
import time | 
				
			||||
import sys | 
				
			||||
from datetime import datetime | 
				
			||||
 | 
				
			||||
def average(avg, sample): | 
				
			||||
  # Weighted avg between existing value and new sample | 
				
			||||
  return ((avg[0] * avg[1] + sample) / (avg[1] + 1), avg[1] + 1) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == '__main__': | 
				
			||||
  start_time = datetime.now() | 
				
			||||
  try: | 
				
			||||
    if len(sys.argv) > 1 and sys.argv[1] == "--charge": | 
				
			||||
      print("not disabling charging") | 
				
			||||
    else: | 
				
			||||
      print("disabling charging") | 
				
			||||
      os.system('echo "0" > /sys/class/power_supply/battery/charging_enabled') | 
				
			||||
 | 
				
			||||
    voltage_average = (0., 0)  # average, count | 
				
			||||
    current_average = (0., 0) | 
				
			||||
    power_average = (0., 0) | 
				
			||||
    capacity_average = (0., 0) | 
				
			||||
    bat_temp_average = (0., 0) | 
				
			||||
    while 1: | 
				
			||||
      with open("/sys/class/power_supply/bms/voltage_now") as f: | 
				
			||||
        voltage = int(f.read()) / 1e6   # volts | 
				
			||||
 | 
				
			||||
      with open("/sys/class/power_supply/bms/current_now") as f: | 
				
			||||
        current = int(f.read()) / 1e3   # ma | 
				
			||||
 | 
				
			||||
      power = voltage * current | 
				
			||||
 | 
				
			||||
      with open("/sys/class/power_supply/bms/capacity_raw") as f: | 
				
			||||
        capacity = int(f.read()) / 1e2  # percent | 
				
			||||
 | 
				
			||||
      with open("/sys/class/power_supply/bms/temp") as f: | 
				
			||||
        bat_temp = int(f.read()) / 1e1  # celsius | 
				
			||||
 | 
				
			||||
      # compute averages | 
				
			||||
      voltage_average = average(voltage_average, voltage) | 
				
			||||
      current_average = average(current_average, current) | 
				
			||||
      power_average = average(power_average, power) | 
				
			||||
      capacity_average = average(capacity_average, capacity) | 
				
			||||
      bat_temp_average = average(bat_temp_average, bat_temp) | 
				
			||||
 | 
				
			||||
      print(f"{voltage:.2f} volts {current:12.2f} ma {power:12.2f} mW {capacity:8.2f}% battery {bat_temp:8.1f} degC") | 
				
			||||
      time.sleep(0.1) | 
				
			||||
  finally: | 
				
			||||
    stop_time = datetime.now() | 
				
			||||
    print("\n----------------------Average-----------------------------------") | 
				
			||||
    voltage = voltage_average[0] | 
				
			||||
    current = current_average[0] | 
				
			||||
    power = power_average[0] | 
				
			||||
    capacity = capacity_average[0] | 
				
			||||
    bat_temp = bat_temp_average[0] | 
				
			||||
    print(f"{voltage:.2f} volts {current:12.2f} ma {power:12.2f} mW {capacity:8.2f}% battery {bat_temp:8.1f} degC") | 
				
			||||
    print(f"  {(stop_time - start_time).total_seconds():.2f} Seconds     {voltage_average[1]} samples") | 
				
			||||
    print("----------------------------------------------------------------") | 
				
			||||
 | 
				
			||||
    # re-enable charging | 
				
			||||
    os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled') | 
				
			||||
    print("charging enabled\n") | 
				
			||||
@ -1,150 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
# pylint: skip-file | 
				
			||||
# flake8: noqa | 
				
			||||
# type: ignore | 
				
			||||
 | 
				
			||||
import math | 
				
			||||
import multiprocessing | 
				
			||||
 | 
				
			||||
import numpy as np | 
				
			||||
from tqdm import tqdm | 
				
			||||
 | 
				
			||||
from selfdrive.locationd.paramsd import ParamsLearner, States | 
				
			||||
from tools.lib.logreader import LogReader | 
				
			||||
from tools.lib.route import Route | 
				
			||||
 | 
				
			||||
ROUTE = "b2f1615665781088|2021-03-14--17-27-47" | 
				
			||||
PLOT = True | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def load_segment(segment_name): | 
				
			||||
  print(f"Loading {segment_name}") | 
				
			||||
  if segment_name is None: | 
				
			||||
    return [] | 
				
			||||
 | 
				
			||||
  try: | 
				
			||||
    return list(LogReader(segment_name)) | 
				
			||||
  except ValueError as e: | 
				
			||||
    print(f"Error parsing {segment_name}: {e}") | 
				
			||||
    return [] | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == "__main__": | 
				
			||||
  route = Route(ROUTE) | 
				
			||||
 | 
				
			||||
  msgs = [] | 
				
			||||
  with multiprocessing.Pool(24) as pool: | 
				
			||||
    for d in pool.map(load_segment, route.log_paths()): | 
				
			||||
      msgs += d | 
				
			||||
 | 
				
			||||
  for m in msgs: | 
				
			||||
    if m.which() == 'carParams': | 
				
			||||
      CP = m.carParams | 
				
			||||
      break | 
				
			||||
 | 
				
			||||
  params = { | 
				
			||||
    'carFingerprint': CP.carFingerprint, | 
				
			||||
    'steerRatio': CP.steerRatio, | 
				
			||||
    'stiffnessFactor': 1.0, | 
				
			||||
    'angleOffsetAverageDeg': 0.0, | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  for m in msgs: | 
				
			||||
    if m.which() == 'liveParameters': | 
				
			||||
      params['steerRatio'] = m.liveParameters.steerRatio | 
				
			||||
      params['angleOffsetAverageDeg'] = m.liveParameters.angleOffsetAverageDeg | 
				
			||||
      break | 
				
			||||
 | 
				
			||||
  for m in msgs: | 
				
			||||
    if m.which() == 'carState': | 
				
			||||
      last_carstate = m | 
				
			||||
      break | 
				
			||||
 | 
				
			||||
  print(params) | 
				
			||||
  learner = ParamsLearner(CP, params['steerRatio'], params['stiffnessFactor'], math.radians(params['angleOffsetAverageDeg'])) | 
				
			||||
  msgs = [m for m in tqdm(msgs) if m.which() in ('liveLocationKalman', 'carState', 'liveParameters')] | 
				
			||||
  msgs = sorted(msgs, key=lambda m: m.logMonoTime) | 
				
			||||
 | 
				
			||||
  ts = [] | 
				
			||||
  ts_log = [] | 
				
			||||
  results = [] | 
				
			||||
  results_log = [] | 
				
			||||
  for m in tqdm(msgs): | 
				
			||||
    if m.which() == 'carState': | 
				
			||||
      last_carstate = m | 
				
			||||
 | 
				
			||||
    elif m.which() == 'liveLocationKalman': | 
				
			||||
      t = last_carstate.logMonoTime / 1e9 | 
				
			||||
      learner.handle_log(t, 'carState', last_carstate.carState) | 
				
			||||
 | 
				
			||||
      t = m.logMonoTime / 1e9 | 
				
			||||
      learner.handle_log(t, 'liveLocationKalman', m.liveLocationKalman) | 
				
			||||
 | 
				
			||||
      x = learner.kf.x | 
				
			||||
      sr = float(x[States.STEER_RATIO]) | 
				
			||||
      st = float(x[States.STIFFNESS]) | 
				
			||||
      ao_avg = math.degrees(x[States.ANGLE_OFFSET]) | 
				
			||||
      ao = ao_avg + math.degrees(x[States.ANGLE_OFFSET_FAST]) | 
				
			||||
      r = [sr, st, ao_avg, ao] | 
				
			||||
      if any(math.isnan(v) for v in r): | 
				
			||||
        print("NaN", t) | 
				
			||||
 | 
				
			||||
      ts.append(t) | 
				
			||||
      results.append(r) | 
				
			||||
 | 
				
			||||
    elif m.which() == 'liveParameters': | 
				
			||||
      t = m.logMonoTime / 1e9 | 
				
			||||
      mm = m.liveParameters | 
				
			||||
 | 
				
			||||
      r = [mm.steerRatio, mm.stiffnessFactor, mm.angleOffsetAverageDeg, mm.angleOffsetDeg] | 
				
			||||
      if any(math.isnan(v) for v in r): | 
				
			||||
        print("NaN in log", t) | 
				
			||||
      ts_log.append(t) | 
				
			||||
      results_log.append(r) | 
				
			||||
 | 
				
			||||
  results = np.asarray(results) | 
				
			||||
  results_log = np.asarray(results_log) | 
				
			||||
 | 
				
			||||
  if PLOT: | 
				
			||||
    import matplotlib.pyplot as plt | 
				
			||||
    plt.figure() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 1) | 
				
			||||
    plt.plot(ts, results[:, 0], label='Steer Ratio') | 
				
			||||
    plt.grid() | 
				
			||||
    plt.ylim([0, 20]) | 
				
			||||
    plt.legend() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 3) | 
				
			||||
    plt.plot(ts, results[:, 1], label='Stiffness') | 
				
			||||
    plt.ylim([0, 2]) | 
				
			||||
    plt.grid() | 
				
			||||
    plt.legend() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 5) | 
				
			||||
    plt.plot(ts, results[:, 2], label='Angle offset (average)') | 
				
			||||
    plt.plot(ts, results[:, 3], label='Angle offset (instant)') | 
				
			||||
    plt.ylim([-5, 5]) | 
				
			||||
    plt.grid() | 
				
			||||
    plt.legend() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 2) | 
				
			||||
    plt.plot(ts_log, results_log[:, 0], label='Steer Ratio') | 
				
			||||
    plt.grid() | 
				
			||||
    plt.ylim([0, 20]) | 
				
			||||
    plt.legend() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 4) | 
				
			||||
    plt.plot(ts_log, results_log[:, 1], label='Stiffness') | 
				
			||||
    plt.ylim([0, 2]) | 
				
			||||
    plt.grid() | 
				
			||||
    plt.legend() | 
				
			||||
 | 
				
			||||
    plt.subplot(3, 2, 6) | 
				
			||||
    plt.plot(ts_log, results_log[:, 2], label='Angle offset (average)') | 
				
			||||
    plt.plot(ts_log, results_log[:, 3], label='Angle offset (instant)') | 
				
			||||
    plt.ylim([-5, 5]) | 
				
			||||
    plt.grid() | 
				
			||||
    plt.legend() | 
				
			||||
    plt.show() | 
				
			||||
 | 
				
			||||
@ -1,133 +0,0 @@ | 
				
			||||
#!/usr/bin/env python3 | 
				
			||||
# pylint: skip-file | 
				
			||||
# type: ignore | 
				
			||||
 | 
				
			||||
import numpy as np | 
				
			||||
import math | 
				
			||||
from tqdm import tqdm | 
				
			||||
from typing import cast | 
				
			||||
 | 
				
			||||
import seaborn as sns | 
				
			||||
import matplotlib.pyplot as plt | 
				
			||||
 | 
				
			||||
 | 
				
			||||
from selfdrive.car.honda.interface import CarInterface | 
				
			||||
from selfdrive.car.honda.values import CAR | 
				
			||||
from selfdrive.controls.lib.vehicle_model import VehicleModel, create_dyn_state_matrices | 
				
			||||
from selfdrive.locationd.kalman.models.car_kf import CarKalman, ObservationKind, States | 
				
			||||
 | 
				
			||||
T_SIM = 5 * 60  # s | 
				
			||||
DT = 0.01 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
CP = CarInterface.get_non_essential_params(CAR.CIVIC) | 
				
			||||
VM = VehicleModel(CP) | 
				
			||||
 | 
				
			||||
x, y = 0, 0  # m, m | 
				
			||||
psi = math.radians(0)  # rad | 
				
			||||
 | 
				
			||||
# The state is x = [v, r]^T | 
				
			||||
# with v lateral speed [m/s], and r rotational speed [rad/s] | 
				
			||||
state = np.array([[0.0], [0.0]]) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
ts = np.arange(0, T_SIM, DT) | 
				
			||||
speeds = 10 * np.sin(2 * np.pi * ts / 200.) + 25 | 
				
			||||
 | 
				
			||||
angle_offsets = math.radians(1.0) * np.ones_like(ts) | 
				
			||||
angle_offsets[ts > 60] = 0 | 
				
			||||
steering_angles = cast(np.ndarray, np.radians(5 * np.cos(2 * np.pi * ts / 100.))) | 
				
			||||
 | 
				
			||||
xs = [] | 
				
			||||
ys = [] | 
				
			||||
psis = [] | 
				
			||||
yaw_rates = [] | 
				
			||||
speed_ys = [] | 
				
			||||
 | 
				
			||||
 | 
				
			||||
kf_states = [] | 
				
			||||
kf_ps = [] | 
				
			||||
 | 
				
			||||
kf = CarKalman() | 
				
			||||
 | 
				
			||||
for i, t in tqdm(list(enumerate(ts))): | 
				
			||||
  u = speeds[i] | 
				
			||||
  sa = steering_angles[i] | 
				
			||||
  ao = angle_offsets[i] | 
				
			||||
 | 
				
			||||
  A, B = create_dyn_state_matrices(u, VM) | 
				
			||||
 | 
				
			||||
  state += DT * (A.dot(state) + B.dot(sa + ao)) | 
				
			||||
 | 
				
			||||
  x += u * math.cos(psi) * DT | 
				
			||||
  y += (float(state[0]) * math.sin(psi) + u * math.sin(psi)) * DT | 
				
			||||
  psi += float(state[1]) * DT | 
				
			||||
 | 
				
			||||
  kf.predict_and_observe(t, ObservationKind.CAL_DEVICE_FRAME_YAW_RATE, [float(state[1])]) | 
				
			||||
  kf.predict_and_observe(t, ObservationKind.CAL_DEVICE_FRAME_XY_SPEED, [[u, float(state[0])]]) | 
				
			||||
  kf.predict_and_observe(t, ObservationKind.STEER_ANGLE, [sa]) | 
				
			||||
  kf.predict_and_observe(t, ObservationKind.ANGLE_OFFSET_FAST, [0]) | 
				
			||||
  kf.predict(t) | 
				
			||||
 | 
				
			||||
  speed_ys.append(float(state[0])) | 
				
			||||
  yaw_rates.append(float(state[1])) | 
				
			||||
  kf_states.append(kf.x.copy()) | 
				
			||||
  kf_ps.append(kf.P.copy()) | 
				
			||||
 | 
				
			||||
  xs.append(x) | 
				
			||||
  ys.append(y) | 
				
			||||
  psis.append(psi) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
xs = np.asarray(xs) | 
				
			||||
ys = np.asarray(ys) | 
				
			||||
psis = np.asarray(psis) | 
				
			||||
speed_ys = np.asarray(speed_ys) | 
				
			||||
kf_states = np.asarray(kf_states) | 
				
			||||
kf_ps = np.asarray(kf_ps) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
palette = sns.color_palette() | 
				
			||||
 | 
				
			||||
def plot_with_bands(ts, state, label, ax, idx=1, converter=None): | 
				
			||||
  mean = kf_states[:, state].flatten() | 
				
			||||
  stds = np.sqrt(kf_ps[:, state, state].flatten()) | 
				
			||||
 | 
				
			||||
  if converter is not None: | 
				
			||||
    mean = converter(mean) | 
				
			||||
    stds = converter(stds) | 
				
			||||
 | 
				
			||||
  sns.lineplot(ts, mean, label=label, ax=ax) | 
				
			||||
  ax.fill_between(ts, mean - stds, mean + stds, alpha=.2, color=palette[idx]) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
print(kf.x) | 
				
			||||
 | 
				
			||||
sns.set_context("paper") | 
				
			||||
f, axes = plt.subplots(6, 1) | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, np.degrees(steering_angles), label='Steering Angle [deg]', ax=axes[0]) | 
				
			||||
plot_with_bands(ts, States.STEER_ANGLE, 'Steering Angle kf [deg]', axes[0], converter=np.degrees) | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, np.degrees(yaw_rates), label='Yaw Rate [deg]', ax=axes[1]) | 
				
			||||
plot_with_bands(ts, States.YAW_RATE, 'Yaw Rate kf [deg]', axes[1], converter=np.degrees) | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, np.ones_like(ts) * VM.sR, label='Steer ratio [-]', ax=axes[2]) | 
				
			||||
plot_with_bands(ts, States.STEER_RATIO, 'Steer ratio kf [-]', axes[2]) | 
				
			||||
axes[2].set_ylim([10, 20]) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, np.ones_like(ts), label='Tire stiffness[-]', ax=axes[3]) | 
				
			||||
plot_with_bands(ts, States.STIFFNESS, 'Tire stiffness kf [-]', axes[3]) | 
				
			||||
axes[3].set_ylim([0.8, 1.2]) | 
				
			||||
 | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, np.degrees(angle_offsets), label='Angle offset [deg]', ax=axes[4]) | 
				
			||||
plot_with_bands(ts, States.ANGLE_OFFSET, 'Angle offset kf deg', axes[4], converter=np.degrees) | 
				
			||||
plot_with_bands(ts, States.ANGLE_OFFSET_FAST, 'Fast Angle offset kf deg', axes[4], converter=np.degrees, idx=2) | 
				
			||||
 | 
				
			||||
axes[4].set_ylim([-2, 2]) | 
				
			||||
 | 
				
			||||
sns.lineplot(ts, speeds, ax=axes[5]) | 
				
			||||
 | 
				
			||||
plt.show() | 
				
			||||
					Loading…
					
					
				
		Reference in new issue