29 #include <VirtualRobot/RobotNodeSet.h>
33 #include "../../util/CollisionCheckUtil.h"
34 #include <MotionPlanning/CSpace/CSpaceSampled.h>
39 const std::string& taskName,
40 Ice::Long maxTimeForPostprocessingInSeconds,
45 MotionPlanningTaskBase(taskName),
46 PostprocessingMotionPlanningTaskBase(taskName, previousStep),
52 maxTimeForPostprocessingInSeconds,
53 minShortcutImprovementRatio,
54 minPathImprovementRatio)
56 if (!this->previousStep)
58 throw std::invalid_argument{
"previousStep is NULL"};
60 if (this->dcdStep <= 0)
62 throw std::invalid_argument{
"dcdStep <= 0"};
64 if (this->maxTimeForPostprocessingInSeconds <= 0)
66 throw std::invalid_argument{
"maxTimeForPostprocessingInSeconds <= 0"};
68 if (this->minShortcutImprovementRatio >= 1)
70 throw std::invalid_argument{
"minShortcutImprovementRatio >=1"};
72 if (this->minShortcutImprovementRatio < 0.01)
75 << this->minShortcutImprovementRatio <<
" to " << 0.01;
76 this->minShortcutImprovementRatio = 0.01;
78 if (this->minPathImprovementRatio >= 1)
80 throw std::invalid_argument{
"minPathImprovementRatio >=1"};
82 if (this->minPathImprovementRatio < 0.001)
85 << this->minShortcutImprovementRatio <<
" to " << 0.001;
86 this->minPathImprovementRatio = 0.001;
93 if (!previousStep->finishedRunning())
95 previousStep->abortTask();
101 Task::run(
const RemoteObjectNodePrxList& nodes,
const Ice::Current&)
103 auto previousStep = MotionPlanningTaskPtr::dynamicCast(this->previousStep);
105 previousStep->addTaskStatusCallback(
106 [
this](TaskStatus::Status
s)
108 if (
s != TaskStatus::eDone)
113 auto endTime = std::chrono::high_resolution_clock::now() +
115 previousStep->run(nodes);
117 std::chrono::high_resolution_clock::now() +
118 std::chrono::seconds{maxTimeForPostprocessingInSeconds});
120 std::lock_guard<std::mutex> lock{
mtx};
122 auto p = previousStep->getPath();
123 paths.emplace_back(p.nodes, 0,
"smooth_" + p.pathName);
124 paths.emplace_back(std::move(p.nodes), 0, std::move(p.pathName));
130 std::vector<float> lengths;
131 auto updateLengths = [&,
this]()
134 lengths.reserve(
paths.front().nodes.size() + 1);
135 lengths.emplace_back(0);
136 for (std::size_t i = 0; i + 1 <
paths.front().nodes.size(); ++i)
138 auto& from =
paths.front().nodes.at(i);
139 auto& to =
paths.front().nodes.at(i + 1);
140 lengths.emplace_back(lengths.back() +
146 paths.at(0).cost = lengths.back();
147 paths.at(1).cost = lengths.back();
157 if (
paths.front().nodes.size() == 2)
166 std::mt19937 gen{std::random_device{}()};
168 for (; iteration < maxTries;)
179 if (endTime <= std::chrono::high_resolution_clock::now())
184 auto segmentOffsets =
calcOffsets(lengths.back(), gen);
185 float segmentLength = segmentOffsets.second - segmentOffsets.first;
187 VectorXf from(
getCSpace()->getDimensionality());
188 VectorXf to(
getCSpace()->getDimensionality());
191 std::size_t takeLastOPTE = 0;
193 std::size_t takeAgainFirstIdx = 0;
200 for (; i < lengths.size() && segmentOffsets.first > lengths.at(i); ++i)
203 if (takeLastOPTE + 1 == lengths.size())
209 if (takeLastOPTE == 0)
213 from =
paths.front().nodes.at(0);
218 const auto fromSubSegLen =
219 lengths.at(takeLastOPTE) - lengths.at(takeLastOPTE - 1);
220 const auto fromSubSegLenPart =
221 segmentOffsets.first - lengths.at(takeLastOPTE - 1);
222 if (fromSubSegLenPart < 1e-5)
226 from =
paths.front().nodes.at(takeLastOPTE - 1);
231 const auto fromSubSegLenRatio = fromSubSegLenPart / fromSubSegLen;
234 paths.front().nodes.at(takeLastOPTE - 1).size());
236 paths.front().nodes.at(takeLastOPTE).size());
239 paths.front().nodes.at(takeLastOPTE - 1).end(),
240 paths.front().nodes.at(takeLastOPTE).begin(),
242 [fromSubSegLenRatio](
float from,
float to) {
243 return (1.f - fromSubSegLenRatio) * from +
244 fromSubSegLenRatio * to;
249 for (; i < lengths.size() && segmentOffsets.second > lengths.at(i); ++i)
251 takeAgainFirstIdx = i;
253 if (takeAgainFirstIdx >= lengths.size())
256 takeAgainFirstIdx =
paths.front().nodes.size();
257 to =
paths.front().nodes.back();
263 const auto toSubSegLen =
264 lengths.at(takeAgainFirstIdx) - lengths.at(takeAgainFirstIdx - 1);
265 const auto toSubSegLenPart =
266 segmentOffsets.second - lengths.at(takeAgainFirstIdx - 1);
267 if (lengths.at(takeAgainFirstIdx) - toSubSegLenPart < 1e-5)
270 to =
paths.front().nodes.at(takeAgainFirstIdx);
275 const auto toSubSegLenRatio = toSubSegLenPart / toSubSegLen;
278 to.size() ==
paths.front().nodes.at(takeAgainFirstIdx - 1).size());
280 paths.front().nodes.at(takeAgainFirstIdx).size());
282 paths.front().nodes.at(takeAgainFirstIdx - 1).begin(),
283 paths.front().nodes.at(takeAgainFirstIdx - 1).end(),
284 paths.front().nodes.at(takeAgainFirstIdx).begin(),
286 [toSubSegLenRatio](
float from,
float to)
287 { return (1.f - toSubSegLenRatio) * from + toSubSegLenRatio * to; });
291 if (takeLastOPTE == takeAgainFirstIdx)
295 float segmentShortcutLength =
euclideanDistance(from.begin(), from.end(), to.begin());
297 if (segmentShortcutLength > segmentLength * (1.f - minShortcutImprovementRatio))
310 VectorXfSeq newPostprocessedSolution;
311 newPostprocessedSolution.reserve(
paths.front().nodes.size() +
314 paths.front().nodes.begin() + takeLastOPTE,
315 std::back_inserter(newPostprocessedSolution));
316 newPostprocessedSolution.emplace_back(std::move(from));
317 newPostprocessedSolution.emplace_back(std::move(to));
319 paths.front().nodes.end(),
320 std::back_inserter(newPostprocessedSolution));
323 std::lock_guard<std::mutex> lock{
mtx};
324 paths.front().nodes = std::move(newPostprocessedSolution);
336 std::lock_guard<std::mutex> lock{
mtx};
349 std::lock_guard<std::mutex> lock{
mtx};
356 std::lock_guard<std::mutex> lock{
mtx};
369 CSpaceAdaptorBasePtr simoxcspaceadapter =
370 CSpaceAdaptorBasePtr::dynamicCast(
getCSpace());
371 if (simoxcspaceadapter)
373 simoxcspace = SimoxCSpacePtr::dynamicCast(simoxcspaceadapter->getOriginalCSpace());
379 VirtualRobot::RobotNodeSetPtr rns = VirtualRobot::RobotNodeSet::createRobotNodeSet(
380 simoxcspace->getAgentSceneObj(),
"tmp", simoxcspace->getAgentJointNames());
381 Saba::CSpaceSampled tmpCSpace(
382 simoxcspace->getAgentSceneObj(),
383 VirtualRobot::CDManagerPtr(
new VirtualRobot::CDManager(simoxcspace->getCD())),
385 auto distance = [&,
this](Eigen::VectorXf
const& from, Eigen::VectorXf
const& to)
386 {
return tmpCSpace.calcDist(from, to); };
389 [&,
this](Eigen::VectorXf
const& from, Eigen::VectorXf
const& to,
float step)
390 {
return tmpCSpace.interpolate(from, to, step); };
395 [
this](
const VectorXf& cfg) {
396 return getCSpace()->isCollisionFree({cfg.data(), cfg.data() + cfg.size()});
399 std::optional<decltype(distance)>(
distance),
400 std::optional<decltype(interpolation)>(interpolation));
408 [
this](
const VectorXf& cfg) {
409 return getCSpace()->isCollisionFree({cfg.data(), cfg.data() + cfg.size()});
415 std::pair<float, float>
418 std::uniform_real_distribution<float> distA{
420 const auto a = distA(gen);
421 const auto minDelta = minPathImprovementRatio * length;
422 std::uniform_real_distribution<float> distB{
424 const auto bSample = distB(gen);
425 const auto b = (bSample <= (
a - minDelta)) ? bSample : bSample + 2 * minDelta;
427 return std::minmax(
a, b);