文章目录

  • 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创建工作空间:

  1. 创建工作空间

首先现在根目录下建立一个文件夹catkin_ws,再在下面建立src文件夹

 mkdir -p -/catkin_ws/srccd -/catkin_ws/srccatkin_init_workspace初始化文件夹改变属性使其变成一个工作空间
(直接右键新建文件夹然后在src文件夹下打开终端输入这句话也行)
  1. 编译工作空间
catkin_make
编译产生deve(开发空间放置开发过程中的可执行文件和库)l和build(编译过程中的编译文件二进制文件)
  1. 设置环境变量
source devel/setup.bash
  1. 检查环境变量
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如何实现一个发布者

  1. 在catkin_ws/src/learning_communication/src中建立talker和listener
  2. 初始化ROS节点
  3. 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
  4. 按照一定频率循环发布消息
/*** 该例程将发布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如何实现一个订阅者

  1. 初始化ROS节点
  2. 订阅需要的话题
  3. 循环等待话题消息,接收到消息后进入回调函数
  4. 在回调函数中完成消息处理
/*** 该例程将订阅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.通信编程——服务编程

  1. 在功能包learnig_communication中建立srv文件夹,添加一个定义文件AddTwoInts.srv
  2. 文件内容如下图所示,其中横线是将数据分为两大部分
  3. 在package.xml中添加功能包依赖,在上述操作中已经添加完毕,可以不需要再多添加
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
  1. 在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讲笔记相关推荐

  1. ROS初学者的笔记(基于古月居21讲)——P11 订阅者Subsciber的编程实现

    学习日期:2022.7.24 初始化节点 创建节点句柄 创建subscriber,订阅需要的话题 循环等待话题消息,接受到消息后进入到回调函数 在回调函数中完成消息处理 回调函数的作用是,subcri ...

  2. 古月居21讲学习笔记 10—15讲总结 话题VS服务

    模型对比 话题模型 服务模型 数据类型 两种数据在建立的时候都建议放在一个单独的文件夹内方便管理 话题消息 msg文件 服务数据 srv文件 自定义数据创建流程(统一) 1.定义对应的msg/srv文 ...

  3. 古月居21讲 第17-18讲学习日记 tf坐标系

    第17讲配置及操作参考链接 https://blog.csdn.net/takedachia/article/details/122602199 实操总结 修改完各种配置之后,要运行rosrun tf ...

  4. 【古月居ROS 21讲】精简理清 - 速刷古月居ROS21讲 ROS概念全过程

    速刷古月居ROS21讲概念全过程 ROS的概念:对应第七讲 通讯机制 节点 (Node)-- 执行单元 节点管理器(ROS Master) 话题和消息 话题(Topic) -- 异步通信机制 消息(M ...

  5. 古月居ROS入门21讲笔记

    ROS入门21讲笔记--古月居 1 C++&Python极简基础 1.1 安装编译/解析器 1.2 for循环 1.3 while循环 1.4 面向对象 2. ROS基础 2.1 ROS概念 ...

  6. 小白向:古月居ROS21讲自学笔记,看一下这个就大概了解这套课程讲什么啦!

    看完这个还能不知道ROS是啥?! 第1讲 课程介绍 第2讲 Linux系统介绍及安装 第3讲 Linux系统基础操作 软件源 命令行 第4讲 C++&Python极简基础 第5讲 安装ROS系 ...

  7. ROS入门21讲笔记(一)基本概念

    一.核心概念 1.1 节点(Node)和节点管理器(ROS Master) 节点是什么? 完成某个任务的进程 节点名具有唯一性 节点管理器可以做什么? 节点的注册和命名 完成.记录节点之间的通信 参数 ...

  8. 【ROS入门21讲二刷古月居】学习笔记3 发布者Publisher的编程实现

    系列文章目录 第一章 ROS命令行工具 第二章 创建工作空间与功能包 第三章 发布者Publisher的编程实现 文章目录 系列文章目录 话题模型 第一步,创建功能包 如何实现一个发布者 包含库 初始 ...

  9. ROS2 学习古月居ros21讲学习笔记

    ROS21讲学习笔记 在Ubuntu上安装的是ros2 foxy 启动小海龟 ros2 run turtlesim turtlesim_node 启动键盘控制 ros2 run turtlesim t ...

最新文章

  1. 一个简单的缓冲区溢出的思考
  2. 关于Spark NLP学习,你需要掌握的LightPipeline(附代码)| CSDN博文精选
  3. Fedora 30系统的升级方法
  4. java properties读取 封装_java properties 文件读取踩坑记
  5. JQUERY的size()与length
  6. 无迹卡尔曼滤波(UKF)详解
  7. 微软总部首席测试专家做客中关村图书大厦“说法”
  8. 网络摄像机如何安装拾音器?进行同步录音
  9. Element UI快速入门
  10. scp远程传输文件之权限被拒绝解决方案
  11. 广州岑村科目二a考场,第一次考满分通过
  12. zjhu1016密码锁
  13. 51单片机基础理论知识(会补充)
  14. 零基础也能用ChatGPT写代码,简直不要太爽
  15. 如何使用按图搜索(拍立淘)获取商品数据
  16. extundelete工具恢复rm -rf 删除的目录(ext4、ext3)
  17. summernote 的快速使用,以及解决图片写入数据库问题
  18. qq聊天机器人 群发工具 (java版) (一)
  19. 1-LTE Network Architecture: Basic
  20. janus视频房间插件协议整理

热门文章

  1. mysql 取当天、昨天、上一个月、当前月和下个月数据
  2. Matlab:创建复数
  3. 吉他六线谱制作软件有哪些 吉他六线谱怎么用电脑制作
  4. lz77优化_压缩时间:10种最佳压缩算法
  5. Android线程间通信
  6. hurdle模型matlab实现,HURDLE MODEL在STATA中的实现
  7. scratch案例——幸运大转盘
  8. deepin商店不能安装软件,解决方法出来了,快看
  9. 历年上海市计算机一级选择题,计算机一级考试选择题历年真题.doc
  10. 广工物理实验报告-分光计的使用和三棱镜折射率的测定