ROS

Read .yaml file (C++)

Guidance about how to use yaml-cpp

Posted by Huajian on August 5, 2022
Viewed times

Reference

Install

  • git clone https://github.com/jbeder/yaml-cpp.git

  • In the source directory:

mkdir build
cd build 
cmake .. 
make 

// you can also use "make install" directly install to "/usr/local/bin"

Configuration

  • configurate your project’s CMakeLists.txt:
pkg_check_modules(YAML_CPP REQUIRED yaml-cpp)
find_path(YAML_CPP_INCLUDE_DIR
          NAMES yaml_cpp.h
          PATHS ${YAML_CPP_INCLUDE_DIRS})
find_library(YAML_CPP_LIBRARY
             NAMES YAML_CPP
             PATHS ${YAML_CPP_LIBRARY_DIRS})
link_directories(${YAML_CPP_LIBRARY_DIRS})


include_directories( ${YAMLCPP_INCLUDE_DIRS})


target_link_libraries(${PROJECT_NAME} yaml-cpp)

Read

  • Our .yaml file as follow:
api: aaaaa
v: 1

label:
  app: hello
  image: abc
  
containers:
  - name: abc
    age: 18
  - name: 222
    age: 12
  • firstly, we need create a node object to load yaml, our node called config
YAML::Node config = YAML::LoadFile(config_path);

Now, all data from yaml are already loaded in config
we need load values depend on their data structure

value

  • api and v are simple value, we can directly read
std::cout << "api: " << config["api"].as<std::string>() << std::endl;
std::cout << "v: " << config["v"].as<int>() << std::endl;

map (key - value pair)

  • label is the map, we need use
template <typename T> 
struct convert;

convert data

  • Example in .hpp file:
struct label {
    std::string app;
    std::string image;
};

namespace YAML {
    template<>
    struct convert<label> {
        static Node encode(const label &rhs) {
            Node node;
            node.push_back(rhs.app);
            node.push_back(rhs.image);
            return node;
        }

        static bool decode(const Node &node, label &rhs) {
            std::cout << node.Type() << std::endl;
            rhs.app = node["app"].as<std::string>();
            rhs.image = node["image"].as<std::string>();
            return true;
        }
    };
}
  • Then in .cpp:
label l = config["label"].as<label>(); 
std::cout << "app: " << l.app << " image: " << l.image << std::endl;

vector

  • similar like map .hpp:
struct container {
    std::string name;
    int age;
};

namespace YAML {
    template<>
    struct convert<container> {
        static Node encode(const container &rhs) {
            Node node;
            node.push_back(rhs.name);
            node.push_back(rhs.age);
            return node;
        }

        static bool decode(const Node &node, container &rhs) {
            rhs.name = node["name"].as<std::string>();
            rhs.age = node["age"].as<int>();
            return true;
        }
    };
}
  • .cpp:
        std::vector<container> vi = config["containers"].as<std::vector<container>>();

        for (std::vector<container>::iterator it = vi.begin(); it != vi.end(); ++it) {
            std::cout << "vector: name: " << it->name << " age: " << it->age << std::endl;
        }

Summary

Read .yaml in cpp is litte hard than in python, but consider most of ros project based on .cpp, we need such knowledge to read config file from yaml.


Top
Down