|
| hardware_interface::CallbackReturn | on_init (const hardware_interface::HardwareComponentInterfaceParams ¶ms) override |
| | Called on initialization to the unconfigured state.
|
| |
| hardware_interface::CallbackReturn | on_shutdown (const rclcpp_lifecycle::State &previous_state) override |
| | Called on the transistion from the inactive, unconfigured and active to the finalized state.
|
| |
| hardware_interface::CallbackReturn | on_configure (const rclcpp_lifecycle::State &previous_state) override |
| | Called on the transistion from the unconfigured to the inactive state.
|
| |
| hardware_interface::CallbackReturn | on_cleanup (const rclcpp_lifecycle::State &previous_state) override |
| | Called on the transistion from the inactive to the unconfigured state.
|
| |
| hardware_interface::CallbackReturn | on_activate (const rclcpp_lifecycle::State &previous_state) override |
| | Called on the transistion from the inactive to the active state.
|
| |
| hardware_interface::CallbackReturn | on_deactivate (const rclcpp_lifecycle::State &previous_state) override |
| | Called on the transistion from the active to the inactive state.
|
| |
| hardware_interface::return_type | read (const rclcpp::Time &time, const rclcpp::Duration &period) override |
| | Reads from the hardware and populates the state interfaces.
|
| |
| hardware_interface::return_type | write (const rclcpp::Time &time, const rclcpp::Duration &period) override |
| | Writes commands to the hardware from the command interfaces.
|
| |
| hardware_interface::return_type | prepare_command_mode_switch (const std::vector< std::string > &start_interfaces, const std::vector< std::string > &stop_interfaces) override |
| | Performs checks and book keeping of the active control mode when changing controllers in non-realtime context.
|
| |
| hardware_interface::return_type | perform_command_mode_switch (const std::vector< std::string > &start_interfaces, const std::vector< std::string > &stop_interfaces) override |
| | Perform the mode-switching for the new command interface combination in realtime context.
|
| |
| hardware_interface::CallbackReturn | on_error (const rclcpp_lifecycle::State &previous_state) override |
| | Called when an error in any state or state transition is thrown.
|
| |
|
| std::unordered_map< std::string, std::unique_ptr< bioscara_hardware_drivers::BaseJoint > > | _joints |
| | unordered map storing the pointers to BaseJoint objects. This will either be a MockJoint or Joint.
|
| |
| std::unordered_map< std::string, joint_config_t > | _joint_cfg |
| | unordered map storing the configuration struct of the joints.
|
| |
| std::unordered_map< std::string, std::set< std::string > > | _joint_command_modes |
| | unordered map of sets storing the active command interfaces for each joint.
|
| |
| std::unordered_map< std::string, std::set< std::string > > | _new_joint_command_modes |
| | Temporary cache of new joint_command_modes when switching controllers.
|
| |
| std::vector< std::pair< std::string, hardware_interface::InterfaceDescription * > > | _ordered_joint_state_interfaces_ptr |
| | A vector of a pair of interface name and pointer of the hardwares state interface which is ordered by joint and state interface type.
|
| |
| std::mutex | mtx |
| | A mutex that is used to prevent concurrent access to hardware and _joint_command_modes.
|
| |
The bioscara arm hardware interface class.
The hardware interface serves to wrap custom hardware interaction with the arm joints in the standardized ros2_control architecture.
Hardware Lifecycle
The hardware follows the ros2_control hardware interface lifecyle which intern is following the ROS2 managed node lifecycle.
Hardware interface lifecycle
| hardware_interface::CallbackReturn bioscara_hardware_interfaces::BioscaraArmHardwareInterface::on_activate |
( |
const rclcpp_lifecycle::State & |
previous_state | ) |
|
|
override |
Called on the transistion from the inactive to the active state.
Calls activate_joint() to enable the joints.
It is allowed to activate the hardware even if it is not homed. To home the joint the homing_controller must be activated, but generally a hardware component must be active in order for controllers to become active.
To prohibit movement on activation the set point for each position command interface is set equal to the current measured position, and the velocity command is set to 0.0 for each command interface. The current values are obtained by calling the read() method once which populates the state interfaces with values.
- Parameters
-
- Returns
- hardware_interface::CallbackReturn
Below a workaround to force a read cycle of all joints to get inital values for the state interfaces. These will be copied to the command interface to prevent movement at startup.
| hardware_interface::CallbackReturn bioscara_hardware_interfaces::BioscaraArmHardwareInterface::on_error |
( |
const rclcpp_lifecycle::State & |
previous_state | ) |
|
|
override |
Called when an error in any state or state transition is thrown.
According to the ros2_control documentation:
Error handling follows the node lifecycle. If successful CallbackReturn::SUCCESS is returned and hardware is again in UNCONFIGURED state, if any ERROR or FAILURE happens the hardware ends in FINALIZED state and can not be recovered. The only option is to reload the complete plugin, but there is currently no service for this in the Controller Manager.
Since the hardware will immediatly return to the unconfigured state (source) if the error could be handled we manually call the transition functions which would normally be called to this state. Those are:
- Previous state:
active
- Previous state:
inactive
In particular the deactivation is important. For example if a joint stalls the read() or write() methods throw an error, which will be handled here and allow the hardware to be deactivated, disableing the joints to allow backdriving.
- Parameters
-
- Returns
- hardware_interface::CallbackReturn
| hardware_interface::CallbackReturn bioscara_hardware_interfaces::BioscaraArmHardwareInterface::on_init |
( |
const hardware_interface::HardwareComponentInterfaceParams & |
params | ) |
|
|
override |
Called on initialization to the unconfigured state.
Performs the following checks on the configures joints parsed form the URDF description:
- Each joint must have the 3 command interfaces (in this order): 'position', 'velocity', 'home'
- Each joint must have the 3 state interfaces (in this order): 'position', 'velocity', 'home'
Stores the configuration parameters for each joint in the _joint_cfg map. Each joint must have these parameters:
- i2c_address (int, HEX)
- reduction (float)
- min (float)
- max (float)
- stall_threshold (int, DEC)
- hold_current (int, DEC)
- drive_current (int, DEC)
- max_acceleration (float)
- max_velocity (float)
- homing
- speed (float)
- threshold (int, DEC)
- current (int, DEC)
- acceleration (float)
Adds each joint to the internal _joints map. Creates a MockJoint object if the use_mock_hardware parameter is 'True' or 'true', or else a hardware Joint.
- Parameters
-
- Returns
- hardware_interface::CallbackReturn
Loop over all joints decribed in the hardware description file, check if they have the position and velocity command and state interface defined and finally add them to the internal _joints list
| hardware_interface::return_type bioscara_hardware_interfaces::BioscaraArmHardwareInterface::prepare_command_mode_switch |
( |
const std::vector< std::string > & |
start_interfaces, |
|
|
const std::vector< std::string > & |
stop_interfaces |
|
) |
| |
|
override |
Performs checks and book keeping of the active control mode when changing controllers in non-realtime context.
For safe operation only one controller may interact with the hardware at the time. For example if the velocity JTC is active and has claimed the velocity command interfaces it is technically possible to activate the position JTC (or a homing controller, or others) that claim a different command interface (position in this case). However if both controllers are active they start writing to the hardware simultaneously which is to be avoided. For this reason a book keeping mechanism has been implemented which stores the currently active command interfaces for each joint in the _joint_command_modes member. Each joint has a set of active command interfaces. When a controller switch is performed the interfaces that should be stopped are removed from each joint set, then the one that should be started are added, if they are already present an error is thrown. Lastly a validation is performed. Currently the validation is simple since each joint may only have one command interface. The validation can be expanded for furture use cases that require a combination of active command interfaces per joint for example.
The following basic checks are implemented:
- On deactivation:
- On activation:
- [ERROR] Activating a command interface that is already started. This should not happen.
- [ERROR] Activating a second command interface for a joint.
- [ERROR] Activating 'position' or 'velocity' command interface if the joint is not homed (bioscara_hardware_drivers::Joint::isHomed() == false).
Since this method operates in non-realtime context it must not access critical members (_joint_command_modes and _joints) to avoid priority inversion. Therefore the new command modes are first saved to a cache _new_joint_command_modes. This will then be applied to _joint_command_modes in the perform_command_mode_switch() which is executed in RT context.
- Parameters
-
| start_interfaces | command interfaces that should be started in the form "joint/interface" |
| stop_interfaces | command interfaces that should be stopped in the form "joint/interface" |
- Returns
- hardware_interface::return_type
| std::unordered_map<std::string, std::set<std::string> > bioscara_hardware_interfaces::BioscaraArmHardwareInterface::_joint_command_modes |
|
private |
unordered map of sets storing the active command interfaces for each joint.
Each joint can have a set of active command interfaces. This type of structure is chosen to group interfaces by joint. In the write() function the interface name can simply be constructed by concatenating joint name with interface name. Although currently only one active command interface is allowed at the time, a set can be used to store multiple command interfaces that are acceptable to be combined, for example it would be acceptable to set velocity and driver current and hence that would be an allowable combination.
An unordered map is chosen to simplify acces via the joint name, as this conforms well with the ROS2_control hardware interface. The map does not need to be ordered. Search, insertion, and removal of elements have average constant-time complexity.
unordered map storing the pointers to BaseJoint objects. This will either be a MockJoint or Joint.
An unordered map is chosen to simplify acces via the joint name, as this conforms well with the ROS2_control hardware interface The map does not need to be ordered. Search, insertion, and removal of elements have average constant-time complexity.
Since the BaseJoint methods are implemented as virtual, dynamic method dispatch can be utilized to call the correct implementation of a method. So either BaseJoint::foo() or Joint::foo()/MockJoint::foo() if foo() is overwritten in Joint or MockJoint. a smart pointer is used to guarantee destruction when the pointer is destructed. A unique pointer is used to prevent copying of the object.
| std::vector<std::pair<std::string, hardware_interface::InterfaceDescription *> > bioscara_hardware_interfaces::BioscaraArmHardwareInterface::_ordered_joint_state_interfaces_ptr |
|
private |
A vector of a pair of interface name and pointer of the hardwares state interface which is ordered by joint and state interface type.
A vector is chosen since it guarantees the correct order by insertion. The vector holds pointers to the actual interface structs stored in the parents HardwareComponentInterface::joint_state_interfaces_ but in the desired order. The order is:
- position
- velocity
- home
This order guarantees that when reading the state interfaces in read() that the 'home' interface is read last and has the latest state flags from the joint.