前言
最近在做一个dwa导航算法的优化,准备对其代价函数动手,将固定的参数改为动态可调整的,并且要求要有一定控制(高)频率。
很多教程都是通过rqt_reconfigue包调参的,虽然有友好的操作界面,但无法满足高频控制的要求(还是手动的,就很蠢233),所以我参照roswiki的方法,实现一个动态调参的客户端,基于pyhton语言(因为C++没有0.0,但有方法,后文会提到)
本文只介绍如何编写client端,至于server端以后再开新坑(懒)
一、查看可动态调整的参数
要注意的是,ros里面不是所有的参数都可以动态调整的(一般来说大部分都是静态的),如果要动态调参,需要按照官方dynamic_reconfigure包的规则(创建cfg文件之类的),因此我们可以查看相关的.cfg文件,查找我们想要修改的参数。
比如我dwa_local_planner包中找到的.cfg文件:
gen.add("sim_time", double_t, 0, "The amount of time to roll trajectories out for in seconds", 1.7, 0)
gen.add("sim_granularity", double_t, 0, "The granularity with which to check for collisions along each trajectory in meters", 0.025, 0)
gen.add("angular_sim_granularity", double_t, 0, "The granularity with which to check for collisions for rotations in radians", 0.1, 0)
gen.add("path_distance_bias", double_t, 0, "The weight for the path distance part of the cost function", 0.6, 0.0)
gen.add("goal_distance_bias", double_t, 0, "The weight for the goal distance part of the cost function", 0.8, 0.0)
gen.add("occdist_scale", double_t, 0, "The weight for the obstacle distance part of the cost function", 0.01, 0.0)
...
这些名称的参数,就是我们可以动态调整的参数了
二、开写一个客户端
原理
直接上官方的代码:
import rospy
import dynamic_reconfigure.client
def callback(config):
rospy.loginfo("Config set to {int_param}, {double_param}, {str_param}, {bool_param}, {size}".format(**config))
if __name__ == "__main__":
rospy.init_node("dynamic_client")
client = dynamic_reconfigure.client.Client("dynamic_tutorials", timeout=30, config_callback=callback)
r = rospy.Rate(0.1)
x = 0
b = False
while not rospy.is_shutdown():
x = x+1
if x>10:
x=0
b = not b
client.update_configuration({"int_param":x, "double_param":(1/(x+1)), "str_param":str(rospy.get_rostime()), "bool_param":b, "size":1})
r.sleep()
官方的已经是最简单的一个demo了,但我再继续精简成三行重要代码
import rospy
import dynamic_reconfigure.client
if __name__ == "__main__":
rospy.init_node("dynamic_client")
client = dynamic_reconfigure.client.Client("dynamic_tutorials", timeout=30, config_callback=callback)
client.update_configuration({"int_param":x, "double_param":y, "str_param":z, "bool_param":a, "size":b})
很容易让人迷糊的就是这些参数名,有些是随便起的,有些是要固定名字的,怎么找到对应的名字,个人觉得这个才是难点!!! 接下来breakdown一下:
import rospy
import dynamic_reconfigure.client
导包,这两个包要是都没有还是重装ros吧
rospy.init_node("dynamic_client")
初始化一个节点,这个名字可以随便起(nice)
client = dynamic_reconfigure.client.Client("dynamic_tutorials", timeout=30, config_callback=callback)
初始化一个客户端(真的只有一行,这个太方便了),但是这个"dynamic_tutorials"就要写成你对应动态参数节点的名字了,可调参数节点就是给你提供动态参数调整的服务端。
client.update_configuration({"int_param":x, "double_param":y, "str_param":z, "bool_param":a, "size":b})
可通过字典的方式,更新你动态参数节点下的参数
实现的一些小trick
有一个简单的方法可以查看你的动态参数节点:运行动态参数服务端节点(如果是move_base之类的话肯定有一堆,或者是你自己实现的服务端),在命令行键入以下命令:
rosrun dynamic_reconfigure dynparam list
我打开导航节点,运行命令后有如下输出:
rosrun dynamic_reconfigure dynparam list
/amcl
/camera/image_raw/compressed
/camera/image_raw/compressedDepth
/camera/image_raw/theora
/move_base
/move_base/DWAPlannerROS
/move_base/GlobalPlanner
/move_base/global_costmap
/move_base/global_costmap/inflation_layer
/move_base/global_costmap/static_layer
/move_base/local_costmap
/move_base/local_costmap/inflation_layer
/move_base/local_costmap/obstacle_layer
/move_base/local_costmap/static_layer
找到你想要的那个参数对应的节点名,替换上面的"dynamic_tutorials"就可以了,我需要是/move_base/DWAPlannerROS:
client = dynamic_reconfigure.client.Client("/move_base/DWAPlannerROS", timeout=10, config_callback=callback)
我想要修改的参数上文提到过(就是之前的gen.add()),所以我就把path_distance_bias更新一下
client.update_configuration({"path_distance_bias" : 114514 })
三、验证
打开各位的rqt_reconfigure:
rosrun rqt_reconfigure rqt_reconfigure
看看自己想要改的参数是不是变了(不变就有鬼了)
写到这我发现,上文需要的动态参数节点名,可以在rqt_reconfigure界面直接查看 动态参数节点名和对应的参数名字都有,果然是教学相长啊(我之前绝对注意到了,不是现在才发现的)
至此结束(终于,写死我了
总结
想用C++的各位,我本身也是用C++的,但API官方到现在好像都还没有给出,不过还是提供了通过调用系统命令修改的方法(用处不大),示例:system("rosrun dynamic_reconfigure dynparam set_from_parameters camera_synchronizer_node narrow_stereo_trig_mode 3"); 个人在小车上测试下来,延时有六七秒左右,实时性不敢恭维
我在网上找动态调参资料的时候,好多人都用rqt_reconfigure的方法,很难找到我想要的代码的方法,所以自己决定写一个相关的博客,给各位作为参考。
参考资料:dynamic_reconfigure的roswiki
|