关于ROS下的Dynamic Reconfig的学习探索
来源:互联网 发布:app下载数据统计 编辑:程序博客网 时间:2024/06/05 23:59
Dynamic Reconfig是ROS比较厉害的一个地方,可以在程序运行的时候动态调整参数,ROS官网关于Dynamic Reconfig的讲解主要有三处
1. http://wiki.ros.org/dynamic_reconfigure/Tutorials
2. http://wiki.ros.org/roscpp_tutorials/Tutorials 最下面
3. http://wiki.ros.org/ROSNodeTutorialC++ 最下面
个人感觉第一个好一点,另外两个比较杂乱。下面就介绍自己关于Dynamic Reconfig学习过程,这里假定大家都做完了,Beginner tutorials的学习,即写一个Publisher ,subscriber,自定义的service(两个数字的加法)以及Msg的学习。
主要参考:
http://wiki.ros.org/dynamic_reconfigure/Tutorials/SettingUpDynamicReconfigureForANode
我的最终的文件目录如图
1.定义cfg文件
首先在catkin_ws/src/beginner_tutorials目录下建立一个名为cfg的文件夹,放入一个名为MyStuff.cfg的文件,这个文件的作用就是告诉ROS 到时侯我们需要动态调整的参数有哪些。
#! /usr/bin/env python # Forearm camera configurationPACKAGE='beginner_tutorials'import roslibroslib.load_manifest(PACKAGE)from math import pifrom driver_base.msg import SensorLevelsfrom dynamic_reconfigure.parameter_generator import *gen = ParameterGenerator()angles = gen.add_group("Angles")# Name Type Reconfiguration level# Description# Default Min Maxangles.add("min_ang", double_t, SensorLevels.RECONFIGURE_STOP, "The angle of the first range measurement. The unit depends on ~ang_radians.", -pi/2,-pi, pi)angles.add("max_ang", double_t, SensorLevels.RECONFIGURE_STOP, "The angle of the first range measurement. The unit depends on ~ang_radians.", pi/2, -pi, pi)gen.add("intensity", bool_t, SensorLevels.RECONFIGURE_STOP, "Whether or not the hokuyo returns intensity values.", False)gen.add("cluster", int_t, SensorLevels.RECONFIGURE_STOP, "The number of adjacent range measurements to cluster into a single reading", 1, 0, 99)gen.add("skip", int_t, SensorLevels.RECONFIGURE_STOP, "The number of scans to skip between each measured scan", 0, 0, 9)gen.add("port", str_t, SensorLevels.RECONFIGURE_CLOSE, "The serial port where the hokuyo device can be found", "/dev/ttyACM0")gen.add("calibrate_time", bool_t, SensorLevels.RECONFIGURE_CLOSE, "Whether the node should calibrate the hokuyo's time offset", True)gen.add("frame_id", str_t, SensorLevels.RECONFIGURE_RUNNING, "The frame in which laser scans will be returned", "laser")gen.add("time_offset", double_t, SensorLevels.RECONFIGURE_RUNNING, "An offet to add to the timestamp before publication of a scan", 0, -0.25, 0.25)gen.add("allow_unsafe_settings",bool_t, SensorLevels.RECONFIGURE_CLOSE, "Turn this on if you wish to use the UTM-30LX with an unsafe angular range. Turning this option on may cause occasional crashes or bad data. This option is a tempory workaround that will hopefully be removed in an upcoming driver version.", False)exit(gen.generate(PACKAGE, "dynamic_reconfigure_node", "MyStuff"))
这里尤其要注意最后一句的第三个参数,必须与config文件同名,我们的config文件名为MyStuff.cfg所以这里为Mytuff。而且第三个参数也决定着我们的config头文件的名称,后面埋个伏笔,头文件生成的名称为MyStuffConfig.h也即,第三个参数加上Config.h.
修改cfg文件的权限
chmod a+x MyStuff.cfg
2.修改依赖项
在manifest.xml文件中加入依赖项即:
<build_depend>dynamic_reconfigure</build_depend>
<build_depend>driver_base</build_depend>
<run_depend>dynamic_reconfigure</run_depend>
<run_depend>driver_base</run_depend>
3.创建server主函数
在src文件夹下建立一个名为dynamic_reconfigure_node.cpp的文件,代码如下,尤其注意这里的第二个头文件的包含,因为我发现编译的时候,生成的config的头文件编译时放在了cfg文件夹下的cpp文件夹中,这个是catkin_make(catkin_make __force-cmake)的时候创建的,但是按照官网的路径它查找不到,我们干脆拷贝到src文件夹下
#include <dynamic_reconfigure/server.h>#include "MyStuffConfig.h"#include <ros/ros.h>void callback(beginner_tutorials::MyStuffConfig &config, uint32_t level){ ROS_INFO("Reconfigure request : %f %f %i %i %i %s %i %s %f %i", config.groups.angles.min_ang, config.groups.angles.max_ang, (int)config.intensity, config.cluster, config.skip, config.port.c_str(), (int)config.calibrate_time, config.frame_id.c_str(), config.time_offset, (int)config.allow_unsafe_settings); // do nothing for now}int main(int argc, char **argv){ ros::init(argc, argv, "dynamic_reconfigure_node"); dynamic_reconfigure::Server<beginner_tutorials::MyStuffConfig> srv; dynamic_reconfigure::Server<beginner_tutorials::MyStuffConfig>::CallbackType f; f = boost::bind(&callback, _1, _2); srv.setCallback(f); ROS_INFO("Starting to spin..."); ros::spin(); return 0;}
4.关于CMakeList.txt的修改
这个文件相信大家不陌生,但是也是最头疼的地方,编译的错误好多都是设置不当引起的。我直接贴上来
cmake_minimum_required(VERSION 2.8.3)project(beginner_tutorials)find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation dynamic_reconfigure)################################################## Declare ROS messages, services and actions #################################################### To declare and build messages, services or actions from within this## package, follow these steps:## * Let MSG_DEP_SET be the set of packages whose message types you use in## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).## * In the file package.xml:## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET## * If MSG_DEP_SET isn't empty the following dependencies might have been## pulled in transitively but can be declared for certainty nonetheless:## * add a build_depend tag for "message_generation"## * add a run_depend tag for "message_runtime"## * In this file (CMakeLists.txt):## * add "message_generation" and every package in MSG_DEP_SET to## find_package(catkin REQUIRED COMPONENTS ...)## * add "message_runtime" and every package in MSG_DEP_SET to## catkin_package(CATKIN_DEPENDS ...)## * uncomment the add_*_files sections below as needed## and list every .msg/.srv/.action file to be processed## * uncomment the generate_messages entry below## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)## Generate messages in the 'msg' folder add_message_files( FILES Num.msg )## Generate services in the 'srv' folder add_service_files( FILES AddTwoInts.srv )## Generate actions in the 'action' folder# add_action_files(# FILES# Action1.action# Action2.action# )## Generate added messages and services with any dependencies listed heregenerate_messages( DEPENDENCIES std_msgs )# for dynamic reconfiguregenerate_dynamic_reconfigure_options( cfg/MyStuff.cfg )##################################### catkin specific configuration ####################################### The catkin_package macro generates cmake config files for your package## Declare things to be passed to dependent projects## INCLUDE_DIRS: uncomment this if you package contains header files## LIBRARIES: libraries you create in this project that dependent projects also need## CATKIN_DEPENDS: catkin_packages dependent projects also need## DEPENDS: system dependencies of this project that dependent projects also needcatkin_package( CATKIN_DEPENDS message_runtime)############# Build ############### Specify additional locations of header files## Your package locations should be listed before other locationsinclude_directories(${dynamic_reconfigure_PACKAGE_PATH}/cmake/cfgbuild.cmake)include_directories(${catkin_INCLUDE_DIRS})## Declare a cpp library# add_library(beginner_tutorials# src/${PROJECT_NAME}/beginner_tutorials.cpp# )## Declare a cpp executable# add_executable(beginner_tutorials_node src/beginner_tutorials_node.cpp)add_executable(talker src/talker.cpp)add_executable(listener src/listener.cpp)# for dynamic reconfigureadd_executable(dynamic_reconfigure_node src/dynamic_reconfigure_node.cpp)add_executable(add_two_ints_server src/add_two_ints_server.cpp)add_executable(add_two_ints_client src/add_two_ints_client.cpp)## Add cmake target dependencies of the executable/library## as an example, message headers may need to be generated before nodes# add_dependencies(beginner_tutorials_node beginner_tutorials_generate_messages_cpp)# for dynamic reconfigureadd_dependencies(dynamic_reconfigure_node beginner_tutorials_gencfg)# for python dynamic clientadd_dependencies(dynamic_reconfigure_node beginner_tutorials_generate_messages_cpp)add_dependencies(talker beginner_tutorials_generate_messages_cpp)add_dependencies(listener beginner_tutorials_generate_messages_cpp)add_dependencies(add_two_ints_server beginner_tutorials_gencpp)add_dependencies(add_two_ints_client beginner_tutorials_gencpp)## Specify libraries to link a library or executable target against# target_link_libraries(beginner_tutorials_node ${catkin_LIBRARIES} )# for dynamic reconfiguretarget_link_libraries(dynamic_reconfigure_node ${catkin_LIBRARIES})target_link_libraries(talker ${catkin_LIBRARIES})target_link_libraries(listener ${catkin_LIBRARIES})target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})############### Install ################ all install targets should use catkin DESTINATION variables# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html## Mark executable scripts (Python etc.) for installation## in contrast to setup.py, you can choose the destination# install(PROGRAMS# scripts/my_python_script# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}# )## Mark executables and/or libraries for installation# install(TARGETS beginner_tutorials beginner_tutorials_node# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}# )## Mark cpp header files for installation# install(DIRECTORY include/${PROJECT_NAME}/# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}# FILES_MATCHING PATTERN "*.h"# PATTERN ".svn" EXCLUDE# )## Mark other files for installation (e.g. launch and bag files, etc.)# install(FILES# # myfile1# # myfile2# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}# )############### Testing ################# Add gtest based cpp test target and link libraries# catkin_add_gtest(${PROJECT_NAME}-test test/test_beginner_tutorials.cpp)# if(TARGET ${PROJECT_NAME}-test)# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})# endif()## Add folders to be run by python nosetests# catkin_add_nosetests(test)关于dynamic reconfig的主要几句是
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
dynamic_reconfigure
)
generate_dynamic_reconfigure_options(
cfg/MyStuff.cfg
)
include_directories(${dynamic_reconfigure_PACKAGE_PATH}/cmake/cfgbuild.cmake)
add_executable(dynamic_reconfigure_node src/dynamic_reconfigure_node.cpp)这里生成可执行的node文件,node名字是dynamic_reconfigure_node
add_dependencies(dynamic_reconfigure_node beginner_tutorials_gencfg)也有写成${PROJECT_NAME}_gencfg的
target_link_libraries(dynamic_reconfigure_node ${catkin_LIBRARIES})生成可执行的node文件,node名字是dynamic_reconfigure_node
5.测试用的程序
测试用到的程序,其实我在这里仿照了http://wiki.ros.org/dynamic_reconfigure/Tutorials/中的client.py的写法,但是它的有个缺点,按照ros.rate(0.1)即0.1Hz也即10s一次,他会复位,就是你调整的参数10s后就由默认值替代了,我这里修改了一下,让他不会复位
在src中放入一个名为yakeclient.py的文件,这里就是客户端了
#!/usr/bin/env pythonPACKAGE = 'beginner_tutorials'import roslib;roslib.load_manifest(PACKAGE)import rospyimport dynamic_reconfigure.clientdef callback(config): rospy.loginfo("Config set to {min_ang}, {max_ang}, {intensity}, {cluster}, {skip}, {port}, {calibrate_time}, {frame_id}, {time_offset},{allow_unsafe_settings}".format(**config)) if __name__ == "__main__": rospy.init_node("yakeclient")# Client first argument is the node names client = dynamic_reconfigure.client.Client("dynamic_reconfigure_node", 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()6.编译并启动程序
7.对比官方教程
这里我们可以看到其实结构都是一样的,最主要的区别还是在于config文件的定义,而他是完全自由的,完全由设计者考虑,需要动态调整一些什么样子的参数。
从下面的这个详细的节点关系图,我们可以看出,其实rqt_reconfig也即图中的rqt_gui_py_node_9301,就是一个client。那个9507是rqt_graph
关掉我们自己的yakeclient如图所示。因此自己的那个client目前只有显示的作用,(即只能看到设定的值)。而rqt_reconfig则包含了设置与显示。所以一般情况下,我们所要做的就是写dynamic server,利用rqt_reconfig作为client来设定目标值。
8.总结
这些内容写起来容易,但是自己花了差不多两天才解决掉,其中主要卡在了cfg.h上,因为系统编译老是提示找不到它,如果你也有这样的问题,首先看看CMakeList.txt内容是否正确,二,就像我之前那样,生成的头文件居然放在cfg文件夹里了。还有就是Client.py文件的写法。我当时起得名字叫yakeclient.py,观察rqt_graph时的节点信息老是订阅不了topic
像上图中的一样,然后仔细查看才发现python中的文件第17行
这里我想当然理解为了package name其实它应该是publisher 的名称,也就是server的名称,这里我们的server节点是dynamic_reconfigure_node所以改完以后就Ok了。引以为戒。
- 关于ROS下的Dynamic Reconfig的学习探索
- ros下的plugin学习
- ROS探索总结(五)学习遇到的问题
- 关于ROS学习的一些反思
- ROS:关于tf的探索(1) Writing a tf broadcaster(Python)
- ROS:关于tf的探索(2)Writing a tf listener(Python)
- ROS:关于tf的探索(3)Adding a frame(Python)
- ROS:关于tf的探索(4)Learning about tf and time(Python)
- 关于网站搭建的学习探索(
- 我的SLAM探索(二)--ROS下编译运行Kinect Viewer
- ROS下利用 moveit 控制gazebo模型并在rviz中显示的探索总结
- ROS学习笔记二:探索ROS文件系统
- ROS学习历程(2)-----ROS的文件系统
- ros学习笔记--ros的服务
- 古月居关于ROS的导航部分要抽空学习一下
- ROS学习之关于服务的一些命令_总结
- ROS学习笔记:关于ROS与rduino之间数据传输的一点心得
- 关于ROS的个人见解
- hdu1698Just a Hook 线段树 成段更新水题
- 关于对快速幂超时问题的优化
- POJ 3691 DNA repair (AC自动机+dp)
- 如何向小白介绍何谓机器学习和数据挖掘?
- 动态数组求n个数的和还有平均数 --- 蓝桥杯
- 关于ROS下的Dynamic Reconfig的学习探索
- C#参数传递之值参数
- SqlServer Bug:扩展存储过程一直运行出现等待类型PREEMPTIVE_OS_GETPROCADDRESS
- win32练习-判断系统类型
- 蓝桥杯--高斯日记
- TOP-N分析
- HTTP响应代码汇总
- win32练习 - CreateThreadpoolWait()
- 操作系统内核的引导