-
Notifications
You must be signed in to change notification settings - Fork 0
hardware_interface
This page walks you through the steps to set up a new robot to work with the controller manager. When you make your robot support one or more of the standard interfaces, you will be able to take advantage of a large library of controllers that work on the standard interfaces.
Suppose we have a robot with 2 joints: A & B. Both joints are position controlled. In this case, your robot should provide the standard `JointPositionInterface` and the `JointStateInterface`, so it can re-use all controllers that are already written to work with the `JointPositionInterface` and the `JointStateInterface`. The code would look like this:
#include <hardware_interface/joint_command_interface.h>
#include <hardware_interface/joint_state_interface.h>
class MyRobot : public hardware_interface::RobotHW
{
public:
MyRobot()
{
// connect and register the joint state interface
jnt_state_interface.registerJoint("A", &pos[0], &vel[0], &eff[0]);
jnt_state_interface.registerJoint("B", &pos[1], &vel[1], &eff[1]);
registerInteface(&jnt_state_interface);
// connect and register the joint position interface
jnt_pos_interface.registerJoint(jnt_state_interface.getJoint("A"), &cmd[0]);
jnt_pos_interface.registerJoint(jnt_state_interface.getJoint("B"), &cmd[1]);
registerInteface(&jnt_pos_interface);
}
private:
JointStateInterface jnt_state_interface;
PositionJointInterface jnt_pos_interface;
double cmd[2];
double pos[2];
double vel[2];
double eff[2];
};
That's it! So how is this code actually controlling your robot? The functions above are designed to give the controller manager (and the controllers inside the controller manager) access to the joint state of your robot, and to the commands of your robot. When the controller manager runs, the controllers will read from the pos, vel and eff variables in your robot, and the controller will write the desired command into the cmd variable. It's your job to make sure the pos, vel and eff variables always have the latest joint state available, and you also need to make sure that whatever is written into the cmd variable gets executed by the robot. To do this, you could for example add a read() and a write() function to your robot class. In your main(), you'd then do something like this:
main()
{
MyRobot robot;
ControllerManager cm(&robot);
while (true)
{
robot.read();
cm.update(robot.get_time());
robot.write();
sleep();
}
}
As the image above suggests, you're of course not limited to inheriting from only one single interface. Your robot can provide as many interfaces as you like. Your robot could for example provide both the 'PositionJointInterface' and the 'VelocityJointInterface', and many more.
The standard interfaces are pretty awesome if you don't want to write a whole new set of controllers for your robot, and you want to take advantage of the libraries of existing controllers. But what if your robot has some features that are not supported by the standard interfaces? Does that mean you can't use the standard interfaces at all? Guess what, turns out you can do both! You can use the standard interfaces (and re-use the standard controllers) for the features of your robot that are standard. And at the same time you can expose your robot-specific features in a robot-specific interface. Take another look at the image above, and see how it shows a robot with both standard and robot-specific interfaces.
What does the code look like for such a situation?
class MyRobot : public hardware_interface::RobotHW { public: MyRobot() { // register the joint state and position interfaces ... ... (see the code above) ... // register some robot specific interfaces registerInteface(&cool_interface); } private: MyCustomInterface cool_interface; };
or... you can register the MyRobot class itself:
class MyRobot : public hardware_interface::RobotHW, public hardware_interface::HardwareInterface { public: MyRobot() { // register the joint state and position interfaces ... ... (see the code above) ... // register the MyRobot class itself to make the 'someCoolFunction' available // the MyRobot class inherits from HardwareInterface to make this possible registerInteface(this); } void someCoolFunction(); };
So the custom interfaces could be nothing more than adding any number of function calls to your robot class, and registering the robot class itself. These robot-specific functions will only be available to controllers that are specifically designed for your robot, but at the same time, your robot will still work with standard controllers using the standard interfaces of your robot.