PlatformUnitDynamicSimulation.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2013-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarXSimulation
19 * @author Valerij Wittenbeck, Nikolaus Vahrenkamp
20 * @date 2014
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
27
29
30#include <cmath>
31
32#include <Eigen/Geometry>
33
35
38
39using namespace armarx;
40
41void
43{
44 linearVelocityMax = getProperty<float>("LinearVelocityMax").getValue();
45 linearVelocityMin = getProperty<float>("LinearVelocityMin").getValue();
46 linearAccelerationMax = getProperty<float>("LinearAccelerationMax").getValue();
47 angularVelocityMax = getProperty<float>("AngularVelocityMax").getValue();
48 angularAccelerationMax = getProperty<float>("AngularAccelerationMax").getValue();
49 platformOrientationOffset = getProperty<float>("PlatformOrientationOffset").getValue();
50
51
52 robotName = getProperty<std::string>("RobotName").getValue();
53 platformName = getProperty<std::string>("PlatformName").getValue();
54
55 simulatorPrxName = getProperty<std::string>("SimulatorProxyName").getValue();
56
57 positionalAccuracy = 0.02f; //in m
58 orientationalAccuracy = 0.1f; //in rad
59
60 intervalMs = getProperty<int>("IntervalMs").getValue();
61 ARMARX_VERBOSE << "Starting platform unit dynamic simulation with " << intervalMs
62 << " ms interval";
64 this,
67 false,
68 "PlatformUnitSimulation");
69 simulationTask->setDelayWarningTolerance(100);
70
71 if (!robotName.empty())
72 {
73 std::string robotTopicName = "Simulator_Robot_";
74 robotTopicName += robotName;
75 ARMARX_INFO << "Simulator Robot topic: " << robotTopicName;
76 usingTopic(robotTopicName);
77 }
78 else
79 {
80 ARMARX_WARNING << "No robot loaded...";
81 }
82
84
85 currentRotation = 0.0f;
86 targetRotation = 0.0f;
87}
88
89void
91{
92 ARMARX_INFO << "Stopping platform unit";
93 std::unique_lock<std::mutex> lock(currentPoseMutex);
94 simulationTask->stop();
95 simulatorPrx = nullptr;
96}
97
98void
100{
101 platformControlMode = eUnknown;
102
103
104 ARMARX_INFO << "Using simulator proxy: " << simulatorPrxName << flush;
106
107 {
108 std::unique_lock<std::mutex> lock(currentPoseMutex);
110 }
113
114 simulationTask->start();
115}
116
117void
122
123Eigen::Vector3f
125 Eigen::Vector3f curV)
126{
127 ARMARX_DEBUG << "calc platform vel, dist:" << distance.transpose()
128 << ", curVel:" << curV.transpose() << ", linearVelocityMax:" << linearVelocityMax
129 << ", linearAccelerationMax:" << linearAccelerationMax << flush;
130
131 if (distance.norm() < positionalAccuracy)
132 {
133 ARMARX_DEBUG << "calc platform vel end: ZERO" << flush;
134 return Eigen::Vector3f::Zero();
135 }
136
137 Eigen::Vector3f v = distance;
138 //make sure there is a minimum velocity so the platform doesn't slow down too much
139 v = clampf(v.norm(), linearVelocityMin, linearVelocityMax) * v.normalized();
140
141 if (!std::isfinite(v(0)) || !std::isfinite(v(1)) || !std::isfinite(v(2)))
142 {
143
144 ARMARX_ERROR << "NAN in platform calculation, v=" << v << ", distance=" << distance
145 << ",distance.normalized()=" << distance.normalized() << flush;
146 return Eigen::Vector3f::Zero();
147 }
148
149 //throttle speed if the change of current to desired is too large (> max. accel)
150 Eigen::Vector3f a = (v - curV);
151
152 if ((v - curV).norm() > 1e-5)
153 {
154 a = std::min<float>(a.norm(), linearAccelerationMax) * a.normalized();
155
156 if (!std::isfinite(a(0)) || !std::isfinite(a(1)) || !std::isfinite(a(2)))
157 {
158
159 ARMARX_ERROR << "NAN in platform calculation, a=" << a << ", (v - curV)=" << (v - curV)
160 << ",(v - curV).normalized()=" << (v - curV).normalized() << flush;
161 return Eigen::Vector3f::Zero();
162 }
163 }
164
165 v = a + curV;
166 ARMARX_DEBUG << "calc platform vel end: " << v.transpose() << flush;
167 return v;
168}
169
170float
171PlatformUnitDynamicSimulation::calculateAngularVelocity(float source, float target, float curV)
172{
173 ARMARX_DEBUG << "calc platform ang vel, from:" << source << " to:" << target
174 << ", curVel:" << curV << flush;
175 const float M_2PI = 2 * M_PI;
176 float cw = fmod(source - target + M_2PI, M_2PI); //ensure that angle is in [0,2PI]
177 float ccw = fmod(target - source + M_2PI, M_2PI);
178 float minDist = (cw < ccw) ? -cw : ccw;
179
180 if (fabs(minDist) < orientationalAccuracy)
181 {
182 ARMARX_DEBUG << "calc platform ang vel end: ZERO" << flush;
183 return 0.f;
184 }
185
186 float v = (minDist < 0) ? -angularVelocityMax : angularVelocityMax;
187 float a = (v - curV);
189 v = a + curV;
190 ARMARX_DEBUG << "calc platform ang vel end:" << v << flush;
191 return v;
192}
193
194void
196{
197 moveRelative(0, 0, 0, 500, 500, current);
198}
199
200static Eigen::Vector2f
201transformToLocalVelocity(float currentRotation, float velX, float velY)
202{
203 // Revert the rotation by rotating by the negative angle
204 return Eigen::Rotation2Df(-currentRotation) * Eigen::Vector2f(velX, velY);
205}
206
207void
209{
210 Eigen::Vector3f relTargetPosition;
211 Eigen::Vector3f curLinVel;
212 float curAngVel = 0.f;
213 {
214 std::unique_lock<std::mutex> lock(currentPoseMutex);
215
216 if (!simulatorPrx)
217 {
218 return;
219 }
220
221 if (platformControlMode == ePositionControl)
222 {
223
224
225 ARMARX_DEBUG << "Platform sim step" << flush;
226
227 SimulatedRobotState state = simulatorPrx->getRobotState(robotName);
228
229 if (!state.hasRobot)
230 {
231 ARMARX_ERROR << deactivateSpam(5) << "No robot with name " << robotName;
232 return;
233 }
234
235 Vector3Ptr p = Vector3Ptr::dynamicCast(state.pose->position);
236 relTargetPosition << (targetPosition.x - p->x) / 1000.f,
237 (targetPosition.y - p->y) / 1000.f, 0;
238
239 Vector3BasePtr v = state.linearVelocity;
240 Vector3BasePtr o = state.angularVelocity;
241 currentVelocity.x = v->x;
242 currentVelocity.y = v->y;
244
245 // The currentVelocity is in the global frame, we need to report the velocity in the platform local frame
246 Eigen::Vector2f localVelocity =
247 transformToLocalVelocity(currentRotation, currentVelocity.x, currentVelocity.y);
248 listenerPrx->begin_reportPlatformVelocity(
249 localVelocity.x(), localVelocity.y(), currentRotationVelocity);
250
251 curLinVel =
252 Eigen::Vector3f(currentVelocity.x / 1000.f, currentVelocity.y / 1000.f, 0.f);
253 curAngVel = currentRotationVelocity;
254
255 const Eigen::Vector3f desiredLinVel =
256 calculateLinearVelocity(relTargetPosition, curLinVel);
257 const float desiredAngVel =
259
260 simulatorPrx->begin_setRobotLinearVelocity(
261 robotName, platformName, new Vector3(desiredLinVel));
262 simulatorPrx->begin_setRobotAngularVelocity(
263 robotName, platformName, new Vector3(Eigen::Vector3f(0.f, 0.f, desiredAngVel)));
264 ARMARX_DEBUG << "Platform sim step end" << flush;
265 }
266 }
267}
268
269void
270PlatformUnitDynamicSimulation::moveTo(Ice::Float targetPlatformPositionX,
271 Ice::Float targetPlatformPositionY,
272 Ice::Float targetPlatformRotation,
273 Ice::Float positionalAccuracy,
274 Ice::Float orientationalAccuracy,
275 const Ice::Current& c)
276{
277 std::unique_lock<std::mutex> lock(currentPoseMutex);
278 platformControlMode = ePositionControl;
279 ARMARX_DEBUG << "Platform move to" << flush;
280 targetPosition.x = targetPlatformPositionX;
281 targetPosition.y = targetPlatformPositionY;
282 targetRotation = targetPlatformRotation;
283 this->positionalAccuracy = positionalAccuracy * .001f;
284 this->orientationalAccuracy = orientationalAccuracy;
285 // listenerPrx->begin_reportNewTargetPose(targetPosition.x, targetPosition.y, targetRotation);
286 ARMARX_INFO << "New Target: " << targetPosition.x << " " << targetPosition.y << " "
287 << targetRotation << flush;
288}
289
290void
291PlatformUnitDynamicSimulation::move(float targetPlatformVelocityX,
292 float targetPlatformVelocityY,
293 float targetPlatformVelocityRotation,
294 const Ice::Current& c)
295{
296 std::unique_lock<std::mutex> lock(currentPoseMutex);
297 targetPlatformVelocityRotation *= 5;
298
299 Eigen::Vector3f translationVel;
300 platformControlMode = eVelocityControl;
301 translationVel << targetPlatformVelocityX, targetPlatformVelocityY, 0;
302 translationVel *= .003;
303 // ARMARX_INFO << deactivateSpam(1) << "New Platformvelocity: " << translationVel << "\nrot vel: " << targetPlatformVelocityRotation;
304
305 simulatorPrx->setRobotLinearVelocityRobotRootFrame(
306 robotName, platformName, new Vector3(translationVel));
307 simulatorPrx->setRobotAngularVelocityRobotRootFrame(
308 robotName,
310 new Vector3(Eigen::Vector3f(0.f, 0.f, targetPlatformVelocityRotation)));
311}
312
313void
315 float targetPlatformOffsetY,
316 float targetPlatformOffsetRotation,
317 float positionalAccuracy,
319 const Ice::Current& c)
320{
321 float targetPositionX, targetPositionY, targetRotation;
322 {
323 std::unique_lock<std::mutex> lock(currentPoseMutex);
324 platformControlMode = ePositionControl;
325 ARMARX_DEBUG << "Platform move relative" << flush;
326 targetPositionX = currentPosition.x + targetPlatformOffsetX;
327 targetPositionY = currentPosition.y + targetPlatformOffsetY;
328 targetRotation = currentRotation + targetPlatformOffsetRotation;
329 }
330 moveTo(targetPositionX,
331 targetPositionY,
335}
336
337void
339 float angularVelocity,
340 const Ice::Current& c)
341{
342 linearVelocityMax = linearVelocity;
343 angularVelocityMax = angularVelocity;
344}
345
346void
348{
349 ARMARX_DEBUG << "Update new platform pose" << flush;
350
351 if (!newPose)
352 {
353 return;
354 }
355
356 Vector3Ptr newPosition = Vector3Ptr::dynamicCast(newPose->position);
357
358 if (newPosition)
359 {
360 currentPosition = Vector3(newPosition->toEigen());
361 }
362
363 QuaternionPtr newOrientation = QuaternionPtr::dynamicCast(newPose->orientation);
364
365 if (newOrientation)
366 {
367 //axis is assumed to be z (fixed)
368 Eigen::Matrix3f rotMat = newOrientation->toEigen();
369 currentRotation = copysign(std::acos(rotMat(0, 0)), std::asin(rotMat(1, 0)));
370 //for some really odd reason, currentRotation can be nan when it should be 0
372
374 }
375}
376
377void
378PlatformUnitDynamicSimulation::updateCurrentVelocity(const Vector3BasePtr& translationVel,
379 const Vector3BasePtr& rotationVel)
380{
381 ARMARX_DEBUG << "Update new platform vel" << flush;
382
383 if (translationVel)
384 {
385 currentVelocity = *Vector3Ptr::dynamicCast(translationVel);
386 ARMARX_DEBUG << "currentVelocity: " << currentVelocity.x << "," << currentVelocity.y << ","
387 << currentVelocity.z;
388 }
389 if (rotationVel)
390 {
391 ARMARX_DEBUG << "currentRotationVelocity (only z is used): " << rotationVel->x << ","
392 << rotationVel->x << "," << rotationVel->z;
393 currentRotationVelocity = rotationVel->z;
394 }
395}
396
397void
398PlatformUnitDynamicSimulation::reportState(SimulatedRobotState const& state, const Ice::Current&)
399{
400 std::unique_lock<std::mutex> lock(currentPoseMutex);
401
402 // Pose
403 updateCurrentPose(state.pose);
404
405 ::armarx::TransformStamped transformStamped;
406
407 FrameHeader header;
408 header.parentFrame = GlobalFrame;
409 header.frame = "root";
410 header.agent = robotName;
411 header.timestampInMicroSeconds = state.timestampInMicroSeconds;
412
413 TransformStamped globalRobotPose;
414 globalRobotPose.header = header;
415 globalRobotPose.transform = armarx::fromIce(state.pose);
416
417 globalPosePrx->reportGlobalRobotPose(globalRobotPose);
418
419 // Velocity
420 updateCurrentVelocity(state.linearVelocity, state.angularVelocity);
421
422 if (platformControlMode != ePositionControl)
423 {
424 // The currentVelocity is in the global frame, we need to report the velocity in the platform local frame
425 Eigen::Vector2f localVelocity =
426 transformToLocalVelocity(currentRotation, currentVelocity.x, currentVelocity.y);
427 listenerPrx->reportPlatformVelocity(
428 localVelocity.x(), localVelocity.y(), currentRotationVelocity);
429 }
430}
431
434{
436
437 def->defineOptionalProperty<int>(
438 "IntervalMs", 100, "The time in milliseconds between two calls to the simulation method.");
439
440 //assures that the platform still gets some amount of velocity when near target
441 def->defineOptionalProperty<float>(
442 "LinearVelocityMin", 0.5, "Minimum Linear velocity of the platform (unit: m/sec).");
443 def->defineOptionalProperty<float>(
444 "LinearVelocityMax", 1.5, "Maximum Linear velocity of the platform (unit: m/sec).");
445 def->defineOptionalProperty<float>(
446 "LinearAccelerationMax", 0.9, "Maximum Linear Acceleration (unit: m/sec^2");
447 def->defineOptionalProperty<float>(
448 "AngularVelocityMax", 0.8, "Maximum Angular velocity of the platform (unit: rad/sec).");
449 def->defineOptionalProperty<float>(
450 "AngularAccelerationMax", 1.9, "Maximum Angular Acceleration (unit: rad/sec^2");
451 def->defineOptionalProperty<float>(
452 "PlatformOrientationOffset", 0, "Rotation offset of the platform (unit: rad).");
453 def->defineOptionalProperty<std::string>("RobotName", "Armar3", "Name of the Robot to use.");
454 def->defineOptionalProperty<std::string>(
455 "PlatformName", "Platform", "Name of the Platform node to use.");
456 def->defineOptionalProperty<std::string>(
457 "SimulatorProxyName", "Simulator", "Name of the simulator proxy to use.");
458
459 return def;
460}
461
462std::string
464{
465 return "PlatformUnitDynamicSimulation";
466}
467
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define M_PI
Definition MathTools.h:17
constexpr T c
Property< PropertyType > getProperty(const std::string &name)
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
The periodic task executes one thread method repeatedly using the time period specified in the constr...
This unit connects to the physics simulator topic (default: "Simulator") and handles platform movemen...
void setMaxVelocities(float linearVelocity, float angularVelocity, const Ice::Current &c=Ice::emptyCurrent) override
float clampf(float x, float min, float max)
void moveTo(Ice::Float targetPlatformPositionX, Ice::Float targetPlatformPositionY, Ice::Float targetPlatformRotation, Ice::Float positionalAccuracy, Ice::Float orientationalAccuracy, const Ice::Current &c=Ice::emptyCurrent) override
PeriodicTask< PlatformUnitDynamicSimulation >::pointer_type simulationTask
void stopPlatform(const Ice::Current &current) override
Eigen::Vector3f calculateLinearVelocity(Eigen::Vector3f distance, Eigen::Vector3f curV)
void reportState(SimulatedRobotState const &state, const Ice::Current &) override
void updateCurrentVelocity(const Vector3BasePtr &translationVel, const Vector3BasePtr &rotationVel)
PropertyDefinitionsPtr createPropertyDefinitions() override
float calculateAngularVelocity(float source, float target, float curV)
void move(float targetPlatformVelocityX, float targetPlatformVelocityY, float targetPlatformVelocityRotation, const Ice::Current &c=Ice::emptyCurrent) override
void moveRelative(float targetPlatformOffsetX, float targetPlatformOffsetY, float targetPlatformOffsetRotation, float positionalAccuracy, float orientationalAccuracy, const Ice::Current &c=Ice::emptyCurrent) override
PlatformUnitListenerPrx listenerPrx
PlatformUnitListener proxy for publishing state updates.
GlobalRobotPoseLocalizationListenerPrx globalPosePrx
PropertyDefinitionsPtr createPropertyDefinitions() override
The Vector3 class.
Definition Pose.h:113
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Vector3 > Vector3Ptr
Definition Pose.h:165
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
IceInternal::Handle< Quaternion > QuaternionPtr
Definition Pose.h:234
const LogSender::manipulator flush
Definition LogSender.h:251
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
bool isfinite(const std::vector< T, Ts... > &v)
Definition algorithm.h:366
double norm(const Point &a)
Definition point.hpp:102
double distance(const Point &a, const Point &b)
Definition point.hpp:95