mkdir catkin_ws
创建一个catkin编译的工作空间cd catkin_ws
进入到catkin_wsmkdir src
再创建一个src的文件夹,这个是必须的cd ../..
回到最外层的目录sudo chmod -R 777 catkin_ws
对整个工作空间及子目录进行可读可执行可操作的赋权catkin_make
在工作空间内执行catkin_make生成所需要的基本框架cd src
进入srccatkin_create_pkg test1
创建一个test1的packagecatkin_create_pkg test2 roscpp rospy std_msgs nav_msgs
创建一个带有依赖的test2的package,roscpp用来cpp,rospy用于python脚本,std_msgs消息,以及导航专门用的nav_msgsgit clone [email protected]:DroidAITech/ROS-Academy-for-Beginners.git
克隆一个别人的packagessh-keygen -t rsa -C "[email protected]"
生成git的公钥,否则git没有权限cd catkin_ws
回到catkin_ws目录rosinstall --from-paths src --ignore-src --rosdistro=melodic -y
安装所有package会用到的依赖,rosdistro需要和ubuntu版本对应,所有用到的依赖可以在每个package中的package.xml的build中找到source ~/catkin_ws/devel/setup.bash
加载当前的环境echo "source ~/catkin_ws/devel/setup.bash " >> ~/.bashrc
这样就不用每次再加载一次环境,打开一个bash自动加载好rospack find test2
rospack find命令可以直接找到相应的packagerosls topic_demon
rosls 可以直接列出package下的内容roscore
启动master,rosout日志输出(warn,error等), parameter server参数服务器rosrun [pkg_name] [node_name]
启动一个节点rosnode list
列出当前运行的node的信息rosnode info [node_name]
显示某个node的详细信息rosnode kill [node_name]
结束某个noderoslaunch [pkg_name] [file_name.launch]
, 可以在pkg中建立一个launch文件夹,xx.launch 专门用来启动多个节点,一般命名为xx_bringup, 不用死记硬背,找别人的模板看着改roslaunch robot_sim_demo robot_spawn.launch
启动sim仿真,比较卡,应该看看网上有没有什么优化的策略rosnode list
列出当前有哪些noderosnode info xxx
列出xxx节点的具体信息rosrun robot_sim_demo robot_keyboard_teleop.py
按ijkl就可以控制仿真中机器人的前后左右运动rosrun image_view image_view image:=camera/rgb/image_raw
可以看到摄像头看到的画面。rostopic list
列出当前所有topicrostopic info /topic_mame
显示某个topic的属性信息rostopic echo /topic_name
显示某个topic的内容rostopic pub /topic_name ...
向某个topic发布内容rosmsg list
列出系统上所有的msgrosmsg show /msg_name
显示某msg的内容rosservice list
列出当前所有活跃的servicerosservice info service_name
显示某个service的属性信息rosservice call service_name args
调用某个service,eg:rosservice call /go/delte_light 'light_name: 'sun''
,删除gazebo中的sun灯光rossrv list
列出系统上所有的srvrossrv show srv_name
显示某个srv内容roscore
时候已经启动parameter serverrosparam list
列出当前所有的参数rosparam get param_key
显示某个参数的值rosparam set param_key param_value
设置某个参数的值rosparam dump file_name
保存参数到文件中rosparam load file_name
从文件中读取参数,yaml格式:key:valuerosparam delete param_key
删除参数rviz
可以启动rqt_graph
显示通信架构,当前有哪些node,哪些topic,数据流rqt_plot
绘制曲线,比如odo的速度,imu的数据等。rosbag record
记录某些topic到bag中rosbag record -a
记录所有的topic到bag中rosbag play
回放bagvoid ros::init();
解析ROS参数,为本node命名ros::NodeHandle
是一个类
ros::Publisher advertise(const string &topic, uint32_t queue_size);
创建话题的publisherros::Subscriber subscribe(const string &topic, uint32_t queue_size, void(*)(M));
创建话题的subscriberros::ServiceServer advertiseService(const string &service, bool(*srv_func)(Mreq &, Mres &));
创建服务的serverrosServiceClient serviceClient(const string &service_name, bool persistent=false);
创建服务的clientbool getParam(const string &key, void &val);
查询某个参数的值bool setParam(const string &key, void val);
给某个参数赋值ros::masters
是一个namespace
bool check();
检查master是否启动const string& getHost();
返回master所处的Hostnamebool getNodes(V_string &nodes);
从master返回已知的node名称列表bool getTopics(V_Topicinfo &topics);
返回所有正在被发布的topic列表bool getURl();
返回到master的URl地址,如http://host:port/
uint32_t getPort();
返回master运行在的端口ros::this_node
是一个namespace
void getAdvertisedTopics(V_string &topics);
返回本node发布的topicconst string &getName();
返回当前node的名称const string &getNamespace();
返回当前node的命名空间void getSubscribedTopics(V_string &topics);
返回当前node订阅的topicros::service
是一个namespace
bool call(const string &service, Service &service);
调用一个RPC服务ServiceClient createClient(const string& service_name, bool persistent=false, const M_string &header_value=M_string());
创建一个服务的clientbool exists(const string& service_name, bool print_failure_reason);
确认服务可调用bool waitForService(const string &service_name, int32_t timeout);
等待一个服务,直到它可以调用catkin_create_pkg topic_demo roscpp rospy std_msgs
mkdir msg
gedit gps.msg
//ROS头文件
#include
//自定义msg产生的头文件
#include
int main(int argc, char **argv)
{
//用于解析ROS参数,第三个参数为本节点名
ros::init(argc, argv, "talker");
//实例化句柄,初始化node
ros::NodeHandle nh;
//自定义gps msg
topic_demo::gps msg;
msg.x = 1.0;
msg.y = 1.0;
msg.state = "working";
//创建publisher
ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info", 1);
//定义发布的频率
ros::Rate loop_rate(1.0);
//循环发布msg
while (ros::ok())
{
//以指数增长,每隔1秒更新一次
msg.x = 1.03 * msg.x ;
msg.y = 1.01 * msg.y;
ROS_INFO("Talker: GPS: x = %f, y = %f ", msg.x ,msg.y);
//以1Hz的频率发布msg
pub.publish(msg);
//根据前面定义的频率, sleep 1s
loop_rate.sleep();//根据前面的定义的loop_rate,设置1s的暂停
}
return 0;
}
//ROS头文件
#include
//包含自定义msg产生的头文件
#include
//ROS标准msg头文件
#include
void gpsCallback(const topic_demo::gps::ConstPtr &msg)
{
//计算离原点(0,0)的距离
std_msgs::Float32 distance;
distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2));
//float distance = sqrt(pow(msg->x,2)+pow(msg->y,2));
ROS_INFO("Listener: Distance to origin = %f, state: %s",distance.data,msg->state.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback);
//ros::spin()用于调用所有可触发的回调函数。将进入循环,不会返回,类似于在循环里反复调用ros::spinOnce()。
ros::spin();
return 0;
}
catkin_create_pkg service_demo roscpp rospy std_msgs
mkdir srv
gedit Greeeting.srv
// This is the C++ version server file of the service demo
//
// 加载必要文件,注意Service_demo的加载方式
# include "ros/ros.h"
# include "service_demo/Greeting.h"
# include "string"
// 定义请求处理函数
bool handle_function(service_demo::Greeting::Request &req,
service_demo::Greeting::Response &res)
{
// 此处我们对请求直接输出
ROS_INFO("Request from %s with age %d ", req.name.c_str(), req.age);
// 返回一个反馈,将response设置为"..."
res.feedback = "Hi " + req.name + ". I'm server!";
return true;
}
int main(int argc, char **argv)
{
// 初始化节点,命名为"greetings_server"
ros::init(argc, argv, "greetings_server");
// 定义service的server端,service名称为“greetings”,收到request请求之后传递给handle_function进行处理
ros::NodeHandle nh;
ros::ServiceServer service = nh.advertiseService("greetings", handle_function);
// 调用可
ros::spin();
return 0;
}
// This is client of the service demo
// 包含必要文件,注意Service文件的包含方式,我们定义的srv文件为Greeting.srv,在包含时需要写成Greeting.h
# include "ros/ros.h"
# include "service_demo/Greeting.h"
int main(int argc, char **argv)
{
// 初始化,节点命名为"greetings_client"
ros::init(argc, argv, "greetings_client");
// 定义service客户端,service名字为“greetings”,service类型为Service_demo
ros::NodeHandle nh;
ros::ServiceClient client = nh.serviceClient<service_demo::Greeting>("greetings");
// 实例化srv,设置其request消息的内容,这里request包含两个变量,name和age,见Greeting.srv
service_demo::Greeting srv;
srv.request.name = "HAN";
srv.request.age = 20;
if (client.call(srv))
{
// 注意我们的response部分中的内容只包含一个变量response,另,注意将其转变成字符串
ROS_INFO("Response from server: %s", srv.response.feedback.c_str());
}
else
{
ROS_ERROR("Failed to call service Service_demo");
return 1;
}
return 0;
}
#include
int main(int argc, char **argv){
ros::init(argc, argv, "param_demo");
ros::NodeHandle nh;
int parameter1, parameter2, parameter3, parameter4, parameter5;
//Get Param的三种方法
//① ros::param::get()获取参数“param1”的value,写入到parameter1上
bool ifget1 = ros::param::get("param1", parameter1);
//② ros::NodeHandle::getParam()获取参数,与①作用相同
bool ifget2 = nh.getParam("param2",parameter2);
//③ ros::NodeHandle::param()类似于①和②
//但如果get不到指定的param,它可以给param指定一个默认值(如33333)
nh.param("param3", parameter3, 33333);
if(ifget1)
ROS_INFO("Get param1 = %d", parameter1);
else
ROS_WARN("Didn't retrieve param1");
if(ifget2)
ROS_INFO("Get param2 = %d", parameter2);
else
ROS_WARN("Didn't retrieve param2");
if(nh.hasParam("param3"))
ROS_INFO("Get param3 = %d", parameter3);
else
ROS_WARN("Didn't retrieve param3");
//Set Param的两种方法
//① ros::param::set()设置参数
parameter4 = 4;
ros::param::set("param4", parameter4);
//② ros::NodeHandle::setParam()设置参数
parameter5 = 5;
nh.setParam("param5",parameter5);
ROS_INFO("Param4 is set to be %d", parameter4);
ROS_INFO("Param5 is set to be %d", parameter5);
//Check Param的两种方法
//① ros::NodeHandle::hasParam()
bool ifparam5 = nh.hasParam("param5");
//② ros::param::has()
bool ifparam6 = ros::param::has("param6");
if(ifparam5)
ROS_INFO("Param5 exists");
else
ROS_INFO("Param5 doesn't exist");
if(ifparam6)
ROS_INFO("Param6 exists");
else
ROS_INFO("Param6 doesn't exist");
//Delete Param的两种方法
//① ros::NodeHandle::deleteParam()
bool ifdeleted5 = nh.deleteParam("param5");
//② ros::param::del()
bool ifdeleted6 = ros::param::del("param6");
if(ifdeleted5)
ROS_INFO("Param5 deleted");
else
ROS_INFO("Param5 not deleted");
if(ifdeleted6)
ROS_INFO("Param6 deleted");
else
ROS_INFO("Param6 not deleted");
ros::Rate rate(0.3);
while(ros::ok()){
int parameter = 0;
ROS_INFO("=============Loop==============");
//roscpp中尚未有ros::param::getallparams()之类的方法
if(ros::param::get("param1", parameter))
ROS_INFO("parameter param1 = %d", parameter);
if(ros::param::get("param2", parameter))
ROS_INFO("parameter param2 = %d", parameter);
if(ros::param::get("param3", parameter))
ROS_INFO("parameter param3 = %d", parameter);
if(ros::param::get("param4", parameter))
ROS_INFO("parameter param4 = %d", parameter);
if(ros::param::get("param5", parameter))
ROS_INFO("parameter param5 = %d", parameter);
if(ros::param::get("param6", parameter))
ROS_INFO("parameter param6 = %d", parameter);
rate.sleep();
}
}
<launch>
<param name="param1" value="1" />
<param name="param2" value="2" />
<rosparam>
param3: 3
param4: 4
param5: 5
rosparam>
<node pkg="param_demo" type="param_demo" name="param_demo" output="screen" />
launch>
http://docs.ros.org/api/rospy/html/
wait_for_message(topic, topic_type, time_out=None)
等待指定topic的一个message,一般用于只执行一次,如按下摄像头的拍照,等待一次信息即可。#!/usr/bin/env python
#coding=utf-8
import rospy
#倒入自定义的数据类型
from topic_demo.msg import gps
def talker():
#Publisher 函数第一个参数是话题名称,第二个参数 数据类型,现在就是我们定义的msg 最后一个是缓冲区的大小
#queue_size: None(不建议) #这将设置为阻塞式同步收发模式!
#queue_size: 0(不建议)#这将设置为无限缓冲区模式,很危险!
#queue_size: 10 or more #一般情况下,设为10 。queue_size太大了会导致数据延迟不同步。
pub = rospy.Publisher('gps_info', gps , queue_size=10)
rospy.init_node('pytalker', anonymous=True)
#更新频率是1hz
rate = rospy.Rate(1)
x=1.0
y=2.0
state='working'
while not rospy.is_shutdown():
#计算距离
rospy.loginfo('Talker: GPS: x=%f ,y= %f',x,y)
pub.publish(gps(state,x,y))
x=1.03*x
y=1.01*y
rate.sleep()
if __name__ == '__main__':
talker()
#!/usr/bin/env python
#coding=utf-8
import rospy
import math
#导入mgs到pkg中
from topic_demo.msg import gps
#回调函数输入的应该是msg
def callback(gps):
distance = math.sqrt(math.pow(gps.x, 2)+math.pow(gps.y, 2))
rospy.loginfo('Listener: GPS: distance=%f, state=%s', distance, gps.state)
def listener():
rospy.init_node('pylistener', anonymous=True)
#Subscriber函数第一个参数是topic的名称,第二个参数是接受的数据类型 第三个参数是回调函数的名称
rospy.Subscriber('gps_info', gps, callback)
rospy.spin()
if __name__ == '__main__':
listener()
#!/usr/bin/env python
# coding:utf-8
# 上面指定编码utf-8,使python能够识别中文
# 加载必需模块,注意service模块的加载方式,from 包名.srv import *
# 其中srv指的是在包根目录下的srv文件夹,也即srv模块
import rospy
from service_demo.srv import *
def server_srv():
# 初始化节点,命名为 "greetings_server"
rospy.init_node("greetings_server")
# 定义service的server端,service名称为"greetings", service类型为Greeting
# 收到的request请求信息将作为参数传递给handle_function进行处理
s = rospy.Service("greetings", Greeting, handle_function)
rospy.loginfo("Ready to handle the request:")
# 阻塞程序结束
rospy.spin()
# Define the handle function to handle the request inputs
def handle_function(req):
# 注意我们是如何调用request请求内容的,与前面client端相似,都是将其认为是一个对象的属性,通过对象调用属性,在我们定义
# 的Service_demo类型的service中,request部分的内容包含两个变量,一个是字符串类型的name,另外一个是整数类型的age
rospy.loginfo( 'Request from %s with age %d', req.name, req.age)
# 返回一个Service_demoResponse实例化对象,其实就是返回一个response的对象,其包含的内容为我们再Service_demo.srv中定义的
# response部分的内容,我们定义了一个string类型的变量,因此,此处实例化时传入字符串即可
return GreetingResponse("Hi %s. I' server!"%req.name)
# 如果单独运行此文件,则将上面定义的server_srv作为主函数运行
if __name__=="__main__":
server_srv()
#!/usr/bin/env python
# coding:utf-8
# 上面的第二句指定编码类型为utf-8,是为了使python能够识别中文
# 加载所需模块
import rospy
from service_demo.srv import *
def client_srv():
rospy.init_node('greetings_client')
# 等待有可用的服务 "greetings"
rospy.wait_for_service("greetings")
try:
# 定义service客户端,service名称为“greetings”,service类型为Greeting
greetings_client = rospy.ServiceProxy("greetings",Greeting)
# 向server端发送请求,发送的request内容为name和age,其值分别为"HAN", 20
# 注意,此处发送的request内容与service文件中定义的request部分的属性是一致的
#resp = greetings_client("HAN",20)
resp = greetings_client.call("HAN",20)
# 打印处理结果,注意调用response的方法,类似于从resp对象中调取response属性
rospy.loginfo("Message From server:%s"%resp.feedback)
except rospy.ServiceException, e:
rospy.logwarn("Service call failed: %s"%e)
# 如果单独运行此文件,则将上面函数client_srv()作为主函数运行
if __name__=="__main__":
client_srv()
rosrun tf_view_frames
根据当前的tf树创建一个pdf图,监听/tf这个topic 5srosrun rqt_tf_tree rqt_tf_tree
查看当前的tf树rosrun tf tf_echo [reference_frame] [target_frame]
查看两个frame之间的变换关系# This represents a 2-D grid map, in which each cell represents the probability of
# occupancy.
Header header
#MetaData for the map
MapMetaData info
# The map data, in row-major order, starting with (0,0). Occupancy
# probabilities are in the range [0,100]. Unknown is -1.
int8[] data
# This hold basic information about the characterists of the OccupancyGrid
# The time at which the map was loaded
time map_load_time
# The map resolution [m/cell]
float32 resolution
# Map width [cells]
uint32 width
# Map height [cells]
uint32 height
# The origin of the map [m, m, rad]. This is the real-world pose of the
# cell (0,0) in the map.
geometry_msgs/Pose origin
roscore
roslaunch robot_sim_demo robot_spawn.launch
roslaunch slam_sim_demo gmapping_demo.launch
roslaunch slam_sim_demo view_slam.launch
ros官方link
rosrun map_server map_server my_map.yaml
发布地图rosrun map_server map_saver [-f my_map]
保存地图