0
$\begingroup$

Rosanswers logo

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::message_traits::MD5Sum<geometry_msgs::Vector3_<ContainerAllocator> >::value(const geometry_msgs::Vector3_<ContainerAllocator>&) [with ContainerAllocator = std::allocator<void>]
   static const char* value(const ::geometry_msgs::Vector3_<ContainerAllocator>&) { return value(); }
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:130:22: note:   no known conversion for argument 1 from ‘const MyVector3’ to ‘const geometry_msgs::Vector3_<std::allocator<void> >&’
/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp: In static member function ‘static const char* ros::message_traits::DataType<MyVector3>::value(const MyVector3&)’:
/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp:51:65: error: no matching function for call to ‘ros::message_traits::DataType<geometry_msgs::Vector3_<std::allocator<void> > >::value(const MyVector3&)’
                 return DataType<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:138:22: note: candidate: static const char* ros::message_traits::DataType<geometry_msgs::Vector3_<ContainerAllocator> >::value() [with ContainerAllocator = std::allocator<void>]
   static const char* value()
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:138:22: note:   candidate expects 0 arguments, 1 provided
/opt/ros/melodic/include/geometry_msgs/Vector3.h:143:22: note: candidate: static const char* ros::message_traits::DataType<geometry_msgs::Vector3_<ContainerAllocator> >::value(const geometry_msgs::Vector3_<ContainerAllocator>&) [with ContainerAllocator = std::allocator<void>]
   static const char* value(const ::geometry_msgs::Vector3_<ContainerAllocator>&) { return value(); }
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:143:22: note:   no known conversion for argument 1 from ‘const MyVector3’ to ‘const geometry_msgs::Vector3_<std::allocator<void> >&’
/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp: In static member function ‘static const char* ros::message_traits::Definition<MyVector3>::value(const MyVector3&)’:
/home/user/catkin_ws/src/message_tests/src/message_tests2.cpp:65:67: error: no matching function for call to ‘ros::message_traits::Definition<geometry_msgs::Vector3_<std::allocator<void> > >::value(const MyVector3&)’
                 return Definition<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:149:22: note: candidate: static const char* ros::message_traits::Definition<geometry_msgs::Vector3_<ContainerAllocator> >::value() [with ContainerAllocator = std::allocator<void>]
   static const char* value()
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:149:22: note:   candidate expects 0 arguments, 1 provided
/opt/ros/melodic/include/geometry_msgs/Vector3.h:164:22: note: candidate: static const char* ros::message_traits::Definition<geometry_msgs::Vector3_<ContainerAllocator> >::value(const geometry_msgs::Vector3_<ContainerAllocator>&) [with ContainerAllocator = std::allocator<void>]
   static const char* value(const ::geometry_msgs::Vector3_<ContainerAllocator>&) { return value(); }
                      ^~~~~
/opt/ros/melodic/include/geometry_msgs/Vector3.h:164:22: note:   no known conversion for argument 1 from ‘const MyVector3’ to ‘const geometry_msgs::Vector3_<std::allocator<void> >&’

My CMakeFile is as follows:

cmake_minimum_required(VERSION 2.8.3)
project(message_tests)

find_package(catkin REQUIRED COMPONENTS
  std_msgs
  roscpp
  geometry_msgs
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES message_tests
#  CATKIN_DEPENDS geometry2d std_msgs
#  DEPENDS system_lib
)

include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  include/${PROJECT_NAME}
)

add_executable(message_tests2 src/message_tests2.cpp)
target_link_libraries(message_tests2 ${catkin_LIBRARIES})

The problem originates in this lines:

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

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

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

The code seems to expect a 'const geometry_msgs::Vector3_std::allocator<void >&' but the value m is a 'const MyVector3& '. If I change geometry_msgs::Vector3 to MyVector3 the function calls itself and I get a segmentation fault.

I dont know enough about templates to find the problem. The only other example I found was this: ROS Answers - custom-classes-in-message-files. Which also has the same issue. I tried compiling using C++11 and C++03 as well as C++14 but unfourtanately I have made no progress.

Any help would be greatly appreciated.


Originally posted by NINMort on ROS Answers with karma: 3 on 2020-02-04

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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.


Originally posted by Delb with karma: 3907 on 2020-02-05

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by NINMort on 2020-02-06:
It works perfectly, thank you so much for your help

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.