当前位置: 首页 > news >正文

Boost库中Boost.PropertyTree使用和实战示例

Boost.PropertyTree 是一个轻量级、跨格式(JSON / XML / INI / INFO)配置数据管理库,特别适合 配置文件管理、参数解析、层级数据存储


1. PropertyTree 的核心概念

PropertyTree 就是一棵树(ptree)

boost::property_tree::ptree pt;

每个节点:

  • 可以有 子节点
  • 可以有 值(value)
  • 可以通过 key 访问

对应 JSON / XML 中的层级关系。


2. PropertyTree 支持的文件格式

格式特性
JSON✔️✔️常用于 SLAM 配置
XML✔️✔️常用于参数结构化更复杂场景
INI✔️✔️简单平铺型配置
INFO✔️✔️Boost 自己的配置格式

导入头文件:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/info_parser.hpp>

3. JSON 读写详解

3.1 读取 JSON 文件

ptree pt;
read_json("config.json", pt);

3.2 获取基本类型

double fx = pt.get<double>("camera.fx");
int width = pt.get<int>("image.width");
std::string dataset = pt.get<std::string>("path.dataset");

如果 key 不存在:

  • pt.get<T>() 会抛异常
  • pt.get<T>("key", default) 不会抛异常

例:

int threads = pt.get<int>("system.threads", 4);

4. 访问数组(JSON array)

Boost.PropertyTree 不支持原生 JSON 数组的类型,但提供了一种约定:
数组元素被视为多个同名子节点。

示例 JSON:

{"topics": {"subscribe": ["imu", "image", "lidar"]}
}

读取:

for (auto& v : pt.get_child("topics.subscribe")) {std::cout << v.second.get_value<std::string>() << std::endl;
}

注意:

  • v.first 是空字符串(因为数组没有键)
  • v.second 是子 node

5. 写 JSON

写简单 key-value

pt.put("camera.fx", 525.0);
pt.put("dataset.path", "/home/data");

写数组

ptree array;
ptree item;item.put("", "imu");
array.push_back(std::make_pair("", item));item.put("", "image");
array.push_back(std::make_pair("", item));pt.add_child("topics.subscribe", array);

保存:

write_json("out.json", pt);

6. 访问子节点(child)

ptree cam = pt.get_child("camera");
double fx = cam.get<double>("fx");

遍历子节点:

ptree& topics = pt.get_child("topics");
for (auto& kv : topics) {std::cout << kv.first << std::endl;
}

7. XML 读写详解

读 XML

ptree pt;
read_xml("config.xml", pt);

XML 特点:

  • 数据就是树,非常契合 ptree
  • 支持属性 <tag attr="value">

访问 XML 节点:

std::string name = pt.get<std::string>("config.camera.<xmlattr>.name");

<xmlattr> 节点专门保存属性。

写 XML

write_xml("out.xml", pt);

8. INI 读写详解

配置文件 ini:

[camera]
fx = 525
fy = 525

读取:

read_ini("config.ini", pt);
double fx = pt.get<double>("camera.fx");

写入:

write_ini("out.ini", pt);

9. INFO 文件读写

INFO 是 Boost 的配置格式,用法与 JSON / INI 类似:

camera
{fx 525fy 525
}

读写:

read_info("cfg.info", pt);
write_info("cfg_out.info", pt);

10. 判断 key 是否存在

if (auto child = pt.get_child_optional("camera")) {std::cout << "camera config exists\n";
}

获取 value 是否存在

if (auto opt = pt.get_optional<double>("camera.fx")) {double fx = opt.get();
}

这是 推荐写法,不会抛异常。


11. 强烈推荐的 SLAM 配置最佳实践

1) 通用配置读取函数

template <typename T>
T Read(const ptree& pt, const std::string& key, const T& default_val) {return pt.get<T>(key, default_val);
}

2) 自动打印所有参数(调试超实用)

void print_ptree(const ptree& pt, int level = 0) {for (auto& kv : pt) {for (int i = 0; i < level; i++) std::cout << "  ";std::cout << kv.first << ": " << kv.second.get_value<std::string>() << "\n";print_ptree(kv.second, level+1);}
}

3) 把参数加载成结构体(推荐 SLAM 做法)

struct CameraConfig {double fx, fy;double cx, cy;
};CameraConfig LoadCameraConfig(const ptree& pt) {CameraConfig c;c.fx = pt.get<double>("camera.fx");c.fy = pt.get<double>("camera.fy");c.cx = pt.get<double>("camera.cx");c.cy = pt.get<double>("camera.cy");return c;
}

比处处写 pt.get<> 更安全。


12. PropertyTree 的坑

1) 不支持非同名数组(JSON array 兼容性差)

