在很多商用机器人中都涉及到机器人与外部设备(比如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)(如下图)。我们举一个例子,现在有一个800×800的地图,我们需要使用鼠标或触摸选择了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数据格式将点击数据下发至机器人。 下一小节我们将介绍机器人图片与原点坐标系的变换方法。 欢迎大家关注,你的关注就是雨哥更新的动力~! 另外,本博客是雨哥在做项目过程中总结提炼的非涉密技术类文档,欢迎大家转发,转载请注明出处,同时不得用于商业用途! ————————————————