Skip to content

C++ reflection library with focus on serialization/configuration (ROS parameters, YAML, JSON, XML, etc)

License

Notifications You must be signed in to change notification settings

asherikov/ariles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

454 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ariles

HEAD v2
CI status Build Status
latest Latest version of 'ariles' @ Cloudsmith
Latest version of 'ariles' @ Cloudsmith
legacy Latest version of 'ariles' @ Cloudsmith
Latest version of 'ariles' @ Cloudsmith

Contents

Links

Introduction

Loosely speaking, ariles is a C++ reflection library, i.e., it provides meta-programming APIs for implementation of class visitors (processors). It also provides a number of (de)serializers based on these APIs, e.g., YAML, JSON, XML, ROS parameter server, ROS2 parameters; and serialization wrappers for some types, e.g., STL containers, smart pointers, Eigen matrices, etc.

Unlike many modern C++ reflection/serialization libraries (see a list of related software below) ariles uses macro approach for injecting code. This is not an archaism, but a design choice which enables a different set of features: virtual serialization methods, no constraints on class construction or inheritance, etc.

Use cases

  1. Parsing and generation of configuration files. Unlike some common serialization libraries, e.g., boost::serialization, ariles tries to be flexible while parsing by:

    • silently ignoring unused entries (if possible),
    • ignoring ordering of entries (if possible),
    • not discriminating attributes from childs in XML,
    • optionally ignoring missing entries.
  2. Conversion between different formats, for example, YAML <-> ROS parameter server. Note that the conversion is not data-agnostic, i.e., the complete data structure must be represented in C++ code.

  3. Flattening of a class hierarchy to a list of name-value pairs (string-double), which is useful for collection of time-series data, see telemetry collection library https://github.com/asherikov/intrometry.

  4. Exporting of numerical data to an Octave or python script for debugging purposes.

  5. Implementation of parsers for specific data formats, e.g., a proof of concept URDF parser https://github.com/asherikov/ariles_urdf.

Minimal example

Class [./tests/api_v2/types/minimal.h]:

class Configurable : public ariles2::DefaultBase
{
    #define ARILES2_DEFAULT_ID "ConfigurableEntryName" // optional, defaults to 'ariles'
    #define ARILES2_ENTRIES(v) \
        ARILES2_TYPED_ENTRY(v, integer_member, int)
    #include ARILES2_INITIALIZE
};

Serialization:

Configurable configurable;
configurable.integer_member = 10;
ariles2::apply<ariles2::yaml_cpp::Writer>("config.yaml", configurable);
ariles2::apply<ariles2::yaml_cpp::Writer>(std::cout, configurable);

Result:

ConfigurableEntryName:
    integer_member: 10

Deserialization:

ariles2::apply<ariles2::yaml_cpp::Reader>("config.yaml", configurable);

Conversion:

// read class from a file
ariles2::apply<ariles2::yaml_cpp::Reader>("config.yaml", configurable);
// dump class to ROS parameter server
ariles2::apply<ariles2::rosparam::Writer>(nh, configurable, "/some_namespace/");

See demo for more examples: https://asherikov.github.io/ariles/2/DEMO.html [./ariles/tests/api_v2/demo_api_v2.cpp]

Visitors

ariles includes a number of optional visitors that support various data representation formats, in particular:

There are also a few utility visitors, e.g.,

  • compare for class comparison;
  • copyto for copying data to non-ariles classes;
  • copyfrom for copying data from non-ariles classes.

The complete list of modules is available at https://asherikov.github.io/ariles/2/modules.html

Supported data types

ariles provides serialization wrappers for the following types:

  • Fundamental types: integers, floats, booleans.
  • STL classes: std::string, std::vector, std::map, std::pair, std::shared_ptr, std::unique_ptr, std::array, std::deque, std::list, std::set, std::unordered_map, std::unordered_set, std::chrono::duration, std::chrono::time_point, std::optional, std::filesystem::path, std::tuple.
  • Eigen types: matrices, transforms, quaternions.
  • Boost classes: boost::optional, boost::movelib::unique_ptr. boost::shared_ptr.
  • Better enums -> https://github.com/aantron/better-enums.

Dependencies and compilation

The library is organized in a core package and a set of dependent visitor packages. It can be built in two different ways:

  • using plain cmake with features configured by cmake options -- the project is located in ariles subdirectory;
  • using catkin/colcon in a ROS1/ROS2 workspace, in which case features are selected by building corresponding wrapper packages, see ariles2_*_ws directories.

Core dependencies

  • cmake >= 3.13
  • C++17 compatible compiler
  • boost

Advanced features

Sloppy maps and pairs

std::pair is by default represented in the following way:

    my_pair:
        first: first_value
        second: second_value

The default behavior is generic and robust, but some users prefer to use a more compact form provided that the first value is represented by std::string:

    my_pair:
        first_value: second_value

The alternative behavior can be enabled using sloppy_pairs_ flag in serialization::Parameters. Note that in general it is up to the user to ensure that first_value is a valid map key in the target serialization format. std::map with string keys are handled in a similar way when sloppy_maps_ parameter is enabled. If you are inheriting from a "sloppy" ariles base classes, e.g., ariles2::SloppyBase (see ariles2/extra.h header), both of these flags are enabled by default.

"Any": polymorphic configurations

ariles2::Any2 class defined in ariles2/types.h provides functionality similar to protobuf::Any: it allows automatic instantiation and configuration reading of user-defined classes based on their string ids. See tests/api_v2/types/any.h for an example.

Tips

  • If you are having problems figuring out the correct configuration file layout for an ariles class, try writing it first to get an example. ariles can parse its own output.

  • It is not possible to make some members optional and require the rest. However, you can wrap these members with smart pointers or boost::optional, which may be uninitialized. ariles automatically adds is_null flag for each of such variables in configuration files.

  • Configuration file readers are defined as aggregate visitors that sequentially do the following: (1) reset values to defaults, (2) read values, (3) finalize values. In some cases you may want to skip (1) and (3), which can be achieved by using ns_ros2param::Reader (pick desired reader namespace) directly or defining your own aggregate visitor. It would be necessary when reading data from multiple partially initialized sources to avoid resets.

Related software

Legacy

Version 1

Version 2

Refer to changelog for more details.

Version 3 (planned)

To be removed:

  • ariles2::namevalue: replaced by ariles2::namevalue2
  • ariles2::Any: replaced by ariles2::Any2
  • rosparam: ROS1 is EOL.
  • rapidjson: poorly maintained, Ubuntu packages are based on an old buggy release Tencent/rapidjson#718. Replaced by nlohmann_json.

About

C++ reflection library with focus on serialization/configuration (ROS parameters, YAML, JSON, XML, etc)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 3

  •  
  •  
  •