Hardware Interface
The hardware interface is the main piece of software that had to be written in order to connect the command/state interfaces used by the differential_drive_controller to the actual robot hardware.
In this case, an actuator component is being used for each motor. The different types of components are described here: https://control.ros.org/master/doc/getting_started/getting_started.html#overview-hardware-components .
The guide on how to write a hardware interface can be found here: https://control.ros.org/master/doc/ros2_control/hardware_interface/doc/writing_new_hardware_interface.html . An essential concept used by the hardware interface are lifecycle nodes, which are used as a form of error handling at different “stages of life” of a node (ie. when configuring, when activating, etc). Refer here for more details on lifecycle nodes: https://design.ros2.org/articles/node_lifecycle.html .
When writing a hardware interface, the following must be defined (according to https://control.ros.org/master/doc/ros2_control/hardware_interface/doc/writing_new_hardware_interface.html):
”Add a constructor without parameters and the following public methods implementing LifecycleNodeInterface
: on_configure
, on_cleanup
, on_shutdown
, on_activate
, on_deactivate
, on_error
; and overriding $InterfaceType$Interface
definition: on_init
, export_state_interfaces
, export_command_interfaces
, prepare_command_mode_switch
(optional), perform_command_mode_switch
(optional), read
, write
.”
That same page has more details on what should go in each section. Refer there for more details.
In our case, here are the important steps done in each public method:
on_configure: Sets the motor velocity (which is altered by the differential drive train controller), and actuator position/velocity (feedback from motors) to zero. Also initialized the CANWrapper with the CAN commands that will be used.
on_cleanup: Sets motor velocity and actuator position/velocity to NaN (not a number).
on_shutdown: Send a velocity command of 0 to the motors.
on_activate: Refer to code.
on_deactivate: Refer to code.
on_error: WE NEED TO ADD THIS. I think this is causing us to not turn off the rover after we shut off the node.
on_init: Validate the number of joints, as well as the number of state/command interfaces.
export_state_interface: Attach the state interface name to the state interface variable(s). In this case, match the velocity state interface with the actuator state velocity variable and the position state interface with the actuator state position variable.
export_command_interface: Attach the command interface name to the command interface variables. In this case, match the velocity command interface with the motor velocity variable.
read: Read velocity and position values from the CAN bus (ie. request a CAN message from the motor controllers to get encoder values) and filter noisy data.
write: Write the adjusted values coming from the controller to the motors via the CAN bus.
Note that at the end, this node must be exported as a plugin that can be used in the ros2 control tag of the urdf.