一、在ROS底下使用.yaml文件配置參數
在ROS底下用起來還是非常方便的,首先,寫一個讀參數的函數getParam(),由於參數類型不止一種,所以要使用模板。
具體語句如下:
template<typename T> T getParam(const string& name,const T& defaultValue) //This name must be namespace+parameter_name { T v; if(ros::param::get(name,v)) //get parameter by name depend on ROS. { ROS_INFO_STREAM("Found parameter: "<<name<<",\tvalue: "<<v); return v; } else ROS_WARN_STREAM("Cannot find value for parameter: "<<name<<",\tassigning default: "<<defaultValue); return defaultValue; //if the parameter haven't been set,it's value will return defaultValue. } //How use. int main(int argc,char** argv) { ros::init(argc,argv,"readyaml"); ros::NodeHandle nh; getParam<int>("readyaml/int",0); getParam<float>("readyaml/float",0.5); getParam<string>("readyaml/string","NotFound"); getParam<bool>("readyaml/bool",false); return 0; }
那么怎么設置參數?看代碼。
<launch> <node pkg="readyaml" type="readyaml" name="readyaml" clear_params="true" output="screen"> <!-- First way: direct set--> <param name="int" value="32760"/> <!-- Second way: use .yaml file--> <rosparam file="$(find readyaml)/rosYaml.yaml"/> </node> </launch>
rosYaml.yaml文件里寫的什么?
#parameter_name: value
string: HaveFound
float: 3.14159
bool: true
程序運行結果:

二、使用Ubuntu下的yaml-cpp
只要在CMakeLists.txt文件中添加相應聲明,就可以在程序中使用Ubuntu下一個關於yaml文件的一個庫,也是非常方便。
要添進去的語句如下:
FIND_LIBRARY(YAML_CPP_LIBRARIES yaml-cpp)
筆者裝的是yaml的庫,也可以安裝package版本,CMakeLists.txt中添加的語句可以改成:
FIND_LIBRARY(YAML_CPP_LIBRARIES yaml-cpp)
if(NOT YAML_CPP_LIBRARIES)
# If yaml-cpp not found in the system, try finding it as a user CMake-generated project
FIND_PACKAGE(yaml-cpp REQUIRED)
INCLUDE_DIRECTORIES(${YAML_CPP_INCLUDE_DIRS})
endif(NOT YAML_CPP_LIBRARIES)
然后,在構建可執行文件時添加相應的依賴
target_link_libraries(use_yaml ${YAML_CPP_LIBRARIES})
下面說怎么使用,
第一步,使用YAML::LoadFile()函數加載yaml文件;
如果參數沒有“歸屬”(自己的理解,下面會解釋),直接使用as()函數讀取該參數;
如果參數有“歸屬”,先找到參數的主體,再使用as()讀取該參數;
說的不清楚,看程序吧。
//自己重寫的讀參數的函數,形參依次是,參數的主體(YAML::Node)、參數名(string)、默認值(和參數的類型一致) template<typename T> T getParam(const YAML::Node& node,const string& name,const T& defaultValue) { T v; try { v=node[name].as<T>(); //讀取參數 std::cout<<"Found parameter: "<<name<<",\tvalue: "<<v<<std::endl; //終端提示讀取成功 } catch (std::exception e) { //找不到該參數的話,將返回默認值 v=defaultValue; std::cout<<"Cannot find parameter: "<<name<<",\tassigning default: "<<v<<std::endl; } return v; } int main() { //加載參數文件 YAML::Node dset_config = YAML::LoadFile("/home/liban/cfiles/Learn_basic/data/test.yaml"); //這里的title0,title1就可以看作其參數的主體 YAML::Node title0=dset_config["title0"]; YAML::Node title1=dset_config["title1"]; //參數single沒有“歸屬“,所以第一個形參為dset_config getParam<string>(dset_config,"single","cannot"); //Int,Str可以看作title0的屬性,Int_,Str_看作title1的屬性。 getParam<int>(title0,"Int",0); getParam<string>(title0,"Str","Null"); getParam<int>(title1,"Int_",0); getParam<string>(title1,"Str_","Null"); return 0; }
yaml文件里怎么寫的?
title0:
Int: 360
Str: helloworld!
title1:
Int_: 480
Str_: success!
single: can
注意事項:
不要用Tab,用空格!用空格!用空格!
程序運行結果截圖:

三、想不到OpenCV庫里也有讀取yaml參數的功能
主要是使用一個cv::FileStorage()函數用來加載參數文件
還是和前面一樣,自己重寫一個函數讀參數 。 。 。
不再細說,直接看demo
template<typename T> T getParam(const cv::FileStorage& file,const string& key) { T v=T(file[key]); // Core sentence,read parameter. std::cout<<"Found parameter: "<<key<<",\tvalue: "<<v<<std::endl; return v; } int main() { string filename="Path to yaml-file"; // Load yaml-file. cv::FileStorage file_=cv::FileStorage(filename,cv::FileStorage::READ); // If cannot find yaml-file. if(file_.isOpened()==false) { std::cerr<<"yaml-file "<<filename<<" does not exist."<<std::endl; file_.release(); return 1; } getParam<string>(file_,"#data"); // Test '#'. getParam<string>(file_,"Str"); getParam<int>(file_,"Int"); getParam<float>(file_,"Float"); ... return 0; }
yaml-file里的數據
%YAML:1.0
#data: cannot
Int: 120
Float: 3.145926
Str: helloworld!
執行結果:

注意事項:
(1) yaml文件開頭一定要加上"%YAML:1.0";
(2) 可以使用'#'注釋文件內容,效果如上截圖;
(3) 如果數據類型為字符串,字符串不能以數字開頭,否則讀不出來(這個也許可以解決,只是沒找着方法);
