Skip to content

Commit c30b6ab

Browse files
committed
Cleanup handling of yarpDeviceName in robotinterface plugin
1 parent 5d390dd commit c30b6ab

File tree

4 files changed

+100
-25
lines changed

4 files changed

+100
-25
lines changed

libraries/singleton/include/GazeboYarpPlugins/Handler.hh

+29-9
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,52 @@ public:
100100

101101
/** \brief Adds a new yarp device pointer to the "database".
102102
*
103-
* If the device already exists and the pointer are the same return success, if pointers doesn't match returns error.
104-
* \param deviceName the name of the device to be added to the internal database
103+
* The YARP device are stored in these database using the following schema:
104+
* * For YARP devices created by Model plugins, the deviceDatabaseKey is
105+
* defined as deviceDatabaseKey = Model::GetScopedName() + "::" + yarpDeviceName
106+
* * For YARP devices created by Sensor plugins, the deviceDatabaseKey is
107+
* defined as deviceDatabaseKey = Sensor::GetScopedName() + "::" + yarpDeviceName
108+
*
109+
* yarpDeviceName is a non-scoped identifier of the specific instance of the YARP device,
110+
* that is tipically specified by the Gazebo plugin configuration file, and corresponds to the
111+
* name attribute of the device XML element when the device is created with the robotinterface
112+
* XML format.
113+
*
114+
* If the device with the same deviceDatabaseKey exists and the pointer are the same return success,
115+
* if pointers doesn't match returns error.
116+
* \param deviceDatabaseKey the deviceDatabaseKey of the device to be added to the internal database
105117
* \param device2add the pointer of the device to be added to the internal database
106118
* \return true if successfully added, or the device already exists. False otherwise.
107119
*/
108-
bool setDevice(std::string deviceName, yarp::dev::PolyDriver* device2add);
120+
bool setDevice(std::string deviceDatabaseKey, yarp::dev::PolyDriver* device2add);
109121

110-
/** Returns the pointer to the device matching the sensor name
111-
* \param deviceName device name to be looked for
122+
/** Returns the pointer to the device matching the deviceDatabaseKey
123+
* \param deviceDatabaseKey deviceDatabaseKey to be looked for
112124
* \return the pointer to the device
113125
*/
114-
yarp::dev::PolyDriver* getDevice(const std::string& deviceName) const;
126+
yarp::dev::PolyDriver* getDevice(const std::string& deviceDatabaseKey) const;
115127

116128
/** \brief Removes a device from the internal database
117-
* \param deviceName the name of the device to be removed
129+
* \param deviceDatabaseKey the deviceDatabaseKey of the device to be removed
118130
*/
119-
void removeDevice(const std::string& deviceName);
131+
void removeDevice(const std::string& deviceDatabaseKey);
120132

121133
/**
122134
* \brief Returns a list of the opened devices
123135
* \note This list acts just as a view of the available devices,
124136
* and it does not transfer or share ownership of the devices.
125137
* The consumer code needs to make sure that the driver lifetime
126138
* is longer then the consumer lifetime.
139+
*
140+
* This method returns all the YARP devices that have been created by the specified model,
141+
* and by all its nested model and sensors. As the PolyDriverList is effectively a map in which
142+
* the key is a string and the value is the PolyDriver pointer, in this case the key of the PolyDriverList
143+
* is the yarpDeviceName without any scope, i.e. the yarpDeviceName and not the deviceDatabaseKey .
144+
*
145+
* If after removing the scope two devices have the same yarpDeviceName, the getModelDevicesAsPolyDriverList
146+
* prints an error and returns false, while true is returned if everything works as expected.
127147
*/
128-
void getDevicesAsPolyDriverList(yarp::dev::PolyDriverList& list);
148+
bool getDevicesAsPolyDriverList(const std::string& modelScopedName, yarp::dev::PolyDriverList& list);
129149

130150

