ros2_controllers
ros2_controllers copied to clipboard
Question on how to launch the hardware interface with an I2C Bus and avoid data race conditions
Lookig at the demo for the DiffBot mock hardware interface, it gives me some good ideas on how to create my own for a motor driver that uses I2C.
However one concern I have is that I plan to wrap I2C functionality inside a couple of classes, like so (this is mainly so I can introduce new devices later into my code without making big changes):
template<typename IOStrategy>
concept HasReadAndWriteMethod = requires(IOStrategy strategy) {
strategy.read();
strategy.write()
};
template<typename InputDataType, typename ReadReturnType>
class Device
{
public:
virtual ReadReturnType read() = 0;
virtual void write(InputDataType data) = 0;
};
/// The ros2 control hardware interface will hold/own this MotorController
template < HasReadAndWriteMethod IOStrategy, typename InputDataType, typename ReadReturnType>
class MotorController : public Device<InputDataType, ReadReturnType> {
ReadReturnType read() {IOStrategy{}.read();};
write(InputDataType) {IOStrategy{}.write(InputDataType);};
};
Then my DiffBotActuatorHardware
will have MotorController<I2CMotorController>
as a class member. The I2CMotorController
is similar to:
class I2CBus {
I2CBus(int busNumber);
read();
write();
int fileDescriper;
std::mutex m;
};
class I2CMotorController {
I2CMotorController(I2CBus i2cBus);
read();
write();
};
Since the controller manager is what ends up spawning the controller and its hardware interface, how do I guarantee no race conditions on that same bus?
Can I define how the manager launches the hardware interface, such that I can pass it a reference to the I2CBus
object instead of instantiating a new one?
For instance, what if I were to have another ros2 controller for a ServoMotor that also uses the same I2C bus (just for the sake of discussion), or perhaps another Node that reads an IMU that is forced to create a different instance of the I2CBus
class.
I saw an example today that uses node composition and passes the hardware interface to the manager.
controller_manager::ControllerManager cm(&hardwareInterface);
I would prefer to not close this issue until it's reviewed/commented by the team or someone more knowledgeable than me on this topic.