如:

"points": [1, 2, 3]

Boost 支持,但复杂结构数组会有问题:

"points": [{"x": 1, "y": 2},{"x": 3, "y": 4}
]

需要:

for (auto &item : pt.get_child("points")) {double x = item.second.get<double>("x");
}

2) JSON 序列化时会多一个缩进或空白

通常无大碍,但不能精确复制原 JSON。

3) 不支持丰富 JSON 特性(null / bool / 原生 array)

只能用 string + number + child tree 表示。

4) 不是 JSON 专用库

Boost.PropertyTree 的定位是“配置树”,不是完整 JSON 实现。

需要强 JSON 支持 → 使用 nlohmann/json。


13. 简单示例:SLAM 配置读写(JSON)

配置文件 config.json

{"camera": {"fx": 525.0,"fy": 525.0,"cx": 319.5,"cy": 239.5},"topics": {"subscribe": ["imu", "image", "lidar"]}
}

读取:

ptree pt;
read_json("config.json", pt);double fx = pt.get<double>("camera.fx");
for (auto& v : pt.get_child("topics.subscribe")) {std::cout << v.second.get_value<std::string>() << "\n";
}

写出:

write_json("out.json", pt);

14、综合示例

下面是 Boost::PropertyTree 在 SLAM 工程中的完整配置模块模板的综合示例

  • 全部模块化封装
  • 跨 JSON / INI / XML / INFO
  • 自动校验参数
  • 自动打印所有配置
  • 支持结构体加载(Camera / IMU / Lidar / Backend)
  • 可直接作为 CMake 项目使用

这是工程级的 SLAM 配置系统,可直接嵌入自研 SLAM 框架。


目录结构

config/├── Config.h├── Config.cpp├── CameraConfig.h├── IMUConfig.h├── BackendConfig.h└── default_config.jsonsrc/└── main.cppCMakeLists.txt

1. Config 模块核心功能

功能说明
自动识别 JSON / INI / XML / INFO文件后缀自动选择解析器
缺省值自动填充get<T>(key, default)
参数不存在时警告不抛异常,便于 SLAM 工程稳定性
自动打印所有配置用于调试非常方便
参数结构体化camera / imu / lidar / backend 单独结构体
支持多文件合并可加载多个 config 文件叠加

2. Config.h(主配置系统头文件)

#pragma once
#include <boost/property_tree/ptree.hpp>
#include <string>
#include <memory>class Config
{
public:static bool Load(const std::string& file);static bool Has(const std::string& key);template<typename T>static T Get(const std::string& key, const T& default_val);template<typename T>static void Set(const std::string& key, const T& value);static void PrintAll();static boost::property_tree::ptree& Tree();private:static boost::property_tree::ptree pt_;static void LoadJson(const std::string& file);static void LoadIni(const std::string& file);static void LoadXml(const std::string& file);static void LoadInfo(const std::string& file);
};

3. Config.cpp(主逻辑)

#include "Config.h"
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <iostream>
#include <algorithm>boost::property_tree::ptree Config::pt_;bool Config::Load(const std::string& file)
{std::string ext;auto pos = file.find_last_of('.');if (pos != std::string::npos)ext = file.substr(pos+1);std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);try {if (ext == "json")      LoadJson(file);else if (ext == "xml")  LoadXml(file);else if (ext == "ini")  LoadIni(file);else if (ext == "info") LoadInfo(file);else {std::cerr << "[Config] Unsupported file type: " << ext << std::endl;return false;}}catch (std::exception& e) {std::cerr << "[Config] Load error: " << e.what() << std::endl;return false;}return true;
}void Config::LoadJson(const std::string& file) {boost::property_tree::read_json(file, pt_);
}
void Config::LoadXml(const std::string& file) {boost::property_tree::read_xml(file, pt_);
}
void Config::LoadIni(const std::string& file) {boost::property_tree::read_ini(file, pt_);
}
void Config::LoadInfo(const std::string& file) {boost::property_tree::read_info(file, pt_);
}bool Config::Has(const std::string& key)
{return bool(pt_.get_child_optional(key));
}template<typename T>
T Config::Get(const std::string& key, const T& default_val)
{return pt_.get<T>(key, default_val);
}template<typename T>
void Config::Set(const std::string& key, const T& value)
{pt_.put(key, value);
}boost::property_tree::ptree& Config::Tree() {return pt_;
}void PrintPT(const boost::property_tree::ptree& pt, int depth)
{for (auto& kv : pt) {for (int i=0; i<depth; i++) std::cout << "  ";std::cout << kv.first << ": " << kv.second.get_value<std::string>() << std::endl;PrintPT(kv.second, depth+1);}
}void Config::PrintAll()
{PrintPT(pt_, 0);
}// 注意:模板函数声明在 .h 中,定义也需在 .h 中或显式实例化
template int    Config::Get<int>(const std::string&, const int&);
template double Config::Get<double>(const std::string&, const double&);
template std::string Config::Get<std::string>(const std::string&, const std::string&);
template void Config::Set<int>(const std::string&, const int&);
template void Config::Set<double>(const std::string&, const double&);
template void Config::Set<std::string>(const std::string&, const std::string&);