131151
/** Destructor

libraries/singleton/src/Handler.cc

+62-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <gazebo/physics/Entity.hh>
1313
#include <gazebo/sensors/sensors.hh>
1414

15+
#include <unordered_map>
16+
1517
using namespace gazebo;
1618

1719
namespace GazeboYarpPlugins {
@@ -170,10 +172,10 @@ void Handler::removeSensor(const std::string& sensorName)
170172
}
171173
}
172174

173-
bool Handler::setDevice(std::string deviceName, yarp::dev::PolyDriver* device2add)
175+
bool Handler::setDevice(std::string deviceDatabaseKey, yarp::dev::PolyDriver* device2add)
174176
{
175177
bool ret = false;
176-
DevicesMap::iterator device = m_devicesMap.find(deviceName);
178+
DevicesMap::iterator device = m_devicesMap.find(deviceDatabaseKey);
177179
if (device != m_devicesMap.end()) {
178180
//device already exists. Increment reference counting
179181
if(device->second.object() == device2add)
@@ -190,7 +192,7 @@ bool Handler::setDevice(std::string deviceName, yarp::dev::PolyDriver* device2ad
190192
} else {
191193
//device does not exists. Add to map
192194
ReferenceCountingDevice countedDevice(device2add);
193-
if (!m_devicesMap.insert(std::pair<std::string, ReferenceCountingDevice>(deviceName, countedDevice)).second) {
195+
if (!m_devicesMap.insert(std::pair<std::string, ReferenceCountingDevice>(deviceDatabaseKey, countedDevice)).second) {
194196
yError() << " Error in GazeboYarpPlugins::Handler while inserting a new device pointer!";
195197
ret = false;
196198
} else {
@@ -200,11 +202,11 @@ bool Handler::setDevice(std::string deviceName, yarp::dev::PolyDriver* device2ad
200202
return ret;
201203
}
202204

203-
yarp::dev::PolyDriver* Handler::getDevice(const std::string& deviceName) const
205+
yarp::dev::PolyDriver* Handler::getDevice(const std::string& deviceDatabaseKey) const
204206
{
205207
yarp::dev::PolyDriver* tmp = NULL;
206208

207-
DevicesMap::const_iterator device = m_devicesMap.find(deviceName);
209+
DevicesMap::const_iterator device = m_devicesMap.find(deviceDatabaseKey);
208210
if (device != m_devicesMap.end()) {
209211
tmp = device->second.object();
210212
} else {
@@ -213,29 +215,76 @@ yarp::dev::PolyDriver* Handler::getDevice(const std::string& deviceName) const
213215
return tmp;
214216
}
215217

216-
void Handler::removeDevice(const std::string& deviceName)
218+
void Handler::removeDevice(const std::string& deviceDatabaseKey)
217219
{
218-
DevicesMap::iterator device = m_devicesMap.find(deviceName);
220+
DevicesMap::iterator device = m_devicesMap.find(deviceDatabaseKey);
219221
if (device != m_devicesMap.end()) {
220222
device->second.decrementCount();
221223
if (!device->second.count()) {
222224
device->second.object()->close();
223225
m_devicesMap.erase(device);
224226
}
225227
} else {
226-
yError() << "Could not remove device " << deviceName << ". Device was not found";
228+
yError() << "Could not remove device " << deviceDatabaseKey << ". Device was not found";
227229
}
228230
return;
229231
}
230232

231-
void Handler::getDevicesAsPolyDriverList(yarp::dev::PolyDriverList& list)
233+
inline bool startsWith(const std::string&completeString,
234+
const std::string&candidatePrefix)
235+
{
236+
// https://stackoverflow.com/a/40441240
237+
return (completeString.rfind(candidatePrefix, 0) == 0);
238+
}
239+
240+
bool Handler::getDevicesAsPolyDriverList(const std::string& modelScopedName, yarp::dev::PolyDriverList& list)
232241
{
233-
for(auto&& devicesMapElem: m_devicesMap) {
234-
yDebug() << "DEBUG TO REMOVE: Add device to " << devicesMapElem.first;
235-
list.push(devicesMapElem.second.object(), devicesMapElem.first.c_str());
242+
list = yarp::dev::PolyDriverList();
243+
244+
// This map contains only the yarpDeviceName that we actually added
245+
// to the returned yarp::dev::PolyDriverList
246+
std::unordered_map<std::string, std::string> inserted_yarpDeviceName2deviceDatabaseKey;
247+
248+
for (auto&& devicesMapElem: m_devicesMap) {
249+
yDebug() << "DEBUG TO REMOVE: Add device deviceDatabaseKey " << devicesMapElem.first
250+
<< " modelScopedName " << modelScopedName;
251+
252+
std::string deviceDatabaseKey = devicesMapElem.first;
253+
254+
std::string yarpDeviceName;
255+
256+
// If the deviceDatabaseKey starts with the modelScopedName, then it is eligible for insertion
257+
// in the returned list
258+
if (startsWith(deviceDatabaseKey, modelScopedName)) {
259+
// Extract yarpDeviceName from deviceDatabaseKey
260+
yarpDeviceName = deviceDatabaseKey.substr(deviceDatabaseKey.find_last_of(":")+1);
261+
262+
// Check if a device with the same yarpDeviceName was already inserted
263+
auto got = inserted_yarpDeviceName2deviceDatabaseKey.find(yarpDeviceName);
264+
265+
// If not found, insert and continue
266+
if (got == inserted_yarpDeviceName2deviceDatabaseKey.end()) {
267+
// If no name collision is found, insert and continue
268+
inserted_yarpDeviceName2deviceDatabaseKey.insert({yarpDeviceName, deviceDatabaseKey});
269+
list.push(devicesMapElem.second.object(), yarpDeviceName.c_str());
270+
yDebug() << " add yarpDeviceName " << yarpDeviceName;
271+
} else {
272+
// If a name collision is found, print a clear error and return
273+
yError() << "GazeboYARPPlugins robotinterface getDevicesAsPolyDriverList error: ";
274+
yError() << "two YARP devices with yarpDeviceName " << yarpDeviceName
275+
<< " found in model " << modelScopedName;
276+
yError() << "First instance: " << got->second;
277+
yError() << "Second instance: " << deviceDatabaseKey;
278+
yError() << "Please eliminate or rename one of the two instances. ";
279+
list = yarp::dev::PolyDriverList();
280+
return false;
281+
}
282+
283+
}
284+
236285
}
237286

238-
return;
287+
return true;
239288
}
240289

241290

plugins/robotinterface/src/GazeboYarpRobotInterface.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,22 @@ void GazeboYarpRobotInterface::Load(physics::ModelPtr _parentModel, sdf::Element
8585

8686
// Extract externalDriverList of devices from the one that have been already opened in the Gazebo model by other gazebo_yarp plugins
8787
yarp::dev::PolyDriverList externalDriverList;
88-
GazeboYarpPlugins::Handler::getHandler()->getDevicesAsPolyDriverList(externalDriverList);
88+
GazeboYarpPlugins::Handler::getHandler()->getDevicesAsPolyDriverList(_parentModel->GetScopedName(), externalDriverList);
8989

9090
// Set external devices from the one that have been already opened in the Gazebo model by other gazebo_yarp plugins
9191
bool ok = m_xmlRobotInterfaceResult.robot.setExternalDevices(externalDriverList);
9292
if (!ok) {
9393
yError() << "GazeboYarpRobotInterface : impossible to set external devices";
94+
return;
9495
}
9596

9697
// Start robotinterface
9798
ok = m_xmlRobotInterfaceResult.robot.enterPhase(yarp::robotinterface::experimental::ActionPhaseStartup);
9899
if (!ok) {
99100
yError() << "GazeboYarpRobotInterface : impossible to start robotinterface";
101+
m_xmlRobotInterfaceResult.robot.enterPhase(yarp::robotinterface::experimental::ActionPhaseInterrupt1);
102+
m_xmlRobotInterfaceResult.robot.enterPhase(yarp::robotinterface::experimental::ActionPhaseShutdown);
103+
return;
100104
}
101105
}
102106

tests/robotinterface/RobotInterfaceTest.xml

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
<param name="joints"> 1 </param>
1212
<action phase="startup" level="5" type="attach">
1313
<paramlist name="networks">
14-
<!-- This should match the name of the device in the .ini file loaded in the Gazebo plugin, prefied by the Gazebo model name -->
15-
<elem name="FirstSetOfJoints"> pendulum_with_base::pendulum_aaa </elem>
14+
<!-- This should match the yarpDeviceName in the .ini file loaded in the Gazebo plugin. -->
15+
<!-- The yarpDeviceName plays the same role of the name attribute of the device XML element
16+
for devices that are created via the robotinterface XML format. -->
17+
<elem name="FirstSetOfJoints"> pendulum_controlboard_ </elem>
1618
</paramlist>
1719
</action>
1820
<action phase="shutdown" level="5" type="detach" />

0 commit comments

Comments
 (0)