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 std::string
203 getDefaultName() const override
204 {
205 return "RobotUnitSimulation";
206 }
207
208 void componentPropertiesUpdated(const std::set<std::string>& changedProperties) override;
209
210 protected:
211 /**
212 * @see PropertyUser::createPropertyDefinitions()
213 */
220
221 // RobotUnit interface
222 protected:
223 void onInitRobotUnit() override;
224 void onConnectRobotUnit() override;
225
226 void joinControlThread() override;
227
228 void rtTask();
229
230 std::atomic_bool shutdownRtThread{false};
231 std::thread rtThread;
232 SimulatorInterfacePrx simulatorPrx;
234 std::string simulatorPrxName;
235 std::string robotName;
236
239
241
242 public:
243 void reportState(SimulatedRobotState const& state,
244 const Ice::Current& = Ice::emptyCurrent) override;
245
246 private:
247 void updateForceTorque(ForceTorqueData const& ftData, IceUtil::Time timestamp);
248 void fillTB(TripleBufferWithGuardAndTime<std::vector<float>>& b,
249 const NameValueMap& nv,
250 const std::string name) const;
251 void rtUpdateSensors(bool wait);
252 void rtSendCommands();
253
254 bool skipReport() const;
255
256 const std::string&
257 getMappedFTName(const std::string& name) const
258 {
259 return ftMappings.count(name) ? ftMappings.at(name).sensorName : name;
260 }
261
262 const std::string&
263 getMappedFTReportingFrame(const std::string& name, const std::string& unmappedFrame) const
264 {
265 return ftMappings.count(name) ? ftMappings.at(name).reportFrame : unmappedFrame;
266 }
267
268 Eigen::Matrix3f
269 getMappedFTReportingTransformation(const std::string& name) const
270 {
271 return ftMappings.count(name) ? ftMappings.at(name).reportTransformation
272 : Eigen::Matrix3f::Identity();
273 }
274
275 void rtPollRobotState();
276 std::atomic_bool isPolling{false};
277
278 struct RobVel
279 {
280 Eigen::Vector3f lin{std::nanf(""), std::nanf(""), std::nanf("")};
281 Eigen::Vector3f ang{std::nanf(""), std::nanf(""), std::nanf("")};
282 };
283
284 struct FT
285 {
286 Eigen::Vector3f force{std::nanf(""), std::nanf(""), std::nanf("")};
287 Eigen::Vector3f torque{std::nanf(""), std::nanf(""), std::nanf("")};
288 };
289
290 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
291 //devs
292 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
293 std::condition_variable cvGotSensorData;
294 std::atomic<bool> gotSensorData{false};
295 IceUtil::Time sensorValuesTimestamp;
296 //joints
297 KeyValueVector<std::string, JointSimulationDevicePtr> jointDevs;
298 TripleBufferWithGuardAndTime<std::vector<float>> torquesTB;
299 TripleBufferWithGuardAndTime<std::vector<float>> anglesTB;
300 TripleBufferWithGuardAndTime<std::vector<float>> velocitiesTB;
301 NameValueMap velocitiesCtrl;
302 NameValueMap anglesCtrl;
303 NameValueMap torquesCtrl;
304 //platform
305 PlatformSimulationDevicePtr platformDev;
306 //pos/vel
307 TripleBufferWithGuardAndTime<Eigen::Matrix4f> robPoseTB;
308 TripleBufferWithGuardAndTime<RobVel> robVelTB;
309 //sensor
310 KeyValueVector<std::string, ForceTorqueSimulationSensorDevicePtr> forceTorqueDevs;
311 TripleBufferWithGuardAndTime<std::vector<FT>> forceTorqueTB;
312 std::vector<AtomicWrapper<std::uintmax_t>> forceTorqueTimes;
313
314 struct FTMappingData
315 {
316 std::string sensorName;
317 std::string originalReportFrame;
318 std::string reportFrame;
319 Eigen::Matrix3f reportTransformation;
320 };
321
322 std::map<std::string, FTMappingData> ftMappings;
323 //pose
324 // GlobalRobotPoseSimulationSensorDevicePtr globalPoseDevice;
325 ///TODO IMU
326 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
327 //other
328 // ////////////////////////////////////////////////////////////////////////////////////////////////// //
329 //settings
330 std::atomic_bool synchronizedSimulation;
331 IceUtil::Time controlIterationMs;
332 std::string simulatorRobotListenerInterfaceTopic;
333 std::string simulatorForceTorqueListenerInterfaceTopic;
334 //metadata
335 std::atomic<std::uintmax_t> iterationCount{0};
336
337 // RobotUnit interface
338 public:
339 IceUtil::Time
341 {
342 return controlIterationMs;
343 }
344
345 // RobotUnitManagementInterface interface
346 public:
347 bool
348 isSimulation(const Ice::Current&) const override
349 {
350 return true;
351 }
352 };
353} // 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
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()