MIRA
FrameworkTransformer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
48 #ifndef _MIRA_FRAMEWORKTRANSFORMER_H_
49 #define _MIRA_FRAMEWORKTRANSFORMER_H_
50 
51 #include <transform/Pose.h>
52 #include <transform/Transformer.h>
56 
57 #include <factory/TypeId.h>
58 
59 #include <fw/Channel.h>
60 
61 namespace mira {
62 
64 
66 class FrameworkTransformer;
67 class Authority;
68 
70 
75 {
77 
78 public:
79  enum Type {
83  };
84 
85 protected:
86  friend class FrameworkTransformer;
87 
95  FrameworkTransformerNode(const std::string& id, Authority& authority) :
96  Base(id), mType(UNSPECIFIED), mAuthority(authority) {}
97 
98 public:
99 
100  virtual bool isEmpty() const;
101 
102  template<typename Transform, typename Filter>
103  Transform getTransform(const Time& time, Filter&& filter);
104 
105  Type getType() const;
106  void setType(Type type);
107 
108 private:
109 
110  template<typename ChannelTransformType, typename Transform, typename Filter>
111  bool getTransformData(const Time& time, Transform& oTransform, Filter&& filter);
112 
113 private:
114 
115  Type mType;
116 
117  Authority& mAuthority;
118  Channel<void> mChannel;
119 };
120 
121 template<>
122 inline std::string toString<FrameworkTransformerNode::Type>(const FrameworkTransformerNode::Type& value,
123  int precision)
124 {
125  switch (value) {
126  case FrameworkTransformerNode::UNSPECIFIED: return "UNSPECIFIED";
127  case FrameworkTransformerNode::MOVING: return "MOVING";
128  case FrameworkTransformerNode::FIXED: return "FIXED";
129  default: return "-INVALID VALUE-";
130  }
131 }
132 
134 
136 template <typename Derived>
138 {
139 public:
140 
141  template <typename Reflector>
142  void reflect(Reflector& r)
143  {
144  Derived* This = static_cast<Derived*>(this);
145 
146  r.interface("IFrameworkTransformer");
147  r.method("addLink",
148  (void (Derived::*)(const std::string&, const std::string&))&Derived::addLink,
149  This,
150  "add a link between the two specified nodes",
151  "child", "child node frame ID", "/robot/ArmFrame",
152  "parent", "parent node frame ID", "/robot/RobotBaseFrame");
153 
154  r.method("getTransform2", &Derived::getTransform2, This,
155  "obtains the 2D transform between the two specified nodes",
156  "target", "target frame ID", "/robot/RobotFrame",
157  "source", "source frame ID", "/GlobalFrame");
158 
159  r.method("getTransformCov2", &Derived::getTransformCov2, This,
160  "obtains the 2D transform with covariance between the two specified nodes",
161  "target", "target frame ID", "/robot/RobotFrame",
162  "source", "source frame ID", "/GlobalFrame");
163 
164  r.method("getTransform3", &Derived::getTransform3, This,
165  "obtains the 3D transform between the two specified nodes",
166  "target", "target frame ID", "/robot/RobotFrame",
167  "source", "source frame ID", "/GlobalFrame");
168 
169  r.method("getTransformCov3", &Derived::getTransformCov3, This,
170  "obtains the 3D transform with covariance between the two specified nodes",
171  "target", "target frame ID", "/robot/RobotFrame",
172  "source", "source frame ID", "/GlobalFrame");
173 
174  r.method("publishTransform2", &Derived::publishTransform2, This,
175  "publishes the 2D transform of the specified node",
176  "nodeID", "ID of node to change", "/robot/HandFrame",
177  "transform", "transformation for the node", Pose2());
178 
179  r.method("publishTransformCov2", &Derived::publishTransformCov2, This,
180  "publishes the 2D transform with covariance of the specified node",
181  "nodeID", "ID of node to change", "/robot/HandFrame",
182  "transform", "transformation for the node", PoseCov2());
183 
184  r.method("publishTransform3", &Derived::publishTransform3, This,
185  "publishes the 3D transform of the specified node",
186  "nodeID", "ID of node to change", "/robot/HandFrame",
187  "transform", "transformation for the node", Pose3());
188 
189  r.method("publishTransformCov3", &Derived::publishTransformCov3, This,
190  "publishes the 3D transform with covariance of the specified node",
191  "nodeID", "ID of node to change", "/robot/HandFrame",
192  "transform", "transformation for the node", PoseCov3());
193  }
194 };
195 
197 template <typename Derived>
199 {
200 public:
201 
203 
204  template <typename Reflector>
205  void reflect(Reflector& r)
206  {
208 
209  Derived* This = static_cast<Derived*>(this);
210 
211  r.interface("IFrameworkTransformerLinkType");
212  r.method("addLink",
213  (void (Derived::*)(const std::string&, const std::string&,
214  FrameworkTransformerNode::Type))&Derived::addLink,
215  This,
216  "add a link between the two specified nodes, with a specified type",
217  "child", "child node frame ID", "/robot/ArmFrame",
218  "parent", "parent node frame ID", "/robot/RobotBaseFrame",
219  "type", "Type of the node", FrameworkTransformerNode::MOVING);
220 
221  r.method("addTypedLink",
222  (void (Derived::*)(const std::string&, const std::string&,
223  FrameworkTransformerNode::Type))&Derived::addLink,
224  This,
225  "alias for addLink(child, parent, type), provided for backward compatibility",
226  "child", "child node frame ID", "/robot/ArmFrame",
227  "parent", "parent node frame ID", "/robot/RobotBaseFrame",
228  "type", "Type of the node", FrameworkTransformerNode::MOVING);
229  }
230 };
231 
233 
238  public GenericTransformer<FrameworkTransformerNode>,
239  public IFrameworkTransformerLinkType<FrameworkTransformer>
240 {
241 
243 
244 public:
245 
246  FrameworkTransformer(Authority& authority);
247 
249 
250 public:
259  void addLink(const std::string& childID, const std::string& parentID);
260 
274  void addLink(const std::string& childID, const std::string& parentID,
276 
283  template<typename Transform>
284  void publishTransform(const std::string& nodeID, const Transform& transform,
285  const Time& time = Time::now() );
286 
303  template<typename Transform, typename Filter = NearestNeighborInterpolator>
304  void publishTransformIndirect(const std::string& nodeID,
305  const std::string& targetID,
306  const std::string& sourceID,
307  const Transform& transform,
308  const Time& time = Time::now(),
309  Filter&& filter = NearestNeighborInterpolator());
310 
314  void storeTransformTree(const Path& filename);
315 
316 protected:
317 
318  void registerInterface(const std::string& interface,
319  const std::string& otherTransformer);
320 
321  bool createLink(const std::string& childID, const std::string& parentID,
323 
324  void notifyTransformerOfLink(const std::string& otherTransformer,
325  const std::string& childID, const std::string& parentID,
327 
328  void notifyTransformerOfLink(const std::string& otherTransformer,
329  bool implementsLinkType,
330  const std::string& childID, const std::string& parentID,
332 
333 private:
334 
336  FrameworkTransformer::NodePtr createNode(const std::string& ID);
337 
338  void setNodeType(NodePtr node, FrameworkTransformerNode::Type type);
339 
340 private:
341 
342  // for rpc calls only
344  RigidTransform2f getTransform2(const std::string& target,
345  const std::string& source);
346  RigidTransformCov2f getTransformCov2(const std::string& target,
347  const std::string& source);
348  RigidTransform3f getTransform3(const std::string& target,
349  const std::string& source);
350  RigidTransformCov3f getTransformCov3(const std::string& target,
351  const std::string& source);
352  void publishTransform2(const std::string& nodeID, const RigidTransform2f& transform);
353  void publishTransformCov2(const std::string& nodeID, const RigidTransformCov2f& transform);
354  void publishTransform3(const std::string& nodeID, const RigidTransform3f& transform);
355  void publishTransformCov3(const std::string& nodeID, const RigidTransformCov3f& transform);
356 
357 private:
358 
359  Authority& mAuthority;
360 
361  // lock node existence check + creation
362  boost::mutex mMutex;
363 };
364 
366 
368 {
369  return mChannel.isEmpty();
370 }
371 
373 {
374  return mType;
375 }
376 
378 {
379  mType = type;
380 }
381 
383 
384 // the general version
385 template <typename ChannelTransformType, typename Filter>
387  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, Filter& filter) {
388  Channel<ChannelTransformType> ch = channel_cast<ChannelTransformType>(channel);
389  oTransform = ch.get(time, filter);
390  }
391 };
392 
393 // special version for NearestNeighborInterpolator (defined in C file for compile speed)
394 template <typename ChannelTransformType>
396  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, NearestNeighborInterpolator&);
397 };
398 
399 // special version for LinearInterpolator (defined in C file for compile speed)
400 template <typename ChannelTransformType>
401 struct FrameworkTransformReadAccessor<ChannelTransformType, LinearInterpolator> {
402  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, LinearInterpolator&);
403 };
404 
405 // special version for LinearInterpolatorNoExtrapolation (defined in C file for compile speed)
406 template <typename ChannelTransformType>
408  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, LinearInterpolatorNoExtrapolation&);
409 };
410 
411 // special version for LinearInterpolatorNearestNeighbourExtrapolator (defined in C file for compile speed)
412 template <typename ChannelTransformType>
414  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, LinearInterpolatorNearestNeighbourExtrapolator&);
415 };
416 
417 // special version for LinearInterpolatorExtrapolationLimit (defined in C file for compile speed)
418 template <typename ChannelTransformType>
420  static void get(Channel<void>& channel, const Time& time, ChannelTransformType& oTransform, LinearInterpolatorExtrapolationLimit&);
421 };
422 
423 // defined in C file for compile speed
424 template <typename Transform>
426  static void set(Authority& authority, const std::string& nodeID,
427  const Transform& transform, const Time& time);
428 };
429 
431 
432 template<typename Transform, typename Filter>
433 inline Transform FrameworkTransformerNode::getTransform(const Time& time,
434  Filter&& filter)
435 {
436  Transform transform;
437 
438  // probe the type of the channel and perform a transform cast
439  // from that type to our desired transform type. If none of the supported
440  // transform types matches, throw an exception
441  // TODO can we do this better somehow??
442  if( !getTransformData<RigidTransform2f>(time,transform,filter) &&
443  !getTransformData<RigidTransform3f>(time,transform,filter) &&
444  !getTransformData<RigidTransformCov2f>(time,transform,filter) &&
445  !getTransformData<RigidTransformCov3f>(time,transform,filter))
446  MIRA_THROW(XRuntime, "Unknown transform type in channel '"
447  << mChannel.getID() << "', typename: "
448  << mChannel.getTypename() << ", typeid: " << mChannel.getTypeId());
449  return transform;
450 }
451 
452 template<typename ChannelTransformType, typename Transform, typename Filter>
453 inline bool FrameworkTransformerNode::getTransformData(const Time& time,
454  Transform& oTransform,
455  Filter&& filter)
456 {
457  int type = mChannel.getTypeId();
458  if(type>=0) {
459  // we have a type id, so use it for fast lookup
460  if(type!=typeId<ChannelTransformType>())
461  return false; // types do not match
462  // else types match
463  } else {
464  // if we trap here, the channel is yet untyped, so we need to
465  // use the typename of the channel to obtain the type
466  if(mChannel.getTypename()!=typeName<ChannelTransformType>())
467  return false; // typenames do not match
468  // else typenames match
469  }
470 
471  // if we reach here, the types match, so get the filtered transform
472  ChannelTransformType transform;
473  typedef typename boost::remove_reference<Filter>::type FilterType;
475  // ... and cast it to the desired type
476  oTransform = transform_cast<Transform>(transform);
477 
478  return true;
479 }
480 
482 
483 template<typename Transform>
484 inline void FrameworkTransformer::publishTransform(const std::string& nodeID,
485  const Transform& transform,
486  const Time& time)
487 {
488  FrameworkTransformWriteAccessor<Transform>::set(mAuthority,nodeID,transform,time);
489 }
490 
491 template<typename Transform, typename Filter>
492 inline void FrameworkTransformer::publishTransformIndirect(const std::string& nodeID,
493  const std::string& targetID,
494  const std::string& sourceID,
495  const Transform& transform,
496  const Time& time,
497  Filter&& filter)
498 {
499  NodePtr node = this->getNode(nodeID);
500  NodePtr target = this->getNode(targetID);
501  NodePtr source = this->getNode(sourceID);
502  if (!node)
503  MIRA_THROW(XRuntime, "Node " << nodeID << " does not exist");
504  if (!target)
505  MIRA_THROW(XRuntime, "Target node " << targetID << " does not exist");
506  if (!source)
507  MIRA_THROW(XRuntime, "Source node " << sourceID << " does not exist");
508  Transform inferredTransform = this->template inferTransform<Transform>(node,target,source,transform,time,filter);
509  publishTransform(nodeID,inferredTransform, time);
510 }
511 
513 
514 } // namespace
515 
516 #endif /* _MIRA_FRAMEWORKTRANSFORMER_H_ */
RigidTransform< float, 3 > Pose3
A 3D pose consisting of a translation and rotation.
Definition: Pose.h:65
Definition: FrameworkTransformer.h:74
TargetTransform transform_cast(const RigidTransform< OtherT, OtherD > &other)
Casts a RigidTransform or RigidTransformCov to a RigidTransform of a different type.
Definition: TransformCast.h:249
const std::string & getID() const
Return the channel ID, its name.
Definition: Channel.h:458
NodePtr getNode(const std::string &nodeID)
Returns a pointer to the node with the given ID or nullptr if it does not exist.
Definition: Transformer.h:528
void reflect(Reflector &r)
Definition: FrameworkTransformer.h:142
A generic transformer base class that can be used with different types of actual transformation nodes...
Definition: Transformer.h:250
Contains transform_cast operator.
Contains the Transformer class that contains everything to handle transformation trees and to compute...
1D nearest neighbor interpolator.
Definition: NearestNeighborInterpolator.h:68
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
boost::filesystem::path Path
Typedef of a Path (shorter version for boost::filesystem::path)
Definition: Path.h:69
FrameworkTransformerNode(const std::string &id, Authority &authority)
Creates a new node of the transform tree, that can be added to the corresponding FrameworkTransformer...
Definition: FrameworkTransformer.h:95
#define MIRA_REFLECT_BASE(reflector, BaseClass)
Macro that can be used to reflect the base class easily.
Definition: ReflectorInterface.h:912
1D linear interpolator.
Definition: LinearInterpolator.h:103
1D linear interpolator.
Definition: LinearInterpolator.h:181
void publishTransformIndirect(const std::string &nodeID, const std::string &targetID, const std::string &sourceID, const Transform &transform, const Time &time=Time::now(), Filter &&filter=NearestNeighborInterpolator())
Publish a transformation (nodeID) indirect by specifying a direct transform between two nodes (source...
Definition: FrameworkTransformer.h:492
void registerInterface(const std::string &interface, const std::string &otherTransformer)
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
Definition: FrameworkTransformer.h:81
Typename getTypename() const
Return the typename of the channel.
Definition: Channel.h:482
Definition: FrameworkTransformer.h:237
Wrapper class for boost::posix_time::ptime for adding more functionality to it.
Definition: Time.h:418
Definition: FrameworkTransformer.h:425
RigidTransform< float, 2 > Pose2
A 2D pose consisting of a translation and rotation.
Definition: Pose.h:62
Definition: FrameworkTransformer.h:82
Filter that returns the nearest neighbor.
Definition: FrameworkTransformer.h:386
bool createLink(const std::string &childID, const std::string &parentID, FrameworkTransformerNode::Type type)
1D linear interpolator.
Definition: LinearInterpolator.h:70
void addLink(const std::string &childID, const std::string &parentID)
Add a transformation link between the given child and parent.
RigidTransformCov< float, 3 > PoseCov3
A 3D pose with covariance consisting of a translation and rotation.
Definition: Pose.h:71
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
void setType(Type type)
Definition: FrameworkTransformer.h:377
Authorities act as a facade to the framework.
Definition: Authority.h:94
void publishTransform(const std::string &nodeID, const Transform &transform, const Time &time=Time::now())
Publish a transformation for a given node.
Definition: FrameworkTransformer.h:484
static void set(Authority &authority, const std::string &nodeID, const Transform &transform, const Time &time)
static Time now()
Returns the current utc based time.
Definition: Time.h:481
1D linear interpolator.
Definition: LinearInterpolator.h:137
IFrameworkTransformer< Derived > Base
Definition: FrameworkTransformer.h:202
Type
Definition: FrameworkTransformer.h:79
Transform getTransform(const Time &time, Filter &&filter)
Definition: FrameworkTransformer.h:433
Framework channel classes.
FrameworkTransformer(Authority &authority)
void storeTransformTree(const Path &filename)
Stores currently known transform tree in a XML config file.
RigidTransformCov< float, 2 > PoseCov2
A 2D pose with covariance consisting of a translation and rotation.
Definition: Pose.h:68
Stamped< T > get()
Returns the latest data from the channel by value.
Definition: Channel.h:893
static void get(Channel< void > &channel, const Time &time, ChannelTransformType &oTransform, Filter &filter)
Definition: FrameworkTransformer.h:387
Extension of IFrameworkTransformer supporting link types.
Definition: FrameworkTransformer.h:198
int getTypeId() const
Returns the type id of the channel.
Definition: Channel.h:468
PropertyHint precision(int p)
Sets the attribute "precision".
Definition: PropertyHint.h:285
void notifyTransformerOfLink(const std::string &otherTransformer, const std::string &childID, const std::string &parentID, FrameworkTransformerNode::Type type)
virtual bool isEmpty() const
Returns if the node has data or is empty.
Definition: FrameworkTransformer.h:367
Abstract base class where all other different types of transformation nodes must be derived from...
Definition: TransformerNode.h:88
Typedefs for different Pose datatypes that are internally RigidTransforms.
Type getType() const
Definition: FrameworkTransformer.h:372
void reflect(Reflector &r)
Definition: FrameworkTransformer.h:205
Provides method for generating a unique id for any type.
Filter that can be used for linear interpolation.
bool isEmpty() const
Returns if the channel is empty (no data has been published)
Definition: Channel.h:525
IFrameworkTransformer defines RPC methods provided by FrameworkTransformer.
Definition: FrameworkTransformer.h:137
Definition: FrameworkTransformer.h:80