WorkerNode.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-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 RobotComponents
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
20  * @date 2015
21  * @copyright http://www.gnu.org/licenses/gpl.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <atomic>
27 #include <deque>
28 #include <mutex>
29 #include <thread>
30 #include <unordered_map>
31 #include <utility>
32 #include <vector>
33 
35 
36 #include <RobotComponents/interface/components/MotionPlanning/Tasks/AdaptiveDynamicDomainInformedRRTStar/WorkerNode.h>
37 
38 #include "../../util/Metrics.h"
39 #include "../../util/PlanningUtil.h"
40 #include "../../util/Samplers.h"
41 #include "Tree.h"
42 
43 namespace armarx
44 {
45  template <class IceBaseClass, class DerivedClass>
46  class GenericFactory;
47 }
48 
49 namespace armarx::addirrtstar
50 {
51  class WorkerNode;
52  /**
53  * @brief An ice handle for a WorkerNode of the addirrt* algorithm
54  */
56 
57  /**
58  * @brief Implements the worker side of the batch distributed adaptive dynamic domain informed rrt* planner.
59  *
60  * This algorithm has two variants for selecting nodes for rewiring.
61  * (see doi> 10.1177/0278364911406761)
62  * One using k-Nearest-Neighbours with:
63  * - k(#nodes)= kRRT * log(#nodes)
64  * - kRRT > 2^(dimensions+1) * e (1 + 1/dimensions)
65  *
66  * One using Nearest-Neighbours with a radius:
67  * - r(#nodes)= min{γRRT( log(#nodes) / #nodes )^(1/dimensions) , η}
68  * - γRRT =(2 ( 1 + 1/dimensions))^(1/d) *(μ(Xfree) / ζd)^(1/dimensions)
69  * - η = maximal step size during 1 extend (+inf in this implementation)
70  * - μ(Xfree) = Lebesgue measure of the obstacle-free space
71  * - ζd = volume of the d-dimensional unit ball in Euclidean space
72  *
73  * since μ(Xfree) can only be estimated the k-NN version is used.
74  */
75  class WorkerNode : virtual public ManagedIceObject, virtual public WorkerNodeBase
76  {
77  public:
78  /**
79  * @brief Type of a configuration.
80  */
82 
83  static_assert(std::numeric_limits<Ice::Float>::has_infinity,
84  "requires inf in current implementation");
85 
86  /**
87  * @brief ctor
88  * @param cspace The palnning cspace.
89  * @param startCfg The start configuration.
90  * @param goalCfg The goal configuration.
91  * @param DCDStepSize The dcd step size.
92  * @param addParams The adaptive dynamic domain parameters.
93  * @param manager A proxy to the manager node.
94  * @param workerId The worker's id.
95  * @param batchSize The batch size.
96  * @param nodeCountDeltaForGoalConnectionTries Number of nodes created (by a worker) before a connect to the goal node is tried (by this worker).
97  * @param topicPrefix The used topic prefix. (for the topic name to distribute updates)
98  * @param rotationMatrix The rotation matrix for the informed ellipsoid.
99  */
100  WorkerNode(const CSpaceBasePtr& cspace,
101  const VectorXf& startCfg,
102  const VectorXf& goalCfg,
103  Ice::Float DCDStepSize,
104  AdaptiveDynamicDomainParameters addParams,
105  const ManagerNodeBasePrx& manager,
106  Ice::Long workerId,
107  Ice::Long batchSize,
108  Ice::Long nodeCountDeltaForGoalConnectionTries,
109  const std::string& topicPrefix,
110  const Ice::FloatSeq& rotationMatrix
111 
112  ) :
113  WorkerNodeBase(cspace,
114  startCfg,
115  goalCfg,
116  DCDStepSize,
117  addParams,
118  manager,
119  workerId,
120  batchSize,
121  nodeCountDeltaForGoalConnectionTries,
122  topicPrefix,
123  rotationMatrix),
125  {
126  }
127 
128  /**
129  * @brief dtor. Asserts the worker thread was joined.
130  */
131  ~WorkerNode() override
132  {
133 #pragma GCC diagnostic push
134 #pragma GCC diagnostic ignored "-Wterminate"
136 #pragma GCC diagnostic pop
137  }
138 
139  //from managedIceObject
140  /**
141  * @brief Initializes the worker and starts the worker thread.
142  */
143  void onInitComponent() override;
144  /**
145  * @brief Gets a proxy to the topic.
146  */
147  void onConnectComponent() override;
148 
149  /**
150  * @brief noop
151  */
152  void
154  {
155  }
156 
157  /**
158  * @brief Kills the worker thread (if it is still running) and joins it.
159  */
160  void onExitComponent() override;
161 
162  /**
163  * @return The component's default name.
164  */
165  std::string
166  getDefaultName() const override
167  {
168  return "ADDIRRTStarWorkerNode";
169  }
170 
171  //from WorkerNodeBase
172  /**
173  * @brief Signals the worker thread to exit.
174  */
175  void
176  killWorker(const Ice::Current& = Ice::emptyCurrent) override
177  {
178  killRequest = true;
179  }
180 
181  void
182  pauseWorker(bool pauseFlag, const Ice::Current& = Ice::emptyCurrent) override
183  {
184  workerPaused = pauseFlag;
185  }
186 
187  /**
188  * @param updateId The updates id.
189  * @return This workers update with the given id.
190  */
191  Update getUpdate(Ice::Long updateId,
192  const Ice::Current& = Ice::emptyCurrent) const override;
193 
194 
195  //from WorkerUpdateInterface
196  /**
197  * @brief Receives an update from other workers and adds it to the queue of pending updates.
198  * @param u the update.
199  */
200  void updateTree(const Update& u, const Ice::Current& = Ice::emptyCurrent) override;
201 
202  //from ice
203  /**
204  * @brief noop
205  */
206  void
207  ice_postUnmarshal() override
208  {
209  }
210 
211  /**
212  * @brief Calculates the euclidian distance between from and to.
213  * @param from First vector.
214  * @param to Second vector.
215  * @return The euclidian distance between from and to.
216  */
217  static float
218  distance(const ConfigType& from, const ConfigType& to)
219  {
220  ARMARX_CHECK_EXPRESSION(from.size() == to.size());
221  return euclideanDistance(from.data(), from.data() + from.size(), to.data());
222  }
223 
224  protected:
225  friend class GenericFactory<WorkerNodeBase, WorkerNode>;
226 
227  /**
228  * @brief Only used when transmitting through ice.
229  */
230  WorkerNode() = default;
231 
232  /**
233  * @param workerNodeId The update's worker id.
234  * @param updateSubId The update's sub id.
235  * @return The update fetched from the manager node.
236  */
237  Update getRemoteUpdate(Ice::Long workerNodeId, Ice::Long updateSubId);
238 
239  /**
240  * @brief The worker task.
241  * It performs all planning.
242  */
243  void workerTask();
244 
245  /**
246  * @brief initializes the tree by getting the current tree from the manager
247  */
248  void
250  {
251  tree.init(manager->getTree(), addParams, workerId);
252  }
253 
254  /**
255  * @brief Does a linear interpolation from from to to and checks the path per DCD.
256  * @param from starting point for the interpolation. (assumed to be collision free)
257  * @param to end point for the interpolation.
258  * @return The point furthest away from from (but collision free reachable from from)
259  * on the line from->to.
260  * If from->to is collision free the return value is identical to to (no floating point error).
261  * If the first step on the path from->to has a collision the return value is identical to from (no floating point error).
262  */
263  ConfigType steer(const ConfigType& from, const ConfigType& to);
264  /**
265  * @param cfg The configuration.
266  * @return Whether the given configuration is collision free.
267  */
268  bool isCollisionFree(const ConfigType& cfg);
269  /**
270  * @param from The start configuration.
271  * @param to The goal configuration.
272  * @return Whether the path from from to to is colliswion free.
273  */
274  bool isPathCollisionFree(const ConfigType& from, const ConfigType& to);
275 
276  /**
277  * @return The cspace's dimensionality
278  */
279  std::size_t
281  {
282  return cspace->getDimensionality();
283  }
284 
285  /**
286  * @return Number of neighbours currently considered as parent.
287  */
288  std::size_t getK();
289 
290  /**
291  * @brief The RRT tree
292  */
294 
295  /**
296  * @brief Wheether the node should shut down.
297  */
298  std::atomic_bool killRequest;
299 
300  /**
301  * @brief workerPaused is true if the worker is currently on hold and does not perform any calculations.
302  */
303  std::atomic_bool workerPaused;
304 
305  /**
306  * @brief Mutex protecting the update structures.
307  */
308  mutable std::mutex updateMutex;
309 
310  /**
311  * @brief Thread executing the worker task.
312  */
313  std::thread workerThread;
314 
315  /**
316  * @brief The update topic's name.
317  */
318  std::string updateTopicName;
319  /**
320  * @brief Proxy used to write to the update topic.
321  */
322  TreeUpdateInterfacePrx globalWorkers;
323  /**
324  * @brief A string representation of the worker id.
325  * Used for output.
326  */
327  std::string workerIdSring;
328 
329  /**
330  * @brief The index one past the last node that was considered to be connected to the goal configuration.
331  */
333 
334  /**
335  * @brief Stores the sampler.
336  *
337  * A pointer is used, since the sampler ctor requires space information and in case of default construction
338  * the information is not available. (the default ctor is used when transmitting this object per ice.)
339  * The pointer gets set during construction or post unmarshalling.
340  */
341  std::unique_ptr<InformedSampler> sampler;
342 
343  /**
344  *@brief required for static factory methode create
345  */
346  friend class ManagedIceObject;
347 
348  /**
349  * @brief Searches the optimal parent for a configuration.
350  * Used by the rrt* component.
351  * @param nodeNearestId The id of the nearest node.
352  * @param cfgReached The reached configuration.
353  * @param outNodeBestId Output parameter: The id of the optimal parent.
354  * @param outCostReachedToNodeBest Output parameter: The distance of reached and the optimal parent.
355  * @param outKNearestIdsAndDistances Output parameter: The k nearest nodes and their distance to reached.
356  * @param outIsCollisionFreeCache Output parameter: Cache storing collision checks for paths between nodes from knearest and reached.
357  */
358  void findBestParent(const NodeId& nodeNearestId,
359  const ConfigType& cfgReached,
360  NodeId& outNodeBestId,
361  float& outCostReachedToNodeBest,
362  std::vector<std::pair<NodeId, float>>& outKNearestIdsAndDistances,
363  std::map<NodeId, bool>& outIsCollisionFreeCache);
364 
365  /**
366  * @brief The rewire operation of the rrt* algorithm.
367  * It optimizes path lengths.
368  * @param nodeId The root node's id
369  * @param kNearestIdsAndDistances The k nearest nodes and their distance to the root node.
370  * @param isCollisionFreeCache Cache storing collision checks for paths between nodes from knearest and the root node..
371  */
372  void rewire(const NodeId& nodeId,
373  const std::vector<std::pair<NodeId, float>>& kNearestIdsAndDistances,
374  const std::map<NodeId, bool>& isCollisionFreeCache);
375 
376  /**
377  * @brief Adds a configuration to the tree.
378  * The configurations best parent is searched and rewiring is performed fot it.
379  * @param cfgReached The configuration.
380  * @param nodeNearestId The nearest node's id.
381  */
382  void addAndRewireConfig(const ConfigType& cfgReached, const NodeId& nodeNearestId);
383 
384  /**
385  * @brief Executes one iteration of a batch.
386  */
387  void doBatchIteration();
388 
389  /**
390  * @brief Executes a batch.
391  */
392  void doBatch();
393 
394  /**
395  * @brief Applies all pending updates to the tree.
396  */
397  void applyPendingUpdates();
398 
399  private:
400  /**
401  * @brief Buffer for the range used by the collision check.
402  */
403  std::pair<const float*, const float*> bufferCDRange;
404  };
405 } // namespace armarx::addirrtstar
armarx::addirrtstar::WorkerNode::getDefaultName
std::string getDefaultName() const override
Definition: WorkerNode.h:166
armarx::addirrtstar::WorkerNode::onInitComponent
void onInitComponent() override
Initializes the worker and starts the worker thread.
Definition: WorkerNode.cpp:38
armarx::addirrtstar::WorkerNode::killRequest
std::atomic_bool killRequest
Wheether the node should shut down.
Definition: WorkerNode.h:298
armarx::addirrtstar::WorkerNode::getUpdate
Update getUpdate(Ice::Long updateId, const Ice::Current &=Ice::emptyCurrent) const override
Definition: WorkerNode.cpp:425
armarx::addirrtstar::WorkerNode::applyPendingUpdates
void applyPendingUpdates()
Applies all pending updates to the tree.
Definition: WorkerNode.cpp:212
armarx::addirrtstar::WorkerNode::rewire
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.
Definition: WorkerNode.cpp:306
armarx::addirrtstar::WorkerNode::updateTopicName
std::string updateTopicName
The update topic's name.
Definition: WorkerNode.h:318
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
armarx::addirrtstar::WorkerNode::initTree
void initTree()
initializes the tree by getting the current tree from the manager
Definition: WorkerNode.h:249
armarx::addirrtstar::WorkerNode::getRemoteUpdate
Update getRemoteUpdate(Ice::Long workerNodeId, Ice::Long updateSubId)
Definition: WorkerNode.cpp:434
armarx::addirrtstar::WorkerNode::ConfigType
Tree::ConfigType ConfigType
Type of a configuration.
Definition: WorkerNode.h:81
armarx::addirrtstar::WorkerNode::~WorkerNode
~WorkerNode() override
dtor.
Definition: WorkerNode.h:131
armarx::addirrtstar::Tree::init
void init(const FullIceTree &iceTree, AdaptiveDynamicDomainParameters newaddParams, std::size_t newWorkerId)
Initailizes the tree from the given tree.
Definition: Tree.cpp:54
armarx::addirrtstar::WorkerNode::tree
Tree tree
The RRT tree.
Definition: WorkerNode.h:293
armarx::addirrtstar::WorkerNode::updateMutex
std::mutex updateMutex
Mutex protecting the update structures.
Definition: WorkerNode.h:308
armarx::addirrtstar::WorkerNode::workerPaused
std::atomic_bool workerPaused
workerPaused is true if the worker is currently on hold and does not perform any calculations.
Definition: WorkerNode.h:303
armarx::addirrtstar::Tree::ConfigType
VectorXf ConfigType
The type of configurations.
Definition: Tree.h:56
armarx::addirrtstar::WorkerNode::WorkerNode
WorkerNode()=default
Only used when transmitting through ice.
Tree.h
armarx::addirrtstar::WorkerNode::distance
static float distance(const ConfigType &from, const ConfigType &to)
Calculates the euclidian distance between from and to.
Definition: WorkerNode.h:218
armarx::addirrtstar::WorkerNode::onDisconnectComponent
void onDisconnectComponent() override
noop
Definition: WorkerNode.h:153
armarx::addirrtstar::WorkerNode::doBatchIteration
void doBatchIteration()
Executes one iteration of a batch.
Definition: WorkerNode.cpp:225
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::addirrtstar::WorkerNode::ice_postUnmarshal
void ice_postUnmarshal() override
noop
Definition: WorkerNode.h:207
armarx::addirrtstar::WorkerNode::onExitComponent
void onExitComponent() override
Kills the worker thread (if it is still running) and joins it.
Definition: WorkerNode.cpp:62
armarx::addirrtstar::WorkerNode
Implements the worker side of the batch distributed adaptive dynamic domain informed rrt* planner.
Definition: WorkerNode.h:75
armarx::addirrtstar::WorkerNode::onConnectComponent
void onConnectComponent() override
Gets a proxy to the topic.
Definition: WorkerNode.cpp:56
armarx::addirrtstar::WorkerNode::workerTask
void workerTask()
The worker task.
Definition: WorkerNode.cpp:77
ManagedIceObject.h
armarx::addirrtstar::WorkerNode::workerThread
std::thread workerThread
Thread executing the worker task.
Definition: WorkerNode.h:313
armarx::addirrtstar::WorkerNode::isCollisionFree
bool isCollisionFree(const ConfigType &cfg)
Definition: WorkerNode.cpp:408
armarx::addirrtstar::WorkerNode::steer
ConfigType steer(const ConfigType &from, const ConfigType &to)
Does a linear interpolation from from to to and checks the path per DCD.
Definition: WorkerNode.cpp:386
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:918
armarx::addirrtstar::WorkerNode::isPathCollisionFree
bool isPathCollisionFree(const ConfigType &from, const ConfigType &to)
Definition: WorkerNode.cpp:396
armarx::addirrtstar::WorkerNode::getDimensionality
std::size_t getDimensionality()
Definition: WorkerNode.h:280
armarx::addirrtstar::WorkerNode::workerIdSring
std::string workerIdSring
A string representation of the worker id.
Definition: WorkerNode.h:327
armarx::addirrtstar::WorkerNode::getK
std::size_t getK()
Definition: WorkerNode.cpp:416
armarx::addirrtstar::WorkerNode::globalWorkers
TreeUpdateInterfacePrx globalWorkers
Proxy used to write to the update topic.
Definition: WorkerNode.h:322
armarx::addirrtstar::WorkerNode::onePastLastGoalConnect
std::size_t onePastLastGoalConnect
The index one past the last node that was considered to be connected to the goal configuration.
Definition: WorkerNode.h:332
armarx::addirrtstar::WorkerNode::doBatch
void doBatch()
Executes a batch.
Definition: WorkerNode.cpp:134
armarx::addirrtstar::WorkerNode::WorkerNode
WorkerNode(const CSpaceBasePtr &cspace, const VectorXf &startCfg, const VectorXf &goalCfg, Ice::Float DCDStepSize, AdaptiveDynamicDomainParameters addParams, const ManagerNodeBasePrx &manager, Ice::Long workerId, Ice::Long batchSize, Ice::Long nodeCountDeltaForGoalConnectionTries, const std::string &topicPrefix, const Ice::FloatSeq &rotationMatrix)
ctor
Definition: WorkerNode.h:100
armarx::addirrtstar::WorkerNode::sampler
std::unique_ptr< InformedSampler > sampler
Stores the sampler.
Definition: WorkerNode.h:341
armarx::euclideanDistance
float euclideanDistance(IteratorType1 first1, IteratorType1 last1, IteratorType2 first2)
Returns the euclidean distance.
Definition: Metrics.h:104
armarx::ManagedIceObject
The ManagedIceObject is the base class for all ArmarX objects.
Definition: ManagedIceObject.h:162
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::addirrtstar::Tree
A structure holding and managing all data connected to the tree used in the ADDIRRT* algorithm.
Definition: Tree.h:49
armarx::addirrtstar::WorkerNode::findBestParent
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.
Definition: WorkerNode.cpp:342
armarx::addirrtstar::WorkerNode::updateTree
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.
Definition: WorkerNode.cpp:70
armarx::GenericFactory
Definition: FactoryCollectionBase.h:51
armarx::addirrtstar::WorkerNode::pauseWorker
void pauseWorker(bool pauseFlag, const Ice::Current &=Ice::emptyCurrent) override
Definition: WorkerNode.h:182
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::addirrtstar::WorkerNode::addAndRewireConfig
void addAndRewireConfig(const ConfigType &cfgReached, const NodeId &nodeNearestId)
Adds a configuration to the tree.
Definition: WorkerNode.cpp:280
armarx::addirrtstar::WorkerNode::killWorker
void killWorker(const Ice::Current &=Ice::emptyCurrent) override
Signals the worker thread to exit.
Definition: WorkerNode.h:176
armarx::addirrtstar
Definition: ManagerNode.cpp:36