目录

  • 1 智能移动机器人-基础篇
    • 1.1 第一讲 坐标变换(5课时)
    • 1.2 第二讲 ROS基本概念(3课时)
      • 1.2.1 实训
    • 1.3 第三讲-编写简单的订阅者和发布者节点(4课时)
      • 1.3.1 实训
      • 1.3.2 实训2
    • 1.4 第四讲 ROS服务及编程(2课时)
    • 1.5 第五讲 ROS坐标变换工具TF(4课时))
    • 1.6 第六讲 ROS参数及应用(2课时))
    • 1.7 第七讲 运动学模型及航迹推算(4课时)
      • 1.7.1 实训1.7.1
    • 1.8 第八讲 URDF机器人建模及应用(4课时))
      • 1.8.1 实训1.8.1
    • 1.9 第九讲 QT-ROS交互界面应用开发(4课时)
  • 2 智能移动机器人-提高篇
    • 2.1 第一讲 栅格地图及应用(2课时)
    • 2.2 第二讲 局部路径规划及避障(6课时)
    • 2.3 第三讲 运动学模型的概率表示(2课时)
    • 2.4 spark实验5-激光雷达信息处理-标定
    • 2.5 第四讲 激光雷达及其测量模型(4课时)
    • 2.6 第五讲 蒙特卡洛定位(MCL)(4课时)
    • 2.7 第六讲 并发定位与建图(SLAM)(4课时)
    • 2.8 第七讲 自主导航(6课时)
    • 2.9 第八讲 Librviz可视化应用开发(4课时)(4课时)
  • 3 实训篇-SparkT移动机器人(室内)
    • 3.1 SparkT移动机器人介绍
    • 3.2 演示视频
    • 3.3 相关工具及资料下载
    • 3.4 spark实验1-控制spark移动
    • 3.5 spark实验2-编写节点控制spark移动
      • 3.5.1 python版本
    • 3.6 spark实验3-并发定位与建图
    • 3.7 spark实验4-机器人定位与导航
    • 3.8 spark实验6-基于激光雷达的行人检测与跟踪
    • 3.9 spark实验7-机械臂抓取
    • 3.10 2023年夺宝奇兵大赛培训资料
    • 3.11 2024年夺宝奇兵半自动赛培训
      • 3.11.1 半自动赛程序设计方法2024年7月3日
    • 3.12 2024年夺宝奇兵自动任务赛培训
      • 3.12.1 代码框架(noetic版本)
      • 3.12.2 代码框架(kinetic版本)
      • 3.12.3 自动赛讲解视频2024年6月29日
      • 3.12.4 ROS下QT界面开发2024年6月30日
      • 3.12.5 目标识别与机械臂抓取7月1日
      • 3.12.6 自动赛思路讲解(2024,.7.3)结课
      • 3.12.7 基于大模型的辅助开发(python)
        • 3.12.7.1 案例1:激光雷达数据订阅与发布
        • 3.12.7.2 案例2:激光雷达与地图匹配程度计算
        • 3.12.7.3 案例3:基于Web的机器人远程控制
        • 3.12.7.4 案例4:ROS的QT界面应用开发
        • 3.12.7.5 案例5:ROS下语音识别及QT界面
        • 3.12.7.6 案例6:从摄像头获取图像数据并进行二维码识别
        • 3.12.7.7 案例7:Gazebo仿真
        • 3.12.7.8 案例8:基于RGBD的行人识别与跟踪
    • 3.13 spark实验-基于teb-local-planner的导航
    • 3.14 Spark实验-利用rf2o提高定位精度
  • 4 室外自主导航车(AGV)-实训篇
    • 4.1 AGV本体介绍
    • 4.2 实训项目1-AGV建模(URDF)
    • 4.3 实训项目2-AGV运动学模型及航迹推算
    • 4.4 实训项目3-AGV运动控制
    • 4.5 实训项目4-基于GPS的点对点导航
    • 4.6 实训项目5-基于GPS的循迹
    • 4.7 实训项目6-基于三维激光雷达(点云)的障碍物检测与避障
    • 4.8 实训项目7-基于深度相机(RGBD)的目标识别与跟踪
  • 5 智能机器人技术实践上课录屏
    • 5.1 实训项目1-2024年9月3日
2024年夺宝奇兵半自动赛培训

2024年校内赛要求:要求参赛选手在指定的比赛设备上建立ROS包,包的名字规则为pkgxxxxxx为选手名字拼音缩写)。选手自行开发的代码需放置在其包下面,通过各自包下的launch文件启动。

参赛设备1:spark-7797,热点为spark-7797,安全密钥连接,密码为:12345678,连接热点后,

通过VNC Viewer连接到该主机,IP地址为:10.42.0.1

工作区:ws_2024

在ws_2024工作区下建立包,包的名字规则为pkgxxxxxx为选手名字拼音缩写)。

步骤1、创建工作区

注:如果该步骤之前已完成,则可以省略

(注:其中ws_2024为工作区的名字)

$ mkdir  -p  ~/ws_2024/src
$ cd  ~/ws_2024/src
$ catkin_init_workspace
$ cd  ~/ws_2024
$ catkin_make
$ source  ~/ws_2024/devel/setup.bash
$ rospack  profile
$ echo   "source  ~/ws_2024/devel/setup.bash"   >>  ~/.bashrc



步骤2、创建包(如果该步骤之前已经完成,则可省略)

(注:其中pkgduan为包的名字)

$ cd  ~/ws_2024/src
$catkin_create_pkg  pkgduan  std_msgs  geometry_msgs rospy roscpp
$ cd  ~/ws_2024
$ catkin_make


步骤3、建立launch目录、scripts目录:

$roscd pkgduan
$mkdir launch
$mkdir scripts
$cp ~/spark_noetic/src/3rd_app/move2grasp/launch/teleop2grasp.launch launch
$cp ~/spark_noetic/src/3rd_app/move2grasp/scripts/teleop.py scripts
$cp ~/spark_noetic/src/3rd_app/move2grasp/scripts/grasp_pro_new.py scripts


将~/spark_noetic/src/3rd_app/move2grasp/launch/teleop2grasp.launch文件拷贝到launch目录,

~/spark_noetic/src/3rd_app/move2grasp/scripts/teleop.py文件拷贝到scripts目录

~/spark_noetic/src/3rd_app/move2grasp/scripts/grasp_pro_new.py文件拷贝到scripts目录

步骤4、修改launch目录下的teleop2grasp.launch文件,修改后存盘退出

$roscd pkgduan/launch
$gedit  teleop2grasp.launch


原来的文件内容包括:

<node pkg="move2grasp" type="teleop.py" name="teleop" launch-prefix="xterm -e" />
<group if="$(eval arg('camera_type_tel')=='d435')">
<node pkg="move2grasp" type="grasp_d435.py" name="grasp" output="screen">
<remap from="/camera/rgb/image_raw" to="/camera/color/image_raw" if="$(eval arg('camera_type_tel')=='d435')"/>
</node>
</group>
<group if="$(eval arg('camera_type_tel')=='astrapro')">
<node pkg="move2grasp" type="grasp_pro_new.py" name="grasp" output="screen"/>
</group>


将其中的 pkg="move2grasp"  改为 pkg="pkgxxx"  (其中pkgxxx为你的包的名字,有三个地方需要改,也就是启动你自己包下的节点),如下:

<node pkg="pkgxxx" type="teleop.py" name="teleop" launch-prefix="xterm -e" />
<group if="$(eval arg('camera_type_tel')=='d435')">
<node pkg="pkgxxx" type="grasp_d435.py" name="grasp" output="screen">
<remap from="/camera/rgb/image_raw" to="/camera/color/image_raw" if="$(eval arg('camera_type_tel')=='d435')"/>
</node>
</group>
<group if="$(eval arg('camera_type_tel')=='astrapro')">
<node pkg="pkgxxx" type="grasp_pro_new.py" name="grasp" output="screen"/>
</group>

步骤5、启动launch文件并实现机器人控制、抓取,新开一个终端,执行下面指令:

$roslaunch  pkgduan  teleop2grasp.launch


启动后,控制界面如下:


点击图标,将遥控界面至于活动界面,通过WASD控制机器人移动和旋转,通过G抓取其前方的分米立方块,通过H放下立方块。


步骤6、如何扩展,基本思路和方法:

通过rosrun rqt_graph rqt_graph可以查看的目前ROS的计算图如下(部分):


其中teloop节点对应的代码就是:teleop.py

grasp节点对应的代码就是:grasp_pro_new.py

修改上述两个节点,就可以实现更为复杂的功能。

例如,在teleop.py中增加更多的功能键,实现不同高度的放置(参考其中H功能键的代码扩展),

grasp_pub = rospy.Publisher('/grasp', String, queue_size=1)

...                
               
               
       # ch为按键
       if ch == 'g':
           if can_grasp:
               msg=String()
               msg.data='1'
               grasp_pub.publish(msg)
               can_grasp=False
               speed = 0
               turn = 0
       elif ch == 'h':
           if can_release:
               msg=String()
               msg.data='0'
               grasp_pub.publish(msg)
               can_release=False
               speed = 0
               turn = 0


上面的代码中,msg.data向/grasp话题发布的消息,该消息被grasp节点订阅,实现不同的功能

目前发布的消息只有"0","1";

例如,可以设置一个按键'k',发布消息"2",表示要放到第二层的高度。

这就交给各位同学,各显神通了!


再来看一下grasp_pro_new.py的核心代码(grasp节点):

self.sub2 = rospy.Subscriber(
           '/grasp', String, self.grasp_cp, queue_size=1)


这说明,该节点从/grasp话题订阅消息,回调函数为self.grasp_cp,只要改该函数就可以增加功能,

    def grasp_cp(self, msg):
       if msg.data == '1':
           # \u8ba2\u9605\u6444\u50cf\u5934\u8bdd\u9898,\u5bf9\u56fe\u50cf\u4fe1\u606f\u8fdb\u884c\u5904\u7406
           self.sub = rospy.Subscriber("/camera/rgb/image_raw", Image, self.image_cb, queue_size=1)
           self.is_found_object = False
           rate = rospy.Rate(10)
           times=0
           steps=0
           while not self.is_found_object:
               rate.sleep()
               times+=1
               # \u8f6c\u4e00\u5708\u6ca1\u6709\u53d1\u73b0\u53ef\u6293\u53d6\u7269\u4f53,\u9000\u51fa\u6293\u53d6
               if steps>=5:
                   self.sub.unregister()
                   print("stop grasp\n")
                   status=String()
                   status.data='-1'
                   self.grasp_status_pub.publish(status)
                   return
               # \u65cb\u8f6c\u4e00\u5b9a\u89d2\u5ea6\u626b\u63cf\u662f\u5426\u6709\u53ef\u4f9b\u6293\u53d6\u7684\u7269\u4f53
               if times>=30:
                   times=0
                   steps+=1
                   self.turn_body()
                   print("not found\n")
           print("unregisting sub\n")
           self.sub.unregister()
           print("unregisted sub\n")
           # \u6293\u53d6\u68c0\u6d4b\u5230\u7684\u7269\u4f53    
           self.grasp()
           status=String()
           status.data='1'
           self.grasp_status_pub.publish(status)
       if msg.data=='0':
           # \u653e\u4e0b\u7269\u4f53
           self.is_found_object = False
           self.release_object()
           status=String()
           status.data='0'
           self.grasp_status_pub.publish(status)





附文件源码:





视频讲解1:(如何扩展功能界面)


视频讲解2:(扩展功能)