PlayPlatformTrajectory.cpp
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 RobotSkillTemplates::PlatformGroup
17  * @author Stefan Reither ( stef dot reither at web dot de )
18  * @date 2017
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "PlayPlatformTrajectory.h"
24 
29 
30 using namespace armarx;
31 using namespace PlatformGroup;
32 
33 #define STATE_POSITION 0
34 #define STATE_VELOCITY 1
35 
36 #define MAX_TRANSLATION_ACCEL 0.5 // m/s²
37 #define MAX_ROTATION_ACCEL 0.75 // rad/s²
38 
39 #define FACTOR_BETWEEN_TRANS_AND_ROT 500.0
40 
41 // DO NOT EDIT NEXT LINE
42 PlayPlatformTrajectory::SubClassRegistry PlayPlatformTrajectory::Registry(PlayPlatformTrajectory::GetName(), &PlayPlatformTrajectory::CreateInstance);
43 
45 {
46  ARMARX_INFO << t->output();
47  double length = t->getLength(0);
48  ARMARX_INFO << VAROUT(length);
49  double timelength = t->getTimeLength();
50  ARMARX_INFO << VAROUT(timelength);
51  auto timestamps = t->getTimestamps();
52  ARMARX_INFO << VAROUT(timestamps);
53  Ice::DoubleSeq newTimestamps;
54  newTimestamps.push_back(0);
55  for (size_t var = 0; var < timestamps.size() - 1; ++var)
56  {
57  double tBefore = timestamps.at(var);
58  double tAfter = (timestamps.at(var + 1));
59  ARMARX_INFO << VAROUT(tBefore) << VAROUT(tAfter);
60  double partLength = t->getLength(0, tBefore, tAfter);
61  double lengthPortion = partLength / length;
62  ARMARX_INFO << VAROUT(partLength) << VAROUT(lengthPortion);
63  newTimestamps.push_back(*newTimestamps.rbegin() + timelength * lengthPortion);
64  }
65  ARMARX_INFO << VAROUT(newTimestamps);
66  TrajectoryPtr newTraj = new Trajectory();
67  for (size_t d = 0; d < t->dim(); ++d)
68  {
69  newTraj->addDimension(t->getDimensionData(d), newTimestamps, t->getDimensionName(d));
70  }
71  ARMARX_INFO << newTraj->output();
72 
73  return newTraj;
74 }
75 
76 TrajectoryPtr normalizeTimestamps(TrajectoryPtr t, float maxTransVel, float maxRotVel)
77 {
78  double totalTime = 0.0;
79  auto timestamps = t->getTimestamps();
80  auto dimNames = t->getDimensionNames();
81 
82  for (size_t var = 0; var < timestamps.size() - 1; ++var)
83  {
84  double xLength = t->getLength(std::find(dimNames.begin(), dimNames.end(), "x") - dimNames.begin(), 0, timestamps.at(var), timestamps.at(var + 1)) / 1000; // conversion mm to m
85  ARMARX_INFO << VAROUT(xLength);
86  double yLength = t->getLength(std::find(dimNames.begin(), dimNames.end(), "y") - dimNames.begin(), 0, timestamps.at(var), timestamps.at(var + 1)) / 1000; // conversion mm to m
87  ARMARX_INFO << VAROUT(yLength);
88  double alphaLength = t->getLength(std::find(dimNames.begin(), dimNames.end(), "alpha") - dimNames.begin(), 0, timestamps.at(var), timestamps.at(var + 1));
89  ARMARX_INFO << VAROUT(alphaLength);
90 
91  double xyLength = std::sqrt(fabs(xLength * xLength + yLength * yLength));
92  ARMARX_INFO << VAROUT(xyLength);
93 
94  double sAcc = 0.5 * maxTransVel * maxTransVel / MAX_TRANSLATION_ACCEL;
95 
96  double xyTime = 0.0;
97 
98  if (xyLength <= 2 * sAcc)
99  {
100  xyTime = 2 * std::sqrt(xyLength / MAX_TRANSLATION_ACCEL);
101  }
102  else
103  {
104  xyTime = 2 * maxTransVel / MAX_TRANSLATION_ACCEL + (xyLength - 2 * sAcc) / maxTransVel;
105  }
106 
107  ARMARX_INFO << VAROUT(xyTime);
108  double rotTime = 2 * maxRotVel / MAX_ROTATION_ACCEL + (alphaLength - 0.5 * maxRotVel * maxRotVel / MAX_ROTATION_ACCEL) / maxRotVel;
109  ARMARX_INFO << VAROUT(rotTime);
110 
111  double dtime = (xyTime > rotTime) ? xyTime : rotTime;
112  totalTime += dtime;
113  }
114 
115  t = t->normalize(0.0, totalTime);
116  ARMARX_INFO << t->output();
117 
118  return t;
119 }
120 
122 {
123  Ice::DoubleSeq factors = {1.0, 1.0, factor};
124  ARMARX_INFO << VAROUT(factors);
125  t->scaleValue(factors);
126  return t;
127 }
128 
129 
131 {
132  TrajectoryPtr platformTraj = in.getTrajectory();
133  auto dimNames = platformTraj->getDimensionNames();
134  if (dimNames.at(0) != "x" ||
135  dimNames.at(1) != "y" ||
136  dimNames.at(2) != "alpha")
137  {
138  ARMARX_WARNING << "Trajectory misses at least one of the following needed dimensions: 'x', 'y' and 'alpha'.";
139  emitFailure();
140  }
141 }
142 
144 {
145  PlatformContext* c = getContext<PlatformContext>();
146  PlatformUnitInterfacePrx platformUnit = c->platformUnitPrx;
147  TrajectoryPtr platformTraj = in.getTrajectory();
148  auto dimNames = platformTraj->getDimensionNames();
149  float maxTransVel = in.getMaxTranslationVelocity();
150  float maxRotVel = in.getMaxRotationVelocity();
151 
152  if (in.getBalanceTrajectory())
153  {
154  // Scaling rotation dimension of the trajectory to fit to the translation trajectory
155 
156  platformTraj = scaleRotationLengths(platformTraj, FACTOR_BETWEEN_TRANS_AND_ROT);
157 
158  // Balancing timestamps of the trajetory
159 
160  platformTraj = balanceTimestamps(platformTraj);
161 
162  // Rescaling rotation dimension of the trajectory
163 
164  platformTraj = scaleRotationLengths(platformTraj, (float)(1 / FACTOR_BETWEEN_TRANS_AND_ROT));
165 
166  // calculate approximation of duration of the movement given a maximal velocity and a maximal acceleration
167 
168  platformTraj = normalizeTimestamps(platformTraj, maxTransVel, maxRotVel);
169  }
170 
171  // Executing trajectory
172 
173 
174  MultiDimPIDController pidTrans(in.getPTranslation(), in.getITranslation(), in.getDTranslation(), maxTransVel, MAX_TRANSLATION_ACCEL * 1000);
175  PIDController pidRot(in.getPOrientation(), in.getIOrientation(), in.getDOrientation(), maxRotVel, MAX_ROTATION_ACCEL);
176  DatafieldRefPtr posXRef = new DatafieldRef(c->platformUnitObserverPrx, "platformPose", "positionX");
177  DatafieldRefPtr posYRef = new DatafieldRef(c->platformUnitObserverPrx, "platformPose", "positionY");
178  DatafieldRefPtr oriRef = new DatafieldRef(c->platformUnitObserverPrx, "platformPose", "rotation");
179 
180  NameValueMap targetValues;
182  double currentTime = 0.0;
183  bool finalPoseReached = false;
184  int cycleTime = in.getCycleTimeMS();
185  CycleUtil cycle(cycleTime);
186 
187  c->debugDrawer->removeLayer("ActualRobotPath");
188 
189  // Vector3Ptr positionOld;
190 
191  IceUtil::Time cycleStart;
192  while (!isRunningTaskStopped()) // stop run function if returning true
193  {
194  cycleStart = armarx::TimeUtil::GetTime();
195 
196  currentTime = (armarx::TimeUtil::GetTime() - startTime).toSecondsDouble();
197  if (currentTime > platformTraj->getTimeLength())
198  {
199  currentTime = platformTraj->getTimeLength();
200  finalPoseReached = true;
201  }
202 
203  float posx = posXRef->getDataField()->getFloat();
204  float posy = posYRef->getDataField()->getFloat();
205  float ori = oriRef->getDataField()->getFloat();
206 
207  // Vector3Ptr v = new Vector3 {posx, posy, 50.f};
208  // if (positionOld)
209  // {
210  // c->debugDrawer->setLineVisu("ActualRobotPath", boost::lexical_cast<std::string>(currentTime), positionOld, v, 2.0, DrawColor {0, 1, 0, 1});
211  // }
212  // positionOld = v;
213 
214  std::vector<Ice::DoubleSeq> allStates = platformTraj->getAllStates(currentTime, 1);
215  for (size_t i = 0; i < platformTraj->dim(); ++i)
216  {
217  targetValues[dimNames.at(i)] = allStates[i][STATE_POSITION];
218  }
219 
220  Eigen::Vector3f pos {posx, posy, 0.0f};
221  Eigen::Vector3f targetPos {targetValues["x"], targetValues["y"], 0.0f};
222 
223  pidTrans.update(pos, targetPos);
224  pidRot.update(ori, targetValues["alpha"]);
225  float newRotVel = pidRot.getControlValue();
226  Eigen::Vector3f globalNewTransVel = {pidTrans.getControlValue()[0], pidTrans.getControlValue()[1], 0};
227  Eigen::Matrix3f m;
228  m = Eigen::AngleAxisf(ori, Eigen::Vector3f::UnitZ());
229  Eigen::Vector3f localVel = m.inverse() * globalNewTransVel;
230 
231 
232  ARMARX_INFO << "New values: x: " << localVel[0] << " , y= " << localVel[1] << " , alpha= " << newRotVel;
233 
234  platformUnit->move(localVel[0],
235  localVel[1],
236  newRotVel);
237 
238  if (finalPoseReached && fabs(pidTrans.previousError) < in.getPositionalAccuracy() && fabs(pidRot.previousError) < in.getOrientationalAccuracy())
239  {
240  disableRunFunction();
241  platformUnit->move(0, 0, 0);
242  ARMARX_INFO << "Success";
243  emitSuccess();
244  }
245  else
246  {
247  cycle.waitForCycleDuration();
248  }
249  }
250 }
251 
253 {
254  // Setting velocities to zero
255  PlatformContext* c = getContext<PlatformContext>();
256  PlatformUnitInterfacePrx platformUnit = c->platformUnitPrx;
257  platformUnit->move(0.0, 0.0, 0.0);
258 }
259 
260 
261 // DO NOT EDIT NEXT FUNCTION
263 {
264  return XMLStateFactoryBasePtr(new PlayPlatformTrajectory(stateData));
265 }
266 
armarx::PlatformGroup::PlayPlatformTrajectory::onEnter
void onEnter() override
Definition: PlayPlatformTrajectory.cpp:130
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:662
MAX_TRANSLATION_ACCEL
#define MAX_TRANSLATION_ACCEL
Definition: PlayPlatformTrajectory.cpp:36
armarx::MultiDimPIDControllerTemplate::update
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:75
armarx::MultiDimPIDControllerTemplate<>
armarx::XMLStateConstructorParams
Definition: XMLState.h:50
armarx::PlatformGroup::PlayPlatformTrajectory::run
void run() override
Definition: PlayPlatformTrajectory.cpp:143
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::PIDController::getControlValue
double getControlValue() const
Definition: PIDController.cpp:273
armarx::PIDController::update
void update(double deltaSec, double measuredValue, double targetValue)
Definition: PIDController.cpp:211
PlayPlatformTrajectory.h
armarx::MultiDimPIDControllerTemplate::previousError
double previousError
Definition: MultiDimPIDController.h:215
scaleRotationLengths
TrajectoryPtr scaleRotationLengths(TrajectoryPtr t, float factor)
Definition: PlayPlatformTrajectory.cpp:121
IceInternal::Handle< Trajectory >
DatafieldRef.h
normalizeTimestamps
TrajectoryPtr normalizeTimestamps(TrajectoryPtr t, float maxTransVel, float maxRotVel)
Definition: PlayPlatformTrajectory.cpp:76
armarx::PIDController
Definition: PIDController.h:43
balanceTimestamps
TrajectoryPtr balanceTimestamps(TrajectoryPtr t)
Definition: PlayPlatformTrajectory.cpp:44
armarx::PlatformGroup::PlayPlatformTrajectory::PlayPlatformTrajectory
PlayPlatformTrajectory(const XMLStateConstructorParams &stateData)
Definition: PlayPlatformTrajectory.h:34
armarx::CycleUtil::waitForCycleDuration
IceUtil::Time waitForCycleDuration()
This function will wait (virtual or system time) until the cycle time is reached.
Definition: CycleUtil.cpp:53
armarx::PIDController::previousError
double previousError
Definition: PIDController.h:73
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::VariantType::Trajectory
const VariantTypeId Trajectory
Definition: Trajectory.h:44
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
armarx::VariantType::DatafieldRef
const VariantTypeId DatafieldRef
Definition: DatafieldRef.h:169
CycleUtil.h
PIDController.h
armarx::XMLStateFactoryBasePtr
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition: XMLState.h:65
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:91
PlatformContext.h
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::MultiDimPIDControllerTemplate::getControlValue
const PIDVectorX & getControlValue() const
Definition: MultiDimPIDController.h:186
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::PlatformContext
Definition: PlatformContext.h:64
MAX_ROTATION_ACCEL
#define MAX_ROTATION_ACCEL
Definition: PlayPlatformTrajectory.cpp:37
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
FACTOR_BETWEEN_TRANS_AND_ROT
#define FACTOR_BETWEEN_TRANS_AND_ROT
Definition: PlayPlatformTrajectory.cpp:39
armarx::PlatformGroup::PlayPlatformTrajectory::CreateInstance
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
Definition: PlayPlatformTrajectory.cpp:262
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::PlatformGroup::PlayPlatformTrajectory::onExit
void onExit() override
Definition: PlayPlatformTrajectory.cpp:252
armarx::PlatformGroup::PlayPlatformTrajectory::Registry
static SubClassRegistry Registry
Definition: PlayPlatformTrajectory.h:47
STATE_POSITION
#define STATE_POSITION
Definition: PlayPlatformTrajectory.cpp:33