Turtle10000
Turtle10000

Reputation: 252

Reading a vector of maps with yaml-cpp fails

I want to read the following yaml data:

camera:
 response_values: [[0.0: 0.0, 1.0: 1.1, 245.0: 250.1], [0.0: 0.1, 1.0: 1.3, 200.0: 250], [0.0: 0.0, 1.0: 1.1, 245.0: 250.1]]

I want to read it into a vector < map <float, float> >. In this case, the vector would have 3 maps with each 3 entries.

My attempt is this:

#include <yaml-cpp/yaml.h>
#include <fstream>
#include <map>

using namespace std;

int main()
{

  YAML::Node camerafile = YAML::LoadFile("/path/to/camera.yaml");

  YAML::Node camera = camerafile["camera"];

  auto response_values_yaml = camera["response_values"];
  for(YAML::const_iterator it=response_values_yaml.begin();it!=response_values_yaml.end();++it) {
    YAML::Node response_values_map = it->as<YAML::Node>(); // e.g. [0.0: 0.0, 1.0: 1.1, 245.0: 250.1]
    string whole_map = YAML::Dump(response_values_map);

    for(YAML::const_iterator at=response_values_map.begin();at!=response_values_map.end();++at) {
      auto the_thing = at->as<YAML::Node>();
      string the_string = YAML::Dump(the_thing);
      float key = at->first.as<float>();
      float val = at->second.as<float>();
    }
  }
}

Debug results:
whole_map: "[{0.0: 0.0}, {1.0: 1.1}, {245.0: 250.1}]"
the_string: "{0.0: 0.0}"
the_thing->Node->Ref->Data has a map item

However, as soon as the program reaches float key = at->first.as<float>();, it crashes.

terminate called after throwing an instance of 'YAML::InvalidNode'
  what():  invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa

GDB jumps into yaml-cpp/node/imlp.h. this is an empty node with m_isValid being false.

Trying as<string> produces the same behaviour. I think I have a map, but I can't interpret it as a map using the .first and .second methods, I think this is what the error messages tells me. What am I missing?

Upvotes: 3

Views: 1124

Answers (1)

ramsay
ramsay

Reputation: 3845

#include <assert.h>
#include <fstream>
#include <iostream>
#include <map>
#include <yaml-cpp/yaml.h>

using namespace std;

int main() {

  YAML::Node camerafile = YAML::LoadFile("./camera.yaml");

  YAML::Node camera = camerafile["camera"];

  auto response_values_yaml = camera["response_values"];
  // it is the sequence iterator
  for (YAML::const_iterator it = response_values_yaml.begin();
       it != response_values_yaml.end(); ++it) {
    YAML::Node response_values_map
        = it->as<YAML::Node>(); // e.g. [0.0: 0.0, 1.0: 1.1, 245.0: 250.1]

    for (YAML::const_iterator at = response_values_map.begin();
         at != response_values_map.end(); ++at) {


      // `at` is a **map iterater** which has a single key/value pair.
      // so it will certainly coredump when you are calling `at->first.as<float>()`
      assert(at->size() == 1);
      // The iterator points to the single key/value pair.
      YAML::Node::const_iterator sub_it = at->begin(); // **The key point.**
      // Then access the key and value.
      float key = sub_it->first.as<float>();
      float value = sub_it->second.as<float>();
      std::cout << " key: " << key << ", val: " << value << '\n';


    }
  }
}

The output will look likes this:

 key: 0, val: 0
 key: 1, val: 1.1
 key: 245, val: 250.1
 key: 0, val: 0.1
 key: 1, val: 1.3
 key: 200, val: 250
 key: 0, val: 0
 key: 1, val: 1.1
 key: 245, val: 250.1

Upvotes: 1

Related Questions