GithubHelp home page GithubHelp logo

facontidavide / ros_type_introspection Goto Github PK

View Code? Open in Web Editor NEW
61.0 7.0 30.0 1.89 MB

Deserialize ROS messages that are unknown at compilation time

License: MIT License

C++ 99.09% CMake 0.91%
rosbag ros-messages deserialize

ros_type_introspection's Introduction

This library will be discontinued !!!

A large refactoring has been done to create a better and simpler library. All the development effort will be moved there.

Have a look at ros_msg_parser

Ros Message Introspection

This simple library extracts information from a ROS Message, even when its type is unknown at compilation time.

Have you ever wanted to build an app that can subscribe to any topic and extract its content, or can read data from any rosbag? What if the topic and/or the bag contains user defined ROS types ignored at compilation time?

The common solution in the ROS ecosystem is to use Python, that provides the needed introspection. Tools, for instance, like rqt_plot and rqt_bag took this approach. This library implements a C++ alternative.

This library is particularly useful to extract data from two type-erasing classes provided by ROS itself:

  1. topic_tools::ShapeShifter: a type used to subscribe to any topic, regardless of the original type.

  2. rosbag::MessageInstance: the generic type commonly used to read data from a ROS bag.

Please take a look to the examples and unit tests to see how to use the library.

Some background

The ROS Message Types can be described as a Interface Description Language. This approach is very well known and commonly used on the web and in distributed systems in general.

A rosmsg is defined by the user; an "IDL compiler", i.e. gencpp, reads this schema and generates a header file that contains the source code that the user shall include in his/her applications. The inclusion of this header file is needed on both the publisher and the subscriber sides.

This approach provides strong and type-safe contracts between the producer and the consumer of the message and, additionally, is needed to implements a fast serialization / deserialization mechanism.

The only "problem" is that in very few use cases (for instance if you want to build a plugin to load ROS bags in MATLAB) you don't know in advance which ROS Messages you will need to read. Therefore, you won't be able to include the necessary header files.

Acknowledgements

This library is inspired by these other libraries matlab_rosbag and cpp_introspection.

ros_type_introspection's People

Contributors

aeudes avatar awesomebytes avatar facontidavide avatar janebert avatar jarvisschultz avatar moooeeeep avatar prclibo avatar rhaschke avatar yiweihan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ros_type_introspection's Issues

Partially deserialize the message?

I have a use case that I want to check a message if it has Header field, then deserialize only this part to get the timestamp in it. Can I use this library to implement this efficiently?

blind/invalid reads

ReadFromBuffer does not know the size of buffer_ptr

array_size = ReadFromBuffer<int32_t>( buffer_ptr );

size_t string_size = (size_t) ReadFromBuffer<int32_t>( buffer_ptr );

