46 cspace->initCollisionTest();
73 tree.addPendingUpdate(u);
80 std::vector<std::pair<float, float>> dimensionBounds{};
83 for (
const auto& dim : cspace->getDimensionsBounds())
85 dimensionBounds.emplace_back(dim.min, dim.max);
93 dimensionBounds.end(),
98 std::mt19937{std::random_device{}()}});
99 rotationMatrix.clear();
120 std::this_thread::sleep_for(std::chrono::seconds(2));
127 auto finalUpdateId =
tree.getPreviousUpdateId();
130 manager->setWorkersFinalUpdateId(workerId, finalUpdateId);
137 sampler->getDistribution().setMaximalCost(
tree.getBestCost());
140 for (Ice::Long currentBatchIteration = 0; currentBatchIteration < batchSize;
141 ++currentBatchIteration)
154 const auto& workersNodes =
tree.getNodes().at(workerId);
158 NodeId goalConnectNodeNearestId;
159 goalConnectNodeNearestId.workerId = workerId;
160 float goalConnectNodeNearestDistance = std::numeric_limits<float>::infinity();
164 numberOfNode < workersNodes.size();
168 const float currNodeDistance =
distance(goalCfg, currNode.
config);
170 if (currNodeDistance < goalConnectNodeNearestDistance)
172 goalConnectNodeNearestDistance = currNodeDistance;
173 goalConnectNodeNearestId.numberOfNode = numberOfNode;
177 if (goalConnectNodeNearestDistance < std::numeric_limits<float>::infinity())
179 const auto cfgReached =
180 steer(
tree.getNode(goalConnectNodeNearestId).config, goalCfg);
182 if (cfgReached ==
tree.getNode(goalConnectNodeNearestId).config)
185 tree.decreaseRadius(goalConnectNodeNearestId);
187 else if (cfgReached == goalCfg)
193 tree.addGoalReached(goalConnectNodeNearestId, goalConnectNodeNearestDistance);
217 [
this](Ice::Long workerNodeId, Ice::Long updateSubId)
232 NodeId nodeNearestId;
233 float nodeNearestDistance;
237 u_int64_t samplingTries{0};
241 if (!(samplingTries % 1000))
251 if (!((samplingTries + 1000) % 10000))
256 (*sampler)(cfgRnd.data());
257 std::tie(nodeNearestId, nodeNearestDistance) =
258 tree.getNearestNeighbourAndDistance(cfgRnd);
260 }
while (nodeNearestDistance >
tree.getNode(nodeNearestId).radius);
263 const auto cfgReached =
steer(
tree.getNode(nodeNearestId).config, cfgRnd);
268 if (
tree.getNode(nodeNearestId).config == cfgReached)
271 tree.decreaseRadius(nodeNearestId);
283 float costReachedToNodeBest;
284 std::vector<std::pair<NodeId, float>> kNearestIdsAndDistances;
285 std::map<NodeId, bool> isCollisionFreeCache;
292 costReachedToNodeBest,
293 kNearestIdsAndDistances,
294 isCollisionFreeCache);
297 const auto nodeReachedId =
tree.addNode(cfgReached,
299 costReachedToNodeBest
302 rewire(nodeReachedId, kNearestIdsAndDistances, isCollisionFreeCache);
307 const std::vector<std::pair<NodeId, float>>& kNearestIdsAndDistances,
308 const std::map<NodeId, bool>& isCollisionFreeCache)
311 const auto& node =
tree.getNode(nodeId);
313 const float nodeFromStartCost = node.fromStartCost;
315 for (
const auto& nearIdAndDist : kNearestIdsAndDistances)
317 const auto& nodeNearId = nearIdAndDist.first;
318 auto& nodeNear =
tree.getNode(nodeNearId);
319 const auto& cfgNodeNear = nodeNear.config;
321 const auto costPathToNearOld = nodeNear.fromStartCost;
322 const auto costNodeToNear = nearIdAndDist.second;
323 const auto costPathToNearOverNode = nodeFromStartCost + costNodeToNear;
326 if (costPathToNearOverNode < costPathToNearOld)
329 const auto it = isCollisionFreeCache.find(nodeNearId);
331 if ((it != isCollisionFreeCache.end() && (*it).second) ||
335 tree.setNodeParent(nodeNearId, nodeId, costNodeToNear);
344 NodeId& outNodeBestId,
345 float& outCostReachedToNodeBest,
346 std::vector<std::pair<NodeId, float>>& outKNearestIdsAndDistances,
347 std::map<NodeId, bool>& outIsCollisionFreeCache)
350 outNodeBestId = nodeNearestId;
351 outCostReachedToNodeBest =
distance(
tree.getNode(outNodeBestId).config, cfgReached);
352 auto costPathToReachedOverNodeBest =
353 tree.getNode(nodeNearestId).fromStartCost + outCostReachedToNodeBest;
354 outKNearestIdsAndDistances =
tree.getKNearestNeighboursAndDistances(cfgReached,
getK());
356 for (
const auto& nearIdAndDist : outKNearestIdsAndDistances)
359 auto& nodeNearId = nearIdAndDist.first;
360 auto& nodeNear =
tree.getNode(nodeNearId);
361 const auto& cfgNodeNear = nodeNear.config;
363 const auto costReachedToNodeNear = nearIdAndDist.second;
364 const auto costPathToReachedOverNodeNear =
365 nodeNear.fromStartCost + costReachedToNodeNear;
367 if (costPathToReachedOverNodeNear < costPathToReachedOverNodeBest)
372 outNodeBestId = nodeNearId;
373 costPathToReachedOverNodeBest = costPathToReachedOverNodeNear;
374 outCostReachedToNodeBest = costReachedToNodeNear;
375 outIsCollisionFreeCache[nodeNearId] =
true;
379 outIsCollisionFreeCache[nodeNearId] =
false;
410 bufferCDRange.first = cfg.data();
411 bufferCDRange.second = bufferCDRange.first + cfg.size();
412 return cspace->isCollisionFree(bufferCDRange);
419 const auto kRRT = std::pow(2.f, dim + 1.f) * M_E * (1.f + 1.f / dim);
420 const auto k = kRRT * std::log(
static_cast<float>(
tree.size()));
421 return static_cast<std::size_t
>(std::ceil(k));
430 return tree.getLocalUpdates().at(
static_cast<std::size_t
>(updateId));
436 return manager->getUpdate(workerNodeId, updateSubId);
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
ArmarXObjectSchedulerPtr getObjectScheduler() const
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
UniformInformedProlateSpheroidDistribution< float > DistributionType
void updateTree(const Update &u, const Ice::Current &=Ice::emptyCurrent) override
Receives an update from other workers and adds it to the queue of pending updates.
std::size_t onePastLastGoalConnect
The index one past the last node that was considered to be connected to the goal configuration.
void findBestParent(const NodeId &nodeNearestId, const ConfigType &cfgReached, NodeId &outNodeBestId, float &outCostReachedToNodeBest, std::vector< std::pair< NodeId, float > > &outKNearestIdsAndDistances, std::map< NodeId, bool > &outIsCollisionFreeCache)
Searches the optimal parent for a configuration.
void onInitComponent() override
Initializes the worker and starts the worker thread.
void applyPendingUpdates()
Applies all pending updates to the tree.
void workerTask()
The worker task.
std::string updateTopicName
The update topic's name.
void doBatch()
Executes a batch.
std::thread workerThread
Thread executing the worker task.
TreeUpdateInterfacePrx globalWorkers
Proxy used to write to the update topic.
std::atomic_bool killRequest
Wheether the node should shut down.
Update getUpdate(Ice::Long updateId, const Ice::Current &=Ice::emptyCurrent) const override
std::mutex updateMutex
Mutex protecting the update structures.
void addAndRewireConfig(const ConfigType &cfgReached, const NodeId &nodeNearestId)
Adds a configuration to the tree.
std::size_t getDimensionality()
std::unique_ptr< InformedSampler > sampler
Stores the sampler.
void initTree()
initializes the tree by getting the current tree from the manager
void onConnectComponent() override
Gets a proxy to the topic.
static float distance(const ConfigType &from, const ConfigType &to)
Calculates the euclidian distance between from and to.
Tree::ConfigType ConfigType
Type of a configuration.
Update getRemoteUpdate(Ice::Long workerNodeId, Ice::Long updateSubId)
void doBatchIteration()
Executes one iteration of a batch.
std::atomic_bool workerPaused
workerPaused is true if the worker is currently on hold and does not perform any calculations.
bool isPathCollisionFree(const ConfigType &from, const ConfigType &to)
ConfigType steer(const ConfigType &from, const ConfigType &to)
Does a linear interpolation from from to to and checks the path per DCD.
void rewire(const NodeId &nodeId, const std::vector< std::pair< NodeId, float > > &kNearestIdsAndDistances, const std::map< NodeId, bool > &isCollisionFreeCache)
The rewire operation of the rrt* algorithm.
void onExitComponent() override
Kills the worker thread (if it is still running) and joins it.
bool isCollisionFree(const ConfigType &cfg)
void killWorker(const Ice::Current &=Ice::emptyCurrent) override
Signals the worker thread to exit.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
bool dcdIsPathCollisionFree(const ConfigType &from, const ConfigType &to, RealType dcdStepSize, CollisionChecker isCollisionFree, bool toIsCollisionFree=true, const std::optional< Distance > &distanceLambda=std::optional< Distance >(), const std::optional< Interpolate > &interpolationLambda=std::optional< Interpolate >(), std::vector< ConfigType > *resultPath=NULL)
Returns whether the line startCfg to to is collision free.
Sampler< UniformInformedProlateSpheroidDistribution< float >, std::mt19937 > InformedSampler
Typedef for a sampler as required by informed rrt*.
ConfigType dcdSteer(const ConfigType &from, const ConfigType &to, RealType dcdStepSize, CollisionChecker isCollisionFree)
Tries to reach to from from using the given stepsize.
Represents a node of thr rrt.
ConfigType config
The node's configuration.