非代码
一、创建工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
二、创建功能包
cd (workspace)/src
catin_create_pkg (name) std_msgs rospy roscpp
三、编译
catkin_make或者catkin build
#单个包的情况下是一样的,前者相当于cmake多个包同时编译,后者会将所有的包同时单独(isolated)编译,编译过程互不影响。
source devel/setup.bash或者zsh
四、查看ros相关的环境变量
env | grep ros
#ros会从ROS_PACKAGE_PATH中依次查找
五、查找功能包
rospack find (name)#找到功能包的位置
六、运行功能包
rosrun 功能包 可执行文件名字#需要roscore
roslaunch 功能包 launch文件名#不需要roscore
七、自定义话题消息
#查看可用基本msg
rosmsg list
#查看msg信息
rosmsg show
#定义msg文件
string name
uint8 age
uint8 unknown=0
uint8 male=1
uint8 female=2
#在package.xml中添加
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
#在CMakeLists.txt中添加
find_package(message_generation)
catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime)
add_message_files(FILES (NAME).msg)
generate_messages(DEPENDENCIES std_msgs)
add_executable(listener src/listener.cpp )
add_dependencies(listener topic_demo_generate_messages_cpp)#这个用于生成自定义msg的h文件
target_link_libraries(listener ${catkin_LIBRARIES})
八、话题相关
rostopic list#查看所有发布的话题
rostopic hz (name)#查看话题的发布频率
rostopic echo (name)#查看话题内容
rostopic pub +话题名+话题类型+需要改的参数以及值 #发布话题
rostopic info
九、节点相关
rosnode list
rosnode info
rosnode kill
十、rosbag相关
rosbag play name.bag -d 2 -l -r 0.5 #延迟两秒,以0.5倍播放速度循环播放rosbag
rosbag info name.bag#查看rosbag信息
rosbag record 话题名字#记录话题名 #所有话题-a
十、params相关
launch文件中也可以
这个是指运行xacro.py文件,传入robot.xacro参数,这个运行的结果给到robot_description。
一般情况使用
相当于rosparam load file_name
#我在写代码过程中学习到了怎么从yaml文件中读取数组,特别记录一下,里面的路径都没修改,只是作为参考
#.launch文件中,放在全局位置,也就是<node>外面
<rosparam command="load" file="$(find process_data)/params/sensor_covariance.yaml" />
#注意位置,如果在<node后面,</node>前,所有的参数前面要加个“/命名空间”,空间名就是你的节点名“name”。
#.yaml文件中
imu_orientation_covariance: [8e-4 , 8e-4 , 8e-4]
#这里使用double或者科学计数法都可以
#.cpp文件中
double imu_ori_co[3];
XmlRpc::XmlRpcValue config;
n.getParam("imu_orientation_covariance", config);
#或者,提供默认值的版本
#n.param<vector<string>>("imu_orientation_covariance", config,XmlRpc::XmlRpcValue() )
#转为double
std::ostringstream ostr;
ostr << config[i];
std::istringstream istr(ostr.str());
istr >> imu_orientation_covariance[i];
#默认值用数组或许比vector更好??
#不知道是不是获取到参数,可以用n.hasParam("name"),也可以用上面两个返回的bool判断
十一、launch相关
十二、tf树
rosrun rqt_tf_tree rqt_tf_tree
十三、服务service相关
rosservice list
rosservice info
rosservice call
rossrv list
rossrv show
十四、行为action相关
分客户端和服务端,服务端可以回传status、result和feedback给客户端,客户端给服务端goal和cancel指令,所以服务端可以被另外的客户端抢断或者被客户端发来的请求抢断。通常用与长时间、可抢占的任务中。
-
.action文件
#package.xml中加入
<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>
#Cmakelist.txt中加入
find_package(catkin REQUIRED actionlib_msgs actionlib)
add_action_files(DIRECTORY action FILES DoDishes.action)
generate_messages(DEPENDENCIES actionlib_msgs)
3、编写
//服务端
#include <ros/ros.h>
#include <actionlib/server/simp1e_action_server.h>
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionServer<learning_communication::DoDishesAction> Server;
// 收到action的goa1后调用该回调函数
void execute (const learning_communication::DoDishesGoalConstPtr& goal, Server* as)
{
ros::Rate r(1);
1earning_communication::DoDishesFeedback feedback;
ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id) ;
//按照1hz的频率发布进度feedback
for(int i=1; i<=10; i++)
{
feedback.percent_complete = i * 10;
as->publishFeedback(feedback) ;
r.sleep() ;
}
ROS_ INFO ("Dishwasher %d finish working.", goal->dishwasher_id);
as->setSucceeded();
}
int main(int argc, char** argv)
{
ros::init(argc,argv, "do_dishes_server") ;
ros::NodeHandle n;
//定义一个服务器
Server server(n, "do_dishes", boost::bind(&execute,_1, &server) ,false) ;
//服务器开始运行
server.start();
ros::spin() ;
return 0;
}
#客户端
#include <action1ib/client/simp1e_action_client.h>
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionClient<learning_communication::DoDishesAction> Client;
//当action完成后会调用该回调函数一次
void doneCb (const actionlib::SimpleClientGoalState& state ,const learning_communication::DoDishesResultConstPtr& result)
{
ROS_INFO("Yay! The dishes are now clean") ;
ros::shutdown() ;
}
// 当action激活后会调用该回调函数一 次
void activeCb ()
{
ROS_INFO("Goal just went active") ;
}
//收到feedback后调用该回调函数
void feedbackCb (const learning_ communication: :DoDi shesFeedbackConstPtr& feedback)
{
ROS_INFO(" percent_ complete: %f ",feedback->percent_complete);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "do_dishes_client") ;
//定义一个客户端
Client client("do_dishes", true) ;
//等待服务器端
ROS_INFO("Waiting for action server to start.");
client.waitForServer();
ROS_INFO("Action server started, sending goal.");
//创建一个action的goal
learning_communication::DoDishesGoal goal ;
goal.dishwasher_id = 1;
//发送action的goal给服务器端,并且设置回调函数
client.sendGoal(goal,&doneCb, &activeCb, &feedbackCb) ;
ros::spin() ;
return 0;
}
十五、常用rqt
rqt_graph显示节点和话题的连接关系
rqt_plot动态绘制曲线(如果wsl中遇到窗口无法控制的情况,rqt_plot --clear-config)
rqt_console查看日志
十六、C++编程
#订阅+发布topic
class sub_pub
{
public:
sub_pub(){
sub = n.subscribe("IMU", 1, &sub_pub::Callback , this);
pub = n.advertise<[your msgs_type]>("outtopic", 1);
}
void callback(const [sensor_msgs::Imu]::Ptr &msg);
//topic_demo::gps::ConstPtr &msg值不可修改,消息类型自行修改
ros::NodeHandle n;
//n.getParam("imu_topic", imu_topic);
ros::Subscriber sub;
ros::Publisher pub;
};
void sub_pub::Callback(const sensor_msgs::Imu::Ptr &msg)
{
//。。。。一顿操作
pub.publish(msg);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "【你的节点名字】");
sub_pub sub_pub;
ros::spin(); //这里也可以用while循环中用ros::spinOnce()
return 0;
}
十七、多线程
参考:
(9条消息) 【ROS】回调的多线程问题_ros 回调函数 多线程_Amelie_xiao的博客-优快云博客
1、pub.cpp
//
// Created by uestc213 on 23-7-24.
//
//这段代码主要是实现定时向Topic发布消息
#include "ros/ros.h"
#include <boost/thread.hpp>
#include <std_msgs/String.h>
int main(int argc, char **argv){
ros::init(argc, argv, "multi_publisher");
ros::NodeHandle n;
ros::Publisher pub_1 = n.advertise<std_msgs::String>("topic_1", 1, true);
ros::Publisher pub_2 = n.advertise<std_msgs::String>("topic_2", 1, true);
ros::Publisher pub_3 = n.advertise<std_msgs::String>("topic_3", 1, true);
int count = 0;
//创建一个ros::Timer每1秒进行发布,回调函数采用lamda4方法的格式
ros::Timer timer = n.createTimer(ros::Duration(1),
[&](const ros::TimerEvent&)
{
std_msgs::String msg;
std::stringstream ss;
ss << "topic1: " << count;
msg.data = ss.str();
pub_1.publish(msg);
std::stringstream ssa;
ssa << "topic2: " << 100+count;
msg.data = ssa.str();
pub_2.publish(msg);
std::stringstream ssab;
ssab << "topic3: " << 200+count;
msg.data = ssab.str();
pub_3.publish(msg);
++count;
});
//确保定时器回调被调用
ros::spin();
return 0;
}
2、sub.cpp
//
// Created by uestc213 on 23-7-25.
//
//为每个subscriber指定队列
#include <ros/ros.h>
#include <boost/thread.hpp>
#include <std_msgs/String.h>
#include <ros/callback_queue.h>
//回调函数,注意参数是const类型的boost::shared_ptr指针
void Callback1(const std_msgs::StringConstPtr& msg)
{
ROS_INFO_STREAM("Thread["<< boost::this_thread::get_id()
<<"],before topic1:"<< msg->data.c_str());
//循环
boost::this_thread::sleep(boost::posix_time::seconds(1.2));
ROS_INFO_STREAM("Thread["<< boost::this_thread::get_id()
<<"], topic1:"<< msg->data.c_str());
}
void Callback2(const std_msgs::StringConstPtr& msg)
{
ROS_INFO_STREAM("Thread["<< boost::this_thread::get_id()
<<"],topic2:"<< msg->data.c_str());
}
//回调函数,注意参数是const类型的boost::shared_ptr指针
void Callback3(const std_msgs::StringConstPtr& msg)
{
ROS_INFO_STREAM("Thread["<< boost::this_thread::get_id()
<<"],topic3:"<< msg->data.c_str());
boost::this_thread::sleep(boost::posix_time::seconds(2));
}
int main(int argc, char **argv){
ros::init(argc, argv, "multi_subscriber");
ros::NodeHandle n;
ros::SubscribeOptions ops;
ops.init<std_msgs::String>("topic_1", 1, Callback1);
ops.allow_concurrent_callbacks = true;
ros::Subscriber sub1 = n.subscribe(ops);
//ros::Subscriber sub1 = n.subscribe("topic_1", 1, Callback1);
ros::Subscriber sub2 = n.subscribe("topic_2", 1, Callback2);
ros::NodeHandle n_1;
ros::CallbackQueue my_queue;
n_1.setCallbackQueue(&my_queue);
ros::SubscribeOptions ops3;
ops3.init<std_msgs::String>("topic_3", 1, Callback3);
ops3.allow_concurrent_callbacks = true;
ros::Subscriber air_sub = n_1.subscribe(ops3);
ROS_INFO_STREAM("Thread["<< boost::this_thread::get_id()<<"]This is main thread.");
ros::AsyncSpinner spinner(2);
spinner.start();
//启动一个线程处理AirQuality单独的队列
ros::AsyncSpinner spinner_1(2, &my_queue);
spinner_1.start();
ros::waitForShutdown();
}
十八、结合boost::bind
(9条消息) 【C++】ROS与boost:bind()详解_Amelie_xiao的博客-优快云博客
十九、nodelet学习
分享一个不错的记录
本文详细介绍了ROS(RobotOperatingSystem)的开发流程,包括创建工作空间和功能包、编译、管理话题和节点、使用rosbag、参数配置、服务和行为的实现,以及多线程编程的应用。还提到了rqt工具的使用和相关命令行工具,如`rostopic`、`rosnode`等。
824

被折叠的 条评论
为什么被折叠?



