ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Adapting C++ Types in ROS Melodic

asked 2020-02-04 17:33:31 -0500

NINMort gravatar image

I'm trying to adapt a lot of code that already has data structures defined to ROS, so I decided to try using roscpp message adaptation since it seems like it could help make the transition easier. But I cant get even the demo code to run.

I've been following this tutorial: " http://wiki.ros.org/roscpp/Overview/MessagesSerializationAndAdaptingTypes#Example:_Adapting_a_custom_Vector3 " in Ubuntu 18.04 with ROS Melodic but it doesn't compile. I copied and pasted the tutorial code, and the things added are:

The include ros/static_assert.h and include geometry_msgs/Vector3.h, to fix dependency issues of the original code

The include ros/ros.h and the main function to test the code

This is the code:

#include <ros/message_traits.h>
#include <ros/serialization.h>
#include "ros/static_assert.h"
#include <ros/ros.h>
#include <geometry_msgs/Vector3.h>

struct MyVector3
{
    double x;
    double y;
    double z;
};
// compile-time assert that sizeof(MyVector3) == serializationLength(x) + serializationLength(y) + serializationLength(z)
ROS_STATIC_ASSERT(sizeof(MyVector3) == 24);

namespace ros
{
    namespace message_traits
    {
// This type is fixed-size (24-bytes)
        template<> struct IsFixedSize<MyVector3> : public TrueType {};
// This type is memcpyable
        template<> struct IsSimple<MyVector3> : public TrueType {};

        template<>
        struct MD5Sum<MyVector3>
        {
            static const char* value()
            {
                // Ensure that if the definition of geometry_msgs/Vector3 changes we have a compile error here.
                ROS_STATIC_ASSERT(MD5Sum<geometry_msgs::Vector3>::static_value1 == 0x4a842b65f413084dULL);
                ROS_STATIC_ASSERT(MD5Sum<geometry_msgs::Vector3>::static_value2 == 0xc2b10fb484ea7f17ULL);
                return MD5Sum<geometry_msgs::Vector3>::value();
            }

            static const char* value(const MyVector3& m)
            {
                return MD5Sum<geometry_msgs::Vector3>::value(m);
            }
        };

        template<>
        struct DataType<MyVector3>
        {
            static const char* value()
            {
                return DataType<geometry_msgs::Vector3>::value();
            }

            static const char* value(const MyVector3& m)
            {
                return DataType<geometry_msgs::Vector3>::value(m);
            }
        };

        template<>
        struct Definition<MyVector3>
        {
            static const char* value()
            {
                return Definition<geometry_msgs::Vector3>::value();
            }

            static const char* value(const MyVector3& m)
            {
                return Definition<geometry_msgs::Vector3>::value(m);
            }
        };
    } // namespace message_traits

    namespace serialization
    {
        template<>
        struct Serializer<MyVector3>
        {
            template<typename Stream, typename T>
            inline static void allInOne(Stream& stream, T t)
            {
                stream.next(t.x);
                stream.next(t.y);
                stream.next(t.z);
            }

            ROS_DECLARE_ALLINONE_SERIALIZER;
        };
    } // namespace serialization
} // namespace ros

int main(int argc, char **argv)
{
    ros::init(argc, argv, "talker");
    ros::NodeHandle n;
    ros::Publisher chatter_pub = n.advertise<geometry_msgs::Vector3>("chatter", 1000);

    ros::Rate loop_rate(10);

    MyVector3 Variance;
    Variance.x = 1.0;
    Variance.y = 2.0;

    int count = 0;
    while (ros::ok())
    {
        chatter_pub.publish(Variance);

        ros::spinOnce();

        loop_rate.sleep();
        ++count;
    }


    return 0;
}

It gives the following error:

/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp: In static member function ‘static const char* ros::message_traits::MD5Sum<MyVector3>::value(const MyVector3&)’:
/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp:37:63: error: no matching function for call to ‘ros::message_traits::MD5Sum<geometry_msgs::Vector3_<std::allocator<void> > >::value(const MyVector3&)’
                 return MD5Sum<geometry_msgs::Vector3>::value(m);
                                                               ^
In file included from /home/user/catkin_ws/src/message_tests/src/message_tests2.cpp:4:0:
/opt/ros/melodic/include/geometry_msgs/Vector3.h:125:22: note: candidate: static const char* ros::message_traits::MD5Sum<geometry_msgs::Vector3_<ContainerAllocator> >::value() [with ContainerAllocator = std::allocator<void>]
   static const char* value()
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:125:22: note:   candidate expects 0 arguments, 1 provided
/opt/ros/melodic/include/geometry_msgs/Vector3.h:130:22: note: candidate: static const char* ros ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
1

answered 2020-02-05 03:59:20 -0500

Delb gravatar image

updated 2020-02-05 04:00:20 -0500

I'm posting an answer as I found how to modify the code to have it building and running to do what you want but I am not totally sure why there is an error in the first place.

The issue is with this function (I took the one for MD5Sum but it 's the same for DataType and Defintion too) :

static const char* value(const MyVector3& m)
{
    return MD5Sum<geometry_msgs::Vector3>::value(m);
}

From Vector3.h, you can see the prototype of the function returned is :

 static const char* value(const ::geometry_msgs::Vector3_<ContainerAllocator>&) { return value(); }

What I understand is that the definition of this function forces you to specify the type signature but you can't actually use an argument.

Now if you simply comment your function I thought it would compile but when you do :

chatter_pub.publish(Variance);

It will call the function const char* ros::message_traits::md5sum(const M&), since you didn't specified the function for M = MyVector3 the compiler returns an error. So the work around is not to comment the function but simply change it to (again don't forget to do it for Definition and DataType too) :

static const char* value(const MyVector3&)
{
    return MD5Sum<geometry_msgs::Vector3>::value();
}

NB : I'm not actually sure about the explanation of the error so if I am wrong or mistaken I would be pleased to be corrected.

edit flag offensive delete link more

Comments

It works perfectly, thank you so much for your help

NINMort gravatar image NINMort  ( 2020-02-06 02:05:47 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2020-02-04 17:33:31 -0500

Seen: 304 times

Last updated: Feb 05 '20