前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ROS1云课→29如何借助ROS实现走迷宫机器人

ROS1云课→29如何借助ROS实现走迷宫机器人

作者头像
zhangrelay
发布2022-09-29 16:38:49
7320
发布2022-09-29 16:38:49
举报
文章被收录于专栏:机器人课程与技术

ROS1云课→28机器人代价地图配置


简述: 在这个项目中,将创建一个机器人,它将进入一个迷宫形式的房间,然后从另一个点离开房间。

详细: 在行业中,有些地方机器人可以收集加工过的物体并将这些物体放入仓库。所以这里在这个对象收集过程中,机器人需要进入机器加工区域,它应该从机器加工区域出来。机器人进入机器区域本质上类似于房间入口,机器人从机器区域出来也称为房间出口。  所以在这个项目中,将开发一个机器人应用程序,该应用程序应该在规定的入口位置进入房间,并通过测量距离来识别机器人进入路径和离开房间的物体/墙壁的距离与规定的出口地点。  为了寻找距离,通常使用激光雷达。通过将 激光测距仪集成到机器人中,将能够找到物体或墙壁的距离。这里需要借助ROS导航算法在STDR模拟器上进出房间。

案例方法也适用于机器人寻宝等竞赛场景。

涉及知识点多且杂。需要熟练掌握1-28节全部内容。 

全局路径规划知识点:

ROS1云课→20迷宫不惑之A*大法(一种虽古老但实用全局路径规划算法)


实际地图:

简化地图:

机器人:

参考文首链接。 

迷宫算法从基础到仿真。


未改进版本视频:

maze_stdr_01


配置文件参考: 

代码语言:javascript
复制
export TURTLEBOT_STDR_MAP_FILE=/home/shiyanlou/Code/demo_ws/src/turtlebot_stdr/maps/maze.yaml
代码语言:javascript
复制
image: maze.png
resolution: 0.1
origin: [0.0, 0.0, 0.0]
occupied_thresh: 0.6
free_thresh: 0.3
negate: 0
代码语言:javascript
复制
<!--
  Turtlebot navigation simulation:
  - stdr
  - move_base
  - amcl
  - map_server
  - rviz view
 -->
