编程技巧
ROS设置参数:
https://www.jianshu.com/p/02ee8f513295
1. rosrun + 参数服务器传递
ros::init(argc, argv, "imu2txt"); ros::NodeHandle nh("~"); std::string file_name; nh.param<std::string>("file_name", file_name, "./imu_data.txt");
首先在节点初始化之后获取参数服务器的参数,并设置初始值,如上面的程序就是在参数服务器的~
空间(即节点本身)获取名字为"file_name"
的参数放到std::string file_name
中,默认参数为后面那个。
接着就可以rosrun了。下面是命令
rosrun package node _parameter:=value
在我们这里就是
rosrun datatxt imu2txt _file_name:=~/Documents/test.txt
就可以将节点内的参数改为想要的值了
注意: string不需要加双引号,string第一个字符不能是数字
2. roslaunch + 参数服务器传递
同样是上面的例子,我们如果想通过roslaunch来调用的话,可以像下面这样,将参数放在node之间。
<launch> <node name="imu2txt" pkg="data2txt" type="imu2txt" respawn="false" output="screen" > <param name="file_name" type="string" value="/home/night_fury/Documents/record_bags/calibration/imudata_to_wall.txt"/> </node> </launch>
3. rosrun + main参数传递
int main(int argc, char** argv)
main函数有两个参数argc, argv。argc = length(argv),argv[0]是程序的名字,argv[1]到argv[argc - 1]是传递给程序的参数,按空格分割参数后以char指针的形式存储。这是C、C++的特性,跟ros无关,你编写的C++程序也可以这么用。你编写的ros程序甚至可以直接运行,并通过这种方式传递参数,而不用rosrun或者roslaunch。
比如我们常用的map_server、rosbag就是用的这种参数传递方式。
rosrun map_server map_saver -f ~/Documents/test
或者直接找到二进制文件后map_saver -f ~/Documents/test
像上面这样运行程序,那么
argc=3 argv[0]="map_server" argv[1]="-f" argv[0]="test"
4. roslaunch + main参数传递
续上,如果使用main参数传递,那在roslaunch应该怎么样呢?如下,使用args
:
<launch> <node name="map_server" pkg="map_server" type="map_server" args="$(find costmap_2d)/test/willow-full-0.025.pgm 0.025" /> <node name="rosplay" pkg="rosbag" type="play" args="-s 5 -r 1 --clock --hz=10 $(find costmap_2d)/test/simple_driving_test_indexed.bag" /> </launch>
一、通过main函数
参数保存在main函数的argc和argv变量中
int main(int argc, char** argv) { ros::init(argc, argv, "param_test"); if(argc > 1) { for(int i=1; i<argc; i++) { std::cout<<"argv["<<i<<"] "<<argv[i]<<std::endl; } } return 0; }
1)rosrun启动
rosrun param_test param_test arg1 arg2
输出结果:
argv[1] arg1 argv[2] arg2
2)也可以找到可执行程序 param_test 所在的目录,直接在目录下运行
./param_test arg1 arg2
3)roslaunch启动,要用到结点的args属性
新建lanuch文件
<launch> <node pkg="param_test" type="param_test" name="param_test" args="arg1 arg2" output="screen"/> </launch>
输出结果同 1)
缺点是如果参数变化,每次都要修改launch文件。
4)还有一种方式是3)方法的改进,使用arg元素在命令行动态传参
<launch> <arg name="my_args" default="arg1 arg2"/> <node pkg="param_test" type="param_test" name="param_test" args="$(arg my_args)" output="screen"/> </launch>
my_args的默认参数是"arg1 arg2",启动launch,给my_args赋值arg3 arg4
roslaunch param_test param_test.launch my_args:="arg3 arg4"
输出结果:
argv[1] arg3 argv[2] arg4
二、通过参数服务器
int main(int argc, char** argv) { ros::init(argc, argv, "param_test"); //全局命名空间 ros::NodeHandle n; std::string n_arg; n.param<std::string>("n_arg",n_arg,"default_arg1"); std::cout<<"n_arg="<<n_arg<<std::endl; //私有命名空间 std::string pn_arg; ros::NodeHandle pn("~"); pn.param<std::string>("pn_arg",pn_arg,"default_arg2"); std::cout<<"pn_arg="<<pn_arg<<std::endl; return 0; }
1)roslaunch+arg
新建launch文件
<launch> <arg name="arg1" default="this is arg1" /> <arg name="arg2" default="this is arg2" /> <param name="n_arg" value="$(arg arg1)" /> <node pkg="param_test" type="param_test" name="param_test" output="screen"> <param name="pn_arg" value="$(arg arg2)"/> </node> </launch>
roslaunch param_test param_test.launch arg2:=wooow
输出结果:
n_arg=this is arg1 pn_arg=wooow
2)rosrun启动,并指定私有参数~parameter,注意“~”用下划线代替。
rosrun param_test param_test _pn_arg:=hahahaha
输出结果:
n_arg=default_arg1
pn_arg=hahahaha