wiggle
July 30, 2022, 3:50am
1
Odrive Pro, fw 0.6.1, running Python script off a raspberry Pi, or using the odrivetool for realtime inputs.
I have a configuration that works decently in position control mode, but it’s pretty rough getting slammed between setpoints. So I’d really like to move it to using the trapezoidal trajectory. But when I switch to trap_traj as the input mode, my changes to the odrv0.axis0.controller.input_pos have no effect. LED is still blinking green, dump errors is clear.
In [23]: odrv0.axis0.pos_vel_mapper.pos_rel
Out[23]: 7.140636444091797e-05
...
In [26]: odrv0.axis0.controller.input_pos = 20
Nothing moves.
Can anybody give me some insight? Thank you.
wiggle
July 30, 2022, 4:03am
2
Here’s more code, if it helps:
import time
import logging
import odrive
from odrive.enums import *
new_pos = 0
pos_mode = InputMode.TRAP_TRAJ
#pos_mode = InputMode.PASSTHROUGH
class OdriveConfiguration:
def __init__(self):
# Connect to Odrive
self.find_odrive()
def find_odrive(self):
while True:
logging.info('Connect to Odrive...')
self.odrv0 = odrive.find_any()
if self.odrv0 is not None:
logging.info('Connect to Odrive Success!!!')
break
else:
logging.info('Disconnect to Odrive...')
def set_odrive_parameters(self):
# Connect to Odrive
self.find_odrive()
# using AC-DC supply rated 24V @ 62.5A (1500W)+
self.odrv0.config.dc_bus_overvoltage_trip_level = 25.5
self.odrv0.config.dc_max_positive_current = 25 # (down-sized) current rating of your power supply in Amps
self.odrv0.config.dc_max_negative_current = -1
self.odrv0.axis0.config.motor.current_soft_max = 40 #50
self.odrv0.axis0.config.motor.current_hard_max = 60
self.odrv0.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
self.odrv0.axis0.config.motor.pole_pairs = 7
self.odrv0.axis0.config.motor.torque_constant = 8.27 / 1150
#configure the encoder
self.odrv0.amt21_encoder_group0.config.enable = True
self.odrv0.axis0.config.load_encoder = EncoderId.AMT21_ENCODER0
self.odrv0.axis0.config.commutation_encoder = EncoderId.AMT21_ENCODER0
#configure the controller -- general items first
self.odrv0.axis0.controller.config.pos_gain = 17 # 5 # 12
self.odrv0.axis0.controller.config.vel_gain = 0.01 # 0.04 works
self.odrv0.axis0.controller.config.vel_integrator_gain = 0.5 * 4 * 0.04
self.odrv0.axis0.controller.config.vel_limit = 40
self.odrv0.axis0.controller.input_vel = 5 # non-zero!!
if pos_mode == InputMode.TRAP_TRAJ: # For trap_traj control:
self.odrv0.axis0.trap_traj.config.vel_limit = 40
self.odrv0.axis0.trap_traj.config.accel_limit = 20
self.odrv0.axis0.trap_traj.config.decel_limit = 20
self.odrv0.axis0.controller.config.inertia = 0
self.odrv0.axis0.controller.config.vel_limit = 40 # Overwriting general setting!
self.odrv0.axis0.controller.config.input_mode = InputMode.TRAP_TRAJ
self.odrv0.axis0.controller.config.control_mode = ControlMode.POSITION_CONTROL
else: # For position control:
self.odrv0.axis0.controller.config.input_mode = InputMode.PASSTHROUGH
self.odrv0.axis0.controller.config.control_mode = ControlMode.POSITION_CONTROL
# self.odrv0.config.enable_brake_resistor = True
def motor_calibration(self):
# Connect to Odrive
self.find_odrive()
self.odrv0.axis0.requested_state = AxisState.MOTOR_CALIBRATION
# Wait for calibration to take place
time.sleep(7)
#self.odrv0.axis0.motor.config.pre_calibrated = True
def encoder_calibration(self):
self.odrv0.axis0.requested_state = AxisState.ENCODER_OFFSET_CALIBRATION
# Wait for calibration to take place
time.sleep(12)
#self.odrv0.axis0.encoder.config.pre_calibrated = True
def config(self):
logging.info('Start set_odrive_parameters')
self.set_odrive_parameters()
logging.info('Finish set_odrive_parameters')
logging.info('Start motor_calibration')
self.motor_calibration()
logging.info('Finish motor_calibration')
logging.info('Position at end of motor_cal = {}'.format(self.odrv0.axis0.pos_vel_mapper.pos_rel))
logging.info('Start encoder_calibration')
self.encoder_calibration()
logging.info('Finish encoder_calibration')
def move_absolute(self):
logging.info('starting move_absolute to pos {}'.format(new_pos))
self.odrv0.axis0.controller.input_pos = new_pos
def log_position(self):
logging.info('Current pos {}'.format(self.odrv0.axis0.pos_vel_mapper.pos_rel))
def operation_check(self):
# Connect to Odrive
self.find_odrive()
logging.info('Motor operation check...')
self.odrv0.axis0.requested_state = AxisState.CLOSED_LOOP_CONTROL
self.odrv0.axis0.controller.move_incremental(2, False)
# Wait for move to take place
#time.sleep(3)
# Move back, wait
#self.odrv0.axis0.controller.move_incremental(-2, False)
#time.sleep(3)
logging.info('Motor operation check Success!!!')
# ############################# start main #######################
# log init
logname = "RollTiltWrestler Log " + time.strftime("%Y%m%d-%H%M%S") + ".log"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(logname),
logging.StreamHandler()
]
)
#logging.info('Hi there')
Odrive_motor_config = OdriveConfiguration()
Odrive_motor_config.config()
Odrive_motor_config.operation_check()
Odrive_motor_config.log_position()
cruise_pos = float(input("Enter position of cruise orientation: "))
logging.info('cruise_pos set to {}'.format(cruise_pos))
swing = float(input("Enter amplitude of half-swing: "))
logging.info('swing set to {}'.format(swing))
loops = 0
manual_steps = True
while True:
if manual_steps:
val = input("<Enter> to make next move, 'a' to go auto ... ")
if val.lower() == "a":
manual_steps = False
factor = loops % 4 # need repeating sequence [0,1,0,-1]
if factor > 1:
factor -=2
factor *= -1
new_pos = cruise_pos + factor * swing
Odrive_motor_config.log_position()
Odrive_motor_config.move_absolute()
time.sleep(3)
Odrive_motor_config.log_position()
loops += 1
logging.info('{:.1f} cycles complete'.format(loops/4))
We recently fixed a bug in trap_traj mode. odrivetool dfu --channel devel
to update to the devel branch software which has it fixed.