<launch>
  <arg name="base"       default="$(optenv TURTLEBOT_BASE kobuki)"/>  <!-- create, rhoomba -->
  <arg name="stacks"     default="$(optenv TURTLEBOT_STACKS hexagons)"/>  <!-- circles, hexagons -->
  <arg name="3d_sensor"  default="$(optenv TURTLEBOT_3D_SENSOR kinect)"/>  <!-- kinect, asus_xtion_pro -->
  <arg name="laser_topic" default="robot0/laser_0"/> <!-- default laser topic in stdr for 1 robot -->
  <arg name="odom_topic" default="robot0/odom"/>
  <arg name="odom_frame_id" default="map"/>
  <arg name="base_frame_id" default="robot0"/>
  <arg name="global_frame_id" default="world"/>
  <!-- Name of the map to use (without path nor extension) and initial position -->
  <arg name="map_file"       default="$(env TURTLEBOT_STDR_MAP_FILE)"/>
  <arg name="initial_pose_x" default="0.5"/>
  <arg name="initial_pose_y" default="15.5"/>
  <arg name="initial_pose_a" default="0.0"/>
  <arg name="min_obstacle_height" default="0.0"/>
  <arg name="max_obstacle_height" default="5.0"/>

  <!--  ******************** Stdr********************  -->
  <include file="$(find stdr_robot)/launch/robot_manager.launch" />
  <!-- Run STDR server with a prefedined map-->
  <node pkg="stdr_server" type="stdr_server_node" name="stdr_server" output="screen" args="$(arg map_file)"/>
  <!--Spawn new robot at init position 2 2 0-->
  <node pkg="stdr_robot" type="robot_handler" name="$(anon robot_spawn)" args="add $(find turtlebot_stdr)/robot/turtlebot.yaml $(arg initial_pose_x) $(arg initial_pose_y) 0"/>
  <!-- Run Gui  -->
  <include file="$(find stdr_gui)/launch/stdr_gui.launch"/>
  <!-- Run the relay to remap topics -->
  <include file="$(find turtlebot_stdr)/launch/includes/relays.launch.xml"/>

  <!--  ***************** Robot Model *****************  -->
  <include file="$(find turtlebot_bringup)/launch/includes/robot.launch.xml">
    <arg name="base" value="$(arg base)" />
    <arg name="stacks" value="$(arg stacks)" />
    <arg name="3d_sensor" value="$(arg 3d_sensor)" />
  </include>
  <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
    <param name="use_gui" value="true"/>
  </node>

  <!-- Command Velocity multiplexer -->
  <node pkg="nodelet" type="nodelet" name="mobile_base_nodelet_manager" args="manager"/>
  <node pkg="nodelet" type="nodelet" name="cmd_vel_mux" args="load yocs_cmd_vel_mux/CmdVelMuxNodelet mobile_base_nodelet_manager">
    <param name="yaml_cfg_file" value="$(find turtlebot_bringup)/param/mux.yaml"/>
    <remap from="cmd_vel_mux/output" to="mobile_base/commands/velocity"/>
  </node>

  <!-- ****** Maps ***** -->
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)">
   <param name="frame_id" value="$(arg global_frame_id)"/>
  </node>


  <!--  ************** Navigation  ***************  -->
  <include file="$(find turtlebot_navigation)/launch/includes/move_base.launch.xml">
   <arg name="odom_topic" value="$(arg odom_topic)"/>
   <arg name="laser_topic" value="$(arg laser_topic)"/>
   <arg name="odom_frame_id"   value="$(arg odom_frame_id)"/>
   <arg name="base_frame_id"   value="$(arg base_frame_id)"/>
   <arg name="global_frame_id" value="$(arg global_frame_id)"/>
  </include>

  <!-- ***************** Manually setting some parameters ************************* -->
    <param name="move_base/local_costmap/obstacle_layer/scan/min_obstacle_height" value="$(arg min_obstacle_height)"/>
    <param name="move_base/local_costmap/obstacle_layer/scan/max_obstacle_height" value="$(arg max_obstacle_height)"/>
    <param name="move_base/global_costmap/obstacle_layer/scan/min_obstacle_height" value="$(arg min_obstacle_height)"/>
    <param name="move_base/global_costmap/obstacle_layer/scan/max_obstacle_height" value="$(arg max_obstacle_height)"/>

  <!--  ************** AMCL ************** -->
  <include file="$(find turtlebot_navigation)/launch/includes/amcl/amcl.launch.xml">
    <arg name="scan_topic" value="$(arg laser_topic)"/>
    <arg name="use_map_topic" value="true"/>
    <arg name="odom_frame_id" value="$(arg odom_frame_id)"/>
    <arg name="base_frame_id" value="$(arg base_frame_id)"/>
    <arg name="global_frame_id" value="$(arg global_frame_id)"/>
    <arg name="initial_pose_x" value="$(arg initial_pose_x)"/>
    <arg name="initial_pose_y" value="$(arg initial_pose_y)"/>
    <arg name="initial_pose_a" value="$(arg initial_pose_a)"/>
  </include>

 <!-- ********** Small tf tree connector between robot0 and base_footprint********* -->
  <node name="tf_connector" pkg="turtlebot_stdr" type="tf_connector.py" output="screen"/>

  <!--  **************** Visualisation ****************  -->
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(find turtlebot_stdr)/rviz/robot_navigation.rviz"/>




</launch>

代码语言:javascript
复制
shiyanlou:~/ $ history                                               [22:37:23]
    1  gedit init.sh
    2  chmod +x init.sh
    3  ./init.sh
    4  git clone https://gitcode.net/ZhangRelay/ros_book.git
    5  cd ros_book
    6  unzip turtlebot_simulator-melodic.zip
    7  sudo apt install ros-kinetic-turtlebot-simulator
    8  catkin_make
    9  source devel/setup.zsh
   10  export TURTLEBOT_STDR_MAP_FILE=/home/shiyanlou/Code/demo_ws/src/turtlebot_stdr/maps/maze.yaml
   11  roslaunch turtlebot_stdr turtlebot_in_stdr.launch 
   12  source devel/setup.zsh
   13  roslaunch turtlebot_stdr turtlebot_in_stdr.launch 
   14  export TURTLEBOT_STDR_MAP_FILE=/home/shiyanlou/Code/demo_ws/src/turtlebot_stdr/maps/hospital_section.yaml
   15  export TURTLEBOT_STDR_MAP_FILE=/home/shiyanlou/Code/demo_ws/src/turtlebot_stdr/maps/hospital_section.yaml
   16  roslaunch turtlebot_stdr turtlebot_in_stdr.launch
   17  export TURTLEBOT_STDR_MAP_FILE=/home/shiyanlou/Code/demo_ws/src/turtlebot_stdr/maps/maze.yaml
   18  roslaunch turtlebot_stdr turtlebot_in_stdr.launch

