Trap_traj input secrets?

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.

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.