yarp-devices
Loading...
Searching...
No Matches
DeviceMapper.hpp
1// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2
3#ifndef __DEVICE_MAPPER_HPP__
4#define __DEVICE_MAPPER_HPP__
5
6#include <cstdlib> // std::size_t
7
8#include <functional> // std::invoke
9#include <memory>
10#include <tuple>
11#include <typeindex>
12#include <unordered_map>
13#include <vector>
14
15#include <yarp/dev/PolyDriver.h>
16
17#include "FutureTask.hpp"
18#include "RawDevice.hpp"
19
20namespace roboticslab
21{
22
64class DeviceMapper final
65{
66public:
69
72
74 void enableParallelization(unsigned int concurrentTasks);
75
77 bool registerDevice(yarp::dev::PolyDriver * driver);
78
80 void clear();
81
83 std::unique_ptr<FutureTask> createTask() const
84 { return taskFactory->createTask(); }
85
87 using dev_index_t = std::tuple<const RawDevice *, int>;
88
90 using dev_group_t = std::tuple<const RawDevice *, std::vector<int>, int>;
91
96 const std::vector<std::unique_ptr<const RawDevice>> & getDevices() const
97 { return devices; }
98
108 dev_index_t getMotorDevice(int globalAxis) const;
109
117 std::vector<dev_index_t> getMotorDevicesWithOffsets() const;
118
127 std::vector<dev_group_t> getMotorDevicesWithIndices(int globalAxesCount, const int * globalAxes) const;
128
131 { return totalAxes; }
132
134 template<typename T, typename... T_ref>
135 using motor_single_joint_fn = bool (T::*)(int, T_ref...);
136
138 template<typename T, typename... T_ref>
140 {
141 auto [device, offset] = getMotorDevice(j);
142 T * p = device->getHandle<T>();
143 return p ? std::invoke(fn, p, offset, ref...) : false;
144 }
145
147 template<typename T, typename... T_refs>
148 using motor_all_joints_fn = bool (T::*)(T_refs *...);
149
151 template<typename T, typename... T_refs>
153 {
154 auto task = createTask();
155 bool ok = false;
156
157 for (const auto & [device, offset] : getMotorDevicesWithOffsets())
158 {
159 T * p = device->template getHandle<T>();
160 ok |= p && (task->add(p, fn, refs + offset...), true);
161 }
162
163 // at least one targeted device must implement the 'T' iface
164 return ok && task->dispatch();
165 }
166
168 template<typename T, typename... T_refs>
169 using motor_multi_joints_fn = bool (T::*)(int, const int *, T_refs *...);
170
172 template<typename T, typename... T_refs>
173 bool mapJointGroup(motor_multi_joints_fn<T, T_refs...> fn, int n_joint, const int * joints, T_refs *... refs)
174 {
175 auto task = createTask();
176 auto devices = getMotorDevicesWithIndices(n_joint, joints); // extend lifetime of vector of local indices
177 bool ok = true;
178
179 for (const auto & [device, localIndices, globalIndex] : devices)
180 {
181 T * p = device->template getHandle<T>();
182 ok &= p && (task->add(p, fn, localIndices.size(), localIndices.data(), refs + globalIndex...), true);
183 }
184
185 // all targeted devices must implement the 'T' iface
186 return ok && task->dispatch();
187 }
188
190 template<typename T>
192 {
193 // operator[] will insert a default-constructed value if not found
194 if (auto it = connectedSensors.find(typeid(T)); it != connectedSensors.cend())
195 {
196 return it->second;
197 }
198
199 return 0;
200 }
201
208 template<typename T>
209 dev_index_t getSensorDevice(int globalIndex) const
210 {
211 if (auto it = sensorOffsets.find(typeid(T)); it != sensorOffsets.cend())
212 {
213 const auto & [deviceIndex, offset, count] = it->second[globalIndex];
214 return {devices[deviceIndex].get(), globalIndex - offset};
215 }
216
217 return {&invalidDevice, 0};
218 }
219
220 template<typename T, typename T_out>
221 using sensor_status_fn = T_out (T::*)(std::size_t) const;
222
227 template<typename T, typename T_out>
228 T_out getSensorStatus(sensor_status_fn<T, T_out> fn, std::size_t index) const
229 {
230 auto [device, offset] = getSensorDevice<T>(index);
231 T * p = device->template getHandle<T>();
232 return p ? std::invoke(fn, p, offset) : static_cast<T_out>(DeviceMapper::getSensorFailureStatus());
233 }
234
235 template<typename T>
236 using sensor_size_fn = std::size_t (T::*)(std::size_t) const;
237
242 template<typename T>
243 std::size_t getSensorArraySize(sensor_size_fn<T> fn, std::size_t index) const
244 {
245 auto [device, offset] = getSensorDevice<T>(index);
246 T * p = device->template getHandle<T>();
247 return p ? std::invoke(fn, p, offset) : 0;
248 }
249
250 template<typename T, typename... T_out_params>
251 using sensor_output_fn = bool (T::*)(std::size_t, T_out_params &...) const;
252
257 template<typename T, typename... T_out_params>
258 bool getSensorOutput(sensor_output_fn<T, T_out_params...> fn, std::size_t index, T_out_params &... params) const
259 {
260 auto [device, offset] = getSensorDevice<T>(index);
261 T * p = device->template getHandle<T>();
262 return p ? std::invoke(fn, p, offset, params...) : false;
263 }
264
265private:
266 static const int getSensorFailureStatus();
267
268 using dev_index_offset_t = std::tuple<int, int, int>;
269
270 std::vector<std::unique_ptr<const RawDevice>> devices;
271 std::vector<dev_index_offset_t> motorOffsets;
272 std::unordered_map<std::type_index, std::vector<dev_index_offset_t>> sensorOffsets;
273 std::unordered_map<std::type_index, int> connectedSensors;
274
275 int totalAxes {0};
276
277 std::unique_ptr<FutureTaskFactory> taskFactory;
278};
279
280} // namespace roboticslab
281
282#endif // __DEVICE_MAPPER_HPP__
Exposes raw subdevice interface handles on a per-axis manner.
Definition DeviceMapper.hpp:65
std::vector< dev_index_t > getMotorDevicesWithOffsets() const
Retrieve all registered motor subdevices and their associated offsets.
Definition DeviceMapper.cpp:166
std::tuple< const RawDevice *, std::vector< int >, int > dev_group_t
Tuple of a raw device pointer, its local indices and the global index.
Definition DeviceMapper.hpp:90
std::tuple< const RawDevice *, int > dev_index_t
Tuple of a raw device pointer and either an offset or a local index.
Definition DeviceMapper.hpp:87
std::unique_ptr< FutureTask > createTask() const
Create an instance of a deferred task.
Definition DeviceMapper.hpp:83
bool(T::*)(T_refs *...) motor_all_joints_fn
Alias for a full-joint command. See class description.
Definition DeviceMapper.hpp:148
const std::vector< std::unique_ptr< const RawDevice > > & getDevices() const
Retrieve all registered raw devices, regardless of type.
Definition DeviceMapper.hpp:96
int getConnectedSensors() const
Retrieve the number of connected sensors of the specified type across all subdevices.
Definition DeviceMapper.hpp:191
std::size_t getSensorArraySize(sensor_size_fn< T > fn, std::size_t index) const
Retrieve the size of the sensor array at the specified global index.
Definition DeviceMapper.hpp:243
DeviceMapper()
Constructor.
Definition DeviceMapper.cpp:110
void enableParallelization(unsigned int concurrentTasks)
Whether to enable parallel mappings and on how many concurrent threads.
Definition DeviceMapper.cpp:119
bool(T::*)(int, T_ref...) motor_single_joint_fn
Alias for a single-joint command. See class description.
Definition DeviceMapper.hpp:135
dev_index_t getSensorDevice(int globalIndex) const
Retrieve a sensor device handle and its local index given a global index.
Definition DeviceMapper.hpp:209
void clear()
Delete all internal handles.
Definition DeviceMapper.cpp:205
bool registerDevice(yarp::dev::PolyDriver *driver)
Extract interface handles and perform sanity checks.
Definition DeviceMapper.cpp:124
~DeviceMapper()
Destructor.
Definition DeviceMapper.cpp:114
T_out getSensorStatus(sensor_status_fn< T, T_out > fn, std::size_t index) const
Retrieve the status of the sensor device at the specified global index.
Definition DeviceMapper.hpp:228
std::vector< dev_group_t > getMotorDevicesWithIndices(int globalAxesCount, const int *globalAxes) const
Retrieve motor subdevices that map to the specified global axes.
Definition DeviceMapper.cpp:180
int getControlledAxes() const
Retrieve the number of controlled axes across all subdevices.
Definition DeviceMapper.hpp:130
bool(T::*)(int, const int *, T_refs *...) motor_multi_joints_fn
Alias for a joint-group command. See class description.
Definition DeviceMapper.hpp:169
bool mapSingleJoint(motor_single_joint_fn< T, T_ref... > fn, int j, T_ref... ref)
Single-joint command mapping. See class description.
Definition DeviceMapper.hpp:139
bool mapJointGroup(motor_multi_joints_fn< T, T_refs... > fn, int n_joint, const int *joints, T_refs *... refs)
Joint-group command mapping. See class description.
Definition DeviceMapper.hpp:173
bool mapAllJoints(motor_all_joints_fn< T, T_refs... > fn, T_refs *... refs)
Full-joint command mapping. See class description.
Definition DeviceMapper.hpp:152
dev_index_t getMotorDevice(int globalAxis) const
Retrieve a motor device handle and its local index given a global index.
Definition DeviceMapper.cpp:160
bool getSensorOutput(sensor_output_fn< T, T_out_params... > fn, std::size_t index, T_out_params &... params) const
Retrieve information from the sensor device at the specified global index.
Definition DeviceMapper.hpp:258
The main, catch-all namespace for Robotics Lab UC3M.
Definition groups.dox:6
const RawDevice invalidDevice(nullptr)
Singleton instance for an invalid (empty) raw device.