代码语言:javascript
复制
// Simple Maze Generator in C++ by Jakub Debski '2006 

#include <time.h>
#include <vector>
#include <list>
using namespace std;

int main() 
{ 
   srand(time(0)); 

   const int maze_size_x=80; 
   const int maze_size_y=25; 
   vector < vector < bool > > maze; 
   list < pair < int, int> > drillers; 

   maze.resize(maze_size_y); 
   for (size_t y=0;y<maze_size_y;y++) 
           maze[y].resize(maze_size_x); 

   for (size_t x=0;x<maze_size_x;x++) 
           for (size_t y=0;y<maze_size_y;y++) 
                   maze[y][x]=false; 

   drillers.push_back(make_pair(maze_size_x/2,maze_size_y/2)); 
   while(drillers.size()>0) 
   { 
           list < pair < int, int> >::iterator m,_m,temp; 
           m=drillers.begin(); 
           _m=drillers.end(); 
           while (m!=_m) 
           { 
                   bool remove_driller=false; 
                   switch(rand()%4) 
                   { 
                   case 0: 
                           (*m).second-=2; 
                           if ((*m).second<0 || maze[(*m).second][(*m).first]) 
                           { 
                                   remove_driller=true; 
                                   break; 
                           } 
                           maze[(*m).second+1][(*m).first]=true; 
                           break; 
                   case 1: 
                           (*m).second+=2; 
                           if ((*m).second>=maze_size_y || maze[(*m).second][(*m).first]) 
                           { 
                                   remove_driller=true; 
                                   break; 
                           } 
                           maze[(*m).second-1][(*m).first]=true; 
                           break; 
                   case 2: 
                           (*m).first-=2; 
                           if ((*m).first<0 || maze[(*m).second][(*m).first]) 
                           { 
                                   remove_driller=true; 
                                   break; 
                           } 
                           maze[(*m).second][(*m).first+1]=true; 
                           break; 
                   case 3: 
                           (*m).first+=2; 
                           if ((*m).first>=maze_size_x || maze[(*m).second][(*m).first]) 
                           { 
                                   remove_driller=true; 
                                   break; 
                           } 
                           maze[(*m).second][(*m).first-1]=true; 
                           break; 
                   } 
                   if (remove_driller) 
                           m = drillers.erase(m); 
                   else 
                   { 
                           drillers.push_back(make_pair((*m).first,(*m).second)); 
                           // uncomment the line below to make the maze easier 
                           // if (rand()%2) 
                           drillers.push_back(make_pair((*m).first,(*m).second)); 

                           maze[(*m).second][(*m).first]=true; 
                           ++m; 
                   } 
           } 
   } 

   // Done 
   for (size_t y=0;y<maze_size_y;y++) 
           for (size_t x=0;x<maze_size_x;x++) 
           { 
                   if (maze[y][x]==true) 
                           printf("."); 
                   else 
                           printf("#"); 
           } 

   return 0; 
}
代码语言:javascript
复制
######.........#.#.......#.....#...#.....#.........#.#...#.#.......#.......##### 
######.#.###.#.#.#.#######.#.#####.#.###.#.#.#####.#.###.#.#.#######.########### 
.....#.#.#...#.#.........#.#.#.....#.###...#.#.....#.......#.......#.....####### 
.#.#.###.#.#####.#.#.#######.#.#.#.#.#####################.#.###.#######.####### 
.#.#.#...#...#...#.#...#.#.#.#.#.#.#.........#.....#...........#.#.............# 
####.#.#######.#######.#.#.#.#.#.#######.#.#.#.#.#.#.#######.#######.#######.#.# 
##...#...#####.#.#####.#...#...#.#...#.#.#.#...#.#...###...#.#.......#.......#.# 
####.###.#####.#.#####.#.###.#.###.###.#.#.###.#########.#####.###.############# 
.........###.#.....###.#...#.#.#.#.......#.#...#...#.#.#.#.......#.###...#.....# 
########.###.#.#.#.###.#.#.###.#.#.#####.#.###.#.###.#.#.#.#.###.#####.###.#.### 
.......#.....#.#.#.#...#.#...........#...#.#.....#.......#.#...#.#.........#...# 
####.#.#.#####.#.###.#######.#######.###.#.#.###.#.#####.#.#####.#.#.#####.##### 
...#.#.#.......#...#.....#.....#.#...#####.#...#.......#.#...#.....#...#.#.....# 
##.###.#.#.#.###.#####.#.#####.#.#.#######.#####.#####.#.###.#.###.#####.#####.# 
##...#...#.#.#.......#.#.....#...#.......#...#...#.....#.....#...#...........#.# 
####.#.###########.###.#.###.#####.#######.###.###########.###.###.#####.###.### 
####...###.....#...#.#.#...#...........###...#.###...#.###.###...#.....#.#.....# 
####.#####.#######.#.###.###.#.#####.#.#############.#.###.#####.#####.#.###.### 
####.........#.#...#.....#.#.#.#.....#.###.#...#.............#...#####.#...#...# 
######.#.#####.#.###.#.#.#.###.#######.###.#.#####.###.#################.####### 
######.#...#.#.....#.#.#.#...#...###...###.....#...#.......#########...#.......# 
######.###.#.#####.#####.#.###.#.###.#.###.#.###.###.#####.#########.#########.# 
######.#.#.#...###...#...#.#.#.#...#.#.....#.#.#...#.###...#########...#.......# 
########.#.###.#######.#.#.#.###.#######.###.#.#####.###############.#.###.##### 
########...###.........#.#.......#######.#.....#####.......#########.#.........#