if( _msg_name.compare( "bool" ) == 0 ) {
_id = RosIntrospection::BOOL;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<bool>(buffer);
};
}
else if(_msg_name.compare( "byte" ) == 0 ) {
_id = RosIntrospection::BYTE;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<int8_t>(buffer);
};
}
else if(_msg_name.compare( "char" ) == 0 ) {
_id = RosIntrospection::CHAR;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<char>(buffer);
};
}
else if(_msg_name.compare( "uint8" ) == 0 ) {
_id = RosIntrospection::UINT8;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<uint8_t>(buffer);
};
}
else if(_msg_name.compare( "uint16" ) == 0 ) {
_id = RosIntrospection::UINT16;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<uint16_t>(buffer);
};
}
else if(_msg_name.compare( "uint32" ) == 0 ) {
_id = RosIntrospection::UINT32;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<uint32_t>(buffer);
};
}
else if(_msg_name.compare( "uint64" ) == 0 ) {
_id = RosIntrospection::UINT64;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<uint64_t>(buffer);
};
}
else if(_msg_name.compare( "int8" ) == 0 ) {
_id = RosIntrospection::INT8;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<int8_t>(buffer);
};
}
else if(_msg_name.compare( "int16" ) == 0 ) {
_id = RosIntrospection::INT16;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<int16_t>(buffer);
};
}
else if(_msg_name.compare( "int32" ) == 0 ) {
_id = RosIntrospection::INT32;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<int32_t>(buffer);
};
}
else if(_msg_name.compare( "int64" ) == 0 ) {
_id = RosIntrospection::INT64;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<int64_t>(buffer);
};
}
else if(_msg_name.compare( "float32" ) == 0 ) {
_id = RosIntrospection::FLOAT32;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<float>(buffer);
};
}
else if(_msg_name.compare( "float64" ) == 0 ) {
_id = RosIntrospection::FLOAT64;
_deserialize_impl = [](uint8_t** buffer) {
return ReadFromBuffer<double>(buffer);
};
}
else if(_msg_name.compare( "time" ) == 0 ) {
_id = RosIntrospection::TIME;
_deserialize_impl = [](uint8_t** buffer) {
ros::Time tmp;
tmp.sec = ReadFromBuffer<uint32_t>(buffer);
tmp.nsec = ReadFromBuffer<uint32_t>(buffer);
return tmp;
};
}
else if(_msg_name.compare( "duration" ) == 0 ) {
_id = RosIntrospection::DURATION;
_deserialize_impl = [](uint8_t** buffer) {
ros::Time tmp;
tmp.sec = ReadFromBuffer<int32_t>(buffer);
tmp.nsec = ReadFromBuffer<int32_t>(buffer);
return tmp;
};

and so can have an invalid read here
T destination = (*( reinterpret_cast<T*>( *buffer ) ) );

If the string_size is larger than the remaining contents of buffer_ptr, this should be an error. It is not safe to trust the user supplied data.

size_t string_size = (size_t) ReadFromBuffer<int32_t>( buffer_ptr );
SString id( (const char*)(*buffer_ptr), string_size );

stack vs recursion and std::function

Another strange performance point (when profiling with perf) seemed to be in buildRosFlatTypeImpl.

Two things I would do would be to remove the usage of std::function
Use a stack to keep up with the tree parent (think that's all that would be needed) rather than using recursion.

I'm working on a patch, but thought I would make an issue in case I am too slow.

Master branch has less features than the ros-kinetic package

I wanted to do some changes to the source code and switched from using the deb package to master. However, my ros node depending on ros_type_introspection did not compile anymore.
I took a closer look and noticed that the renamed_values vector doesn't exist anymore in the ROSTypeFlat structure. The class VarNumber doesn't overload the operator double() anymore and buildRosFlatType now requires a fifth parameter max_array_size.
Is there a reason for those changes?

include directory order

when building, if you change the headers, you can run into the project being compiled against the installed headers rather than the current source headers.

I think this is more robust:

include_directories(SYSTEM
   ${catkin_INCLUDE_DIRS}
)
include_directories(BEFORE
   include
)

Parser::applyVisitorToBuffer() method is slow for sensor_msgs/Image

I am trying to use ros_type_introspection to get a header of different image messages.
Found that Parser::applyVisitorToBuffer() method is slow for sensor_msgs/Image message type when image have high resolution (1920x1080).

Code snippet for subscriber callback:

void TopicMonitor::topicCallback(const topic_tools::ShapeShifter::ConstPtr& msg, const string 
    &topicName, const unsigned int topicIndex)
{
    const string&  datatype   =  msg->getDataType();
    const string&  definition =  msg->getMessageDefinition();
    parser_.registerMessageDefinition(topicName, RosIntrospection::ROSType(datatype), definition);
    static vector<uint8_t> buffer;

    buffer.resize(msg->size());
    ros::serialization::OStream stream(buffer.data(), buffer.size());
    msg->write(stream);

    std_msgs::Header header;

    const RosIntrospection::Parser::VisitingCallback deserializeHeader =
            [&header](const RosIntrospection::ROSType&, absl::Span<uint8_t>& buffer)
            {
                ros::serialization::IStream is( buffer.data(), buffer.size() );
                ros::serialization::deserialize(is, header);
            };

    const RosIntrospection::ROSType header_type(ros::message_traits::DataType<std_msgs::Header>::value());
    static absl::Span<uint8_t> buffer_span(buffer);

    parser_.applyVisitorToBuffer(topicName, header_type, buffer_span, deserializeHeader);

    ...
}

Thanks.

Filter out variables

In the same fashion as RosIntrospection::SubstitutionRule it would be nice to have a RosIntrospection::FilterRule to filter out unwanted variables.

Use case 1
I get a Twist Stamped but I am only interested on the twist, then I apply a filter to remove the header part. Once filtered, I can apply Substitution Rules to rename the vars if wanted.

Use case 1
I get a sensor_msgs/BatteryState but I am only interested in the percentage. I apply the filter and can use only the data I am interested in.

Ideal features

  • We can define multiple filters per topic
  • We can define rules with regex

-Wsign-compare warnings triggered by abseil removal

Starting with the removal of abseil, if an executable is compiled that includes, for example, helper_functions.hpp I now get warnings about comparisons between signed and unsigned integers (assuming -Wsign-compare is passed to catkin_make):

In file included from /home/jarvis/catkinws/src/ros_type_introspection/src/ros_type.cpp:37:0:
/home/jarvis/autoyard/src/ext/ros_type_introspection/include/ros_type_introspection/helper_functions.hpp: In function ‘void RosIntrospection::ReadFromBuffer(RosIntrospection::Span<unsigned char>&, size_t&, T&) [with T = std::__cxx11::basic_string<char>; RosIntrospection::Span<unsign
ed char> = nonstd::span_lite::span<unsigned char, -1l>; size_t = long unsigned int]’:
/home/jarvis/catkinws/src/ros_type_introspection/include/ros_type_introspection/helper_functions.hpp:95:28: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if( offset + string_size > buffer.size())

fragile code

These builtin types are not given actual values like (BOOL=0,BYTE=1,...)

enum BuiltinType {
BOOL , BYTE, CHAR,
UINT8, UINT16, UINT32, UINT64,
INT8, INT16, INT32, INT64,
FLOAT32, FLOAT64,
TIME, DURATION,
STRING, OTHER
};

so changing the order in the enum can break other code (also a potential crash here is more likely since BuiltinType is not a type-safe enum)
inline const char* toStr(const BuiltinType& c)
{
static const char* names[] =
{
"BOOL" , "BYTE", "CHAR",
"UINT8", "UINT16", "UINT32", "UINT64",
"INT8", "INT16", "INT32", "INT64",
"FLOAT32", "FLOAT64",
"TIME", "DURATION",
"STRING", "OTHER"
};
return names[ static_cast<int>(c) ];
}

const int BuiltinTypeSize[OTHER] = {
1, 1, 1,
1, 2, 4, 8,
1, 2, 4, 8,
4, 8,
8, 8,
-1
};

maybe better to use runtime asserts, and an unordered map (instead of compares)

inline const char* toStr(const BuiltinType& c)
{
  switch (c) {
  case BOOL:     return "BOOL";
  case BYTE:     return "BYTE";
  case INT8:     return "INT8";
  case CHAR:     return "CHAR";
  case UINT8:    return "UINT8";
  case UINT16:   return "UINT16";
  case UINT32:   return "UINT32";
  case UINT64:   return "UINT64";
  case INT16:    return "INT16";
  case INT32:    return "INT32";
  case INT64:    return "INT64";
  case FLOAT32:  return "FLOAT32";
  case FLOAT64:  return "FLOAT64";
  case TIME:     return "TIME";
  case DURATION: return "DURATION";
  case STRING:   return "STRING";
  case OTHER:    return "OTHER";
  }
  LOG(FATAL) << "unsupported builtin type value:" << static_cast<int>(c);
}

// this should only be called if BuiltinType has a size, otherwise is a programmer error
inline std::size_t builtinSize(const BuiltinType c) {
  DCHECK(HasSize(c));
  switch (c) {
  case BOOL:
  case BYTE:
  case INT8:
  case CHAR:
  case UINT8:    return 8;
  case UINT16:
  case INT16:    return 16;
  case UINT32:
  case INT32:
  case FLOAT32:  return 32;
  case UINT64:
  case INT64:
  case FLOAT64:
  case TIME:
  case DURATION: return 64;
  case STRING:
  case OTHER:
  }
  LOG(FATAL) << "invalid call to builtinSize for type:" << toStr(c);
}

inline BuiltinType toBuiltinType(const std::string& s) {
  static std::unordered_map<std::string, BuiltinType> string_to_builtin_map {
    { "bool", BOOL },
    { "byte", BYTE },
    { "char", CHAR },
    { "uint8", UINT8 },
    { "uint16", UINT16 },
    { "uint32", UINT32 },
    { "uint64", UINT64 },
    { "int8", INT8 },
    { "int16", INT16 },
    { "int32", INT32 },
    { "int64", INT64 },
    { "float32", FLOAT32 },
    { "float64", FLOAT64 },
    { "time", TIME },
    { "duration", DURATION },
    { "string", STRING },
  };
  CHECK(!s.empty());
  auto it = string_to_builtin_map.find(s);
  return it == string_to_builtin_map.cend() ? OTHER : it->second;
}

Bridging generic subscribers and publishers

Hello @facontidavide! I appreciate you for this useful library and tutorials which let me use your tool without any problem.

I'm trying to building a type agnostic bridge to publish a vector of subscribed topics of interest without disturbing the type of the subscribed message. I have problems to deserialize and move the subscribed data without knowing the type in advance to my publishers. FlatContainers are good but I would like to make my topic publications practically easier to use in other functional components.

  1. I see, I can get the datatype and definition of the subscribed topic but I'm not sure if the current development allows me to create a variant ros message that could adapt during the runtime?
  2. Is it possible to define a variant deserializer which adapts during the runtime?

Thanks.

libraries shouldn't write to stdout

std::cout << "Warning: skipped a vector of type "
<< type.baseName() << " and size "
<< array_size << " because max_array_size = "
<< max_array_size << "\n";

stderr would be better, but I don't want to be forced to see that either.

If this is about the buffer being too small and so it only partially parsed, that seems like possibly desirable behavior, so a warning is kind of annoying.
Maybe it would be better to return the required array_size instead? Possibly return bool regarding whether it was completely processed or not.

buildRosFlatType(...., array_size, &required_array_size);
// at least the user can control the output now
LOG_IF(WARNING, required_array_size > array_size) << "buffer too small, results will be truncated";

For instance, I'm mostly interested in only parsing the Header and not the entire message.

gcc 7.4.0 gives [-Wmaybe-uninitialized] on code using variant.hpp's convert function

Compiling

void printMessage(const RosIntrospection::FlatMessage& flat_container)
{
  for (auto& it : flat_container.value)
    if (it.second.convert<std::uint8_t>()) // error value, of type franka_msgs::Errors::_tau_j_range_violation_type
      ROS_ERROR(" - %s", it.first.toStdString().c_str()); // error name
}

with gcc 7.4.0 -Wall -O3 returns:

<...>/source.cpp: In function ‘void ns::printMessage(const RosIntrospection::FlatMessage&)’:
<...>/source.cpp:892:5: warning: ‘target’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     if (it.second.convert<std::uint8_t>())

Looking into it, I found -Wmaybe-uninitialized's cause and tried to see if I'm in that case, but I can't see any issues.

Now I'm not discounting being wrong, but if I add a default case to the convert function in variant.hpp, the warning disappears:

  case OTHER: throw TypeException("Variant::convert -> cannot convert type" + std::to_string(_type)); break;

  default: throw TypeException("Variant::convert -> cannot convert type" + std::to_string(_type)); break;

  }
  return  target;

Also, I hadn't realized until this last copy-paste, but target is exactly the return variable of the convert function.

I'd actually suggest changing the OTHER type (actually most of the times I see enums, the last one is the total number of enumerated cases, i.e. an ALL_TYPES in this case. It'd probably be useless though) with the default case.

