RobotUnitSimulation.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarXSimulation::ArmarXObjects::RobotUnitSimulation
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <condition_variable>
26#include <mutex>
27#include <thread>
28
29#include <VirtualRobot/Robot.h>
30
32
36
37#include <ArmarXSimulation/interface/RobotUnitSimulationInterface.h>
38
44
45namespace armarx
46{
47 using ClockT = std::chrono::high_resolution_clock;
48
49 //we can't store durations in atoms -> store nanoseconds
50 inline std::uintmax_t
52 {
53 return std::chrono::duration_cast<std::chrono::nanoseconds>(
54 ClockT::now().time_since_epoch())
55 .count();
56 }
57
58 template <class T>
60 {
61 TripleBufferWithGuardAndTime(std::condition_variable* cv) : cv{cv}
62 {
63 }
64
65 std::unique_lock<std::recursive_mutex>
67 {
68 return std::unique_lock<std::recursive_mutex>{m};
69 }
70
71 std::size_t
73 {
74 return lastwriteNs;
75 }
76
77 bool
79 {
80 return (lastwriteNs + 1000000000 < nowNS());
81 }
82
83 void
84 reinit(const T& i)
85 {
86 tb.reinitAllBuffers(i);
87 }
88
89 T&
91 {
92 return tb.getWriteBuffer();
93 }
94
95 const T&
97 {
98 return tb.getReadBuffer();
99 }
100
101 void
103 {
104 auto g = guard();
105 lastwriteNs = nowNS();
106 tb.commitWrite();
107 cv->notify_all();
108 }
109
110 void
112 {
113 tb.updateReadBuffer();
114 }
115
116 private:
117 mutable std::recursive_mutex m;
119 std::atomic<std::uintmax_t> lastwriteNs{0};
120 std::condition_variable* cv;
121 };
122
123 /**
124 * @class RobotUnitSimulationPropertyDefinitions
125 * @brief
126 */
128 {
129 public:
132 {
134 "SimulatorName",
135 "Simulator",
136 "Name of the simulator component that should be used");
137 defineOptionalProperty<bool>("SynchronizedSimulation",
138 false,
139 "If the simulation should be synchronized",
142 "ControlIterationMs", 10, "Time each iteration should take (in ms)");
144 "SimulatorRobotListenerInterfaceTopic",
145 "",
146 "Name of the simulator topic for SimulatorRobotListenerInterface (empty defaults "
147 "to Simulator_Robot_<ROBOTNAME>");
149 "SimulatorForceTorqueListenerInterfaceTopic",
150 "ForceTorqueDynamicSimulationValues",
151 "Name of the simulator topic for SimulatorForceTorqueListenerInterface");
152
153 defineOptionalProperty<float>("maxLinearPlatformVelocity", 2000, "[mm/s]");
154 defineOptionalProperty<float>("maxAngularPlatformVelocity", 1, "[rad/s]");
155
157 "ForceTorqueSensorMapping",
158 "",
159 "A list of mappings to modify the forceTorque sensors given in the robot format. "
160 "Syntax (comma SV of colon SV): "
161 "'NameInFile:ReportName[:ReportFrame],NameInFile2:ReportName2[:ReportFrame2]' "
162 "This would cause reporting of the ft sensor called 'NameInFile' under the name "
163 "'ReportName' and optionally change the report frame to 'ReportFrame'. "
164 "IMPORTANT: (1) The original reporting frame of the simulator has to be the parent "
165 "node of 'NameInFile'."
166 " (2) The transformation from the original reporting frame to 'ReportFrame' should "
167 "be fix "
168 "(there should be no joints in the kinematic chain between them),"
169 " since the transformation is done without access to the joint values");
170 }
171 };
172
173 /**
174 * @defgroup Component-RobotUnitSimulation RobotUnitSimulation
175 * @ingroup ArmarXSimulation-Components
176 * A description of the component RobotUnitSimulation.
177 *
178 * @class RobotUnitSimulation
179 * @ingroup Component-RobotUnitSimulation
180 * @brief Brief description of class RobotUnitSimulation.
181 *
182 * Detailed description of class RobotUnitSimulation.
183 */
185 virtual public RobotUnit,
186 virtual public RobotUnitSimulationSinterface
187 {
188 public:
190 torquesTB{&cvGotSensorData},
191 anglesTB{&cvGotSensorData},
192 velocitiesTB{&cvGotSensorData},
193 robPoseTB{&cvGotSensorData},
194 robVelTB{&cvGotSensorData},
195 forceTorqueTB{&cvGotSensorData}
196 {
197 }
198
199 /**
200 * @see armarx::ManagedIceObject::getDefaultName()
201 */
202 static std::string
204 {
205 return "RobotUnitSimulation";
206 }
207
208 std::string
209 getDefaultName() const override
210 {
211 return GetDefaultName();
212 }
213
214 void componentPropertiesUpdated(const std::set<std::string>& changedProperties) override;
215
216 protected:
217 /**
218 * @see PropertyUser::createPropertyDefinitions()
219 */
226
227 // RobotUnit interface
228 protected:
229 void onInitRobotUnit() override;
230 void onConnectRobotUnit() override;
231
232 void joinControlThread() override;
233
234 void rtTask();
235
236 std::atomic_bool shutdownRtThread{false};
237 std::thread rtThread;
238 SimulatorInterfacePrx simulatorPrx;
240 std::string simulatorPrxName;
241 std::string robotName;
242
245
247
248 public:
249 void reportState(SimulatedRobotState const& state,
250 const Ice::Current& = Ice::emptyCurrent) override;
251
252 private:
253 void updateForceTorque(ForceTorqueData const& ftData, IceUtil::Time timestamp);
254 void fillTB(TripleBufferWithGuardAndTime<std::vector<float>>& b,
255 const NameValueMap& nv,
256 const std::string name) const;
257 void rtUpdateSensors(bool wait);
258 void rtSendCommands();
259
260 bool skipReport() const;
261
262 const std::string&
263 getMappedFTName(const std::string& name) const
264 {
265 return ftMappings.count(name) ? ftMappings.at(name).sensorName : name;
266 }
267
268 const std::string&
269 getMappedFTReportingFrame(const std::string& name, const std::string& unmappedFrame) const
270 {
271 return ftMappings.count(name) ? ftMappings.at(name).reportFrame : unmappedFrame;
272 }
273
274 Eigen::Matrix3f
275 getMappedFTReportingTransformation(const std::string& name) const
276 {
277 return ftMappings.count(name) ? ftMappings.at(name).reportTransformation
278 : Eigen::Matrix3f::Identity();
279 }
280
281 void rtPollRobotState();
282 std::atomic_bool isPolling{false};
283
284 struct RobVel
285 {
286 Eigen::Vector3f lin{std::nanf(""), std::nanf(""), std::nanf("")};
287 Eigen::Vector3f ang{std::nanf(""), std::nanf(""), std::nanf("")};
288 };
289
290 struct FT
291 {
292 Eigen::Vector3f force{std::nanf(""), std::nanf(""), std::nanf("")};
293 Eigen::Vector3f torque{std::nanf(""), std::nanf(""), std::nanf("")};
294 };
295
296 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
297 //devs
298 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
299 std::condition_variable cvGotSensorData;
300 std::atomic<bool> gotSensorData{false};
301 IceUtil::Time sensorValuesTimestamp;
302 //joints
303 KeyValueVector<std::string, JointSimulationDevicePtr> jointDevs;
304 TripleBufferWithGuardAndTime<std::vector<float>> torquesTB;
305 TripleBufferWithGuardAndTime<std::vector<float>> anglesTB;
306 TripleBufferWithGuardAndTime<std::vector<float>> velocitiesTB;
307 NameValueMap velocitiesCtrl;
308 NameValueMap anglesCtrl;
309 NameValueMap torquesCtrl;
310 //platform
311 PlatformSimulationDevicePtr platformDev;
312 //pos/vel
313 TripleBufferWithGuardAndTime<Eigen::Matrix4f> robPoseTB;
314 TripleBufferWithGuardAndTime<RobVel> robVelTB;
315 //sensor
316 KeyValueVector<std::string, ForceTorqueSimulationSensorDevicePtr> forceTorqueDevs;
317 TripleBufferWithGuardAndTime<std::vector<FT>> forceTorqueTB;
318 std::vector<AtomicWrapper<std::uintmax_t>> forceTorqueTimes;
319
320 struct FTMappingData
321 {
322 std::string sensorName;
323 std::string originalReportFrame;
324 std::string reportFrame;
325 Eigen::Matrix3f reportTransformation;
326 };
327
328 std::map<std::string, FTMappingData> ftMappings;
329 //pose
330 // GlobalRobotPoseSimulationSensorDevicePtr globalPoseDevice;
331 ///TODO IMU
332 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
333 //other
334 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
335 //settings
336 std::atomic_bool synchronizedSimulation;
337 IceUtil::Time controlIterationMs;
338 std::string simulatorRobotListenerInterfaceTopic;
339 std::string simulatorForceTorqueListenerInterfaceTopic;
340 //metadata
341 std::atomic<std::uintmax_t> iterationCount{0};
342
343 // RobotUnit interface
344 public:
345 IceUtil::Time
347 {
348 return controlIterationMs;
349 }
350
351 // RobotUnitManagementInterface interface
352 public:
353 bool
354 isSimulation(const Ice::Current&) const override
355 {
356 return true;
357 }
358 };
359} // namespace armarx
std::string timestamp()
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
RobotUnitPropertyDefinitions(std::string prefix)
Definition RobotUnit.h:56
IceUtil::Time getControlThreadTargetPeriod() const override
The ControlThread's period.
void joinControlThread() override
Implementations have to join their ControlThread in this hook. (used by RobotUnit::finishRunning())
void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
std::atomic< long > simulationDataTimestampInMicroSeconds
bool isSimulation(const Ice::Current &) const override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
SimulatorInterfacePrx simulatorPrx
void onConnectRobotUnit() override
called in onConnectComponent
static std::string GetDefaultName()
void reportState(SimulatedRobotState const &state, const Ice::Current &=Ice::emptyCurrent) override
void onInitRobotUnit() override
called in onInitComponent
std::string getDefaultName() const override
The RobotUnit class manages a robot and its controllers.
Definition RobotUnit.h:192
Same as the TripleBuffer, but partial writes of the data structure are ok. The write operation may be...
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::uintmax_t nowNS()
std::chrono::high_resolution_clock ClockT
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition helper.h:35
TripleBufferWithGuardAndTime(std::condition_variable *cv)
std::unique_lock< std::recursive_mutex > guard()