只有Windows上的Rose-Ros才支持rivz。
一、下载官方Ros(版本:noetic)
有了Rose-Ros源码后,Ros已经能工作,但为使用rviz,以及更多第三方Ros node,还是要安装个官方Ros。Rose-Ros中的Ros版本是noetic,这里安装版本也须要是noetic。
对如何在windows安装ros,微软额外做了工作。安装也就变得简单了。网上有文章介绍如何安装,个人建议直接看Ros wiki:ROS on Windows installation。
安装有个步骤是“Using the new Windows Terminal”,个人认为可以略过,终端就用cmd。microsoft新开发的一个终端,既不是cmd、也不是powershell。我用下来,基本功能都有问题,真不明白之前都两个终端了,在上面改不好吗,偏还要再折腾。后来我不管它,依旧用cmd,没遇到有啥问题。
本机ros安装路径是c:\opt,以下“Create a ROS Command Window shortcut”阶段Ros终端命令,用的是Microsoft Visual Studio Enterprise 2022 (64-bit)
C:\Windows\System32\cmd.exe /k "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64&& set ChocolateyInstall=c:\opt\chocolatey&& c:\opt\ros\noetic\x64\setup.bat
要测试安装结果,运行Ros cmd,敲入“roscore”,如果出现图1,那表示安装成功了。
二、让Ros工作在一node一进程
为使用rivz,须让Rose-Ros工作Ros原有一node一进程。
<libros>/ros_comm/roscpp/src/libros/common.cpp ------ namespace ros { #ifdef _WIN32 // nocopy_intra置为false。 bool nocopy_intra = false; #else bool nocopy_intra = true; #endif }
把表示进程内不复制的变量nocopy_intra置为false,然后编译。
二、新开ROS cmd:roscore

三、新开ROS cmd:rosrun rviz rviz

四、操作rviz(导航)

File -- Recent Configs -- navigation_rose.rviz
- {Global Options}Fixed Frame: map。map是世界坐标系。
- {Global Map:Costmap}1)Color Scheme选择“costmap”。2)打勾“Draw Behind”。查看时,rviz极可能同时订阅着全局代价地图、局部代价地图costmap,这时局部代价地图会覆盖在是全局代价地之上。为方便开发者分清哪是全局地图、哪是局部地图,这时建议把全局地图的rviz选项“Draw Behind”打勾,这样全局地图颜色变暗。
- {Global Map:Costmap}Color Scheme选择“costmap”。
Add | C++类型 | Topic | 描述 |
(rviz)TF | tf树,一个就够了 | ||
(rviz)Polygon | geometry_msgs/PolygonStamped | /move_group/global_costmap/footprint(注1) | 全局代价地图中的footprint |
(rviz)Polygon | geometry_msgs/PolygonStamped | /move_group/local_costmap/footprint | 局部代价地图中的footprint |
(rviz)Map | nav_msgs::OccupancyGrid | /move_group/global_costmap/costmap | 全局代价地图uint8_t数组(注2) |
(rviz)Map | nav_msgs::OccupancyGrid | /move_group/local_costmap/costmap | 局部代价地图uint8_t数组(注2) |
(rviz)PointCloud2 | sensor_msgs::PointCloud2 | /move_group/DWAPlannerROS/trajectory_cloud | 显示候选轨迹 |
(rviz)Path | nav_msgs::Path | /move_group/GlobalPlanner/plan | 在全局代价地图,makePlan规划出的路径MoveBase.planner_plan_(注3)。绿色 |
(rviz)Path | nav_msgs::Path | /move_group/DWAPlannerROS/global_plan | 全局路径,基本和MoveBase.planner_plan_重合。红色 |
(rviz)Path | nav_msgs::Path | /move_group/DWAPlannerROS/local_plan | 局部路径,即最优轨迹中路径。蓝色 |
注
- 在“Topic”,话题放在“move_group”这个名字空间,是为和move_group相关那些topic兼容。
- 还有个和costmap话题相似的/move_group/global_costmap/costmap_updates。always_send_full_costmap_==false时,如果代价地图尺寸、原点没变过,只是内容变了,那只会发布constmap_updates,不会有costmap。always_send_full_costmap_==true时则只会发costmap。
- GlobalPlanner/plan是makePlan出的来全局路径。DWAPlannerROS/global_plan是从全局路径MoveBase.planner_plan_截取出的位在局部代价地图内的路径。对官方ros来说,这路径和GlobalPlanner/plan重合。DWAPlannerROS/local_plan是候选轨迹选出的、最优轨迹中路径。
grid_.data[n] | 颜色值 | rviz显示的颜色(Color Scheme选择“costmap”) |
255(NO_INFORMATION) | -1 | 白色(半透明)rviz上看到的显示的是半透明底下图像,通常就是地图。它那里像被镂空 |
254(LETHAL_OBSTACLE) | 100 | 红色 |
253(INSCRIBED_INFLATED_OBSTACLE) | 99 | 青色 |
0(FREE_SPACE) | 0 | 没有颜色。rviz上看到的显示的是底下图像,通常就是地图。它那里像被镂空 |
[1, 252],值记为i | 1 + (97 * (i - 1)) / 251 | 值从98到1时,从红变成蓝 |
4.1 Costmap2DPublisher
Costmap2DPublisher负责发布costmap、costmap_updates话题。
Costmap2DPublisher(ros::NodeHandle * ros_node, Costmap2D* costmap, std::string global_frame, std::string topic_name, bool always_send_full_costmap = false);
always_send_full_costmap_==false时,如果代价地图尺寸、原点没变过,只是内容变了,那只会发布constmap_updates,不会有costmap。always_send_full_costmap_==true时则只会发costmap。因为只是在开发时才会看costmap,而且如果没有订阅者,即使到发布时间了,也不会发布话题,免得麻烦,我是总把always_send_full_costmap_设为true。
void updateBounds(unsigned int x0, unsigned int xn, unsigned int y0, unsigned int yn) { x0_ = std::min(x0, x0_); xn_ = std::max(xn, xn_); y0_ = std::min(y0, y0_); yn_ = std::max(yn, yn_); }
xn、yn尺度是size值。x0_、xn_、y0_、yn_都是基于map坐标系的值。
{x0, xn, y0, yn}表示当前代价地图边界,为什么不是直接替代,而是要包含原来存在、而此刻不存在的部分呢?
void Costmap2DPublisher::publishCostmap() { if (costmap_pub_.getNumSubscribers() == 0) { // No subscribers, so why do any work? // 如果没有订阅者,即使到发布时间了,也不会发布话题。 return; } boost::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex())); float resolution = costmap_->getResolution(); if (always_send_full_costmap_ || grid_.info.resolution != resolution || grid_.info.width != costmap_->getSizeInCellsX() || grid_.info.height != costmap_->getSizeInCellsY() || saved_origin_x_ != costmap_->getOriginX() || saved_origin_y_ != costmap_->getOriginY()) { // prepareGrid功能填充grid_。 prepareGrid(); costmap_pub_.publish(grid_); } else if (x0_ < xn_) { ... costmap_update_pub_.publish(update); } xn_ = yn_ = 0; x0_ = costmap_->getSizeInCellsX(); y0_ = costmap_->getSizeInCellsY(); }
如果没有订阅者,即使到发布时间了,也不会发布话题。