ROS Answer 官网:https://answers.ros.org/questions/
古月居 · ROS入门21讲:https://www.bilibili.com/video/BV1zt411G7Vn?p=1
古月居 · 对应代码:https://github.com/huchunxu/ros_21_tutorials
中科院软件所-机器人操作系统入门(ROS入门教程)
ROS是一种机器人开发框架(robot frameworks)
特点:兼容多平台语言共同使用,主要兼容c++和python;结构简单
通信机制采用异步通信:topic话题(pub-sub)机制和C-S(client-Server)机制;
此外:
action基于C-S机制,增加了server端持续反馈,主要用于需长时间响应的情况;
还有tf使用的broadcast,是基于topic,用来发布topic tf信息。
http://wiki.ros.org/melodic/Installation/Ubuntu
合理选择ROS的镜像源:http://wiki.ros.org/ROS/Installation/UbuntuMirrors
参考链接装ros慢怎么办,只需要少执行一步就可以了
#以下命令选其一
##1.国内镜像源,建议
sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list'
#2.官方镜像源,非常慢
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
#以下命令选其一
#1.
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
#2.
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
#ros全安装,包括rviz还有2D/3D仿真包
sudo apt install ros-melodic-desktop-full
#安装一些常用依赖包:
sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
#安装ros管理依赖工具
sudo apt install python-rosdep
sudo rosdep init
rosdep update
cannot download default sources list from:【closed】
解决:报raw.githubusercontent.com/xxx 网站down的
ping raw.githubusercontent.com
看看网站是否通sudo vim /etc/hosts
151.101.84.133 raw.githubusercontent.com
或者
151.101.76.133 raw.githubusercontent.com
或者去http://tool.chinaz.com/dns找到 raw.githubusercontent.com对应的ip,TTL值大一些的。
sudo service networking restart
重启network服务ping raw.githubusercontent.com
看看网站是否通了,对应ip是否为151.101.84.133。解决rosdep update一直timeout的问题
sudo vim /usr/lib/python2.7/dist-packages/rosdep2/gbpdistro_support.py
将DOWNLOAD_TIMEOUT = 15.0
改大一点。
#设置打开终端生效
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
创建ros工作空间:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
ros 下source会清理ROS_PACKAGE_PATH,因此一个终端启动跨工作空间下的包会有问题
通过以下的方式将空间变量添加到ROS_PACKAGE_PATH变量可解决此问题
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/xxx/ws/src/packxxx
#启动ros server
roscore
#启动小海龟节点node
rosrun turtlesim turtlesim_node
#启动小海龟键盘控制节点node
rosrun turtlesim turtle_teleop_key
roscore
从机配置:
export ROS_MASTER_URI=http://[master_ip]:11311
eg: export ROS_MASTER_URI=http://192.168.1.2:11311
主机配置:启动roscore [ros master]的机器,如果ROS_HOSTNAME用的host_name,须在/etc/hosts中对应匹配上master_ip.
export ROS_HOSTNAME=[host_name/master_ip]
export ROS_MASTER_URI=http://[host_name/master_ip]:11311
这样即可以在从机的export下的终端接收到主机的topic。
ssh [user_name]@[user_ip] -X
rviz
可以远程打开rviz#软件包列表
rospack list
#查找软件包目录
rospack find package-name
#查看指定包下文件目录
rosls package-name
#直接进入对应包路径下
roscd package-name
#编辑ros文件,有时候需要编辑apt安装的ros包的文件,以下就会启用vi编辑pacname/filename文件
rosed pacname filename
#新建包
catkin_create_pkg [depend1] [depend2] [depend3]
#查看包依赖
rospack depends
#自定义包卸载就用rm 删除其对应的src下的文件夹。
#系统自带包,则通过安装包管理工具apt一类的进行卸载。
#手动创建包
1.mkdir tstpck 或者 cp xxtstpck tstpck
2.cd tstpck
3.vi package.xml
#填入对应的等信息。一般填入信息包就能被识别了
#使用rosls 及 roscd查看是否系统是否找的道tstpak了
#记得要source对应ws的devel/setup.sh
Metapackage(功能包集)是把一些相近的功能模块、 软件包放到一起。
metapacakge和普通package不同点是:
CMakeLists.txt :加入了catkin_metapackage()宏, 指定本软件包为一个metapacakge。
package.xml :标签将所有软件包列为依赖项, 标签中添加标签声明。
以上参考https://www.cnblogs.com/long5683/p/9941458.html
#启动节点
rosrun package-name executable-name
#查看节点列表
rosnode list
#查看节点信息
rosnode info node-name
#停止节点
rosnode kill node-name
#为启动的节点命名node_name
rosrun pkg_name node_type __name:=node_name
#查看是否能联通node
rostopic ping node_name
#启动节点时映射topic,类似节点输入
rosrun node_name node_name origin_topic:=new_topic
>
1.pkg:功能包名称
2.type:可执行文件,节点名称
3.name:定义节点运行的名称,将覆盖节点中init()赋予节点的名称。
4.output = “screen”
将节点的标准输出打印到终端屏幕,默认输出为日志文档。
5.respawn=”true”
复位属性,该节点停止时,会自动重启,默认为false。
6.respawn_delay =“30” (可选,默认为0)ROS indigo中的新功能
如果respawn为true,请在尝试重新启动之前检测到节点故障后等待respawn_delay秒。
6.required=”true”
必要节点,当该节点终止时,launch文件中的其他节点也被终止。
7.launch-prefix =“prefix arguments” (可选)
用于预先添加到节点的启动参数的命令/参数。这是一个强大的功能,使您能够启用gdb,valgrind,xterm,漂亮或其他方便的工具。
eg: launch-prefix = “command-prefix”
roslaunch 命令 的一个潜在的缺点:相比我们原来对每个节点在单独的终端使用 rosrun 命令启动的做法,roslaunch 则是让所有的节点共享同一个终端。 那些只需要生产简单的日志消息文件而不需要终端(console)输入的节点是容易管理的,而那些依赖终端输入的节点,它可能要优先的保留在独立的终端上。
在launch文件中,使用launch-prefix=”xterm -e”.属性,可以使启动这个 node 元素的 rosrun 命令大致相当于:xterm -e rosrun pkg_name node_name.
xterm 命令会开一个新的终端窗口。 -e 参数告诉 xterm :执行其命令行剩余部分(rosrun turtlesim turtle_teleop_key)。=
用于预先添加到节点的启动参数的命令/参数。这是一个强大的功能,使您能够启用gdb,valgrind,xterm,漂亮或其他方便的工具。
8.args =“arg1 arg2 arg3” (可选)
传递参数到节点。
9.machine =“machine-name” (可选)
在指定机器上启动节点。
10.ns =“foo” (可选)
在“foo”命名空间中启动节点。
11.clear_params =“true | false” (可选)
在启动前删除节点的私有命名空间中的所有参数。
12.output =“log | screen” (可选)
如果’screen’,stdout / stderr从节点将被发送到屏幕。如果是“log”,stdout / stderr输出将被发送到$ ROS_HOME/ log中的日志文件,stderr将继续发送到屏幕。默认值为“log”。
13.cwd =“ROS_HOME | node” (可选)
如果为“node”,则节点的工作目录将设置为与节点的可执行文件相同的目录。在C Turtle中,默认值为“ROS_HOME”。在Box Turtle(ROS 1.0.x)中,默认值是’ros-root’。使用’ros-root’在C Turtle中已被弃用。
参考链接-https://www.cnblogs.com/qixianyu/p/6579798.html
launch文件用来同时启动多个node节点及配置更多的参数。在roslaunch时,ros master会被启动
在launch文件头使用声明,在vi中打开该launch,可以使用xml格式显示(带颜色区分)。
respawn复位节点
respawn=”true”,这样当节点停止的时候,roslaunch会重新启动该节点。
<node name="Stereo" pkg="ORB_SLAM2" type="Stereo"
args=" $(find ORB_SLAM2)../../../Vocabulary/ORBvoc.txt $(find ORB_SLAM2)Asus_imsee.yaml false"
output="screen" respawn="true" respawn_delay="10">
</node>
来自launch文件remap标签
<!--start_talker.launch-->
<launch>
<node pkg="test" type="talker" name="talker" output="screen">
<!--talker节点发布的topic为/talker-->
<!--一个例子:将talker节点发布的话题/talker映射到/re_talker的名字上去-->
<remap from="/talker" to="/re_talker" />
</node>
</launch>
通过rosrun也可以进行topic remap
#1
<!-- 使用launch-prefix="gnome-terminal --" -->
<node pkg="prometheus_mission" type="planning_mission" name="planning_mission" output="screen" launch-prefix="gnome-terminal --">
<param name="planning_mission/control_yaw_flag" value="false" type="bool"/>
</node>
#2
#xterm 命令会开一个新的终端窗口。 -e 参数告诉 xterm :执行其命令行剩余部分(rosrun package_name node_name)。
<!-- 使用launch-prefix="xterm -e" -->
<node pkg="prometheus_mission" type="planning_mission" name="planning_mission" output="screen" launch-prefix="xterm -e">
<param name="planning_mission/control_yaw_flag" value="false" type="bool"/>
</node>
<!--start_test1.launch-->
<launch>
<node pkg="test" type="test1" name="test1" output="screen">
<!--test1节点需要订阅话题为/talker_mid-->
<!--一个例子将节点订阅的topic改名字为/re_talker-->
<remap from="/talker_mid" to="/re_talker" />
</node>
</launch>
示例:
节点公有参数
<launch>
#所有节点的公共参数
<param name="use_sim_time" value="true"/>
#launch文件的外部参数
<arg name="scan_topic" default="sick_scan" />
#node本身也可通过arg传递节点外部参数
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" args="" output="screen">
#单个节点的私有参数
<param name="throttle_scans" value="1"/>
...
</node>
... ...
<\launch>
eg: vins_estimator/launch:
>
>
>
... ...
>
>
>
>
... ...
>
>
eg: loam_velodyne
>
-prefix="nice" pkg="rviz" type="rviz" name="rviz" args="-d $(find loam_velodyne)/rviz_cfg/loam_velodyne.rviz" />
>
在节点源程序中,对launch文件中的公有参数读取:
ros::init(argc, argv, "xxxx");
ros::NodeHandle nh;
//3中获取函数
//1
nh.param<std::string>("data_save_dir", data_save_dir, "~/");//可以设置默认值
//2
nh->getParam("/aruco_mapping/marker_size", temp_marker_size);
//3
ROS::param::get()
节点私有参数
节点私有参数读取:将"~"赋值给node,便可读取xxx.launch 文件中定义的param。
ros::NodeHandle private_nh_("~");
if(!private_nh_.getParam("throttle_scans", throttle_scans_))
throttle_scans_ = 1
args传入多个参数
>
-full-0.025.pgm 0.025" />
-s 5 -r 1 --clock --hz=10 $(find costmap_2d)/test/simple_driving_test_indexed.bag" />
>
launch中添加其他launch文件:使用$(find 节点名称)
>
>
-d $(find imsee_ros_wrapper)/rviz/imsee.rviz"
output="screen" />
>
group使用
launch group用来管理node的启动。
<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group if="0-or-1" />
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
. . .
</group>
<group unless="1-or-0" />
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
. . .
</group>
https://www.jianshu.com/p/13efab3f67e0
https://www.cnblogs.com/zx-hit/p/11777992.html
#列出所有topic清单
rostop list
#实时指定topic内容 -n 指定打印的topic数
rostopic echo -n 1 [topic]
#rostopic取消打印矩阵或者字符串
rostopic echo --nostr [topic]
rostopic echo --noarr [topic]
#rostopic
#发布topic,-r 指定发布次数
rostopic pub [-1] [-r 1] -- [args] [args]
#查看topic发布的频率
rostopic hz [topic]
#改变topic发布频率:intopic为要改变的topic名称,outtopic为更改后发布topic名称(可省),msgs_per_sec要设置的频率
#temp:rosrun topic_tools throttle messages [outtopic]
rosrun topic_tools throttle messages /topic 1.0
#重映射消息名称:
rosrun :=
eg:
rosrun rospy_tutorials talker chatter:=/wg/chatter
#列出service 清单
rosservice list
#service调用
rosservice call [service] [args]
#记录所有信息
rosbag record -a -O filename.bag
#记录过滤掉/monitor/*之外的其他topic
rosbag record -a -O xxx.bag -x "/monitor/(.*)"
#记录指定topic信息
rosbag record -O subset
#查看rosbag内容
rosbag info
#指定播放的起始时间戳
#rosbag play -s
#等待一定时间之后发布bag文件中的内容
rosbag play -d
#回放指定话题
rosbag play --topics
#过滤包
#创建一个除了/tf消息的新包
rosbag filter file.bag .bag "topic != '/tf'"
rosbag filter input.bag output.bag "topic == '/velodyne_point_cloud' or topic =='/visensor/imu' or topic == '/visensor/left/image_raw'"
#根据时间过滤
rosbag filter input.bag output.bag "t.to_sec() <= xxxx"
#同时过滤topic和时间
rosbag filter input.bag output.bag "topic == '/topic' and t.to_sec() <= xxxx"
#重映射topic信息(将output.bag中topic1转为topic2)
rosbag play
#发布clock虚拟时钟
1. rosbag play xxx.bag --clock
#打开/use_sim_tim参数,使参数设置后启动的node均使用虚拟时钟
2. rosparam set /use_sim_time true
eg:
3. rosbag play xxx.bag --clock
4. rosparam set /use_sim_time true
5. rosrun tf static_transform_publisher 0 0 0 0 0 0 camera_init map 50
#便可成功订阅camera_init frame下的点云或pose等,解决message removedbecause it is too old问题
查看bag包指定帧数据
rqt_bag bag_name.bag
//同步订阅两个topic然后处理
message_filters::Subscriber<sensor_msgs::PointCloud2> cloud_sub(n, VELODYNE_TOPIC, 1);
message_filters::Subscriber<lidar_camera_calibration::marker_6dof> rt_sub(n, "lidar_camera_calibration_rt", 1);
typedef sync_policies::ApproximateTime<sensor_msgs::PointCloud2, lidar_camera_calibration::marker_6dof> MySyncPolicy;
Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), cloud_sub, rt_sub);
sync.registerCallback(boost::bind(&callback_noCam, _1, _2));
void callback_noCam(const sensor_msgs::PointCloud2ConstPtr& msg_pc,
const lidar_camera_calibration::marker_6dof::ConstPtr& msg_rt)
#列出所有消息名称
rosmsg list
#查看topic下指定message的信息
rosmsg show [msg_type]
#参数设置
rosparam set [parame_name] [args]
#参数获取查看
rosparam get [parame_name]
#加载指定文件中的所有参数配置
rosparam load [file_name] [namespace]
#参数删除
rosparam delete
使用rosrun时传递参数:
rosrun package node _parameter:=value
注意parameter前加下划线。rosrun gmapping slam_gmapping _map_update_interval:=1.0
rosrun map_server map_saver -f ~/Documents/test
也可使用launch文件传入参数
http://wiki.ros.org/tf/
#查看两个坐标系之间的变换,以下为查看map和odom之间的变换关系
rosrun tf tf_echo map odom
#查看tf tree
rosrun rqt_tf_tree rqt_tf_tree
#报告在ROS上任意两个坐标系发布的变换。
rosrun tf tf_echo [reference_frame] [target_frame]
#使用命令发布tf变换信息
#1使用yaw pitch roll欧拉角来定义旋转
#period_in_ms每秒发布多少次(速率) 100为不错的选择
rosrun tf static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms
#2使用四元数来定义旋转
static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_ms
#examples tf pub use cmd
rosrun tf static_transform_publisher 0 0 0 0 0 0 base_link velodyne 100
有三种方法设置日志级别:
# Set the default ros output to warning and higher
log4j.logger.ros=WARN
# Override my package to output everything
log4j.logger.ros.move_base=DEBUG
<env name="ROSCONSOLE_CONFIG_FILE"
value="myfolder_path/rosconsole.config"/> // myfolder_path 是你的rosconsole.config 文件所在的文件夹
#打开图形界面,选择对应的
rqt_logger_level
#include
if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) ) {
ros::console::notifyLoggerLevelsChanged();
}
ros log级别设置 https://www.jianshu.com/p/8d23b4c12f6f
1.ROS2
<node pkg="rosservice" type="rosservice" name="set_move_base_log_level" args="--log-level debug" />
2.
<node pkg="rosservice" type="rosservice" name="set_move_base_log_level" args="call --wait /move_base/set_logger_level 'ros.move_base' 'debug'" />
命令
rosrun packname nodename __log_level:=debug
rosservice call /node-name/set_logger_level rospackage-name Debug
launch文件中加入:
<env name="ROSCONSOLE_FORMAT" value="${logger}: { ${message} }" />
也同直接设置环境变量:
export ROSCONSOLE_FORMAT='${logger}: ${message}'
log打印结果如下:
设置前:
设置后:
rqt_plot
打开绘图界面,输入’/'下方会提示选项,输入变量全路径,点击右侧+号,下方会显示变量跟随时间的变化情况
nodelet是实现将多个算法运行在同一个进程。
ROS中的 nodelet
http://wiki.ros.org/nodelet
node与nodelet实现通信的不同:node每个节点各占一个进程,需通过topic互相通信。nodelet各算法节点占用一个线程,所有算法共享一个进程,通信也通过topic,但是nodelet的topic通信底层是通过指针的传递实现的。
node:图中说node间的topic交互是通过tcp(连接式)通信方式;
nodelet:各个节点虽与node相似,也采用topic方式。但是其nodelet的各个节点运行在一个进程中,实际topic的交互是通过指针传递实现。详细使用见参考链接。
因此使用nodelet启动的node的起始不是main,而是onInit()
sudo apt install ros-melodic-map-server
保存地图:
rosrun map_server map_saver map:=/
显示地图:运行map_server 重新发布topic节点,在使用rviz add topic显示地图。
rosrun map_server map_server mymap.yaml
rviz
终端输入rviz可直接启动rviz;
点击rviz下方add可以添加要显示的topic
rviz -d xxx.rviz
可以根据xxx.rviz的配置订阅topic信息进行显示。
保存并查看Loam的三维点云地图-https://blog.csdn.net/qq_36396941/article/details/83048415
PCL点云库-https://blog.csdn.net/qq_43145072/article/details/85953948
#pcl库文件安装
sudo apt-get install libpcl-dev
#pcl工具安装,如pcl_viewer
sudo apt-get install pcl-tools
#从bag中保存点云地图,input.bag为bag包,/laser_cloud_surround为点云topic
rosrun pcl_ros bag_to_pcd input.bag /laser_cloud_surround pcd
#查看pcd点云图
pcl_viewer map.pcd
c++中保存点云地图
#include
#include
#include
#include
using namespace std; // 可以加入 std 的命名空间
int
main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr INcloud(new pcl::PointCloud<pcl::PointXYZ>); // 存放提取出来的边界点云
if (pcl::io::loadPCDFile<pcl::PointXYZ>("boudary_200_100.pcd", *INcloud) == -1)//*打开点云文件。
{ //带路径的格式【注意路径的反斜杠与电脑自己的不同】:if (pcl::io::loadPCDFile("E:/rabbit_gra.pcd", *cloud) == -1)
PCL_ERROR("Couldn't read that boundary pcd file\n"); // //不带路径的格式【只是把路径删掉即可】:if (pcl::io::loadPCDFile("rabbit_gra.pcd", *cloud) == -1)
return(-1);
}
//写入磁盘
//写入方法一:
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ>("name_cluster.pcd", *INcloud, false);//将点云保存到PCD文件中
//写入方法二:
pcl::io::savePCDFileASCII("name_cluster.pcd", *INcloud); //将点云保存到PCD文件中
}
两种读取和写入pcd点云文件的方法
ros pcl sensor::pointcloud2 转换成pcl::pointcloud
rosclean check
查看ros log文件及大小
rosclean purge
清除log文件
cd ~/catkin_ws
#编译所有文件,catkin_make需再catkin workspace下进行,而 catkin_init_workspace是在src下
catkin_make
#编译指定包
catkin_make -DCATKIN_WHITELIST_PACKAGES="package1;package2"
#指定不编译指定包
catkin_make -DCATKIN_BLACKLIST_PACKAGES="package1;package2"
#或:
catkin_make --pkg package_name
#或:
catkin_make --source [package_path] --build build/[pacakge_name]
#或:直接使用cmake/make
#build和devel可以放在ws下,也可以指定放在package下,这样可以通过ROS_PACKAGE_PATH来切换同名包
#ROS会在ws以及package path下去寻找可用的可执行文件
cd [packge_path]
mkdir build
cmake ..
make
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:${PWD}
2.使用catkin build
安装:sudo apt install python-catkin-tools
使用:catkin build [pacname]
3. 使用rosmake
#安装包依赖,根据package.xml配置
rosdep install pkg_name
#进入package目录
roscd pkg_name
#编译该package
rosmake pkg_name
catkin_package
catkin_package DEPENDS 和 CATKIN_DEPENDS 用来告诉 catkin 需要将你程序包的哪些依赖项传递给使用 find_package(…) 查找你的程序包的程序包。
catkin_package()是catkin提供的CMake宏,用于为catkin提供构建、生成pkg-config和CMake文件所需要的信息。
sudo apt-get install python-rosinstall
mkdir ~/rosbuild_ws
cd ~/rosbuild_ws
rosws init . /opt/ros/indigo
mkdir package_dir
rosws set ~/rosbuild_ws/package_dir -t .
echo "source ~/rosbuild_ws/setup.bash" >> ~/.bashrc
cd package_dir
<copy package to .>
rosmake package_name
参考链接:https://docs.ros.org/en/independent/api/rosinstall/html/rosws_tutorial.html
ros 自定义workspace编译的可执行文件位置/${workspace}/devel/lib/
下
ros安装的包的可执行文件位置:/opt/ros/melodic/lib
#卸载ros相关包
sudo apt-get purge ros-*
#卸载相关自动下载的依赖包
sudo apt-get autoremove
ros接口定义查询http://docs.ros.org/jade/api/
launch文件中arg与param的区别:
arg是launch文件的参数,在roslaunch xxxpackage xxx.launch argname:=argvalue
param是启动的node要传入的参数
// 使用“~”则private_nh 可以接受launch文件中给定的param
ros::NodeHandle private_nh("~");
private_nh.param("base_global_planner", global_planner, std::string("navfn/NavfnROS"));
ros::spin 和ros::spinOnce – ROS消息回调处理函数:
ros::spin 和ros::spinOnce 都是用来触发ros节点订阅的所有topic的消息处理函数。
两者区别在于ros::spinOnce只触发一次消息处理,而ros::spin会block触发所有节点订阅的topic处理函数。
对于有些传输特别快的消息,需要注意合理控制消息池大小和ros::spinOnce()执行频率; 比如消息送达频率为10Hz, ros::spinOnce()的调用频率为5Hz,那么消息池的大小就一定要大于2,才能保证数据不丢失,无延迟。
ros::spin()和ros::spinOnce()的意义与区别-https://blog.csdn.net/datase/article/details/79742421
http://wiki.ros.org/Clock
http://wiki.ros.org/roscpp/Overview/Time
ROS 中有 ROS::Time()和ROS::WallTime()
参考:https://blog.csdn.net/sru_alo/article/details/102893536
在开启一个Node之前,当把use_sim_time设置为true时,这个节点会从clock Topic获得时间。所以操作这个clock的发布者,可以实现一个让Node中得到ROS Time暂停、加速、减速的效果。同时下面这些方面都是跟Node透明的,所以非常适合离线的调试方式。当把ROSbag记下来以后重新play出来时,加两个横杠,–clock,它就会发布出这个消息。
如,使用rosbag播放数据包时,处理的数据的程序也想采用bag中的时间,就可以将use_sim_time设为true,同时播放bag包时加上–clock。但是同时rosbag play时 可以加上-r [r]来改变ros的播放速度。因此模拟时间可通过ROS::Time()获得,且此时的时钟时间是可调,可控的。为防止特殊情况下,用户需要使用绝对的系统时间,则ROS::WallTime()。
当不开启use_sim_time时,ROS::Time()和ROS::WallTime()获取的时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
两外:ROS::Time也分time 和 duration 两种类型,相应的有 ros::Time 和 ros::Duration 类。
time 表示的是时刻
duration 表示的是时间间隔
参考链接
gdb -ex run --args ./exefile
gdb -ex run --args ./Examples/Monocular/mono_euroc Vocabulary/ORBvoc.txt Examples/Monocular/EuRoC.yaml ../EUROC_dataset/mav0/cam0/data Examples/Monocular/EuRoC_TimeStamps/MH05.txt
gdb --args /exefile arg1 args2
在ros程序运行出错时会红色字打印cmd,将cmd后的命令直接跟在gdb --args之后就可以进行调试
2.在launch文件中加入:
python : launch-prefix="xterm -e python -m pdb "
c++: launch-prefix="xterm -e gdb -ex run --args "
eg:
-prefix="xterm -e gdb -ex run --args">
>
>
然后使用rosrun或launch运行node,程序会自动启用gdb
附:gdb常用命令:
r: 运行程序
c:继续运行程序
s:单步运行程序
bt:打印backtrace调用栈区符号表
https://www.linuxidc.com/linux/2016-03/129600.htm