海康威视复赛题 ---- 碰撞避免方案(1)

题目详情:http://www.cnblogs.com/wlzy/p/7096182.html

复赛题要求机器人之间不允许发生碰撞和相遇,拿到题目后,大体有以下几个解题思路:

1.基于侧边停车的碰撞避免算法

  侧边停车是属于一种局部路径规划,只要保证每辆车时时刻刻拥有独立的侧停车位,那么即使发生相遇冲突,也可以及时侧停避让,算法大体描述如下:

  

定义机器人占据点属性:    机器人可获取侧停车位的最小路径点集。
         预测点属性:    从占据点下个点到路径终点的点集。

开始:
        1.初始化地图map
        2.计算每个机器人的占据点,然后添加到map中相应的占据点队列中
        3.计算每个机器人的预测点和机器人到每个预测点的距离值 ,并添加到map相应的预测点队列中。
        4.检测占据点是否冲突。
        5.遍历每个机器人,检测第一个预测点是否冲突
            若无冲突,继续前进
            有冲突,检测冲突类型:如果是相交冲突,只需简单令其中一个暂停。如果是相遇冲突,根据优先级选择一辆车侧停避让。
        6.死锁检测和处理结束。

  

  该算法只需遍历每个机器人的占据点和第一个预测点,执行速度很快,机器人通行效率较高,但是存在以下问题:当机器人较多时,动态移动的机器人可能随时占用其他机器人的侧停车位,使得机器人无法满足调度的基本条件,从而容易导致死锁。

  可以通过加长预测点来减少死锁发生的概率,或者添加一些死锁处理算法,但是这只能是治标不治本,总会有遗漏的情况。

2.基于相遇检测的碰撞避免算法

  为了避免调度陷入死锁状态,提出了一种相遇避免算法,只要时刻检测每个机器人的预测点是否会相遇,若发生相遇则调度使其中部分暂停。

  

定义机器人占据点属性:    机器人当前位置点。
         预测点属性:    从占据点下个点到路径终点的点集。

开始:
        1.初始化地图map
        2.计算每个机器人的占据点,然后添加到map中相应的占据点队列中
        3.计算每个机器人的预测点和机器人到每个预测点的距离值 ,并添加到map相应的预测点队列中。
        4.检测占据点是否冲突。
        5.遍历每个机器人:
            6.检测第一个预测点是否有冲突,若无则继续走,如有则记录该点中所有有冲突的机器人RobotList。
            7.遍历剩余的预测点,若RobotList中机器人的占据在预测点中被找到,说明该机器人未来路径会发生相遇,立即停止运行。
                             若没有机器人机器人占据点,则比较所有冲突机器人到那段路径的距离,距离最小的取得改路径使用权。

结束。

    算法2已经成功实现了,执行速度还算快,结果稳定无错误。由于添加了相遇检测,彻底避免了机器人在移动过程中相遇的情况,因此只需处理十字路口相交的冲突。

    但是算法2采用的相遇检测机制注定了效率低下,会因为避免相遇而等待大量时间。不过有个优化的解决方案:在机器人执行任务前规划一条较优的路径,这样就能大量减少相遇冲突的等待时间。

核心代码:

