ros-controls/ros_control — pull request #151 by Igorec (2014-04-10 10:39:22+00:00)
Title: Add Composite Robot Hardware Interface

Composite robot hardware interface can dynamically load, configure and run together a set of robot devices. ```CompositeRobotHW``` derived from ```RobotHW``` class. It work like ```ControllerManager``` for controllers but for devices. CompositeRobotHW loads device libraries and configures each device at ```configure``` method.

Configure example:
```yaml
device_list:
left_arm:
type: my_arm_hardware/MyArmHW
address: 192.168.1.200
root_name: l_base_link
tip_name: l_tip_link

right_arm:
type: my_arm_hardware/MyArmHW
address: 192.168.1.201
root_name: r_base_link
tip_name: r_tip_link

left_gripper:
type: my_gripper_hardware/MyGripperHW
address: /dev/ttyS0
palm_name: l_palm_link
```

Each device class should be derived from ```DeviceHW``` and exported as pluginlib module. All devices share the same interfaces thru ```CompositeInterfaceManager``` and may share resources thru ```ResourceInterfaceManager```. Each device must implement configure method, for example:

```cpp
using namespace composite_hardware_interface;

bool MyGripperHW::configure(SharedInterfaceManager& ifaces,
SharedResourceManager& resources,
const std::string& name,
const urdf::Model& urdf_model,
const ros::NodeHandle& nh)
{
using namespace hardware_interface;
command_joint = getCommandJoint(urdf_model, nh);

JointStateHandle state_h(command_joint, &position_, &velocity_, &effort_);

// If interface with type JointStateInterface registered in the manager,
// the function returns a pointer to its mapped value.
// If interface with type JointStateInterface does not yet registered in the
// manager, the function insert a new interface with that type to the cash,
// register it in the manger and returns a pointer to its mapped value.
ifaces.get()->registerHandle(state_h);

JointHandle pos_h(state_h, &position_cmd_);
ifaces.get()->registerHandle(pos_h);

JointHandle eff_h(state_h, &effort_cmd_);
ifaces.get()->registerHandle(eff_h);

// For example joint_mode - resource that must be shared between devices
if( !resources.exists("joint_mode") )
{
// "joint_mode" does not yet match the key of any element in the cash, so the
// get function inserts a new element with that key and returns a pointer to its
// mapped value.
JointModeHandle jm_h("joint_mode", resources.get("joint_mode"));
ifaces.get()->registerHandle(jm_h);
}
// "joint_mode" matches the key of an element in the cash,so the function
// returns a pointer to its mapped value.
joint_mode_ = resources.get("joint_mode");
}

int* joint_mode_;
```