From b0c3768ec0e279ae638e314d7de863cc5ee06842 Mon Sep 17 00:00:00 2001 From: Thomas Moulard <thomas.moulard@gmail.com> Date: Mon, 14 Nov 2011 11:29:24 +0100 Subject: [PATCH] Add Twist support and clean code. --- src/converter.hh | 267 ++++++++++++++++++++++++++++----------------- src/ros_export.cpp | 5 + src/ros_export.hxx | 4 +- src/ros_import.cpp | 4 + src/ros_import.hxx | 1 + src/sot_to_ros.cpp | 4 + src/sot_to_ros.hh | 88 +++++++++++++++ 7 files changed, 273 insertions(+), 100 deletions(-) diff --git a/src/converter.hh b/src/converter.hh index bd4443f..4b12fc9 100644 --- a/src/converter.hh +++ b/src/converter.hh @@ -1,12 +1,37 @@ #ifndef DYNAMIC_GRAPH_ROS_CONVERTER_HH # define DYNAMIC_GRAPH_ROS_CONVERTER_HH +# include <stdexcept> # include "sot_to_ros.hh" +# include <boost/static_assert.hpp> + +# include <ros/time.h> +# include <std_msgs/Header.h> + # include <LinearMath/btMatrix3x3.h> # include <LinearMath/btQuaternion.h> +# define SOT_TO_ROS_IMPL(T) \ + template <> \ + inline void \ + converter (SotToRos<T>::ros_t& dst, const SotToRos<T>::sot_t& src) + +# define ROS_TO_SOT_IMPL(T) \ + template <> \ + inline void \ + converter (SotToRos<T>::sot_t& dst, const SotToRos<T>::ros_t& src) + namespace dynamicgraph { + inline + void + makeHeader(std_msgs::Header& header) + { + header.seq = 0; + header.stamp = ros::Time::now (); + header.frame_id = "/dynamic_graph/world"; + } + /// \brief Handle ROS <-> dynamic-graph conversion. /// /// Implements all ROS/dynamic-graph conversions required by the @@ -17,23 +42,35 @@ namespace dynamicgraph template <typename D, typename S> void converter (D& dst, const S& src); - template <> - inline void converter (SotToRos<double>::ros_t& dst, - const SotToRos<double>::sot_t& src) + // Double + SOT_TO_ROS_IMPL(double) { dst.data = src; } - template <> - inline void converter (SotToRos<double>::sot_t& dst, - const SotToRos<double>::ros_const_ptr_t& src) + ROS_TO_SOT_IMPL(double) + { + dst = src.data; + } + + // Vector + SOT_TO_ROS_IMPL(ml::Vector) + { + dst.data.resize (src.size ()); + for (unsigned i = 0; i < src.size (); ++i) + dst.data[i] = src.elementAt (i); + } + + ROS_TO_SOT_IMPL(ml::Vector) { - dst = src->data; + dst.resize (src.data.size ()); + for (unsigned i = 0; i < src.data.size (); ++i) + dst.elementAt (i) = src.data[i]; } - template <> - inline void converter (SotToRos<ml::Matrix>::ros_t& dst, - const SotToRos<ml::Matrix>::sot_t& src) + + // Matrix + SOT_TO_ROS_IMPL(ml::Matrix) { dst.width = src.nbRows (); dst.data.resize (src.nbCols () * src.nbRows ()); @@ -41,9 +78,15 @@ namespace dynamicgraph dst.data[i] = src.elementAt (i); } - template <> - inline void converter (SotToRos<sot::MatrixHomogeneous>::ros_t& dst, - const SotToRos<sot::MatrixHomogeneous>::sot_t& src) + ROS_TO_SOT_IMPL(ml::Matrix) + { + dst.resize (src.width, src.data.size () / src.width); + for (unsigned i = 0; i < src.data.size (); ++i) + dst.elementAt (i) = src.data[i]; + } + + // Homogeneous matrix. + SOT_TO_ROS_IMPL(sot::MatrixHomogeneous) { btMatrix3x3 rotation; btQuaternion quaternion; @@ -62,49 +105,7 @@ namespace dynamicgraph dst.rotation.w = quaternion.w (); } - template <> - inline void converter - (SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::ros_t& dst, - const SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::sot_t& src) - { - converter - <SotToRos<sot::MatrixHomogeneous>::ros_t, - SotToRos<sot::MatrixHomogeneous>::sot_t> (dst.transform, src); - } - - template <> - inline void converter (SotToRos<ml::Vector>::ros_t& dst, - const SotToRos<ml::Vector>::sot_t& src) - { - dst.data.resize (src.size ()); - for (unsigned i = 0; i < src.size (); ++i) - dst.data[i] = src.elementAt (i); - } - - template <> - inline void converter - (SotToRos<ml::Vector>::sot_t& dst, - const SotToRos<ml::Vector>::ros_t& src) - { - dst.resize (src.data.size ()); - for (unsigned i = 0; i < src.data.size (); ++i) - dst.elementAt (i) = src.data[i]; - } - - template <> - inline void converter - (SotToRos<ml::Matrix>::sot_t& dst, - const SotToRos<ml::Matrix>::ros_t& src) - { - dst.resize (src.width, src.data.size () / src.width); - for (unsigned i = 0; i < src.data.size (); ++i) - dst.elementAt (i) = src.data[i]; - } - - template <> - inline void converter - (SotToRos<sot::MatrixHomogeneous>::sot_t& dst, - const SotToRos<sot::MatrixHomogeneous>::ros_t& src) + ROS_TO_SOT_IMPL(sot::MatrixHomogeneous) { btQuaternion quaternion (src.rotation.x, src.rotation.y, src.rotation.z, src.rotation.w); @@ -121,58 +122,128 @@ namespace dynamicgraph dst(2, 3) = src.translation.z; } - template <> - inline void converter - (SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::sot_t& dst, - const SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::ros_t& src) - { - converter - <SotToRos<sot::MatrixHomogeneous>::sot_t, - SotToRos<sot::MatrixHomogeneous>::ros_t> (dst, src.transform); - } - template <> - inline void converter - (SotToRos<ml::Vector>::sot_t& dst, - const boost::shared_ptr<SotToRos<ml::Vector>::ros_t const>& src) + // Twist. + SOT_TO_ROS_IMPL(specific::Twist) { - converter - <SotToRos<ml::Vector>::sot_t, - SotToRos<ml::Vector>::ros_t> (dst, *src); + if (src.size () != 6) + throw std::runtime_error ("failed to convert invalid twist"); + dst.linear.x = src (0); + dst.linear.y = src (1); + dst.linear.z = src (2); + dst.angular.x = src (3); + dst.angular.y = src (4); + dst.angular.z = src (5); } - template <> - inline void converter - (SotToRos<ml::Matrix>::sot_t& dst, - const boost::shared_ptr<SotToRos<ml::Matrix>::ros_t const>& src) + ROS_TO_SOT_IMPL(specific::Twist) { - converter - <SotToRos<ml::Matrix>::sot_t, - SotToRos<ml::Matrix>::ros_t> (dst, *src); + dst.resize (6); + dst (0) = src.linear.x; + dst (1) = src.linear.y; + dst (2) = src.linear.z; + dst (3) = src.angular.x; + dst (4) = src.angular.y; + dst (5) = src.angular.z; } - template <> - inline void converter - (SotToRos<sot::MatrixHomogeneous>::sot_t& dst, - const boost::shared_ptr<SotToRos<sot::MatrixHomogeneous>::ros_t const>& src) - { - converter - <SotToRos<sot::MatrixHomogeneous>::sot_t, - SotToRos<sot::MatrixHomogeneous>::ros_t> (dst, *src); - } - template <> - inline void converter - (SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::sot_t& dst, - const boost::shared_ptr - <SotToRos<std::pair<sot::MatrixHomogeneous, ml::Vector> >::ros_t const>& src) + /// \brief This macro generates a converter for a stamped type from + /// dynamic-graph to ROS. I.e. A data associated with its + /// timestamp. +# define DG_BRIDGE_TO_ROS_MAKE_STAMPED_IMPL(T, ATTRIBUTE, EXTRA) \ + template <> \ + inline void converter \ + (SotToRos<std::pair<T, ml::Vector> >::ros_t& dst, \ + const SotToRos<std::pair<T, ml::Vector> >::sot_t& src) \ + { \ + makeHeader(dst.header); \ + converter<SotToRos<T>::ros_t, SotToRos<T>::sot_t> (dst.ATTRIBUTE, src); \ + do { EXTRA } while (0); \ + } \ + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + + DG_BRIDGE_TO_ROS_MAKE_STAMPED_IMPL(sot::MatrixHomogeneous, transform, + dst.child_frame_id = "";); + DG_BRIDGE_TO_ROS_MAKE_STAMPED_IMPL(specific::Twist, twist, ;); + + + /// \brief This macro generates a converter for a shared pointer on + /// a ROS type to a dynamic-graph type. + /// + /// A converter for the underlying type is required. I.e. to + /// convert a shared_ptr<T> to T', a converter from T to T' + /// is required. +# define DG_BRIDGE_MAKE_SHPTR_IMPL(T) \ + template <> \ + inline void converter \ + (SotToRos<T>::sot_t& dst, \ + const boost::shared_ptr<SotToRos<T>::ros_t const>& src) \ + { \ + converter<SotToRos<T>::sot_t, SotToRos<T>::ros_t> (dst, *src); \ + } \ + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + + DG_BRIDGE_MAKE_SHPTR_IMPL(double); + DG_BRIDGE_MAKE_SHPTR_IMPL(ml::Vector); + DG_BRIDGE_MAKE_SHPTR_IMPL(ml::Matrix); + DG_BRIDGE_MAKE_SHPTR_IMPL(sot::MatrixHomogeneous); + DG_BRIDGE_MAKE_SHPTR_IMPL(specific::Twist); + + /// \brief This macro generates a converter for a stamped type. + /// I.e. A data associated with its timestamp. + /// + /// FIXME: the timestamp is not yet forwarded to the dg signal. +# define DG_BRIDGE_MAKE_STAMPED_IMPL(T, ATTRIBUTE, EXTRA) \ + template <> \ + inline void converter \ + (SotToRos<std::pair<T, ml::Vector> >::sot_t& dst, \ + const SotToRos<std::pair<T, ml::Vector> >::ros_t& src) \ + { \ + converter<SotToRos<T>::sot_t, SotToRos<T>::ros_t> (dst, src.ATTRIBUTE); \ + do { EXTRA } while (0); \ + } \ + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + + DG_BRIDGE_MAKE_STAMPED_IMPL(sot::MatrixHomogeneous, transform, ;); + DG_BRIDGE_MAKE_STAMPED_IMPL(specific::Twist, twist, ;); + + /// \brief This macro generates a converter for a shared pointer on + /// a stamped type. I.e. A data associated with its timestamp. + /// + /// FIXME: the timestamp is not yet forwarded to the dg signal. +# define DG_BRIDGE_MAKE_STAMPED_SHPTR_IMPL(T, ATTRIBUTE, EXTRA) \ + template <> \ + inline void converter \ + (SotToRos<std::pair<T, ml::Vector> >::sot_t& dst, \ + const boost::shared_ptr \ + <SotToRos<std::pair<T, ml::Vector> >::ros_t const>& src) \ + { \ + converter<SotToRos<T>::sot_t, SotToRos<T>::ros_t> (dst, src->ATTRIBUTE); \ + do { EXTRA } while (0); \ + } \ + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + + DG_BRIDGE_MAKE_STAMPED_SHPTR_IMPL(sot::MatrixHomogeneous, transform, ;); + DG_BRIDGE_MAKE_STAMPED_SHPTR_IMPL(specific::Twist, twist, ;); + + + /// \brief If an impossible/unimplemented conversion is required, fail. + /// + /// IMPORTANT, READ ME: + /// + /// If the compiler generates an error in the following function, + /// this is /normal/. + /// + /// This error means that either you try to use an undefined + /// conversion. You can either fix your code or provide the wanted + /// conversion by updating this header. + template <typename U, typename V> + inline void converter (U& dst, V& src) { - converter - <SotToRos<sot::MatrixHomogeneous>::sot_t, - SotToRos<sot::MatrixHomogeneous>::ros_t> (dst, src->transform); + // This will always fail if instantiated. + BOOST_STATIC_ASSERT (sizeof (U) == 0); } - - } // end of namespace dynamicgraph. #endif //! DYNAMIC_GRAPH_ROS_CONVERTER_HH diff --git a/src/ros_export.cpp b/src/ros_export.cpp index d28ff28..f5f6e53 100644 --- a/src/ros_export.cpp +++ b/src/ros_export.cpp @@ -82,6 +82,11 @@ namespace dynamicgraph else if (type == "matrixHomoStamped") entity.add<std::pair<sot::MatrixHomogeneous, ml::Vector> > (signal, topic); + else if (type == "Twist") + entity.add<specific::Twist> (signal, topic); + else if (type == "TwistStamped") + entity.add<std::pair<specific::Twist, ml::Vector> > + (signal, topic); else throw std::runtime_error("bad type"); return Value (); diff --git a/src/ros_export.hxx b/src/ros_export.hxx index 64fe3c5..0293e67 100644 --- a/src/ros_export.hxx +++ b/src/ros_export.hxx @@ -58,7 +58,7 @@ namespace dynamicgraph boost::shared_ptr<signal_t> signal_ (new signal_t (0, signalName.str ())); - signal_->setConstant (sot_t ()); + SotToRos<T>::setDefault(*signal_); bindedSignal.first = signal_; rosExport.signalRegistration (*bindedSignal.first); @@ -98,7 +98,7 @@ namespace dynamicgraph boost::shared_ptr<signal_t> signal_ (new signal_t (0, signalName.str ())); - signal_->setConstant (sot_t ()); + SotToRos<T>::setDefault(*signal_); bindedSignal.first = signal_; rosExport.signalRegistration (*bindedSignal.first); diff --git a/src/ros_import.cpp b/src/ros_import.cpp index a6990e6..556c69c 100644 --- a/src/ros_import.cpp +++ b/src/ros_import.cpp @@ -86,6 +86,10 @@ namespace dynamicgraph else if (type == "matrixHomoStamped") entity.add<std::pair<sot::MatrixHomogeneous, ml::Vector> > (signal, topic); + else if (type == "twist") + entity.add<specific::Twist> (signal, topic); + else if (type == "twistStamped") + entity.add<std::pair<specific::Twist, ml::Vector> > (signal, topic); else throw std::runtime_error("bad type"); return Value (); diff --git a/src/ros_import.hxx b/src/ros_import.hxx index 146714f..8555565 100644 --- a/src/ros_import.hxx +++ b/src/ros_import.hxx @@ -51,6 +51,7 @@ namespace dynamicgraph boost::make_shared<signal_t> (MAKE_SIGNAL_STRING(name, true, SotToRos<T>::signalTypeName, signal)); boost::get<0> (bindedSignal) = signalPtr; + SotToRos<T>::setDefault(*signalPtr); signalRegistration (*boost::get<0> (bindedSignal)); // Initialize the callback. diff --git a/src/sot_to_ros.cpp b/src/sot_to_ros.cpp index 89df1c0..bfdbc79 100644 --- a/src/sot_to_ros.cpp +++ b/src/sot_to_ros.cpp @@ -7,8 +7,12 @@ namespace dynamicgraph const char* SotToRos<ml::Matrix>::signalTypeName = "Matrix"; const char* SotToRos<ml::Vector>::signalTypeName = "Vector"; const char* SotToRos<sot::MatrixHomogeneous>::signalTypeName = "MatrixHomo"; + const char* SotToRos<specific::Twist>::signalTypeName = "Twist"; const char* SotToRos <std::pair<sot::MatrixHomogeneous, ml::Vector> >::signalTypeName = "MatrixHomo"; + const char* SotToRos + <std::pair<specific::Twist, ml::Vector> >::signalTypeName + = "Twist"; } // end of namespace dynamicgraph. diff --git a/src/sot_to_ros.hh b/src/sot_to_ros.hh index bf5752f..8dbbb35 100644 --- a/src/sot_to_ros.hh +++ b/src/sot_to_ros.hh @@ -12,6 +12,8 @@ # include "geometry_msgs/Transform.h" # include "geometry_msgs/TransformStamped.h" +# include "geometry_msgs/Twist.h" +# include "geometry_msgs/TwistStamped.h" # include <dynamic-graph/signal-time-dependent.h> # include <dynamic-graph/signal-ptr.h> @@ -25,6 +27,16 @@ namespace dynamicgraph { namespace ml = maal::boost; + /// \brief Types dedicated to identify pairs of (dg,ros) data. + /// + /// They do not contain any data but allow to make the difference + /// between different types with the same structure. + /// For instance a vector of six elements vs a twist coordinate. + namespace specific + { + class Twist {}; + } // end of namespace specific. + /// \brief SotToRos trait type. /// /// This trait provides types associated to a dynamic-graph type: @@ -45,6 +57,12 @@ namespace dynamicgraph typedef boost::function<sot_t& (sot_t&, int)> callback_t; static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + s.setConstant (0.); + } }; template <> @@ -58,6 +76,14 @@ namespace dynamicgraph typedef boost::function<sot_t& (sot_t&, int)> callback_t; static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + ml::Matrix m; + m.resize(0, 0); + s.setConstant (m); + } }; template <> @@ -71,6 +97,14 @@ namespace dynamicgraph typedef boost::function<sot_t& (sot_t&, int)> callback_t; static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + ml::Vector v; + v.resize (0); + s.setConstant (v); + } }; template <> @@ -84,6 +118,34 @@ namespace dynamicgraph typedef boost::function<sot_t& (sot_t&, int)> callback_t; static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + sot::MatrixHomogeneous m; + s.setConstant (m); + } + }; + + template <> + struct SotToRos<specific::Twist> + { + typedef ml::Vector sot_t; + typedef geometry_msgs::Twist ros_t; + typedef geometry_msgs::TwistConstPtr ros_const_ptr_t; + typedef dynamicgraph::SignalTimeDependent<sot_t, int> signal_t; + typedef dynamicgraph::SignalPtr<sot_t, int> signalIn_t; + typedef boost::function<sot_t& (sot_t&, int)> callback_t; + + static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + ml::Vector v (6); + v.setZero (); + s.setConstant (v); + } }; // Stamped transformation @@ -98,6 +160,32 @@ namespace dynamicgraph typedef boost::function<sot_t& (sot_t&, int)> callback_t; static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + SotToRos<sot_t>::setDefault(s); + } + }; + + // Stamped twist + template <> + struct SotToRos<std::pair<specific::Twist, ml::Vector> > + { + typedef ml::Vector sot_t; + typedef geometry_msgs::TwistStamped ros_t; + typedef geometry_msgs::TwistStampedConstPtr ros_const_ptr_t; + typedef dynamicgraph::SignalTimeDependent<sot_t, int> signal_t; + typedef dynamicgraph::SignalPtr<sot_t, int> signalIn_t; + typedef boost::function<sot_t& (sot_t&, int)> callback_t; + + static const char* signalTypeName; + + template <typename S> + static void setDefault(S& s) + { + SotToRos<sot_t>::setDefault(s); + } }; inline std::string -- GitLab