//生成冲突地图
void Dispatch::GenConflict(TreeMsg &msg)
{
    msg.Map_map.clear(); //清空冲突地图
    //busy机器人冲突点设置
    if(msg.RobotBusy_map.empty() == false)
    {

        map<ZY_UINT32,RobotInfo>::iterator rit;
        for(rit = msg.RobotBusy_map.begin();rit != msg.RobotBusy_map.end();rit++)
        {
            RobotInfo robot_info = rit->second;

            //获取占据点 只有一个
            map<PointItem,PointInfo>::iterator fit_o1 =  msg.Map_map.find(robot_info.Current_Pos.Pos);
            if(fit_o1 != msg.Map_map.end())   //在map中存在,添加占据点
            {
                PointInfo point_info = fit_o1->second;
                point_info.OccupyList.insert(RobotInfoP(robot_info,0));
                msg.Map_map[robot_info.Current_Pos.Pos] = point_info;
            }
            else
            {
                PointInfo point_info;
                point_info.OccupyList.insert(RobotInfoP(robot_info,0));
                msg.Map_map.insert(map<PointItem,PointInfo>::value_type(robot_info.Current_Pos.Pos,point_info));
            }

            //获取预测点
            if(robot_info.Relative_Pos < robot_info.Route_Size)   //为走到终点
            {
                for(int i=(robot_info.Relative_Pos +1);i <= robot_info.Route_Size;i++)
                {
                    PointItem point_item = robot_info.Route->at(i);
                    map<PointItem,PointInfo>::iterator fit_p =  msg.Map_map.find(point_item);
                    if(fit_p != msg.Map_map.end())
                    {
                        PointInfo point_info = fit_p->second;
                        point_info.PredictList.insert(RobotInfoP(robot_info,i - robot_info.Relative_Pos));
                        msg.Map_map[point_item] = point_info;
                    }
                    else
                    {
                        PointInfo point_info;
                        point_info.PredictList.insert(RobotInfoP(robot_info,i - robot_info.Relative_Pos));
                        msg.Map_map.insert(map<PointItem,PointInfo>::value_type(point_item,point_info));
                    }
                }
            }

            //
            robot_info.LastOccupyP = robot_info.Route->at(robot_info.Relative_Pos);
            if(robot_info.Relative_Pos < robot_info.Route_Size)
                robot_info.FirstPredictP = robot_info.Route->at(robot_info.Relative_Pos+1);
            else
                robot_info.FirstPredictP = robot_info.Route->at(robot_info.Relative_Pos);
            msg.RobotBusy_map[rit->first] = robot_info;
        }
    }
}

  

