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

Trouble Reading Back Array of Characters

asked 2022-05-23 23:08:52 -0600

teddybouch gravatar image

In order to accommodate an encoded string that might have a terminal character, I'm trying to pass the data as a custom message with a char array rather than a standard string. Everything in the publisher seems to be fine, but when I try to read the array back using an iterator the error seems to tell me that the array entry is no longer the std::vector<char> that I expected, but now a std::vector<unsigned char, std::allocator<unsigned char> >::iterator that I can't assign to the iterator type I want to use.

This is my custom message, EncodedString.msg:

char[] data
int32 length

and this is the subscriber code where I try to read it back out:

#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "tutorial_interfaces/msg/encoded_string.hpp"

class MinimalSubscriber : public rclcpp::Node
{
public:
  MinimalSubscriber()
  : Node("minimal_subscriber")
  {
    subscription_ = this->create_subscription<tutorial_interfaces::msg::EncodedString>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, std::placeholders::_1));
  }

private:
  void topic_callback(const tutorial_interfaces::msg::EncodedString::SharedPtr msg) const
  {
    int char_length = msg->length;

    std::string encoded_bytes = "";
    std::vector<char>::iterator char_it;
    for( char_it = msg->data.begin(); msg->data.end(); char_it++ )
    {
      encoded_bytes.append( msg->data[char_it] );
    }
  }
  rclcpp::Subscription<tutorial_interfaces::msg::EncodedString>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}

If it looks familiar, it's because I'm using the standard publisher/subscriber to test the concept before I do anything more complicated, so hopefully this is a proper minimal example. The problem arises when I go to build the package, and the first error that I get is:

Starting >>> cpp_pubsub
--- stderr: cpp_pubsub                             
/home/teddybouch/workspace/ros2_ws/src/cpp_pubsub/src/subscriber_member_function.cpp: In member function ‘void MinimalSubscriber::topic_callback(tutorial_interfaces::msg::EncodedString_<std::allocator<void> >::SharedPtr) const’:
/home/teddybouch/workspace/ros2_ws/src/cpp_pubsub/src/subscriber_member_function.cpp:45:36: error: no match for ‘operator=’ (operand types are ‘std::vector<char>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<char*, std::vector<char> >’} and ‘std::vector<unsigned char, std::allocator<unsigned char> >::iterator’ {aka ‘__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >’})
   45 |     for( char_it = msg->data.begin(); msg->data.end(); char_it++ )
      |                                    ^
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,
                 from /usr/include/c++/9/memory:62,
                 from /home/teddybouch/workspace/ros2_ws/src/cpp_pubsub/src/subscriber_member_function.cpp:15:
/usr/include/c++/9/bits/stl_iterator.h:784:11: note: candidate: ‘constexpr __gnu_cxx::__normal_iterator<char*, std::vector<char> >& __gnu_cxx::__normal_iterator<char*, std::vector<char> >::operator=(const __gnu_cxx::__normal_iterator<char*, std::vector<char> >&)’
  784 |     class __normal_iterator
      |           ^~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:784:11: note:   no known conversion for argument 1 from ‘std::vector<unsigned char, std::allocator<unsigned char> >::iterator’ {aka ‘__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >’} to ‘const __gnu_cxx::__normal_iterator<char*, std::vector<char> >&’
/usr/include/c++/9/bits/stl_iterator.h:784:11: note: candidate: ‘constexpr __gnu_cxx::__normal_iterator<char*, std::vector<char> >& __gnu_cxx::__normal_iterator<char*, std::vector<char> >::operator=(__gnu_cxx::__normal_iterator<char*, std::vector<char> >&&)’
/usr/include/c++/9/bits/stl_iterator.h:784:11: note:   no known conversion for argument 1 from ‘std::vector<unsigned char, std::allocator<unsigned ...
(more)
edit retag flag offensive close merge delete

Comments

1

Out of curiosity: what are you publishing that "is a string, but might contain a terminal character"?

Is it a binary payload? Would a plain unbounded uint8 array not be a better fit in that case?

gvdhoorn gravatar image gvdhoorn  ( 2022-05-24 02:03:44 -0600 )edit

I'm using DCCL to encode and decode protobufs, which outputs a string but in practice I've found will sometimes only pass part of the string when sent as a standard string message. I need to get it back into a string to decode on the other end, so using a char[] seemed more straightforward than dealing with the conversions to use a uint8[]. I may end up using the latter and can mess around with that option after work, but either way I think that it's worth my figuring out what's going on here that I can't get the char[] back on the subscriber end.

teddybouch gravatar image teddybouch  ( 2022-05-24 04:45:36 -0600 )edit

I'm using DCCL to encode and decode protobufs, which outputs a string [..]

an actual std::string, or a const char* or something similar?

In both cases sending that as a char[] field in a ROS message doesn't seem like it would be appropriate.

Having written that though: the error message basically tells you the iterator type is incompatible.

ROS messages use a configurable allocator, and the type of the iterator defined for the message type carries that type with it. You'll either have to match the type, or use auto.

gvdhoorn gravatar image gvdhoorn  ( 2022-05-24 06:53:31 -0600 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2022-05-24 06:38:32 -0600

Mike Scheutzow gravatar image

According to http://design.ros2.org/articles/idl_i..., by definition a char is unsigned in ros2.

In c++, a char is either signed or unsigned, whichever the compiler-writer decided to use. You (the developer) are responsible for handling the mismatch, if there is one.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2022-05-23 23:08:52 -0600

Seen: 157 times

Last updated: May 24 '22