ROS古月居21讲笔记
文章目录
- 1.C++&python极简教程:
- 1.1安装编译器(python是解析器)
- 1.2 for循环
- 1.3 while循环
- 1.4 面向对象
- 2.ROS命令行工具
- 3.初始化操作
- 3.1创建工作空间:
- 3.2创建功能包
- 4.话题编程
- 4.1如何实现一个发布者
- 4.2如何实现一个订阅者
- 4.3编译代码
- 4.4自定义话题消息处理
- 5.通信编程——服务编程
- 5.1如何实现一个服务器
- 5.2如何实现一个客户端
- 5.3编译代码
- 6.参数的使用与编程方法
- 7.ROS坐标系管理系统
- 8.TF坐标系广播与实现
- 9.launch启动文件的使用方法
- 10.常用可视化工具的使用
- 10.1Qt工具箱
- 10.2Rviz
- 10.3Gazebo
1.C++&python极简教程:
1.1安装编译器(python是解析器)
sudo apt-get install g++
sudo apt-get install python
1.2 for循环
- python:
for a in range(5,10):if a< 10:print 'a = ',aa+=1else:break
- 使用Python解析器运行py程序
python fileName.py
1.3 while循环
- Python
a = 5
while a < 10:print 'a = ' , aa += 1
1.4 面向对象
- C++
#include <iostream>class A //用class定义为一个类
{public:int i; //变量:i代表一个属性void test() //输出i的值{std::cout << i <<std::endl;}
};int main()
{A a; //调用a的定义a.i = 10; //a里i的属性值a.test(); //测试a的值return 0;
}
- python
class A:i = 10def test(self)print self.i
a = A()
a.test()
2.ROS命令行工具
3.初始化操作
3.1创建工作空间:
- 创建工作空间
首先现在根目录下建立一个文件夹catkin_ws,再在下面建立src文件夹
mkdir -p -/catkin_ws/srccd -/catkin_ws/srccatkin_init_workspace初始化文件夹改变属性使其变成一个工作空间
(直接右键新建文件夹然后在src文件夹下打开终端输入这句话也行)
- 编译工作空间
catkin_make
编译产生deve(开发空间放置开发过程中的可执行文件和库)l和build(编译过程中的编译文件二进制文件)
- 设置环境变量
source devel/setup.bash
- 检查环境变量
echo $ROS_PACKAGE_PATH
将配置文件放入根目录下(方便以后使用)
vi ~/.bashrc
//在最下面复制地址修改成
//注意是修改为你文件所在的文件夹的地址,例如source /home/simon(你的用户名)/catkin_ws/setup.bash当然下述内容也可以
source ~/catkin_ws/devel/setup.bash
//然后按ESC,输入:wq退出
//这样就将环境变量设置到根目录了
或者进入到根目录下,按ctrl+H可以显示隐藏文件,然后打开.bashrc的文件夹,将上述的环境变量放入到文件的最后一行,即可完成工作
建立install空间:catkin_make install
3.2创建功能包
在src中创建一个pkg:
catkin_create_pkg 包名+依赖(roscpp rospy std_msgs(消息)右键新建也行但是创建功能包的依赖没有所以还得catkin_create_pkg)
cd src
#创建指令 #包名(文件名字) #依赖的功能包
catkin_create_pkg learning_communication std_msgs rospy roscpp
cd ..#返回上一个目录
catkin_make
同一个工作空间下,不允许存在同名功能包
不同工作空间下,允许存在同名功能包
4.话题编程
4.1如何实现一个发布者
- 在catkin_ws/src/learning_communication/src中建立talker和listener
- 初始化ROS节点
- 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
- 按照一定频率循环发布消息
/*** 该例程将发布chatter话题,消息类型String*/#include <sstream>
#include "ros/ros.h" //ros中常用的Api
#include "std_msgs/String.h" int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "talker");//定义节点的名称;// 创建节点句柄ros::NodeHandle n;//句柄管理发布者、订阅者的资源内容哦// 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);//发布者的消息类型为string //1000指代发布者的队列长度,如果速度过快或者对方来不及接受,发布者就会把数据放在队列里,当队列满了会将最早的数据删除// 设置循环的频率ros::Rate loop_rate(10);//定义一个10HZ的循环周期,100ms//通过以下代码,可以把chatter中的数据发送出去int count = 0; while (ros::ok()) {// 初始化std_msgs::String类型的消息std_msgs::String msg;std::stringstream ss;ss << "hello world " << count;//发送内容msg.data = ss.str();//将内容放到data里// 发布消息ROS_INFO("%s", msg.data.c_str());chatter_pub.publish(msg);//用publish的API接口把数据发送出去// 循环等待回调函数ros::spinOnce();//在这个程序中上面的语句没有意义//spinOnce只会查询一次回调函数队列,是否有数据进入 // 按照循环频率延时,按照100ms时间休眠,如果没有这个语句会导致CPU占用很高loop_rate.sleep();++count;}return 0;
}
4.2如何实现一个订阅者
- 初始化ROS节点
- 订阅需要的话题
- 循环等待话题消息,接收到消息后进入回调函数
- 在回调函数中完成消息处理
/*** 该例程将订阅chatter话题,消息类型String*/#include "ros/ros.h"
#include "std_msgs/String.h"// 接收到订阅的消息后,会进入消息回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{// 将接收到的消息打印出来ROS_INFO("I heard: [%s]", msg->data.c_str());//通过指针来访问
}int main(int argc, char **argv)//跟listener类似
{// 初始化ROS节点ros::init(argc, argv, "listener");// 创建节点句柄ros::NodeHandle n;// 创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback:通过多线程等待数据进入,如果数据进入,就进入回调函数ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);//订阅数据队列是1000// 循环等待回调函数ros::spin();return 0;
}
C++需要编译代码,python不需要
python版本代码:
- publisher
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twistimport rospy
from geometry_msgs.msg import Twistdef velocity_publisher():# ROS节点初始化rospy.init_node('velocity_publisher', anonymous=True)# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)#设置循环的频率rate = rospy.Rate(10) while not rospy.is_shutdown():# 初始化geometry_msgs::Twist类型的消息vel_msg = Twist()vel_msg.linear.x = 0.5vel_msg.angular.z = 0.2# 发布消息turtle_vel_pub.publish(vel_msg)rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.angular.z)# 按照循环频率延时rate.sleep()if __name__ == '__main__':try:velocity_publisher()except rospy.ROSInterruptException:pass
- listener
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Poseimport rospy
from turtlesim.msg import Posedef poseCallback(msg):rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)def pose_subscriber():# ROS节点初始化rospy.init_node('pose_subscriber', anonymous=True)# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallbackrospy.Subscriber("/turtle1/pose", Pose, poseCallback)# 循环等待回调函数rospy.spin()if __name__ == '__main__':pose_subscriber()
注意:为了使python文件有可执行权限,需要将python文件的属性进行修改:
点击python文件,在打开方式栏中点击允许作为程序执行文件
4.3编译代码
在CMakeLists.txt文件(这个文件配置编译选项)
将一个代码生成可执行文件,需要使用
add_executable(talker src/talker.cpp)
生成talker可执行文件/需要用talker.cpp文件生成
如果需要多个文件生成,就多添加文件进入其中
例如add_executable(talker src/talker.cpp 1.cpp 2.cpp)
很多文件生成需要第三方库,因此可以使用
target_link_libraries(talker ${catkin_LIBRARIES})
在这里没有使用其他第三方库,只是使用默认的catkin_LIBRARIES这个库就可以了
以上内容可以实现将talker.cpp变成可执行文件的过程,listener类似如下
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
然后回到工作路径catkin_ws中,使用catkin_make进行编译,编译结果如下:
打开devel文件目录,在lib文件下面有功能包文件夹,可以看到talker和listener的可编译文件
运行ros程序第一步,
先启动rosmaster
然后使用以下代码,结果如下
rosrun learning_communication talker
rosrun learning_communication listener
4.4自定义话题消息处理
- 在功能包下面,创建文件夹msg,在文件夹下面创建person.msg文件
- 在package.xml中添加功能包依赖,文件在功能包learning_communication中,在文件内容最下面添加两个依赖
<build_depend>message_generation</build_depend>//编译依赖
<exec_depend>message_runtime</exec_depend>//运行依赖
在Cmakelist中添加具体编译选项
- 通过添加message_generation来完成将话题消息转换成代码的操作,链接到这个库中
找到find package子函数,将代码添加到其中
在
catkin_package
这个子函数中,将CATKIN_DEPENDS roscpp rospy std_msgs
的注释取消,并在尾部添加message_runtime
添加以下代码来声明使用的那个msg文件
add_message_files(FILES Person.msg)//作为定义接口
generate_messages(DEPENDENCIES std_msgs)//依赖那些依赖的库
回到根目录下,使用catkin_make进行编译
在终端中输入 rosmsg show Person
可以查看是否定义成功
话题的操作使用:
C++_publisher:
/*** 该例程将发布/person_info话题,自定义消息类型learning_topic::Person*/#include <ros/ros.h>
#include "learning_topic/Person.h"//添加消息接口int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "person_publisher");// 创建节点句柄ros::NodeHandle n;// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);// 设置循环的频率ros::Rate loop_rate(1);int count = 0;while (ros::ok()){// 初始化learning_topic::Person类型的消息learning_topic::Person person_msg;person_msg.name = "Tom";person_msg.age = 18;person_msg.sex = learning_topic::Person::male;// 发布消息person_info_pub.publish(person_msg);ROS_INFO("Publish Person Info: name:%s age:%d sex:%d", person_msg.name.c_str(), person_msg.age, person_msg.sex);// 按照循环频率延时loop_rate.sleep();}return 0;
}
C++_listener:
/*** 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person*/#include <ros/ros.h>
#include "learning_topic/Person.h"// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{// 将接收到的消息打印出来ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d", msg->name.c_str(), msg->age, msg->sex);
}int main(int argc, char **argv)
{// 初始化ROS节点ros::init(argc, argv, "person_subscriber");// 创建节点句柄ros::NodeHandle n;// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);// 循环等待回调函数ros::spin();return 0;
}
python_publisher:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布/person_info话题,自定义消息类型learning_topic::Personimport rospy
from learning_topic.msg import Persondef velocity_publisher():# ROS节点初始化rospy.init_node('person_publisher', anonymous=True)# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)#设置循环的频率rate = rospy.Rate(10) while not rospy.is_shutdown():# 初始化learning_topic::Person类型的消息person_msg = Person()person_msg.name = "Tom";person_msg.age = 18;person_msg.sex = Person.male;# 发布消息person_info_pub.publish(person_msg)rospy.loginfo("Publsh person message[%s, %d, %d]", person_msg.name, person_msg.age, person_msg.sex)# 按照循环频率延时rate.sleep()if __name__ == '__main__':try:velocity_publisher()except rospy.ROSInterruptException:pass
python_listerner:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/person_info话题,自定义消息类型learning_topic::Personimport rospy
from learning_topic.msg import Persondef personInfoCallback(msg):rospy.loginfo("Subcribe Person Info: name:%s age:%d sex:%d", msg.name, msg.age, msg.sex)def person_subscriber():# ROS节点初始化rospy.init_node('person_subscriber', anonymous=True)# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackrospy.Subscriber("/person_info", Person, personInfoCallback)# 循环等待回调函数rospy.spin()if __name__ == '__main__':person_subscriber()
5.通信编程——服务编程
- 在功能包
learnig_communication
中建立srv
文件夹,添加一个定义文件AddTwoInts.srv
- 文件内容如下图所示,其中横线是将数据分为两大部分
- 在package.xml中添加功能包依赖,在上述操作中已经添加完毕,可以不需要再多添加
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
- 在CmakeList.txt文件中
在find_package
子函数中添加message_generation
在catkin_package
这个子函数中,将CATKIN_DEPENDS roscpp rospy std_msgs
的注释取消,并在尾部添加message_runtime
为了告诉系统我们需要使用那个srv文件,需要添加指令add_service_files(FILES AddTwoInts.srv)
然后进入到根目录中使用catkin_make进行编译,如没有红字则编译成功。在编译结果中可以看到系统生成了Python等其他语言的代码
5.1如何实现一个服务器
server代码:
/*** AddTwoInts Server*/#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h"// service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{// 将输入参数中的请求数据相加,结果放到应答变量中res.sum = req.a + req.b;ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);ROS_INFO("sending back response: [%ld]", (long int)res.sum);return true;
}int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "add_two_ints_server");// 创建节点句柄ros::NodeHandle n;// 创建一个名为add_two_ints的server,注册回调函数add()//利用ServiceServer定义一个定向的服务端对象,服务名为add_two_ints//add为回调函数,进行具体的服务处理ros::ServiceServer service = n.advertiseService("add_two_ints", add);// 循环等待回调函数ROS_INFO("Ready to add two ints.");ros::spin();return 0;
}
5.2如何实现一个客户端
/*** AddTwoInts Client*/#include <cstdlib>
#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h"int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "add_two_ints_client");// 从终端命令行获取两个加数if (argc != 3){ROS_INFO("usage: add_two_ints_client X Y");return 1;}// 创建节点句柄ros::NodeHandle n;// 创建一个client,请求add_two_int service,service消息类型是learning_communication::AddTwoIntsros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");// 创建learning_communication::AddTwoInts类型的service消息learning_communication::AddTwoInts srv;srv.request.a = atoll(argv[1]);srv.request.b = atoll(argv[2]);// 发布service请求,等待加法运算的应答结果//call是阻塞命令,如果没有消息会一直阻塞,程序不会进行下去if (client.call(srv)){ROS_INFO("Sum: %ld", (long int)srv.response.sum);}else{ROS_ERROR("Failed to call service add_two_ints");return 1;}return 0;
}
5.3编译代码
在CMakeLists.txt文件(这个文件配置编译选项)将下面的代码复制进去,原理与上述一致
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)//在这里生成自定义的请求和应答数据内容,将依赖添加到server和client中
add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)
然后回到根目录用catkin_make,可以在devel/lib/learning_communication中看到生成的文件
先使用roscore,然后再使用图中命令会实现上述效果。
再启动客户端时需要添加参数,例如3,4。
6.参数的使用与编程方法
首先先创建功能包,还是在src文件夹下打开终端
$ catkin_create_pkg learning_parameter roscpp rospy std_srvs
以小海龟案例为例:
打开小海龟例程
roscore
rosrun turtlesim turtlesim_node
rosparam list查看参数
rosparam get /参数名 获取参数
rosparam set /参数名 变量值 修改变量的数值
rosservice call /clear "{}" 服务器根据请求获取新的参数值
rosparam dump 文件名 运行后不会有提示,但是会在里的目录保存参数文件
rosparam load 文件名 从文件中读取参数
rosparam delet 参数名
在你设置的文件夹中添加代码,例如learning_parameter
C++代码
/*** 该例程设置/读取海龟例程中的参数*/
#include <string>
#include <ros/ros.h>
#include <std_srvs/Empty.h>int main(int argc, char **argv)
{int red, green, blue;// ROS节点初始化ros::init(argc, argv, "parameter_config");// 创建节点句柄ros::NodeHandle node;// 读取背景颜色参数ros::param::get("/background_r", red);ros::param::get("/background_g", green);ros::param::get("/background_b", blue);ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);// 设置背景颜色参数ros::param::set("/background_r", 255);ros::param::set("/background_g", 255);ros::param::set("/background_b", 255);ROS_INFO("Set Backgroud Color[255, 255, 255]");// 读取背景颜色参数ros::param::get("/background_r", red);ros::param::get("/background_g", green);ros::param::get("/background_b", blue);ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);// 调用服务,刷新背景颜色ros::service::waitForService("/clear");ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");std_srvs::Empty srv;clear_background.call(srv);sleep(1);return 0;
}
添加编译规则:
add_executable(parameter_config src/parameter_config.cpp)
target_link_libraries(parameter_config ${catkin_LIBRARIES})
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
#上三步为初始配置程序
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_parameter parameter_config
Python中
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程设置/读取海龟例程中的参数import sys
import rospy
from std_srvs.srv import Emptydef parameter_config():# ROS节点初始化rospy.init_node('parameter_config', anonymous=True)# 读取背景颜色参数red = rospy.get_param('/background_r')green = rospy.get_param('/background_g')blue = rospy.get_param('/background_b')rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)# 设置背景颜色参数rospy.set_param("/background_r", 255);rospy.set_param("/background_g", 255);rospy.set_param("/background_b", 255);rospy.loginfo("Set Backgroud Color[255, 255, 255]");# 读取背景颜色参数red = rospy.get_param('/background_r')green = rospy.get_param('/background_g')blue = rospy.get_param('/background_b')rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的servicerospy.wait_for_service('/clear')try:clear_background = rospy.ServiceProxy('/clear', Empty)# 请求服务调用,输入请求数据response = clear_background()return responseexcept rospy.ServiceException, e:print "Service call failed: %s"%eif __name__ == "__main__":parameter_config()
7.ROS坐标系管理系统
安装实例安装包
$ sudo apt-get install ros-melodic-turtle-tf
$ roslaunch turtle_tf turtle_tf_demo.launch
#启动一个脚本文件
$ rosrun turtlesim turtle_teleop_key
#用键盘控制海龟运动
$ rosrun tf view_frames
#TF中小工具,可以看到机器人的坐标变化的底层原理
rosrun tf tf_echo 目标坐标系1 目标坐标系2
#可以看到两个坐标系的变化程度
$ rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz
#将两个坐标进行可视化处理
8.TF坐标系广播与实现
$ cd ~/catkin_ws/src
$ catkin_create_pkg learning_tf roscpp rospy tf turtlesim
C++
/*** 该例程产生tf数据,并计算、发布turtle2的速度指令*/#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>std::string turtle_name;void poseCallback(const turtlesim::PoseConstPtr& msg)
{// 创建tf的广播器static tf::TransformBroadcaster br;// 初始化tf数据tf::Transform transform;transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );//设置平移参数,相对于x,y的平移位置tf::Quaternion q;q.setRPY(0, 0, msg->theta);//两个坐标系的姿态变化的数据设置transform.setRotation(q);// 广播world与海龟坐标系之间的tf数据 //当前时间 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));//将姿态广播出去,添加一个时间戳
}int main(int argc, char** argv)
{// 初始化ROS节点ros::init(argc, argv, "my_tf_broadcaster");// 输入参数作为海龟的名字if (argc != 2){ROS_ERROR("need turtle name as argument"); return -1;}turtle_name = argv[1];//获取海龟的名字// 订阅海龟的位姿话题ros::NodeHandle node;//创建句柄ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);//订阅海龟的位置消息,得到消息,就跳到poseCallback// 循环等待回调函数ros::spin();//等待数据,有数据就跳到call backreturn 0;
};
监听器的编写
/*** 该例程监听tf数据,并计算、发布turtle2的速度指令*/#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>//调用spawn服务产生第二只海龟int main(int argc, char** argv)
{// 初始化ROS节点ros::init(argc, argv, "my_tf_listener");// 创建节点句柄ros::NodeHandle node;// 请求产生turtle2ros::service::waitForService("/spawn");ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");turtlesim::Spawn srv;add_turtle.call(srv);// 创建发布turtle2速度控制指令的发布者ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);// 创建tf的监听器tf::TransformListener listener;ros::Rate rate(10.0);while (node.ok()){// 获取turtle1与turtle2坐标系之间的tf数据tf::StampedTransform transform;try{//查询是否有这两个坐标系,查询当前时间,如果超过3s则报错listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));//等待系统中是否存在这两个乌龟,等待三秒如果不存在就会超时//ros会保存十秒的数据,我们查询最新的数据listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);}catch (tf::TransformException &ex) {ROS_ERROR("%s",ex.what());ros::Duration(1.0).sleep();continue;}// 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令geometry_msgs::Twist vel_msg;vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),transform.getOrigin().x());vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +pow(transform.getOrigin().y(), 2));turtle_vel.publish(vel_msg);rate.sleep();}return 0;
};
配置tf广播器与监听器代码的编译原则
add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
$ rosrun turtlesim turtlesim_node
$ rosrun learning_tf turtle_tf_broadcaster name:=turtle1_tf_broadcaster /turtle1
#这句话会取代初始化节点的名字
$ rosrun learning_tf turtle_tf_broadcaster name:=turtle2_tf_broadcaster /turtle2
#这句话会取代初始化节点的名字
$ rosrun learning_tf turtle_tf_listener
$ rosrun turtlesim turtle_teleop_key
Python版广播器的编写:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Personimport roslib
roslib.load_manifest('learning_tf')
import rospyimport tf
import turtlesim.msgdef handle_turtle_pose(msg, turtlename):br = tf.TransformBroadcaster()br.sendTransform((msg.x, msg.y, 0),tf.transformations.quaternion_from_euler(0, 0, msg.theta),rospy.Time.now(),turtlename,"world")if __name__ == '__main__':rospy.init_node('turtle_tf_broadcaster')turtlename = rospy.get_param('~turtle')rospy.Subscriber('/%s/pose' % turtlename,turtlesim.msg.Pose,handle_turtle_pose,turtlename)rospy.spin()
Python版监听器的编写:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Personimport roslib
roslib.load_manifest('learning_tf')
import rospy
import math
import tf
import geometry_msgs.msg
import turtlesim.srvif __name__ == '__main__':rospy.init_node('turtle_tf_listener')listener = tf.TransformListener()rospy.wait_for_service('spawn')spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)spawner(4, 2, 0, 'turtle2')turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)rate = rospy.Rate(10.0)while not rospy.is_shutdown():try:(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):continueangular = 4 * math.atan2(trans[1], trans[0])linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)cmd = geometry_msgs.msg.Twist()cmd.linear.x = linearcmd.angular.z = angularturtle_vel.publish(cmd)rate.sleep()
9.launch启动文件的使用方法
Launch文件 :通过XML文件实现多节点的配置和启动(可自动启动ROS Master)
Launch文件语法:
output:控制节点是否将日志信息打印到节点中
respawn:节点启动中挂掉后是否重启
required:launch中要求必须启动
ns:命名空间,防止重复
ards:给每个节点输入参数
实例操作:
catkin_create_pkg learning_launch
在新建的文件夹中建立文件夹launch(方便管理功能包中的资源)
simple_launch:
<launch><node pkg="learning_topic" type="person_subscriber" name="talker" output="screen" />#成功后不打印文本信息<node pkg="learning_topic" type="person_publisher" name="listener" output="screen" />
</launch>
#可以修改文本显示为xml,就会有高亮显示
输入roslaunch+功能包名+功能包中launch文件名
启动launch文件
turtlesim_parameter_config.launch:
<launch><param name="/turtle_number" value="2"/>#设置变量名和值,在外面添加命名是为了添加命名空间,防止外面有一个冲突<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"><param name="turtle_name1" value="Tom"/><param name="turtle_name2" value="Jerry"/><rosparam file="$(find learning_launch)/config/param.yaml" command="load"/>#加载一个参数文件,$(find为系统指令、后面为文件名/文件夹/文件</node><node pkg="turtlesim" type="turtle_teleop_key" name="turtle_teleop_key" output="screen"/></launch>
start_tf_demo_c++.launch:
启动两个海龟跟随案例
<launch><!-- Turtlesim Node--><node pkg="turtlesim" type="turtlesim_node" name="sim"/>#启动海龟控制器<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>#启动键盘控制节点<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle1" name="turtle1_tf_broadcaster" />#启动控制节点 name是取代type的名字,让一个程序启动两次,而args是为节点命名<node pkg="learning_tf" type="turtle_tf_broadcaster" args="/turtle2" name="turtle2_tf_broadcaster" /><node pkg="learning_tf" type="turtle_tf_listener" name="listener" />#启动listener</launch>
turtlesim_remap.launch
remap和include的使用案例:
<launch><include file="$(find learning_launch)/launch/simple.launch" />包含之前的simple文件<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"><remap from="/turtle1/cmd_vel" to="/cmd_vel"/>#to后面名字替换前面的</node></launch>
10.常用可视化工具的使用
10.1Qt工具箱
输入rqt,会显示一个rqt完整的工具箱,在上方工具栏调用工具。
10.2Rviz
数据显示平台
先启动roscore
,在输入rosrun rviz rviz
或者直接输入rviz
也可以
10.3Gazebo
三维仿真平台
输入roslaunch gazebo_ros +(模拟运行环境)
ROS古月居21讲笔记相关推荐
- ROS初学者的笔记(基于古月居21讲)——P11 订阅者Subsciber的编程实现
学习日期:2022.7.24 初始化节点 创建节点句柄 创建subscriber,订阅需要的话题 循环等待话题消息,接受到消息后进入到回调函数 在回调函数中完成消息处理 回调函数的作用是,subcri ...
- 古月居21讲学习笔记 10—15讲总结 话题VS服务
模型对比 话题模型 服务模型 数据类型 两种数据在建立的时候都建议放在一个单独的文件夹内方便管理 话题消息 msg文件 服务数据 srv文件 自定义数据创建流程(统一) 1.定义对应的msg/srv文 ...
- 古月居21讲 第17-18讲学习日记 tf坐标系
第17讲配置及操作参考链接 https://blog.csdn.net/takedachia/article/details/122602199 实操总结 修改完各种配置之后,要运行rosrun tf ...
- 【古月居ROS 21讲】精简理清 - 速刷古月居ROS21讲 ROS概念全过程
速刷古月居ROS21讲概念全过程 ROS的概念:对应第七讲 通讯机制 节点 (Node)-- 执行单元 节点管理器(ROS Master) 话题和消息 话题(Topic) -- 异步通信机制 消息(M ...
- 古月居ROS入门21讲笔记
ROS入门21讲笔记--古月居 1 C++&Python极简基础 1.1 安装编译/解析器 1.2 for循环 1.3 while循环 1.4 面向对象 2. ROS基础 2.1 ROS概念 ...
- 小白向:古月居ROS21讲自学笔记,看一下这个就大概了解这套课程讲什么啦!
看完这个还能不知道ROS是啥?! 第1讲 课程介绍 第2讲 Linux系统介绍及安装 第3讲 Linux系统基础操作 软件源 命令行 第4讲 C++&Python极简基础 第5讲 安装ROS系 ...
- ROS入门21讲笔记(一)基本概念
一.核心概念 1.1 节点(Node)和节点管理器(ROS Master) 节点是什么? 完成某个任务的进程 节点名具有唯一性 节点管理器可以做什么? 节点的注册和命名 完成.记录节点之间的通信 参数 ...
- 【ROS入门21讲二刷古月居】学习笔记3 发布者Publisher的编程实现
系列文章目录 第一章 ROS命令行工具 第二章 创建工作空间与功能包 第三章 发布者Publisher的编程实现 文章目录 系列文章目录 话题模型 第一步,创建功能包 如何实现一个发布者 包含库 初始 ...
- ROS2 学习古月居ros21讲学习笔记
ROS21讲学习笔记 在Ubuntu上安装的是ros2 foxy 启动小海龟 ros2 run turtlesim turtlesim_node 启动键盘控制 ros2 run turtlesim t ...
最新文章
- 一个简单的缓冲区溢出的思考
- 关于Spark NLP学习,你需要掌握的LightPipeline(附代码)| CSDN博文精选
- Fedora 30系统的升级方法
- java properties读取 封装_java properties 文件读取踩坑记
- JQUERY的size()与length
- 无迹卡尔曼滤波(UKF)详解
- 微软总部首席测试专家做客中关村图书大厦“说法”
- 网络摄像机如何安装拾音器?进行同步录音
- Element UI快速入门
- scp远程传输文件之权限被拒绝解决方案
- 广州岑村科目二a考场,第一次考满分通过
- zjhu1016密码锁
- 51单片机基础理论知识(会补充)
- 零基础也能用ChatGPT写代码,简直不要太爽
- 如何使用按图搜索(拍立淘)获取商品数据
- extundelete工具恢复rm -rf 删除的目录(ext4、ext3)
- summernote 的快速使用,以及解决图片写入数据库问题
- qq聊天机器人 群发工具 (java版) (一)
- 1-LTE Network Architecture: Basic
- janus视频房间插件协议整理