void Dispatch::ConflictProcess(TreeMsg &msg)
{
    //将机器人状态全部置为未更新
    {
        map<ZY_UINT32,RobotInfo>::iterator rit;
        for(rit = msg.RobotBusy_map.begin();rit != msg.RobotBusy_map.end();rit++)
        {
            RobotInfo robot_info = rit->second;
            robot_info.IsUpdated = false;
            robot_info.AddTail = false;
            msg.RobotBusy_map[rit->first] = robot_info;
        }
        map<RobotKey,RobotInfo>::iterator rit2;
        for(rit2 = msg.RobotIdle_map.begin();rit2 != msg.RobotIdle_map.end();rit2++)
        {
            RobotInfo robot_info = rit2->second;
            robot_info.IsUpdated = false;
            robot_info.AddTail = false;
            msg.RobotIdle_map[rit2->first] = robot_info;
        }
    }
    if(msg.RobotBusy_map.empty() == false)
    {
        set<PointItem> IO_CollisionPoint;             //出入口出的冲突点
        IO_CollisionPoint.clear();
        while(1)
        {
            bool IsChanged = false;
            map<ZY_UINT32,RobotInfo>::iterator ritg;
            GenConflict(msg);            //生冲突处理地图
            for(ritg = msg.RobotBusy_map.begin();ritg != msg.RobotBusy_map.end();ritg++)
            {
                RobotInfo robot_info = ritg->second;

                //检测是否更新过
                if(robot_info.IsUpdated == true)
                    continue;

                //占据点与占据点冲突检测 忽略出入口冲突
                if((msg.Map_map.at(robot_info.LastOccupyP).OccupyList.size() > 1)&&(robot_info.LastOccupyP != Map_In)                        &&(robot_info.LastOccupyP != Map_Out))
                {
#ifdef ZYVV_DEBUG
                    cout<<"OccupyP Error\r\n";
#endif
                    continue;
                }

                //若预测点为出入口 则忽略
                if((robot_info.FirstPredictP == Map_In)||(robot_info.FirstPredictP == Map_Out))
                {
                    robot_info.Relative_Pos++;
                    robot_info.Current_Pos.Pos = robot_info.Route->at(robot_info.Relative_Pos);
                    robot_info.DistToE--;
                    robot_info.IsUpdated = true;
                    msg.RobotBusy_map[ritg->first] = robot_info;
                    IsChanged = true;
                    GenConflict(msg);
                    //添加到出入口冲突点
                    IO_CollisionPoint.insert(robot_info.LastOccupyP);
                    continue;
                }

                //预测点和占据点冲突
                if(msg.Map_map.at(robot_info.FirstPredictP).OccupyList.empty() == false)
                {
                    //等待
                    continue;
                }

                {
                //剔除同向预测点
                set<RobotInfoP>::iterator rit1;
                set<RobotInfoP> predict_listp = msg.Map_map.at(robot_info.FirstPredictP).PredictList;
                set<RobotInfoP> predict_listp2 = msg.Map_map.at(robot_info.LastOccupyP).PredictList;
                for(rit1 = predict_listp.begin();rit1 != predict_listp.end();)
                {
                    RobotInfoP robot_infop1 = *rit1;
                    set<RobotInfoP>::iterator rit2;
                    rit2 = predict_listp2.find(robot_infop1);
                    if((rit2 != predict_listp2.end()))  //若找到并且方向相同
                    {
                        RobotInfoP robot_infop2 = *rit2;
                        if(robot_infop1.pos > robot_infop2.pos)
                            rit1 = predict_listp.erase(rit1);
                        else
                            rit1++;
                    }
                    else
                        rit1++;
                }
                msg.Map_map[robot_info.FirstPredictP].PredictList = predict_listp;
                }

                //无预测点冲突 继续前进
                if(msg.Map_map.at(robot_info.FirstPredictP).PredictList.size() == 1)
                {
                    //若在出入口,需要避免相遇

                    if((robot_info.LastOccupyP != Map_In)&&(robot_info.LastOccupyP != Map_Out))
                    {
                        robot_info.Relative_Pos++;
                        robot_info.Current_Pos.Pos = robot_info.Route->at(robot_info.Relative_Pos);
                        robot_info.DistToE--;
                        robot_info.IsUpdated = true;
                        msg.RobotBusy_map[ritg->first] = robot_info;
                        IsChanged = true;
                        GenConflict(msg);
                        continue;
                    }
                    else
                    {
                        set<PointItem>::iterator fit;
                        fit = IO_CollisionPoint.find(robot_info.FirstPredictP);
                        if(fit == IO_CollisionPoint.end())   //未找到,表示不冲突
                        {
                            robot_info.Relative_Pos++;
                            robot_info.Current_Pos.Pos = robot_info.Route->at(robot_info.Relative_Pos);
                            robot_info.DistToE--;
                            robot_info.IsUpdated = true;
                            msg.RobotBusy_map[ritg->first] = robot_info;
                            IsChanged = true;
                            GenConflict(msg);
                            continue;
                        }
                        else
                        {
                            continue;
                        }
                    }

                }

                //预测点冲突
                if(msg.Map_map.at(robot_info.FirstPredictP).PredictList.size() > 1)
                {
                    set<RobotInfoP>::iterator rit;
                    bool IsWin = true;
                    set<RobotInfoP> predict_listp = msg.Map_map.at(robot_info.FirstPredictP).PredictList;

                    //检测相同距离预测点冲突
                    for(rit = predict_listp.begin();rit != predict_listp.end();rit++)
                    {
                        RobotInfoP robot_infop1 = *rit;
                        if((robot_infop1.pos == 1)&&(robot_infop1.robot_info.Robot_Serial != robot_info.Robot_Serial))
                        {
                            if(robot_infop1.robot_info.Robot_Priority > robot_info.Robot_Priority)
                            {
                                IsWin == false;
                                break;
                            }
                        }
                    }

                    if((IsWin == true)&&((robot_info.Relative_Pos + 1) < robot_info.Route_Size))
                    {
                        //检测相遇冲突
                        for(int i = (robot_info.Relative_Pos + 2); i <= robot_info.Route_Size;i++)
                        {
                            //忽略出入口冲突
                            if((robot_info.Route->at(i) == Map_In)||(robot_info.Route->at(i) == Map_Out))
                                continue;
                            set<RobotInfoP>::iterator rit3;
                            set<RobotInfoP> predict_listp_t = msg.Map_map.at(robot_info.Route->at(i)).PredictList;
                            set<RobotInfoP> occupy_listp_t = msg.Map_map.at(robot_info.Route->at(i)).OccupyList;
                            for(rit3 = predict_listp.begin();rit3 != predict_listp.end();)
                            {
                                set<RobotInfoP>::iterator t_it;
                                t_it = occupy_listp_t.find(*rit3);
                                if(t_it != occupy_listp_t.end())   //预测点被占据 则暂停
                                {
                                    IsWin = false;
                                    break;
                                }
                                else
                                {
                                    t_it = predict_listp_t.find(*rit3);
                                    if(t_it == predict_listp_t.end())    //冲突预测点中间断开,则移除
                                    {
                                        //rit3 = predict_listp.erase(rit3);
                                        rit3++;
                                    }
                                    else
                                        rit3++;
                                }
                            }
                            if(IsWin == false)
                                break;
                        }
                    }

                    //赢得预测点,更新机器人运行状态
                    if(IsWin == true)
                    {
                        if((robot_info.LastOccupyP != Map_In)&&(robot_info.LastOccupyP != Map_Out))
                        {
                            robot_info.Relative_Pos++;
                            robot_info.Current_Pos.Pos = robot_info.Route->at(robot_info.Relative_Pos);
                            robot_info.DistToE--;
                            robot_info.IsUpdated = true;
                            msg.RobotBusy_map[ritg->first] = robot_info;
                            IsChanged = true;
                            GenConflict(msg);
                            continue;
                        }
                        else
                        {
                            set<PointItem>::iterator fit;
                            fit = IO_CollisionPoint.find(robot_info.FirstPredictP);
                            if(fit == IO_CollisionPoint.end())   //未找到,表示不冲突
                            {
                                robot_info.Relative_Pos++;
                                robot_info.Current_Pos.Pos = robot_info.Route->at(robot_info.Relative_Pos);
                                robot_info.DistToE--;
                                robot_info.IsUpdated = true;
                                msg.RobotBusy_map[ritg->first] = robot_info;
                                IsChanged = true;
                                GenConflict(msg);
                                continue;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            if(IsChanged == false)
                    break;
        }

    }
}

  

时间: 2024-10-05 04:58:32

海康威视复赛题 ---- 碰撞避免方案(1)的相关文章

海康威视复赛题 --- 算法说明书

一.  题目背景 海康威视智能泊车机器人依托海康威视多年在图像处理.硬件设计及嵌入式软件领域的技术积累,以及阡陌系列智能仓储机器人历经两年多来精雕细琢已成熟应用的核心技术,瞄准"停车难"痛点,为用户带来完美的停车体验.智能泊车机器人采用海康机器人成熟的视觉和惯性双导航技术实现自主定位,定位精度误差小于5mm,可完成2000kg汽车的升举.搬运.旋转.下放,智能泊车机器人系统可同时调度500辆汽车,同等面积停车场停车位数量增加40%.系统配备海康威视智能停车系统的仓库,最多可并排停放4排

海康威视复赛题

题目概述 在车库中安排若干泊车机器人,根据给定的车位地图,合理优化机器人的数量及其运动路径,尽量减少客户在停车和取车中的等待时间,并使总成本最小. 参数设定 为了简化问题,我们对泊车机器人的实际运行情况做出如下规定和说明,与"题目背景"中所述的泊车机器人真实运行情况有所不同,请注意. 地图说明: 给定一个停车地图,以下图为例:地图中红色部分表示车位(P),黑色部分表示障碍物(B),黄色部分表示入口(I),绿色部分表示出口(E),白色表示行车道路(X),每个车位都与行车道路(X)相邻,每

网络流24题-飞行员配对方案问题-二分图最大匹配

这道题,是个人都看得出来,是求一个二分图的最大匹配. 但是网络流24题嘛,我们考虑一下用网络流的方法做. 一般二分图的题,转网络流做,都需要建立一个起点和汇点.然后求一个最大流,这个最大流就是二分图的最大匹配. 我用的是Edmonds-Karp算法bfs版本 代码 #include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #include<queue>

[网络流24题]飞行员配对方案问题

https://www.luogu.org/problemnew/show/2756 二分图网络流 鬼才去写网络流,输出方案?二分图匹配吧 网络流输出方案,枚举与汇点有流量的边,输出方案 #include<cstdio> #include<cstring> #include<algorithm> const int maxn = 10007; int m,n; inline int read() { int x=0,f=1;char c=getchar(); while

[C++] 2017联发科技杯编程挑战赛 复赛题 “杰克船长的烦恼”

题目如下. 规则 杰克船长这次运气不错,抢到了一大堆金币.但他马上又开始发愁了, 因为如何给大家分金币,一直都是件不容易的事,每次杰克船长都要头疼好几天. 关于分金币,海盗的行规是这样的: 每次行动,船长会根据各个海盗的表现记功,事后论功行赏,给大家分金币. 分战利品的时候,海盗们会随意的站成一排,船长给每个人发一袋金币.袋子里的金币数目有多有少,但船长保证每个海盗至少会分到一枚金币. 拿到金币后,相邻的两个海盗会互相比较.如果其中一个功劳高些,那他的金币必须多一些,如果两个人分数一样,他们的金

基于Seajs的可控台球碰撞游戏

前言 不记得哪个黑色星期五,贪吃鱼基本完工的时候,产品突然增加需求,要求金币扔出去后不消失,互相可碰撞,其最终结果还要由服务器控制(没错,至今做的所有游戏都有幕后黑手,=W=). 对于碰撞以前只写过一个球到处碰墙壁的,小球之间的碰撞倒是没有接触,想到他们碰撞过程中的角度变化.速度分配,就不敢往下想了,于是马上想到box2d这个牛逼哄哄的引擎. 但是,使用物理引擎虽然高效.逼真,但所有碰撞都是不可控,包括最终的落点.所以引擎不能解决这次遇到的需求. 不能用引擎,咱自己写也不怕,反正当年物理和高数都

【网络流24题】航空线路问题(费用流)

[网络流24题]航空线路问题(费用流) 题面 Cogs数据有误,提供洛谷题面 题解 这题和原来做过的一道题周游加拿大是一模一样的 所以,这题DP+记录方案应该也是可行的 来考虑网络流的做法 现在的来回,被看成是去两次 所以流量被限定死了,为2 因此要考虑费用流来求解. 每个点只能经过一次 很显然先拆点 如果一个城市被访问了 那么,他的两个点直接的流量是一定存在的 为了记录下这个点被访问过 所以,给定它一个费用1 然后其他的连边和原来做的题目没有什么区别 对于每一条航线,从\(i'\)向\(j\)

2018华为网络技术大赛---从初赛到复赛到决赛

2018.4.21 进行了初赛 初赛的准备过程不长,前前后后也就三四天时间吧,云平台上的视频都没来得及看完,只看了"基础平台"一部分,"微服务","大数据",然后其他的就都是看的文档了,包括云平台上的文档和往届提供的文档,其中还花了一天的时间刷了一下群里提供的hcna相关的题目(感觉并没有什么用),还是看文档来的快,也来的直接,视频它讲的很慢,而且不能倍速观看,其中有很多又是废话,所以感觉还是看文档比较好,都是干货.周六下午就去比赛,一个小时的时

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二