路径规划研究的起源(如下为引用)

问题简介

18世纪初普鲁士的哥尼斯堡,有一条河穿过,河上有两个小岛,有七座桥把两个岛与河岸联系起来(如概述图)。有个人提出一个问题:一个步行者怎样才能不重复、不遗漏地一次走完七座桥,最后回到出发点。后来大数学家欧拉把它转化成一个几何问题——一笔画问题。他不仅解决了此问题,且给出了连通图可以一笔画的充要条件是:奇点的数目不是0个就是2个(连到一点的数目如果是奇数条,就称为奇点;如果是偶数条,就称为偶点。要想一笔画成,必须中间点均是偶点,也就是有来路必有另一条去路,奇点只可能在两端。因此任何图能一笔画成,奇点要么没有,要么在两端) 。

推断方法

当欧拉在1736年访问普鲁士的哥尼斯堡(现俄罗斯加里宁格勒)时,他发现当地的市民正从事一项非常有趣的消遣活动。哥尼斯堡城中有一条名叫Pregel的河流横经其中,这项有趣的消遣活动是在星期六作一次走过所有七座桥的散步,每座桥只能经过一次而且起点与终点必须是同一地点。

欧拉把每一块陆地考虑成一个点,连接两块陆地的桥以线表示。

后来推论出此种走法是不可能的。他的论点是这样的,除了起点以外,每一次当一个人由一座桥进入一块陆地(或点)时,他(或她)同时也由另一座桥离开此点。所以每行经一点时,计算两座桥(或线),从起点离开的线与最后回到始点的线亦计算两座桥,因此每一个陆地与其他陆地连接的桥数必为偶数。

存在问题

著名数学家欧拉的画像

著名数学家欧拉的画像

七桥所成之图形中,没有一点含有偶数条数,因此上述的任务无法完成。

欧拉的这个考虑非常重要,也非常巧妙,它正表明了数学家处理实际问题的独特之处——把一个实际问题抽象成合适的“数学模型”。这种研究方法就是“数学模型方法”。这并不需要运用多么深奥的理论,但想到这一点,却是解决难题的关键。

接下来,欧拉运用图中的一笔画定理为判断准则,很快地就判断出要一次不重复走遍哥尼斯堡的7座桥是不可能的。也就是说,多少年来,人们费脑费力寻找的那种不重复的路线,根本就不存在。一个曾难住了那么多人的问题,竟是这么一个出人意料的答案!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档