27 #include "../../util/CollisionCheckUtil.h"
29 #include <MotionPlanning/CSpace/CSpaceSampled.h>
30 #include <VirtualRobot/RobotNodeSet.h>
34 const std::string& taskName,
35 Ice::Long maxTimeForPostprocessingInSeconds,
40 MotionPlanningTaskBase(taskName),
41 PostprocessingMotionPlanningTaskBase(taskName, previousStep),
43 TaskBase(taskName, previousStep, dcdStep, maxTries, maxTimeForPostprocessingInSeconds, minShortcutImprovementRatio, minPathImprovementRatio)
45 if (! this->previousStep)
47 throw std::invalid_argument {
"previousStep is NULL"};
49 if (this->dcdStep <= 0)
51 throw std::invalid_argument {
"dcdStep <= 0"};
53 if (this->maxTimeForPostprocessingInSeconds <= 0)
55 throw std::invalid_argument {
"maxTimeForPostprocessingInSeconds <= 0"};
57 if (this->minShortcutImprovementRatio >= 1)
59 throw std::invalid_argument {
"minShortcutImprovementRatio >=1"};
61 if (this->minShortcutImprovementRatio < 0.01)
63 ARMARX_VERBOSE_S <<
"Changed minShortcutImprovementRatio from " << this->minShortcutImprovementRatio <<
" to " << 0.01;
64 this->minShortcutImprovementRatio = 0.01;
66 if (this->minPathImprovementRatio >= 1)
68 throw std::invalid_argument {
"minPathImprovementRatio >=1"};
70 if (this->minPathImprovementRatio < 0.001)
72 ARMARX_VERBOSE_S <<
"Changed minShortcutImprovementRatio from " << this->minShortcutImprovementRatio <<
" to " << 0.001;
73 this->minPathImprovementRatio = 0.001;
79 if (!previousStep->finishedRunning())
81 previousStep->abortTask();
86 void Task::run(
const RemoteObjectNodePrxList& nodes,
const Ice::Current&)
88 auto previousStep = MotionPlanningTaskPtr::dynamicCast(this->previousStep);
90 previousStep->addTaskStatusCallback(
91 [
this](TaskStatus::Status
s)
93 if (
s != TaskStatus::eDone)
100 previousStep->run(nodes);
101 endTime =
std::min(endTime, std::chrono::high_resolution_clock::now() + std::chrono::seconds {maxTimeForPostprocessingInSeconds});
103 std::lock_guard<std::mutex> lock {
mtx};
105 auto p = previousStep->getPath();
106 paths.emplace_back(p.nodes, 0,
"smooth_" + p.pathName);
107 paths.emplace_back(std::move(p.nodes), 0, std::move(p.pathName));
113 std::vector<float> lengths;
114 auto updateLengths = [&,
this]()
117 lengths.reserve(
paths.front().nodes.size() + 1);
118 lengths.emplace_back(0);
119 for (std::size_t i = 0; i + 1 <
paths.front().nodes.size(); ++i)
121 auto& from =
paths.front().nodes.at(i);
122 auto& to =
paths.front().nodes.at(i + 1);
123 lengths.emplace_back(lengths.back() +
euclideanDistance(from.begin(), from.end(), to.begin()));
128 paths.at(0).cost = lengths.back();
129 paths.at(1).cost = lengths.back();
139 if (
paths.front().nodes.size() == 2)
148 std::mt19937 gen {std::random_device{}()};
150 for (; iteration < maxTries;)
161 if (endTime <= std::chrono::high_resolution_clock::now())
166 auto segmentOffsets =
calcOffsets(lengths.back(), gen);
167 float segmentLength = segmentOffsets.second - segmentOffsets.first;
169 VectorXf from(
getCSpace()->getDimensionality());
170 VectorXf to(
getCSpace()->getDimensionality());
173 std::size_t takeLastOPTE = 0;
175 std::size_t takeAgainFirstIdx = 0;
182 for (; i < lengths.size() && segmentOffsets.first > lengths.at(i); ++i);
184 if (takeLastOPTE + 1 == lengths.size())
190 if (takeLastOPTE == 0)
194 from =
paths.front().nodes.at(0);
199 const auto fromSubSegLen = lengths.at(takeLastOPTE) - lengths.at(takeLastOPTE - 1);
200 const auto fromSubSegLenPart = segmentOffsets.first - lengths.at(takeLastOPTE - 1);
201 if (fromSubSegLenPart < 1e-5)
205 from =
paths.front().nodes.at(takeLastOPTE - 1);
210 const auto fromSubSegLenRatio = fromSubSegLenPart / fromSubSegLen;
216 paths.front().nodes.at(takeLastOPTE - 1).begin(),
217 paths.front().nodes.at(takeLastOPTE - 1).end(),
218 paths.front().nodes.at(takeLastOPTE).begin(),
220 [fromSubSegLenRatio](
float from,
float to)
222 return (1.f - fromSubSegLenRatio) * from + fromSubSegLenRatio * to;
228 for (; i < lengths.size() && segmentOffsets.second > lengths.at(i); ++i);
229 takeAgainFirstIdx = i;
231 if (takeAgainFirstIdx >= lengths.size())
234 takeAgainFirstIdx =
paths.front().nodes.size();
235 to =
paths.front().nodes.back();
241 const auto toSubSegLen = lengths.at(takeAgainFirstIdx) - lengths.at(takeAgainFirstIdx - 1);
242 const auto toSubSegLenPart = segmentOffsets.second - lengths.at(takeAgainFirstIdx - 1);
243 if (lengths.at(takeAgainFirstIdx) - toSubSegLenPart < 1e-5)
246 to =
paths.front().nodes.at(takeAgainFirstIdx);
251 const auto toSubSegLenRatio = toSubSegLenPart / toSubSegLen;
256 paths.front().nodes.at(takeAgainFirstIdx - 1).begin(),
257 paths.front().nodes.at(takeAgainFirstIdx - 1).end(),
258 paths.front().nodes.at(takeAgainFirstIdx).begin(),
260 [toSubSegLenRatio](
float from,
float to)
262 return (1.f - toSubSegLenRatio) * from + toSubSegLenRatio * to;
268 if (takeLastOPTE == takeAgainFirstIdx)
272 float segmentShortcutLength =
euclideanDistance(from.begin(), from.end(), to.begin());
274 if (segmentShortcutLength > segmentLength * (1.f - minShortcutImprovementRatio))
287 VectorXfSeq newPostprocessedSolution;
288 newPostprocessedSolution.reserve(
paths.front().nodes.size() + 1);
289 std::copy(
paths.front().nodes.begin(),
paths.front().nodes.begin() + takeLastOPTE, std::back_inserter(newPostprocessedSolution));
290 newPostprocessedSolution.emplace_back(std::move(from));
291 newPostprocessedSolution.emplace_back(std::move(to));
292 std::copy(
paths.front().nodes.begin() + takeAgainFirstIdx,
paths.front().nodes.end(), std::back_inserter(newPostprocessedSolution));
295 std::lock_guard<std::mutex> lock {
mtx};
296 paths.front().nodes = std::move(newPostprocessedSolution);
307 std::lock_guard<std::mutex> lock {
mtx};
318 std::lock_guard<std::mutex> lock {
mtx};
324 std::lock_guard<std::mutex> lock {
mtx};
336 CSpaceAdaptorBasePtr simoxcspaceadapter = CSpaceAdaptorBasePtr::dynamicCast(
getCSpace());
337 if (simoxcspaceadapter)
339 simoxcspace = SimoxCSpacePtr::dynamicCast(simoxcspaceadapter->getOriginalCSpace());
345 VirtualRobot::RobotNodeSetPtr rns = VirtualRobot::RobotNodeSet::createRobotNodeSet(simoxcspace->getAgentSceneObj(),
"tmp",
346 simoxcspace->getAgentJointNames());
347 Saba::CSpaceSampled tmpCSpace(simoxcspace->getAgentSceneObj(), VirtualRobot::CDManagerPtr(
new VirtualRobot::CDManager(simoxcspace->getCD())), rns);
348 auto distance = [&,
this](Eigen::VectorXf
const & from, Eigen::VectorXf
const & to)
350 return tmpCSpace.calcDist(from, to);
353 auto interpolation = [&,
this](Eigen::VectorXf
const & from, Eigen::VectorXf
const & to,
float step)
355 return tmpCSpace.interpolate(from, to, step);
359 [
this](
const VectorXf & cfg)
361 return getCSpace()->isCollisionFree({cfg.data(), cfg.data() + cfg.size()});
364 std::optional<decltype(distance)>(
distance),
365 std::optional<decltype(interpolation)>(interpolation)
372 [
this](
const VectorXf & cfg)
374 return getCSpace()->isCollisionFree({cfg.data(), cfg.data() + cfg.size()});
385 const auto a = distA(gen);
386 const auto minDelta = minPathImprovementRatio * length;
388 const auto bSample = distB(gen);
389 const auto b = (bSample <= (
a - minDelta)) ? bSample : bSample + 2 * minDelta;
391 return std::minmax(
a, b);