added libraries
This commit is contained in:
+30
-9
@@ -2,6 +2,7 @@
|
||||
"""
|
||||
sudo python3 balance.py imu # find the balance point
|
||||
sudo python3 balance.py balance --offset X # balance
|
||||
sudo python3 balance.py balance --offset X --speed 200 # drive forward at 200 mm/s
|
||||
"""
|
||||
import argparse, math, os, sys, threading, time
|
||||
import numpy as np
|
||||
@@ -17,6 +18,7 @@ START_ANGLE = 5.0 # deg: arms when held this close to upright
|
||||
PWM_MAX = 2000 # power-bank limit
|
||||
PWM_SLEW = 300 # max PWM change per tick (no instant reversals)
|
||||
ENC_TIMEOUT = 0.05 # s without encoder data -> motors off, re-init driver board
|
||||
ACCEL_MAX = 150 # mm/s per second: how fast the speed setpoint ramps
|
||||
LEFT, RIGHT = 2, 3 # M3 = left, M4 = right
|
||||
MOTOR_SIGN = (-1, +1) # +PWM on M3 rolls the robot backward, so flip it
|
||||
ENC_SIGN = (-1, +1) # M3 counts down when rolling forward, so flip it
|
||||
@@ -167,7 +169,9 @@ def balance(imu, tilt, motors, args):
|
||||
out = target = v = 0.0
|
||||
prev = prev_t = None
|
||||
last_reinit = time.perf_counter()
|
||||
print(f"kp={args.kp} kd={args.kd} kv={args.kv} ki={args.ki} offset={args.offset}")
|
||||
stats = [] # (wheel position mm, tilt, pwm) for the stillness readout
|
||||
print(f"kp={args.kp} kd={args.kd} kv={args.kv} ki={args.ki} offset={args.offset} "
|
||||
f"slew={args.slew} deadband={args.deadband} speed={args.speed}")
|
||||
print("Hold it upright and still to arm. Ctrl-C to quit.", flush=True)
|
||||
|
||||
for tick, (dt, now) in enumerate(ticker(LOOP_HZ)):
|
||||
@@ -193,6 +197,8 @@ def balance(imu, tilt, motors, args):
|
||||
if tilt.ready() and abs(theta) < START_ANGLE and abs(rate) < 30:
|
||||
armed, out, target, v = True, 0.0, 0.0, 0.0
|
||||
speed_pid.reset()
|
||||
speed_pid.setpoint = 0.0 # always start standing still, then ramp
|
||||
stats.clear()
|
||||
prev, prev_t = wheels, now
|
||||
print("ARMED", flush=True)
|
||||
elif tick % 20 == 0:
|
||||
@@ -209,27 +215,42 @@ def balance(imu, tilt, motors, args):
|
||||
if tick % 4 == 0:
|
||||
v_now = (wheels[0] - prev[0] + wheels[1] - prev[1]) / 2 * MM_PER_TICK / (now - prev_t)
|
||||
v = 0.7 * v + 0.3 * v_now # mm/s, smoothed
|
||||
speed_pid.setpoint += clamp(args.speed - speed_pid.setpoint, ACCEL_MAX * (now - prev_t))
|
||||
target = speed_pid(v, dt=now - prev_t)
|
||||
prev, prev_t = wheels, now
|
||||
|
||||
# inner loop, 200 Hz: angle PD (D straight from the gyro, no differentiating)
|
||||
u = clamp(args.kp * (theta - target) + args.kd * rate, PWM_MAX)
|
||||
out += clamp(u - out, PWM_SLEW) # ramp, never jump
|
||||
u = args.kp * (theta - target) + args.kd * rate
|
||||
if u:
|
||||
u += math.copysign(args.deadband, u) # help the wheels past static friction
|
||||
u = clamp(u, PWM_MAX)
|
||||
out += clamp(u - out, args.slew) # ramp, never jump
|
||||
motors.pwm(out, out)
|
||||
|
||||
# stillness readout every 5 s: lower = stiller
|
||||
stats.append(((wheels[0] + wheels[1]) / 2 * MM_PER_TICK, theta, out))
|
||||
if len(stats) == 5 * LOOP_HZ:
|
||||
pos, th, pw = (np.array(c) for c in zip(*stats))
|
||||
print(f"STILLNESS 5s: wheels p-p {np.ptp(pos):5.1f} mm rms {pos.std():4.1f} mm "
|
||||
f"tilt rms {th.std():5.2f} deg pwm rms {pw.std():4.0f}", flush=True)
|
||||
stats.clear()
|
||||
|
||||
if tick % 20 == 0:
|
||||
print(f"th {theta:+6.2f} tgt {target:+5.2f} rate {rate:+7.1f} v {v:+6.0f} mm/s pwm {out:+6.0f}",
|
||||
flush=True)
|
||||
print(f"th {theta:+6.2f} tgt {target:+5.2f} rate {rate:+7.1f} v {v:+6.0f} mm/s "
|
||||
f"sp {speed_pid.setpoint:+4.0f} pwm {out:+6.0f}", flush=True)
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument("mode", choices=["imu", "balance"])
|
||||
p.add_argument("--offset", type=float, default=0.0, help="pitch at the balance point, deg")
|
||||
p.add_argument("--kp", type=float, default=100.0, help="PWM per deg of lean")
|
||||
p.add_argument("--kd", type=float, default=2.5, help="PWM per deg/s of tipping")
|
||||
p.add_argument("--kv", type=float, default=0.0, help="deg of lean per mm/s of speed")
|
||||
p.add_argument("--ki", type=float, default=0.0, help="deg of lean per mm of drift")
|
||||
p.add_argument("--kp", type=float, default=120.0, help="PWM per deg of lean")
|
||||
p.add_argument("--kd", type=float, default=3.0, help="PWM per deg/s of tipping")
|
||||
p.add_argument("--kv", type=float, default=0.02, help="deg of lean per mm/s of speed")
|
||||
p.add_argument("--ki", type=float, default=0.003, help="deg of lean per mm of drift")
|
||||
p.add_argument("--speed", type=float, default=0.0, help="drive speed, mm/s, + = forward")
|
||||
p.add_argument("--slew", type=float, default=PWM_SLEW, help="max PWM change per tick")
|
||||
p.add_argument("--deadband", type=float, default=0.0, help="PWM added to beat static friction")
|
||||
args = p.parse_args()
|
||||
|
||||
realtime()
|
||||
|
||||
Reference in New Issue
Block a user