Device routing is a mechanism that allows users to send commands to specific devices using the connection with the base. This is done by specifying a device_identifier when sending a command through a service. This service doesn't need to be implemented by the base.
In other words, you can send a command to a sub device with a service known only by the sub device (e.g.: ActuatorConfigClient
) as long as the device_identifier is specified as an additional command parameter.
The Device Manager service is used to obtain the device_identifier.
The Device Manager service contains a method ReadAllDevices()
which returns a device handle list containing handles for all current devices in the robot.
- The device handle list returned by
ReadAllDevices()
is not in any particular order with respect to the location of devices in the robot. - Device handles also have a device_type field and an order field.
namespace k_api = Kinova::Api;
/* API initialisation */
auto device_manager = new k_api::DeviceManager::DeviceManagerClient(router);
auto allDevicesInfo = device_manager->ReadAllDevices();
The Device Config service provides information about the device being interrogated, including:
- device type
- firmware and bootloader version
- part and serial numbers
- MAC address and
- hardware revision
namespace k_api = Kinova::Api;
/* API initialisation */
auto device_manager = new k_api::DeviceManager::DeviceManagerClient(router);
auto device_config = new k_api::DeviceConfig::DeviceConfigClient(router);
// Get all device routing information (from DeviceManagerClient service)
auto allDevicesInfo = device_manager->ReadAllDevices();
k_api::RouterClientSendOptions options;
options.timeout_ms = 4000; // (milliseconds)
// Use device routing information to route to every device (base, actuator, interconnect, etc.) in the arm base system and request general device information
for (auto device : allDevicesInfo.device_handle())
{
std::cout << "-----------------------------\n";
std::cout << "-- " << k_api::Common::DeviceTypes_Name(device.device_type()) << ": id = " << device.device_identifier() << " --\n";
std::string str;
google::protobuf::TextFormat::PrintToString(device_config->GetDeviceType(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetFirmwareVersion(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetBootloaderVersion(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetModelNumber(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetPartNumber(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetPartNumberRevision(device.device_identifier(), options), &str);
std::cout << str;
google::protobuf::TextFormat::PrintToString(device_config->GetSerialNumber(device.device_identifier(), options), &str);
std::cout << str;
std::cout << std::endl;
}
The device_identifier can be used by other services to directly interrogate a device.
namespace k_api = Kinova::Api;
/* API initialisation */
auto device_manager = new k_api::DeviceManager::DeviceManagerClient(router);
auto vision_config = new k_api::VisionConfig::VisionConfigClient(router);
auto allDevicesInfo = device_manager->ReadAllDevices();
// uses device routing information to route to every device (base, actuator, interconnect, etc.)
for (auto dev : allDevicesInfo.device_handle())
{
if (dev.device_type() == k_api::Common::DeviceTypes::VISION)
{
std::cout << "-- Using Vision Config Service to get intrinsic parameters --" << std::endl;
k_api::VisionConfig::SensorIdentifier sensor_id;
sensor_id.set_sensor(k_api::VisionConfig::SENSOR_COLOR);
// We can now use the Vision service with the base connection by specifing the device_identifier
auto intrinsic_value = vision_config->GetIntrinsicParameters(sensor_id, dev.device_identifier());
std::cout << "Width: " << intrinsic_value.width() << std::endl;
std::cout << "Height: " << intrinsic_value.height() << std::endl;
std::cout << "Principal point x: " << intrinsic_value.principal_point_x() << std::endl;
std::cout << "Principal point y: " << intrinsic_value.principal_point_y() << std::endl;
std::cout << "Focal length x: " << intrinsic_value.focal_length_x() << std::endl;
std::cout << "Focal length y: " << intrinsic_value.focal_length_y() << std::endl;
break;
}
}