C++ client bindings for moteus

For a long time, moteus has had a python library, that lets most people quickly develop motion control applications. However, python is not a suitable solution in every domain. Embedded systems often either don’t have access to python, or cannot tolerate the resource or timing penalties it imposes. In some cases, managing interoperability between python asyncio and systems using legacy python IO like ROS can be challenging. For others, python is just not familiar. The new C++ client library included in the moteus repository is designed to handle all of these scenarios with a flexible, yet ergonomic approach that makes simple things simple, and complex things possible.

Introduction

To start with, here’s a simple example that mirrors the example from the initial python release 3 years ago:

#include <iostream>
#include "moteus.h"

int main(int argc, char** argv) {
  mjbots::moteus::Controller::DefaultArgProcess(argc, argv);
  mjbots::moteus::Controller c;
  mjbots::moteus::PositionMode::Command command;
  command.position = NaN;
  const auto maybe_result = c.SetPosition(command);
  if (maybe_result) {
    const auto& v = maybe_result->values;
    std::cout << "Position: " << v.position 
              << " Velocity: " << v.velocity
              << "\n";
  } else {
    std::cout << "No response!\n";
  }
  return 0;
}

This is a bit more verbose than python, but in some ways is a bit more explicit, while being even more flexible. This code will attempt to locate a fdcanusb on your host and use it to communicate with controller ID 1. It then will send a single “position” mode command along with a query for a few default values. If a response is received, it will be printed out.

Like in the python case, all of the above behavior can be customized or omitted if desired. The default argument processing, is just that, default. It can be omitted entirely, a transport can be constructed in code, or the arguments that the moteus library consumes can be integrated into other argument processing libraries. The ID of the controller and communication details can be customized when the Controller instance is created, and which registers and resolutions are sent in commands and requested in queries can similarly be customized. There are also exposed classes that can be used exclusively for generating and parsing moteus CAN-FD messages, all with no memory allocation required.

Finally, the transports available for selection at the command line can be extended purely at link time, without code changes required. Look out for a pi3hat integration announcement soon and operation with socketcan is also hopefully not far behind.

Documentation

There is currently no dedicated documentation aside from the headers themselves, but they are designed to be readable. A good place to start is by reading the top level file:

And by looking at the various examples included in the repository:

How to use it

There are a few ways to use the new C++ library in your project. It is header only, so one option is to just copy all the relevant headers into your source tree:

There is also now a top level CMakeLists.txt for use with CMake. This can be used with FetchContent to pull the headers into a CMake-based project.

include(FetchContent)
FetchContent_Declare(
  moteus
  GIT_REPOSITORY https://github.com/mjbots/moteus.git
  GIT_TAG        25c847a7b7b739aa00d4f9a1a30fb041f2ce7a7b
)

FetchContent_MakeAvailable(moteus)

add_executable(myproject myproject.cc)
target_link_libraries(myproject moteus::cpp)

Finally, moteus does export bazel BUILD files and can be integrated into bazel projects using that mechanism as well.

Example

You can see some fully worked examples using the new API in the video series below: