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

2022-11-30 15:51:14 浏览数 (1)

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

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

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

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

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

全局路径规划知识点:

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

实际地图:

简化地图:

机器人:

参考文首链接。 

迷宫算法从基础到仿真。

未改进版本视频:

https://live.csdn.net/v/embed/2396

配置文件参考: 

代码语言: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座桥是不可能的。也就是说,多少年来,人们费脑费力寻找的那种不重复的路线,根本就不存在。一个曾难住了那么多人的问题,竟是这么一个出人意料的答案!

0 人点赞