Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full CAN Interface Support #23

Open
daisukes opened this issue Aug 29, 2024 · 4 comments
Open

Full CAN Interface Support #23

daisukes opened this issue Aug 29, 2024 · 4 comments

Comments

@daisukes
Copy link

Hello @samuelsadok,

Thank you for providing ROS2/CAN support for Odrive!

We have been developing robots with Pro and S1 connected through CAN and wanted to use SetVelGain and Arbitrary Parameter Access, but it looks like the current implementation supports a part of the interface.

Do you plan to support all CAN interfaces listed in the link?

@samuelsadok
Copy link
Member

Currently this is not on our roadmap, but we're open to suggestions. Can you tell us more about your use case?

Are you using the standalone odrive_node or the odrive_ros2_control plugin?

For the standalone odrive_node, to support SetVelGain, we'd need to add a corresponding (optional) field to ControlMessage.msg. This is however perhaps not the most scalable to do for all messages.
For Arbitrary Parameter Access, I think a higher level approach is needed. Ideally, the parameters are identified by string and a user ROS node can simply do "write axis0.config.torque_soft_max = 1.0" and "subscribe to axis0.pos_estimate and axis0.vel_estimate at 10Hz" (for example). I haven't looked into how this would be expressed in terms of ROS messages yet.

For the odrive_ros2_control plugin, the feature set is defined by the standard ROS control interface, and I'm not sure yet what the best way is to add device-specific features. Maybe the plugin can simultaneously publish itself as a node and in this way provide a "side-channel" that bypasses ros2_control. It would be helpful if people with more ros2_control experience chime in on what the recommended approach is.

If you only need it at startup, the approach could be based on a config file.

@daisukes
Copy link
Author

daisukes commented Sep 9, 2024

We currently use the standalone node and have implemented a "side-channel" node to send SetVelGain frame to change vel_gain/vel_integrator_gain.
It is not a continuous control and will change when we switch the robot's mode.

For the standalone odrive_node, to support SetVelGain, we'd need to add a corresponding (optional) field to ControlMessage.msg. This is however perhaps not the most scalable to do for all messages.

I thought it would be helpful for us if the odrive_node supports such value change through ROS2 parameters.
(Set_Traj_Vel_Limit, Set_Traj_Accel_Limits, Set_Traj_Intertia, Set_Pos_Gain, Set_Vel_Gains)
One drawback is that it is not straightforward to get the initial value of those settings from the ODrive board.
We may use the "unset" state to indicate the value on the board is used.

For the odrive_ros2_control plugin

I am unfamiliar with ROS2 control, but GPIO interfaces can be used.

https://control.ros.org/rolling/doc/ros2_control_demos/example_10/doc/userdoc.html#ros2-control-demos-example-10-userdoc

@samuelsadok
Copy link
Member

Meanwhile there have been multiple users wanting to access more ODrive parameters, so I took a closer look at the possibilities.

Here are some approaches how this could look like. If anyone who's reading this is interested in this, please drop a comment or reaction. Also let us know what approach would work best for you or if you have other ideas or comments.

Curated ROS messages

This is what we've been doing so far, except that there are only very few exposed parameters currently. Adding more curated message might make sense but it will be hard to get exactly right what users want to access. Adding too many parameters to one ROS message introduces CAN overhead, unless we make the fields optional by adding a bool is_valid for each field, but that feels awkward.

Applies to: ROS node: yes, ROS control: indirectly (*)

1:1 mapping between CAN messages and ROS messages

The ODrive CAN messages are documented here.
Pros:

  • easy for users to transfer their mental model if they've already read about ODrive's CAN protocol
  • lowest effort thing to do

Cons:

  • it's CAN(-classic)-centric and might not make sense on other transport layers, such as CAN-FD or USB
  • the segmentation of the CAN messages is finer-grained (due to payload limitations) than what makes sense for most ROS2 users
  • it introduces coupling between firmware version and ROS package version
  • still does not include all parameters

Applies to: ROS node: yes, ROS control: indirectly (*)

Static config file

This would be intended for configuring ODrive parameters with statically known values.

User defines static list of ODrive configuration parameters in a JSON/YAML file:

axis0.controller.config.vel_limit: 10
axis0.controller.config.vel_limit_tolerance: 2.0
...

The configuration file would be written when the ROS node starts and whenever the ODrive reboots.

The file can be copied straight out of the GUI during initial development of the robot. After that, an ODrive fresh from factory only needs to be connected to the ROS node and will be automatically configured. (user action needed to invoke initial calibration sequence.)

Applies to: ROS node: yes, ROS control: yes

Custom topics

This is intended for when you need to read/write a parameter at runtime which is not part of the predefined ROS messages.

User defines the desired pub/sub topics in a YAML/JSON file:

publishers:
  estimates: # user-defined topic name
    fields:
      fet_temp: axis0.motor.fet_thermistor.temperature
      motor_temp: axis0.motor.motor_thermistor.temperature
    interval: 0.5
subscribers:
  limits:
    fields:
      torque_soft_min: axis0.config.torque_soft_min
      torque_soft_max: axis0.config.torque_soft_max

Based on that, the ROS node publishes odrive_node/pub/estimates with a message format:

float32 fet_temp
float32 motor_temp

and subscribes on odrive_node/sub/limits expecting a message format:

float32 torque_soft_min
float32 torque_soft_max

(possibly relevant for dynamic message types: ros2/rclcpp#2260 (comment), but that's only needed at the ODrive node side. Users can just type out their desired message format statically.)

Applies to: ROS node: yes, ROS control: yes/indirectly (*)

(*) A custom controller might be required to expose ROS topics when using ROS Control. The GPIO demo linked by @daisukes appears to be doing something like that. In the last approach, it may be sufficient to expose custom "command interfaces" and "state interfaces" based on the config file.

@daisukes
Copy link
Author

daisukes commented Nov 8, 2024

@samuelsadok

Thank you for the consideration!

I like 1:1 mapping for the ROS node.
ROS control plugin can support abstracted interfaces, so I want the node has the precise control.

As for the arbitrary parameter access, I think if the node exposes RxSdo and TxSdo through a service or pub/sub topics, it is good enough to access arbitrary parameters for the first step.

I think Static config file and Custom topics are convenient, but they are too limited or too much for my usecases. I would rather want parameter access through ros2 parameter server. We may be able to tweek the parameter service so that the service redirects a get/set parameter call to CAN arbitrary parameter access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants