室外低速自动导航车的设计(4)——APP与机器人内的ROS地图的同步和匹配

 ̄綄美尐妖づ 提交于 2020-02-27 01:45:33

    在很多商用机器人中都涉及到机器人与外部设备(比如APP)之间的交互。而在交互中,最为首要的就是地图与机器人位置的交互了。在这一个章节中,我们介绍一个机器人将内部的地图,机器人位置等数据与用户端进行同步的案例。

1. 实际场景与机器人(ROS)地图的对应关系:

    我们来看一下下面这副图片,这是一个机器人在实际环境中绘制的二维地图,在图片的左下角是地图原点(map所在的位置),在原点上已经标明了这个地图的三维坐标轴,其中红色的代表x轴方向,绿色代表y轴方向。

         

   在ROS的地图中,地图同样是以像素标记的,每一个像素代表0.05m,也就是一个像素是5厘米。比如下图上的星星,他的位置在像素层面上的坐标为:x:400像素,y:150像素;那么这个机器人实际的横坐标就应该是:400*0.05=20米,纵坐标是150*0.05=7.5m。再换句话说,如果一个地图的场合宽都是800像素,那么它能够代表的实际长和宽度为800*0.05=40米。

           

    当然,有时候地图的原点并不一定在左下角,它的原点可以在地图的任意一个地方。比如说下面这张图:

        

    这张图的地图原点就跑到了地图图片里,那么假如机器人在原点左下角的位置上,那么机器人的X和Y坐标就会为负值。

    在ROS中,地图的类型是nav_msgs/OccupancyGrid,每个像素代表的长度以及地图的原点都被定义在了消息结构体之中:

std_msgs/Header header

nav_msgs/MapMetaData info

  time map_load_time

  float32 resolution      分辨率

  geometry_msgs/Pose origin原点坐标

   ......

    geometry_msgs/Quaternion orientation

     ......

int8[] data    地图像素信息
 

2. 地图坐标系与Python canvas鼠标点击位置之间的对应关系:

    我们使用python编写客户端的时候(Java于此类似),地图是要被绘制到canvas,也就是虚拟画布上面。虚拟画布是以其左上角为坐标原点(0,0)(如下图)。我们举一个例子,现在有一个800x800的地图,我们需要使用鼠标或触摸选择了APP中地图的左上角,那么显然的,在APP中,我们得到的点击位置是(0,0)。

      

     但是如果我们把这个数据输入ROS的地图中,可以看到,在ROS中,(0,0)点位置对应的是左下角。所以造成的问题就会如下图:

             

    这个问题解决的方法很简单,就是在用户端软件(如APP)中,将点击的点做一些处理(坐标系变换),再将其数据传输到机器人上即可。

3. Python  Canvas与机器人内ROS之间的数据传输(http)

    一般的机器人与客户端的通讯方式采用http方式传输信息,http协议的详细内容请参见新安浅滩的博文:

    https://blog.csdn.net/hu694028833/article/details/80862695

    整个机器人与Python之间地图与坐标系的传递过程中,Python要向机器人获取三个信息(已知地图每个像素为0.05米):

    1)机器人中当前地图的图片

    2)地图图片的右下角在机器人坐标系中所处的位置(或者说地图的原点在地图图片中所处的像素位置

    3)机器人相对于地图坐标系原点的位置

    由于传输数据量很大,所以Python客户端向机器人请求地图的频率不能太高(基本为数秒一次,或只在加载时请求)。而因为机器人在时刻移动,机器人相对地图坐标原点的位置我们必须要频繁的请求。所以在数据通讯上,我们将以上三个信息分为两类:

    1)当前机器人内部地图图片以及地图原点信息(加载地图,以及绘制地图时请求)

    2)机器人相对地图原点的位置(数百毫秒,轮询请求)

    例如,Python在机器人加载地图后,向机器人发送一个名为: GET /robot_map HTTP/1.1的消息

    机器人向Python反馈jpeg压缩格式的地图图片

    Python程序向机器人发送一个名为:GET /robot_map_origin HTTP/1.1的消息

    机器人反馈地图的原点坐标:

    {

        "x": 1.0

        "y":1.0

    }

   这样就实现了地图与地图坐标原点的传输。

   同时,Python每间隔1000ms向机器人发送:GET /robot_state HTTP/1.1的消息

   机器人反馈机器人实时位置:  

    {
        “navigation_state”:
        {
            “x”:1.23   //注意:这里指的是机器人相对地图原点的实际位置,带小数点的。
            “y:2.34
        }
    }
这样就获取到了机器人的位置。

4.  Python上显示机器人位置以及正确发送点击坐标

    现在我们得到了地图,地图原点,机器人在实际环境中相对于地图原点的位置。那么我们就要在地图中正确显示出机器人所在位置,具体的方法如下:

    1)采用比例变换,将机器人相对于原点的实际位置坐标转换为像素坐标

    2)在已知地图原点在图片中像素的前提下,将机器人相对于地图原点的像素坐标,映射到相对地图图片的像素中坐标。

    3)在地图图片上,按照机器人的像素坐标叠加机器人图片。

    4)显示

    如果我们想向机器人输出一个鼠标或触摸点击的坐标,我们要执行以下步骤:

    1)获得鼠标点击的位置像素坐标(x,y)

    2)对Python Canvas的坐标进行Y轴反转,获得临时像素坐标(例如地图高度为800,点击了(100,700)位置,那么发送的Y坐标为800-700=100)

   3)在获取地图原点的基础上,利用坐标系变换,将临时像素坐标转换为相对于原点的像素坐标

   4)根据像素-实际尺寸的比例变换,将像素坐标变为实际坐标

   5)通过http的POST结合json数据格式将点击数据下发至机器人。

 

下一小节我们将介绍机器人图片与原点坐标系的变换方法。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!