EDIT: no, not changing the OTHER type, but introducing the default where you anyways throw

Problems with some message types

Hi, I have problems with some message types.

  • Byte fields are interpreted as UInt8
  • Duration is always 0.0
  • Char fields are causing this error
terminate called after throwing an instance of 'std::runtime_error'
what():  unsupported builtin type value

I used the generic_subscriber code and tested it on ros melodic with the packaged version 1.3.1-0bionic.20190325.150517 and version 1.4.0 from github.

multiple definitions

Non-templated methods in shape_shifter.hpp should be marked inline or moved to a module, otherwise, can result in multiple definitions if included by multiple files in a single project.

Methods:



const uint8_t* ShapeShifter::raw_data() const {


std::string const& ShapeShifter::getDataType() const { return datatype_; }

std::string const& ShapeShifter::getMD5Sum() const { return md5_; }

std::string const& ShapeShifter::getMessageDefinition() const { return msg_def_; }

void ShapeShifter::morph(const std::string& _md5sum, const std::string& _datatype, const std::string& _msg_def)

ros::Publisher ShapeShifter::advertise(ros::NodeHandle& nh, const std::string& topic, uint32_t queue_size, bool latch,

How can/why is ShapeShifter::instantiate const?

Hi,

Regarding the function

boost::shared_ptr<M> instantiate() const;

Note the const qualifier.

I suddenly had trouble compiling PlotJuggler with ROS, giving me build errors of the form:

In file included from <..>/plotjuggler/ws_plotjuggler/src/PlotJuggler/plugins/ROS/RosoutPublisher/rosout_publisher.cpp:3:
In file included from <..>/plotjuggler/ws_plotjuggler/src/PlotJuggler/plugins/ROS/RosoutPublisher/../shape_shifter_factory.hpp:4:
/opt/ros/kinetic/include/ros_type_introspection/utils/shape_shifter.hpp:207:31: error: 
      no matching constructor for initialization of
      'ros::serialization::IStream'
  ros::serialization::IStream s(msgBuf_.data(), msgBuf_.size() );
                              ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/ros/kinetic/include/ros/serialization.h:749:3: note: candidate constructor
      not viable: 1st argument ('const unsigned char *') would lose const
      qualifier
  IStream(uint8_t* data, uint32_t count)
  ^

Which was odd, as I had it compiling fine before, without any obvious changes to my setup. As far as I can understand though, the compiler correctly asserts that accessing the vector data in the implementation

ros::serialization::IStream s(msgBuf_.data(), msgBuf_.size() );

through the vector<>::data() function from within the const method instantiate indeed returns the const pointer const uint8_t*:

https://en.cppreference.com/w/cpp/container/vector/data

Which constructs an IStream object which (for kinetic at least), in serialization.h is not const:
http://docs.ros.org/kinetic/api/roscpp_serialization/html/serialization_8h_source.html#l00709

Removing the const qualifier from instantiate resulted in a working build.

Now, obviously there is something with my setup that triggers this now as I had it building before and no one else has had this issue compiling introspection or plotjuggler. However, should this method really be const?

Best,
Kristian

Update Wiki

The ROS wiki example for creating a generic subscriber does not work for ROS Kinetic. I ended up using the example code provided in type_introspection_tests
Here's the question I asked on the issue before posting here. The example code on ROS Wiki needs to be updated for Kinetic (and newer I guess)

[SUGGESTION] Parser::applyVisitorToBuffer to support early termination

Parser::applyVisitorToBuffer is an extremely useful function.
If we can control the traversal from within the visiting callback and decide whether it should continue or terminate, that will be awesome!
I think if the callback has bool as the return value, the implementation will be easy.
Any idea?

ROSTypeFlat::tree shall be moved to BuildROSTypeMapFromDefinition

The StringTree inside ROSTypeFlat is updated every time the BuildRosFlatType is called. Actually it is unique for any kind of messagesm, therefore there is no reason to build it every time.

Move the creation of that StringTree into BuildROSTypeMapFromDefinition

Building a tree with values from FlatMessage

Hey,

first off, thank you for working on this!
However, I ran into a problem. I'm trying to build a tree from the deserialized message in FlatMessage. I assumed the tree member would be a perfect fit and it is partly.
I can build my tree by traversing it but I don't see how I can retrieve the values from the leaves.
The values are stored as pairs of StringTreeLeaf and the value in FlatMessage.
But how do I obtain the StringTreeLeaf representing the StringTreeNode.
It looks like I have to go through the values vector for each leaf node to obtain the value which is far from optimal.
To be honest, I don't really see the point of the StringTreeLeaf struct.
For example, why does it have a fixed size index array?
Is there a limit for ros messages that they can't be more than 8 layers deep?
Why isn't the mapping in FlatMessage just from StringTreeNode's that are leaves to values?
And why is it a vector of pairs instead of a map?

Best,
Stefan

File to message in c++

Hi,
I just came across this repo, great stuff !
Is there any way this can be used to write a function fileToMsg, that would basically do in c++ what
rostopic pub /topic type_of/msg -f /to/file.yml does ?

Does not build with the latest abseil-cpp from https://github.com/Eurecat/abseil-cpp

I was trying to compile PlotJuggler from source after cloning the latest versions of PlotJuggler, ros_type_introspection and abseil-cpp (your catkinized version) and got errors for this package. I am using catkin_tools to build the workspace and the one "non-standard" thing that I did was to enable the install option (catkin config --install) for the workspace. The output I got is as follows:

----------------------------------------------------------------------------------
Profile:                     default
Extending:             [env] /opt/ros/melodic
Workspace:                   /home/kartikmohta/programs/ros/plotjuggler_ws
----------------------------------------------------------------------------------
Source Space:       [exists] /home/kartikmohta/programs/ros/plotjuggler_ws/src
Log Space:         [missing] /home/kartikmohta/programs/ros/plotjuggler_ws/logs
Build Space:        [exists] /home/kartikmohta/programs/ros/plotjuggler_ws/build
Devel Space:        [exists] /home/kartikmohta/programs/ros/plotjuggler_ws/devel
Install Space:     [missing] /home/kartikmohta/programs/ros/plotjuggler_ws/install
DESTDIR:            [unused] None
----------------------------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        merged
----------------------------------------------------------------------------------
Additional CMake Args:       -DCMAKE_BUILD_TYPE=RelWithDebInfo
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------------------------
Workspace configuration appears valid.

NOTE: Forcing CMake to run for each package.
----------------------------------------------------------------------------------
[build] Found '3' packages in 0.0 seconds.                                                                                                                                                                        
Starting  >>> catkin_tools_prebuild                                                                                                                                                                               
Finished  <<< catkin_tools_prebuild                 [ 2.8 seconds ]                                                                                                                                               
Starting  >>> abseil_cpp                                                                                                                                                                                          
Finished  <<< abseil_cpp                            [ 13.6 seconds ]                                                                                                                                              
Starting  >>> ros_type_introspection                                                                                                                                                                              
__________________________________________________________________________________________________________________________________________________________________________________________________________________
Errors     << ros_type_introspection:cmake /home/kartikmohta/programs/ros/plotjuggler_ws/logs/ros_type_introspection/build.cmake.000.log                                                                          
CMake Error at /home/kartikmohta/programs/ros/plotjuggler_ws/install/share/abseil_cpp/cmake/abseil_cppConfig.cmake:148 (message):
  Project 'ros_type_introspection' tried to find library 'absl_container'.
  The library is neither a target nor built/installed properly.  Did you
  compile project 'abseil_cpp'? Did you find_package() it before the
  subdirectory containing its code is included?
Call Stack (most recent call first):
  /opt/ros/melodic/share/catkin/cmake/catkinConfig.cmake:76 (find_package)
  CMakeLists.txt:7 (find_package)


cd /home/kartikmohta/programs/ros/plotjuggler_ws/build/ros_type_introspection; catkin build --get-env ros_type_introspection | catkin env -si  /usr/bin/cmake /home/kartikmohta/programs/ros/plotjuggler_ws/src/ros_type_introspection --no-warn-unused-cli -DCATKIN_DEVEL_PREFIX=/home/kartikmohta/programs/ros/plotjuggler_ws/devel/.private/ros_type_introspection -DCMAKE_INSTALL_PREFIX=/home/kartikmohta/programs/ros/plotjuggler_ws/install -DCMAKE_BUILD_TYPE=RelWithDebInfo; cd -
..................................................................................................................................................................................................................
Failed     << ros_type_introspection:cmake          [ Exited with code 1 ] 

Should I not be using the latest abseil-cpp from https://github.com/Eurecat/abseil-cpp?

Move to abseil

Abseil, a C++ library built by Google, has been released a couple of days ago.
https://github.com/abseil/abseil-cpp
It has a lot of interesting features that will make the code of this library more expressive.

I am planning to build a catkinized version of abseil and depend on it

ANNOUNCEMENT: 1.0 beta

https://github.com/facontidavide/ros_type_introspection/tree/dev

@ibtaylor @mehditlili , you are the users that contributed in the past, you might want to take a look before I merge into master.

I rewrote the library using a different interface.
Originally I used a stateless API with 3 C like function.

The new approach use a class named Parser because in this way it is easier to keep a cache of some computed values as private members of the class.
https://github.com/facontidavide/ros_type_introspection/blob/dev/include/ros_type_introspection/ros_introspection.hpp

The new implementation outperform the old one by a factor 2X.

Still the most expensive step is applyNameTransform, that takes much more than deserializeIntoFlatContainer.

The new implementation was tested successfully against all the rosbags I commonly parse for testing (and the unit tests, of course).

Lookup ROS msg definitions

As far as I can see, the message parser needs registration of messages with full-fledged definitions, including all definitions of sub messages - as they are provided by ros::message_traits::Definition<ros_type>::value(). So far, the use case of this lib seems to process arbitrary messages received externally together with this full-fledged message definition.
I intended to use the lib to parse serialized messages, where I only knew the ros type (in form of pkg_name/type_name) and I was disappointed that this doesn't work out of the box.

I think, by looking up msg definitions from the (ROS) file system, utilizing
roslib::getPath(), you can easily handle this use case as well. Probably it will be a valuable extension to augment the existing API with a registerMessageDefinition(const ROSType &ros_type).

Serialize a message?

Is there also a way to serialize a message from RenamedValues, i.e. the reverse process of parsing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.