记植保无人机航线规划算法的实现

1. 引言

​ 无人机航线规划是植保无人机能否正常作业的重点,航线规划的好坏决定了无人机能否对整个区域全覆盖、不飞出边界、不重复、不遗漏的扫描喷洒作业。目前市面上不乏好的植保航线规划算法,大多数是基于凸多边形的航线规划,对凹多边形的航线规划不能做到全覆盖、不飞出边界的要求。下面介绍我所实现的植保无人机航线规划算法,目的是解决区域全覆盖、不飞出边界等作业要求,性能上不一定是最优实现。

2. 作业区域要求

​ 本算法对作业区域没有过多要求,但对区域过于复杂、作业面积过小或过大、区域中有两条边线之间夹角过小等不能实现最优。

3. 算法实现

3.1 区域旋转

​ 在给定的参数中,选择的方向可能是任意方向,规定航线方向可以使航线规划更方便。所以整个区域在给定的方向需要旋转90°,使给定方向与水平方向平行。目前做法是以整个区域的最左上角坐标为原点进行旋转,给出代码:

/**
  * 旋转坐标系
  *
  * @param boundPoints  需要旋转的坐标
  * @param rotateRadian 旋转弧度
  * @return 旋转的数据
  * @throws IOException
  * @throws ClassNotFoundException
  */
private static TranslateAndRotateBean translateAndRotateBoundFromWorld(List<? extends PointD> boundPoints, double rotateRadian) throws IOException, ClassNotFoundException {
    MaxMinLatLng maxMinLatLng = getMaxMinLatLng(boundPoints);
    PointD intersectPoint = new PointD(maxMinLatLng.getMinLat(), maxMinLatLng.getMinLng());//旋转后的原点
    double reallyRotateRadian = -rotateRadian + PI12;

    TranslateAndRotateBean translateAndRotateBean = new TranslateAndRotateBean(intersectPoint, reallyRotateRadian);
    //旋转
    for (PointD boundPoint : boundPoints) {
        rotateFromWorld(boundPoint, translateAndRotateBean);
    }
    return translateAndRotateBean;
}

/**
  * 旋转
  *
  * @param pointD 点
  * @param t      旋转参数
  */
private static void rotateFromWorld(PointD pointD, TranslateAndRotateBean t) {
    double x = pointD.x;
    double y = pointD.y;
    pointD.x = (x - t.getIntersectPoint().x) * cos(t.getReallyRotateRadian()) - (y - t.getIntersectPoint().y) * sin(t.getReallyRotateRadian()) + t.getIntersectPoint().x;
    pointD.y = (y - t.getIntersectPoint().y) * cos(t.getReallyRotateRadian()) + (x - t.getIntersectPoint().x) * sin(t.getReallyRotateRadian()) + t.getIntersectPoint().y;
    }

3.2 生成航线

​ 根据3.1操作,得到了旋转后的区域,接下来的操作会针对旋转后的区域进行航线生成。

start=>start: 开始
1=>operation: 找到整个区域中最高点,
            将此点记录到当前最高点
2=>condition: 当前最高点是否比最低点大
3=>operation: 根据给定喷幅从当前最高点向
            下移动半个喷幅的距离,
            对整个区域画横线
4=>operation: 获得横线与区域的交点,
            将所有区域交点按照
            从左至右的顺序排序
5=>condition: 交点数量是否大于2个
6=>operation: 取出前两个点,生成
            航线并加入到航线集合中
7=>operation: 移出这两个交点
8=>operation: 将当前最高点再向
            下移动半个喷幅高度
end=>end: 结束

start->1
1->2
2(no)->end
2(yes)->3
3->4
4->5
5(yes)->6
5(no)->8
6->7
7->5
8->2
  1. 首先找到整个区域中最高点,将此点记录到当前最高点;
  2. 判断当前最高点是否已经比最低点小,如果是则进行步骤8,如果否,则进行步骤3;
  3. 根据给定喷幅从当前最高点向下移动半个喷幅的距离,对整个区域画横线;
  4. 获得横线与区域的交点,将所有区域交点按照从左至右的顺序排序;
  5. 判断交点数量是否大于2个,如果是,进行步骤6,如果否进行步骤(这里存在一个问题,待后续介绍);
  6. 取出前两个点,生成航线并加入到航线集合中;
  7. 移出这两个交点,进行步骤4;
  8. 将当前最高点再向下移动半个喷幅高度,进行步骤2;

自此,所有航线都已经添加到航线集合中了。

3.3 连接航线

​ 首先对生成的航线按照旋转的角度以及原来的旋转原点对航线还原成真实的航线。

​ 拿出第一条航线,根据用户给定的起飞点的位置,判断这条航线的开始点、结束点哪个距离起飞点更近,如果结束点距离起飞点更近,则交换开始点、结束点。

​ 取出第二条航线,判断第二条航线的起飞点与结束点哪个与上一条航线的结束点更近,如果结束点更近,则交换开始点与结束点,以此类推。

3.4 小结

​ 此刻,航线已经生成,已经可以做到全覆盖,但是对于某些情况下,无法做到航线飞出区域外、空飞路径过长问题,所以目前生成的航线需要优化。

4 航线优化

4.1 航线顺序优化

​ 航线生成时,所有航线都是一个个的添加到航线集合中,这样导致航线在有些情况下,两条航线的连接会穿过区域,使航线在区域外。所以优化之一就是在3.2基础上,在得到每条航线的交点时,记录每条航线与区域的哪两条边相交,将航线关联到两条边上,相同的两条边上的航线应该连接在一起。

/**
* 获取对应航线区域
*
* @param sprayGraphList         航线区域的Map
* @param startLinePointPosition 航线起始交点在区域中的边的位置
* @param endLinePointPosition   航线结束交点在区域中的边的位置
* @return 所对应的航线区域
*/
private static SprayGraph getAssignSprayGraph(Map<String, SprayGraph> sprayGraphList, int startLinePointPosition, int endLinePointPosition) {
    String hashCode = startLinePointPosition + " " + endLinePointPosition;
    SprayGraph sprayGraph = sprayGraphList.get(hashCode);
    if (sprayGraph == null) {
        sprayGraph = new SprayGraph();
        sprayGraphList.put(hashCode, sprayGraph);
    }
    return sprayGraph;
}

SprayGraph类:是真正保存航线的位置。

sprayGraphList:这个Map中存储SprayGraph,它的键是以航线开始交点的边的位置和结束交点边的位置构成的字符串,因为生成航线时,航线的开始位置一定会在航线的结束位置的左边,所以不会出现”1 2“,”2 1“的情况。

4.2 添加A*算法

在4.1中,通过对航线顺序的优化,可以做到大部分航线能够在区域内,但还是有部分航线会越过区域边线飞到区域之外。所以从一条航线的结束点到下一条航线的开始点需要在区域内找出最短路径,目前使用A*算法来达到不飞到区域外的情况。关于A*算法的实现,将下下一篇文章中介绍。

4.3 减少过短航线

航线过短会让无人机在还没有加速时就要开始减速,影响无人机的作业效率。计算航线长度,判断航线长度是否小于给定的最短航线长度时,此航线将不加入到航线集合中。

4.4 航线缩进

航线缩进是为了保证无人机作业时不飞出作业区域,更是为了A*算法的实现提供实施基础。航线缩进的实现是以飞机的半径为准,所以航线的缩进要保证以飞机中心点画圆不能与区域有交点或仅有一个交点。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容