Rust binding for controlling ODrives with CAN!

My teammates (@Vihaan_Shah, @UltraArceus3) and I have been pretty active on the ODrive forum for this robotics project we’re working on and we decided to share our Rust client library for communicating with ODrives through CAN. It’s in very early stages and has not fully implemented all the supported CAN messages, but it’s pretty much usable for anyone who likes working with Rust as much as we do.

It also is quirky and safely implements multi-threaded access to ODrives which we’re using to implement our own control GUI. We’re also thinking of adding the ability to playback messages for testing purposes.

There is some necessary boilerplate to handle ctrl-c escapes, but that aside here’s how the API looks:

fn main() -> Result<(), Box<dyn Error>> {
   let mut can_proxy = CANProxy::new("can0");

   // We register a thread that is capable of reading state, but also modifying it
   // We can also register a thread that can send "read only" commands.
   can_proxy.register_rw("thread 1", odrive_main);
   can_proxy.register_ro("read only thread", |read_only| {})

   // Turn on the thread to process CAN commands from various threads
   let stop_all = can_proxy.begin();

   // Handle ctrl-c to exit (see repo for full boilerplate)
   // ...

   println!("all done!");
fn odrive_main(can_read_write: ReadWriteCANThread) {
    // Specify the CAN ids of all odrives connected
    let odrives = ODriveGroup::new(can_read_write, &[0, 1, 2, 3, 4, 5]);
    odrv.all_axes(|ax| ax.set_state(EncoderIndexSearch));

    odrives.all_axes(|ax| ax.set_state(ClosedLoop));
    odrives.all_axes(|ax| ax.motor.set_control_mode(ControlMode::PositionControl, InputMode::PosFilter));
    odrives.all_axes(|ax| ax.motor.set_input_pos(180.0 / 360.0));

We hope you all find rustodrive useful! If you have any issues, feel free to reply here!