4. CameraConfig.h

#pragma once
#include "Config.h"struct CameraConfig
{double fx = 0, fy = 0;double cx = 0, cy = 0;void Load() {fx = Config::Get<double>("camera.fx", 0);fy = Config::Get<double>("camera.fy", 0);cx = Config::Get<double>("camera.cx", 0);cy = Config::Get<double>("camera.cy", 0);}
};

5. IMUConfig.h

#pragma once
#include "Config.h"struct IMUConfig
{double gyro_noise = 0;double acc_noise = 0;double gyro_bias = 0;double acc_bias = 0;void Load() {gyro_noise = Config::Get<double>("imu.gyro_noise", 0.0);acc_noise  = Config::Get<double>("imu.acc_noise", 0.0);gyro_bias  = Config::Get<double>("imu.gyro_bias", 0.0);acc_bias   = Config::Get<double>("imu.acc_bias", 0.0);}
};

6. BackendConfig.h

#pragma once
#include "Config.h"struct BackendConfig
{int max_iterations = 10;double huber_delta = 1.0;void Load() {max_iterations = Config::Get<int>("backend.max_iter", 10);huber_delta    = Config::Get<double>("backend.huber_delta", 1.0);}
};

7. default_config.json(示例配置)

{"camera": {"fx": 525.0,"fy": 525.0,"cx": 319.5,"cy": 239.5},"imu": {"gyro_noise": 0.001,"acc_noise": 0.002,"gyro_bias": 0.0001,"acc_bias": 0.0002},"backend": {"max_iter": 20,"huber_delta": 1.0}
}

8. main.cpp

#include "Config.h"
#include "CameraConfig.h"
#include "IMUConfig.h"
#include "BackendConfig.h"int main()
{Config::Load("config/default_config.json");Config::PrintAll();CameraConfig cam;IMUConfig imu;BackendConfig backend;cam.Load();imu.Load();backend.Load();std::cout << "fx = " << cam.fx << std::endl;std::cout << "gyro_noise = " << imu.gyro_noise << std::endl;std::cout << "backend iter = " << backend.max_iterations << std::endl;return 0;
}

http://www.dtcms.com/a/610896.html

相关文章:

  • 公司网站维护建设费入什么科目广东华电建设股份有限公司网站
  • 上海营销型网站建设价格线上运营推广是做什么的
  • 织梦绿色企业网站模板 苗木企业网站源码 dedecms5.7内核WordPress 营利
  • 高端建设网站建设北京网站建设最好公司
  • 成都制作网站软件网站建设新闻稿
  • 网站地图格式wordpress安装虚拟主机
  • 代理模式啦
  • 自动化测试:Python开发IDE介绍
  • 国产操作系统调研报告:产业现状与未来方向
  • 好用的远程软件!ToDesk、向日葵、UU远程横测
  • 商务网站建设用的是什么软件成都比较好的设计公司
  • ESP32基础-PWM_步进电机
  • (修改认证方式、设置密码策略);)Zabbix安装(配置清华源、安装必要组件);)数据库初始化(创建库/用户、导入数据);)服... ...
  • 爱网站在线观看视频vi展示效果图
  • 网站ip地址查询域名网站建设388
  • 郑州网站建设价格wordpress编辑文章更新失败
  • 打造“移动的风景线”:RTMP推流平台EasyDSS无人机推流直播实现文旅宣传新形态
  • 测试测试测试测试测试
  • 异形零件自动化排列:整列机与传统振动盘的 5 大技术维度解析
  • google网站质量做网站的网页用什么软件好
  • 深度学习:正则化(Regularization)实践(无正则化 vs 有正则化(L2 正则化、Dropout))
  • 郑州网站seo优wordpress登陆代码
  • 网站建设哪家做的好一点网站图片链接是怎么做的
  • Pytorch性能调优简单总结
  • 探索回文诗歌的艺术:从Python视角理解语言的对称性
  • 【工具变量】全国质量强市示范城市DID数据(2000-2025年)
  • 网站优化与seo的区别内部优惠券网站怎么做
  • 开发网站软件重庆找工作最新招聘信息
  • C语言--详解--冒泡排序(Bubble Sort)
  • 网站图标icowordpress报表工具