MTC
container_p.h
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Bielefeld University
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Bielefeld University nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Robert Haschke
36  Desc: Private Implementation of the Containers
37 */
38 
39 #pragma once
40 
41 #include <moveit/task_constructor/container.h>
42 #include <moveit/macros/class_forward.h>
43 #include "stage_p.h"
44 
45 #include <boost/bimap.hpp>
46 #include <boost/bimap/unordered_set_of.hpp>
47 #include <boost/bimap/unordered_multiset_of.hpp>
48 
49 #include <map>
50 #include <climits>
51 
52 namespace moveit {
53 namespace core {
54 MOVEIT_CLASS_FORWARD(JointModelGroup);
55 MOVEIT_CLASS_FORWARD(RobotState);
56 } // namespace core
57 } // namespace moveit
58 
59 namespace moveit {
60 namespace task_constructor {
61 
62 /* A container needs to decouple its own (external) interfaces
63  * from those (internal) of its children.
64  * Both, the container and the children have their own pull interfaces: starts_ and ends_.
65  * The container forwards states received in its pull interfaces to the
66  * corresponding interfaces of the children.
67  * States pushed by children are temporarily stored in pending_backward_ and pending_forward_.
68  *
69  * Solutions found by the children need to be lifted from the internal level to the
70  * external level. To this end, we remember the mapping from internal to external states.
71  *
72  * Note, that there might be many solutions connecting a single start-end pair.
73  * These solutions might origin from different children (ParallelContainer)
74  * or from different solution paths in a SerialContainer.
75  */
76 class ContainerBasePrivate : public StagePrivate
77 {
78  friend class ContainerBase;
79  friend class ConnectingPrivate; // needed propagate setStatus() in newState()
80 
81 public:
82  using container_type = StagePrivate::container_type;
83  using iterator = container_type::iterator;
84  using const_iterator = container_type::const_iterator;
85  using NonConstStageCallback = std::function<bool(Stage&, int)>;
86 
87  inline const container_type& children() const { return children_; }
88 
93  const_iterator childByIndex(int index, bool for_insert = false) const;
94 
96  Stage::pointer remove(ContainerBasePrivate::const_iterator pos);
97 
99  bool traverseStages(const ContainerBase::StageCallback& processor, unsigned int cur_depth,
100  unsigned int max_depth) const;
101 
103  bool traverseStages(const NonConstStageCallback& processor, unsigned int cur_depth, unsigned int max_depth) {
104  const auto& const_processor = [&processor](const Stage& stage, unsigned int depth) {
105  return processor(const_cast<Stage&>(stage), depth);
106  };
107  return const_cast<const ContainerBasePrivate*>(this)->traverseStages(const_processor, cur_depth, max_depth);
108  }
109 
110  void validateConnectivity() const override;
111 
112  // Containers derive their required interface from their children
113  // UNKNOWN until resolveInterface was called
114  InterfaceFlags requiredInterface() const override { return required_interface_; }
115 
116  // forward these methods to the public interface for containers
117  bool canCompute() const override;
118  void compute() override;
119 
120  // internal interface for first/last child to push to if required
121  InterfacePtr pendingBackward() const { return pending_backward_; }
122  InterfacePtr pendingForward() const { return pending_forward_; }
123 
124  // tags for internal_external_ bimap
125  struct INTERNAL
126  {};
127  struct EXTERNAL
128  {};
129  // map InterfaceStates from children to external InterfaceStates of the container
130  inline const auto& internalToExternalMap() const { return internal_external_.by<INTERNAL>(); }
131  inline const auto& externalToInternalMap() const { return internal_external_.by<EXTERNAL>(); }
132 
134  virtual void onNewFailure(const Stage& child, const InterfaceState* from, const InterfaceState* to);
135 
136 protected:
137  ContainerBasePrivate(ContainerBase* me, const std::string& name);
138  ContainerBasePrivate& operator=(ContainerBasePrivate&& other);
139 
140  // Set child's push interfaces: allow pushing if child requires it.
141  inline void setChildsPushBackwardInterface(StagePrivate* child) {
142  InterfaceFlags required = child->requiredInterface();
143  bool allowed = (required & WRITES_PREV_END);
144  child->setPrevEnds(allowed ? pending_backward_ : InterfacePtr());
145  }
146  inline void setChildsPushForwardInterface(StagePrivate* child) {
147  InterfaceFlags required = child->requiredInterface();
148  bool allowed = (required & WRITES_NEXT_START);
149  child->setNextStarts(allowed ? pending_forward_ : InterfacePtr());
150  }
151 
153  template <Interface::Direction dir>
154  void setStatus(const Stage* creator, const InterfaceState* source, const InterfaceState* target,
155  InterfaceState::Status status);
156 
158  template <Interface::Direction>
159  void copyState(Interface::iterator external, const InterfacePtr& target, Interface::UpdateFlags updated);
160  // non-template version
161  void copyState(Interface::Direction dir, Interface::iterator external, const InterfacePtr& target,
162  Interface::UpdateFlags updated);
163 
165  void liftSolution(const SolutionBasePtr& solution, const InterfaceState* internal_from,
166  const InterfaceState* internal_to);
167 
169  inline auto& internalToExternalMap() { return internal_external_.by<INTERNAL>(); }
170  inline auto& externalToInternalMap() { return internal_external_.by<EXTERNAL>(); }
171 
172  // set in resolveInterface()
173  InterfaceFlags required_interface_;
174 
175 private:
176  container_type children_;
177 
178  // map start/end states of children (internal) to corresponding states in our external interfaces
179  boost::bimap<boost::bimaps::unordered_set_of<boost::bimaps::tagged<const InterfaceState*, INTERNAL>>,
180  boost::bimaps::unordered_multiset_of<boost::bimaps::tagged<const InterfaceState*, EXTERNAL>>>
181  internal_external_;
182 
183  /* TODO: these interfaces don't need to be priority-sorted.
184  * Introduce base class UnsortedInterface (which is a plain list) for this use case. */
185  // interface to receive children's sendBackward() states
186  InterfacePtr pending_backward_;
187  // interface to receive children's sendForward() states
188  InterfacePtr pending_forward_;
189 };
190 PIMPL_FUNCTIONS(ContainerBase)
191 
192 /* A solution of a SerialContainer needs to connect start to end via a full path.
193  * The solution of a single child stage is usually disconnected to the container's start or end.
194  * Only if all the children in the chain have found a coherent solution from start to end,
195  * this solution can be announced as a solution of the SerialContainer.
196  */
197 class SerialContainerPrivate : public ContainerBasePrivate
198 {
199  friend class SerialContainer;
200 
201 public:
202  SerialContainerPrivate(SerialContainer* me, const std::string& name);
203 
204  // called by parent asking for pruning of this' interface
205  void resolveInterface(InterfaceFlags expected) override;
206  // validate connectivity of chain
207  void validateConnectivity() const override;
208 
209  void reset();
210 
211 protected:
212  // connect two neighbors
213  void connect(StagePrivate& stage1, StagePrivate& stage2);
214 
215  // validate that child's interface matches mine (considering start or end only as determined by mask)
216  template <unsigned int mask>
217  void validateInterface(const StagePrivate& child, InterfaceFlags required) const;
218 };
219 PIMPL_FUNCTIONS(SerialContainer)
220 
221 class ParallelContainerBasePrivate : public ContainerBasePrivate
222 {
223  friend class ParallelContainerBase;
224 
225 public:
226  ParallelContainerBasePrivate(ParallelContainerBase* me, const std::string& name);
227 
228  // called by parent asking for pruning of this' interface
229  void resolveInterface(InterfaceFlags expected) override;
230 
231  void validateConnectivity() const override;
232 
233 protected:
234  void validateInterfaces(const StagePrivate& child, InterfaceFlags& external, bool first = false) const;
235 
236 private:
238  template <typename Interface::Direction>
239  void propagateStateToAllChildren(Interface::iterator external, Interface::UpdateFlags updated);
240 
241  // override to customize behavior on received interface states (default: propagateStateToAllChildren())
242  virtual void initializeExternalInterfaces();
243 };
244 PIMPL_FUNCTIONS(ParallelContainerBase)
245 
246 /* The Fallbacks container needs to implement different behaviour based on its interface.
247  * Thus, we implement 3 different classes: for Generator, Propagator, and Connect-like interfaces.
248  * FallbacksPrivate is the common base class for all of them, defining the common API
249  * to be used by the Fallbacks container.
250  * The actual interface-specific class is instantiated in initializeExternalInterfaces()
251  * resp. Fallbacks::replaceImpl() when the actual interface is known.
252  * The key difference between the 3 variants is how they advance to the next job. */
253 class FallbacksPrivate : public ParallelContainerBasePrivate
254 {
255 public:
256  FallbacksPrivate(Fallbacks* me, const std::string& name);
257  FallbacksPrivate(FallbacksPrivate&& other);
258 
259  void initializeExternalInterfaces() final;
260  void onNewFailure(const Stage& child, const InterfaceState* from, const InterfaceState* to) override;
261 
262  // virtual methods specific to each variant
263  virtual void onNewSolution(const SolutionBase& s);
264  virtual void reset() {}
265 };
266 PIMPL_FUNCTIONS(Fallbacks)
267 
268 /* Class shared between FallbacksPrivateGenerator and FallbacksPrivatePropagator,
269  which both have the notion of a currently active child stage */
270 class FallbacksPrivateCommon : public FallbacksPrivate
271 {
272 public:
273  FallbacksPrivateCommon(FallbacksPrivate&& other) : FallbacksPrivate(std::move(other)) {}
274 
276  inline void nextChild();
278  virtual bool nextJob() = 0;
279 
280  void reset() override;
281  bool canCompute() const override;
282  void compute() override;
283 
284  container_type::const_iterator current_; // currently active child
285 };
286 
289 {
290  FallbacksPrivateGenerator(FallbacksPrivate&& old);
291  bool nextJob() override;
292 };
293 
296 {
297  FallbacksPrivatePropagator(FallbacksPrivate&& old);
298  void reset() override;
299  void onNewSolution(const SolutionBase& s) override;
300  bool nextJob() override;
301 
302  Interface::Direction dir_; // propagation direction
303  Interface::iterator job_; // pointer to currently processed external state
304  bool job_has_solutions_; // flag indicating whether the current job generated solutions
305 };
306 
308 struct FallbacksPrivateConnect : FallbacksPrivate
309 {
310  FallbacksPrivateConnect(FallbacksPrivate&& old);
311  void reset() override;
312  bool canCompute() const override;
313  void compute() override;
314  void onNewFailure(const Stage& child, const InterfaceState* from, const InterfaceState* to) override;
315 
316  template <Interface::Direction dir>
317  void propagateStateUpdate(Interface::iterator external, Interface::UpdateFlags updated);
318 
319  mutable container_type::const_iterator active_; // child picked for compute()
320 };
321 
322 class WrapperBasePrivate : public ParallelContainerBasePrivate
323 {
324  friend class WrapperBase;
325 
326 public:
327  WrapperBasePrivate(WrapperBase* me, const std::string& name);
328 };
329 PIMPL_FUNCTIONS(WrapperBase)
330 
331 class MergerPrivate : public ParallelContainerBasePrivate
332 {
333  friend class Merger;
334 
335  moveit::core::JointModelGroupPtr jmg_merged_;
336  using ChildSolutionList = std::vector<const SubTrajectory*>;
337  using ChildSolutionMap = std::map<const Stage*, ChildSolutionList>;
338  // map from external source state (iterator) to all corresponding children's solutions
339  std::map<const InterfaceState*, ChildSolutionMap> source_state_to_solutions_;
340 
341 public:
342  using Spawner = std::function<void(SubTrajectory&&)>;
343  MergerPrivate(Merger* me, const std::string& name);
344 
345  void resolveInterface(InterfaceFlags expected) override;
346 
347  void onNewPropagateSolution(const SolutionBase& s);
348  void onNewGeneratorSolution(const SolutionBase& s);
349  void mergeAnyCombination(const ChildSolutionMap& all_solutions, const SolutionBase& current,
350  const planning_scene::PlanningSceneConstPtr& start_scene, const Spawner& spawner);
351  void merge(const ChildSolutionList& sub_solutions, const planning_scene::PlanningSceneConstPtr& start_scene,
352  const Spawner& spawner);
353 
354  void sendForward(SubTrajectory&& t, const InterfaceState* from);
355  void sendBackward(SubTrajectory&& t, const InterfaceState* to);
356 };
357 PIMPL_FUNCTIONS(Merger)
358 } // namespace task_constructor
359 } // namespace moveit
std::function< bool(const Stage &, unsigned int)> StageCallback
Definition: container.h:65
virtual bool nextJob()=0
Advance to the next job, assuming that the current child is exhausted on the current job.
abstract base class for solutions (primitive and sequences)
Definition: storage.h:269
Definition: stage.h:147
Definition: container.h:214
Fallbacks implementation for CONNECT interface.
Definition: container_p.h:309
Fallbacks implementation for GENERATOR interface.
Definition: container_p.h:289
bool nextJob() override
Advance to the next job, assuming that the current child is exhausted on the current job.
Definition: container.cpp:959
Fallbacks implementation for FORWARD or BACKWARD interface.
Definition: container_p.h:296
bool nextJob() override
Advance to the next job, assuming that the current child is exhausted on the current job.
Definition: container.cpp:1004