PlatformUnitSimulation.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2012-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 ArmarXCore::units
19 * @author Christian Boege (boege at kit dot edu)
20 * @date 2011
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
27
28#include <cmath>
29
30#include <Eigen/Geometry>
31
32#include <VirtualRobot/MathTools.h>
33
35
37#include <RobotAPI/interface/core/GeometryBase.h>
38#include <RobotAPI/interface/units/PlatformUnitInterface.h>
40
41namespace armarx
42{
45 {
47
48 def->defineOptionalProperty<int>(
49 "IntervalMs",
50 10,
51 "The time in milliseconds between two calls to the simulation method.");
52 def->defineOptionalProperty<float>(
53 "InitialRotation", 0, "Initial rotation of the platform.");
54 def->defineOptionalProperty<float>(
55 "InitialPosition.x", 0, "Initial x position of the platform.");
56 def->defineOptionalProperty<float>(
57 "InitialPosition.y", 0, "Initial y position of the platform.");
58 def->defineOptionalProperty<std::string>(
59 "ReferenceFrame",
60 "Platform",
61 "Reference frame in which the platform position is reported.");
62 def->defineOptionalProperty<float>(
63 "LinearVelocity", 1000.0, "Linear velocity of the platform (default: 1000 mm/sec).");
64 def->defineOptionalProperty<float>(
65 "MaxLinearAcceleration",
66 1000.0,
67 "Linear acceleration of the platform (default: 1000 mm/sec).");
68 def->defineOptionalProperty<float>(
69 "Kp_Position", 5.0, "P value of the PID position controller");
70 def->defineOptionalProperty<float>(
71 "Kp_Velocity", 5.0, "P value of the PID velocity controller");
72 def->defineOptionalProperty<float>(
73 "AngularVelocity", 1.5, "Angular velocity of the platform (default: 1.5 rad/sec).");
74
75 def->component(robotStateComponent);
76
77 return def;
78 }
79
80 void
82 {
84 referenceFrame = getProperty<std::string>("ReferenceFrame").getValue();
85 targetPositionX = currentPositionX = getProperty<float>("InitialPosition.x").getValue();
86 targetPositionY = currentPositionY = getProperty<float>("InitialPosition.y").getValue();
87 targetRotation = 0.0;
88 targetRotation = currentRotation = getProperty<float>("InitialRotation").getValue();
89
90 maxLinearVelocity = getProperty<float>("LinearVelocity").getValue();
91 maxAngularVelocity = getProperty<float>("AngularVelocity").getValue();
92
93 velPID.reset(
94 new MultiDimPIDController(getProperty<float>("Kp_Velocity").getValue(),
95 0,
96 0,
97 getProperty<float>("MaxLinearAcceleration").getValue()));
98 posPID.reset(
99 new MultiDimPIDController(getProperty<float>("Kp_Position").getValue(),
100 0,
101 0,
103 getProperty<float>("MaxLinearAcceleration").getValue()));
104
105
106 positionalAccuracy = 0.01;
107
108 intervalMs = getProperty<int>("IntervalMs").getValue();
109 ARMARX_VERBOSE << "Starting platform unit simulation with " << intervalMs << " ms interval";
114 false,
115 "PlatformUnitSimulation");
116 }
117
118 Eigen::Matrix4f
119 PlatformUnitSimulation::currentPlatformPose() const
120 {
121 return VirtualRobot::MathTools::posrpy2eigen4f(
123 }
124
125 void
127 {
128 agentName = robotStateComponent->getRobotName();
129 robotRootFrame = robotStateComponent->getSynchronizedRobot()->getRootNode()->getName();
130
131 TransformStamped currentPose;
132 currentPose.header.parentFrame = GlobalFrame;
133 currentPose.header.frame = robotRootFrame;
134 currentPose.header.agent = agentName;
135 currentPose.header.timestampInMicroSeconds = TimeUtil::GetTime().toMicroSeconds();
136 currentPose.transform = currentPlatformPose();
137
138 globalPosePrx->reportGlobalRobotPose(currentPose);
139
140 simulationTask->start();
141 }
142
143 void
145 {
146 if (simulationTask)
147 {
148 simulationTask->stop();
149 }
150 }
151
152 void
154 {
155 if (simulationTask)
156 {
157 simulationTask->stop();
158 }
159 }
160
161 void
163 {
164 // the time it took until this method was called again
165 auto now = TimeUtil::GetTime();
166 double timeDeltaInSeconds = (now - lastExecutionTime).toSecondsDouble();
167 lastExecutionTime = now;
168 std::vector<float> vel(3, 0.0f);
169 {
170 std::unique_lock lock(currentPoseMutex);
171 switch (platformMode)
172 {
173 case ePositionControl:
174 {
175 posPID->update(timeDeltaInSeconds,
176 Eigen::Vector2f(currentPositionX, currentPositionY),
177 Eigen::Vector2f(targetPositionX, targetPositionY));
178 float newXTickMotion = posPID->getControlValue()[0] * timeDeltaInSeconds;
179 currentPositionX += newXTickMotion;
180 currentPositionY += posPID->getControlValue()[1] * timeDeltaInSeconds;
181 vel[0] = posPID->getControlValue()[0];
182 vel[1] = posPID->getControlValue()[1];
183
184 float diff = fabs(targetRotation - currentRotation);
185
186 if (diff > orientationalAccuracy)
187 {
188 int sign = copysignf(1.0f, (targetRotation - currentRotation));
190 sign * std::min<float>(maxAngularVelocity * timeDeltaInSeconds, diff);
191
192 // stay between +/- M_2_PI
193 if (currentRotation > 2 * M_PI)
194 {
195 currentRotation -= 2 * M_PI;
196 }
197
198 if (currentRotation < -2 * M_PI)
199 {
200 currentRotation += 2 * M_PI;
201 }
202
203 vel[2] = angularVelocity;
204 }
205 }
206 break;
207 case eVelocityControl:
208 {
209 Eigen::Vector2f targetVel(linearVelocityX, linearVelocityY);
210 Eigen::Rotation2Df rot(currentRotation);
211 targetVel = rot * targetVel;
212 velPID->update(timeDeltaInSeconds, currentTranslationVelocity, targetVel);
213 currentTranslationVelocity = timeDeltaInSeconds * velPID->getControlValue();
214 currentPositionX += timeDeltaInSeconds * currentTranslationVelocity[0];
215 currentPositionY += timeDeltaInSeconds * currentTranslationVelocity[1];
216
217
218 currentRotation += angularVelocity * timeDeltaInSeconds;
219
220 // stay between +/- M_2_PI
221 if (currentRotation > 2 * M_PI)
222 {
223 currentRotation -= 2 * M_PI;
224 }
225
226 if (currentRotation < -2 * M_PI)
227 {
228 currentRotation += 2 * M_PI;
229 }
230 vel[0] = currentTranslationVelocity[0];
231 vel[1] = currentTranslationVelocity[1];
232 vel[2] = angularVelocity;
233 }
234 break;
235 default:
236 break;
237 }
238 }
239
240 // odom velocity is in local robot frame
241 FrameHeader odomVelocityHeader;
242 odomVelocityHeader.parentFrame = robotRootFrame;
243 odomVelocityHeader.frame = robotRootFrame;
244 odomVelocityHeader.agent = agentName;
245 odomVelocityHeader.timestampInMicroSeconds = TimeUtil::GetTime().toMicroSeconds();
246 ;
247
248 // odom pose is in odom frame
249 FrameHeader odomPoseHeader;
250 odomPoseHeader.parentFrame = OdometryFrame;
251 odomPoseHeader.frame = robotRootFrame;
252 odomPoseHeader.agent = agentName;
253 odomPoseHeader.timestampInMicroSeconds = TimeUtil::GetTime().toMicroSeconds();
254 ;
255
256 TransformStamped platformPose;
257 platformPose.header = odomPoseHeader;
258 platformPose.transform = currentPlatformPose();
259
260 TwistStamped platformVelocity;
261 platformVelocity.header = odomVelocityHeader;
262 platformVelocity.twist.linear << vel[0], vel[1], 0;
263 platformVelocity.twist.angular << 0, 0, vel[2];
264
265 odometryPrx->reportOdometryPose(platformPose);
266 odometryPrx->reportOdometryVelocity(platformVelocity);
267
268 {
269 TransformStamped currentPose;
270 currentPose.header.parentFrame = GlobalFrame;
271 currentPose.header.frame = robotRootFrame;
272 currentPose.header.agent = agentName;
273 currentPose.header.timestampInMicroSeconds = TimeUtil::GetTime().toMicroSeconds();
274 currentPose.transform = currentPlatformPose();
275
276 globalPosePrx->reportGlobalRobotPose(currentPose);
277 }
278
279
280 // legacy
281 const auto& velo = platformVelocity.twist;
282 listenerPrx->reportPlatformVelocity(velo.linear.x(), velo.linear.y(), velo.angular.z());
283 }
284
285 void
286 PlatformUnitSimulation::moveTo(Ice::Float targetPlatformPositionX,
287 Ice::Float targetPlatformPositionY,
288 Ice::Float targetPlatformRotation,
289 Ice::Float positionalAccuracy,
290 Ice::Float orientationalAccuracy,
291 const Ice::Current& c)
292 {
293 ARMARX_INFO << "new target pose : " << targetPlatformPositionX << ", "
294 << targetPlatformPositionY << " with angle " << targetPlatformRotation;
295 {
296 std::unique_lock lock(currentPoseMutex);
298 targetPositionX = targetPlatformPositionX;
299 targetPositionY = targetPlatformPositionY;
300 targetRotation = targetPlatformRotation;
301 this->positionalAccuracy = positionalAccuracy;
302 this->orientationalAccuracy = orientationalAccuracy;
303 }
304
305 FrameHeader header;
306 header.timestampInMicroSeconds = TimeUtil::GetTime().toMicroSeconds();
307 header.parentFrame = GlobalFrame;
308 header.frame = robotRootFrame;
309 header.agent = agentName;
310
311 TransformStamped targetPose;
312 targetPose.header = header;
313 targetPose.transform = VirtualRobot::MathTools::posrpy2eigen4f(
315 }
316
317 void
318 armarx::PlatformUnitSimulation::move(float targetPlatformVelocityX,
319 float targetPlatformVelocityY,
320 float targetPlatformVelocityRotation,
321 const Ice::Current& c)
322 {
323 ARMARX_INFO << deactivateSpam(1) << "New velocity: " << targetPlatformVelocityX << ", "
324 << targetPlatformVelocityY
325 << " with angular velocity: " << targetPlatformVelocityRotation;
326 std::unique_lock lock(currentPoseMutex);
328 linearVelocityX = std::min(maxLinearVelocity, targetPlatformVelocityX);
329 linearVelocityY = std::min(maxLinearVelocity, targetPlatformVelocityY);
330 angularVelocity = std::min(maxAngularVelocity, targetPlatformVelocityRotation);
331 }
332
333 void
334 PlatformUnitSimulation::moveRelative(float targetPlatformOffsetX,
335 float targetPlatformOffsetY,
336 float targetPlatformOffsetRotation,
337 float positionalAccuracy,
339 const Ice::Current& c)
340 {
342 {
343 std::unique_lock lock(currentPoseMutex);
344 targetPositionX = currentPositionX + targetPlatformOffsetX;
345 targetPositionY = currentPositionY + targetPlatformOffsetY;
346 targetRotation = currentRotation + targetPlatformOffsetRotation;
347 }
353 }
354
355 void
357 float orientaionalVelocity,
358 const Ice::Current& c)
359 {
360 std::unique_lock lock(currentPoseMutex);
361 maxLinearVelocity = positionalVelocity;
362 maxAngularVelocity = orientaionalVelocity;
363 }
364
365 void
367 {
368 move(0, 0, 0);
369 }
370} // namespace armarx
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)
The periodic task executes one thread method repeatedly using the time period specified in the constr...
void setMaxVelocities(float positionalVelocity, float orientaionalVelocity, const Ice::Current &c=Ice::emptyCurrent) override
void moveTo(Ice::Float targetPlatformPositionX, Ice::Float targetPlatformPositionY, Ice::Float targetPlatformRotation, Ice::Float positionalAccuracy, Ice::Float orientationalAccuracy, const Ice::Current &c=Ice::emptyCurrent) override
enum armarx::PlatformUnitSimulation::PlatformMode platformMode
PropertyDefinitionsPtr createPropertyDefinitions() override
void move(float targetPlatformVelocityX, float targetPlatformVelocityY, float targetPlatformVelocityRotation, const Ice::Current &c=Ice::emptyCurrent) override
void stopPlatform(const Ice::Current &c=Ice::emptyCurrent) override
PeriodicTask< PlatformUnitSimulation >::pointer_type simulationTask
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.
OdometryListenerPrx odometryPrx
GlobalRobotPoseLocalizationListenerPrx globalPosePrx
PropertyDefinitionsPtr createPropertyDefinitions() override
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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.
std::string const OdometryFrame
Definition FramedPose.h:66
MultiDimPIDControllerTemplate<> MultiDimPIDController
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
T sign(T t)
Definition algorithm.h:214