[英]How to emit or write a map of maps in yaml file? c++
所以我有几个虚拟护目镜……每个都有不同的校准参数。 我决定将这些参数保存到一个 yaml 文件中(作为配置文件)……每个护目镜都有自己的序列号/识别号……然后根据这个编号,我选择要使用的那个。 如果没有预先保存的护目镜信息。 我校准它并将这些参数添加到文件中
所以现在我正在尝试写入一个如下所示的 yaml 文件:
Headset:
IdentificationNumber: b630cc42-9a03-42da-a039-0e023cf5b090
GyroOffset:
GyroX:
Value: -0.013776619
GyroY:
Value: -0.016475508
GyroZ:
Value: -0.0114268782
这就是我实际得到的:
Headset2:
IdentificationNumber: b630cc42-9a03-42da-a039-0e023cf5b090
? GyroOffset:
GyroX:
Value: -0.013776619
? GyroY:
Value: -0.016475508
: GyroZ:
Value: -0.0114268782
我不明白我做错了什么! .. 这是我写入 yaml 文件的函数:
void ParseInputDeviceYaml::addCalibrationToConfigFile(const char* identificationNumber, const float* in)
{
try {
std::ofstream updatedFile;
updatedFile.open(m_filename.toStdString(), std::ios::app);
std::map<std::string, std::string> IDNumber;
std::map<std::string, std::map<std::string, float>> gyroXOffset;
std::map<std::string, std::map<std::string, float>> gyroYOffset;
std::map<std::string, std::map<std::string, float>> gyroZOffset;
IDNumber["IdentificationNumber"] = identificationNumber;
gyroXOffset["GyroX"]["Value"] = *in;
gyroYOffset["GyroY"]["Value"] = *(in + 1);
gyroZOffset["GyroZ"]["Value"] = *(in + 2);
YAML::Emitter newNode;
newNode << YAML::BeginMap;
newNode << YAML::Key << "Headset2";
newNode << YAML::Value << YAML::BeginMap << YAML::Key << "IdentificationNumber" << YAML::Value << identificationNumber << YAML::EndMap;
newNode << YAML::BeginMap << YAML::Key << "GyroOffset" << YAML::Value << gyroXOffset << gyroYOffset << gyroZOffset << YAML::EndMap;
newNode << YAML::EndMap;
updatedFile << newNode.c_str() << "\n";
updatedFile.close();
} catch (std::exception& e) {
LOG4CPLUS_FATAL(m_logger, e.what());
throw std::runtime_error(QObject::tr("Writing gyroscope offsets ").toStdString());
}
}
主要问题似乎是您建立在大量错误信息的基础上。 我会试着澄清一些事情:
std::ios::app
附加到文件,这将始终创建一个新条目。 相反,您应该将文件加载到 YAML 节点中,修改该节点的内容,然后写回整个节点。? GyroOffset
? GyroOffset
在同一深度为Headset2:
使其成为同级Headset2
。 另请注意,在同一映射中将隐式 ( foo:
) 与显式 ( ? foo
) 键混合是一种极端情况,可能会混淆某些实现。 YAML 文件可以简单地如下所示:Headset2:
IdentificationNumber: b630cc42-9a03-42da-a039-0e023cf5b090
GyroOffset:
GyroX:
Value: -0.012388126
GyroY:
Value: -0.0155748781
GyroZ:
Value: -0.0115196211
为了使您的代码更具可读性,我建议使用辅助类来访问您的值。 假设上面的代码是整个 YAML 文件,它可能如下所示:
struct Value {
YAML::Node data;
// access existing node
explicit Value(YAML::Node data): data(data) {
assert(data.IsMapping());
}
// create new node
explicit Value(float value) {
data["Value"] = value;
}
float get() { return data["Value"].as<float>(); }
void set(float value) { data["Value"] = value; }
};
struct GyroOffset {
YAML::Node data;
explicit GyroOffset(YAML::Node data): data(data) {
assert(data.IsMapping());
}
GyroOffset(float x, float y, float z) {
data["GyroX"] = Value(x).data;
data["GyroY"] = Value(y).data;
data["GyroZ"] = Value(z).data;
}
Value gyroX() { return Value(data["GyroX"]); }
Value gyroX() { return Value(data["GyroY"]); }
Value gyroZ() { return Value(data["GyroZ"]); }
};
struct Headset {
YAML::Node data;
Headset(YAML::Node data): data(data) {
assert(data.IsMapping());
}
Headset(const char *id) {
data["IdentificationNumber"] = id;
// initialize with zero values
data["GyroOffset"] = GyroOffset(0, 0, 0).data;
}
std::string id() { return data["IdentificationNumber"].as<std::string>(); }
void setId(const char *value) { data["IdentificationNumber"] = value; }
GyroOffset gyroOffset() { return GyroOffset(data["GyroOffset"]); }
}
现在,找到给定标识号的 GyroOffset 看起来像这样(我展示了一个简单的函数,因为我不知道您类的字段,因为您没有显示它们):
// write found values to output of found
bool findHedasetGyroOffset(Yaml::Node &input /* the file as shown above */, const char *id, GyroOffset &output) {
for (auto it = input.begin(); it != input.end(); ++it) {
Headset hs(it->second);
if (hs.id() == id) {
output = hs.gyroOffset();
return true;
}
}
return false;
}
由于YAML::Node
基本上是一个引用,因此当您更改返回的GyroOffset
值时,原始数据会发生变化。 然后,您可以将根节点写回文件(而不是附加它)并拥有一个更新的文件。
附加一个新耳机看起来像这样:
void addCalibrationToConfigFile(Yaml::Node &file, const char* identificationNumber, const float* in) {
Headset newHs(identificationNumber);
auto go = newHs.gyroOffset();
go.gyroX().set(*in);
go.gyroY().set(*(in + 1));
go.gyroZ().set(*(in + 2));
// note that this will overwrite an existing Headset2
file["Headset2"] = newHs.data;
}
虽然我试图坚持你展示的结构,但我觉得映射中的实际键不应该是Headset2
,而是 IdentificationNumber:
b630cc42-9a03-42da-a039-0e023cf5b090:
Name: Headset2
GyroOffset:
GyroX:
Value: -0.012388126
GyroY:
Value: -0.0155748781
GyroZ:
Value: -0.0115196211
由于您根据 ID 进行查找,这会更有意义。 此外,创建新配置实际上会起作用(目前,由于硬编码的"Headset2"
值,如果存在,它将始终覆盖该耳机)。
当心,我写的代码只是作为演示,并没有测试它; 可能有错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.