/// <summary> /// 构造RRT树上的路径 /// </summary> /// <param name="mRrtTree">从中选择路径的树</param> /// <returns>路径</returns> protected List <RrtStarNode> BuildPath(HashSet <RrtStarNode> mRrtTree) { //如果树为空,则返回空 if ((null == mRrtTree)) { return(null); } //选取并存储路径 int targetNodeIndex = mRrtTree.Max(e => e.NodeIndex); RrtStarNode mTempNode = mRrtTree.First(e => e.NodeIndex == targetNodeIndex); List <RrtStarNode> mTempRrtPath = new List <RrtStarNode>(); //循环搜索 while (mTempNode.ParentNode != null) { //增加节点 mTempRrtPath.Add(mTempNode); //递增 mTempNode = mTempNode.ParentNode; } mTempRrtPath.Add(mTempNode);//实际上是初始节点 //由于是按照倒序添加,这里将顺序反转 mTempRrtPath.Reverse(); //返回值 return(mTempRrtPath); }
/// <summary> /// 计算两个节点之间的距离 /// </summary> /// <param name="mNode1">节点1</param> /// <param name="mNode2">节点2</param> /// <returns></returns> public double DistanceBetweenTwoNode(RrtStarNode mNode1, RrtStarNode mNode2) { //二维算法使用 return(FPoint3.DistanceBetweenTwoSpacePointsXY(mNode1.NodeLocation, mNode2.NodeLocation)); //三维算法使用 //return FPoint3.DistanceBetweenTwoSpacePoints(mNode1.NodeLocation, mNode2.NodeLocation); }
/// <summary> /// 深度搜索更新Childnode 的costfunc /// </summary> /// <param name="node"></param> protected void UpdateChildnodeCostFunc(RrtStarNode node) { //不论如何都要更新的事情 if (node.ParentNode != null) { node.CostFuncValue = node.ParentNode.CostFuncValue + MLineCostFunc(node.ParentNode, node); } //检查子类是否需要更新 if (node.ChildNodes == null) { return; } else if (node.ChildNodes.Count == 0) { return; } else if (node.ChildNodes.Count > 0) { foreach (var childnode in node.ChildNodes) { UpdateChildnodeCostFunc(childnode); } } }
private void SetDeleted(RrtStarNode topNode) { topNode.IsAbandoned = true; foreach (var item in topNode.ChildNodes) { SetDeleted(item); } }
/// <summary> /// 扩展树算法 /// </summary> /// <param name="mRrtStarTree"></param> /// <param name="mRrtNearNode"></param> /// <param name="mRrtNewSteerNode"></param> public void ExpandTree(ref HashSet <RrtStarNode> mRrtStarTree, RrtStarNode mRrtNearNode, RrtStarNode mRrtNewSteerNode, int index) { //设置是否到达目标的标志 //bool isReachTarget = false; //保存Steer节点信息 if (mRrtNewSteerNode != null) { //设置节点编号 mRrtNewSteerNode.NodeIndex = index; //设置父节点 mRrtNewSteerNode.ParentNode = mRrtNearNode; //增加新节点 mRrtStarTree.Add(mRrtNewSteerNode); } //创建Near集合 HashSet <RrtStarNode> nearNodes = NearNeighbors(ref mRrtStarTree, mRrtNewSteerNode); RrtStarNode minCostNode = mRrtNearNode; double minCost = minCostNode.CostFuncValue + MLineCostFunc(minCostNode, mRrtNewSteerNode); //记录初始化父节点 mRrtNewSteerNode.ParentNode = minCostNode; //记录初始化最优minCost参数 mRrtNewSteerNode.CostFuncValue = minCost; //寻找安全的Cost函数最小值 foreach (var node in nearNodes) { if (_isSafeLine(mRrtNewSteerNode.NodeLocation, node.NodeLocation) && _isSafePoint(mRrtNewSteerNode.NodeLocation) && node.CostFuncValue + MLineCostFunc(node, mRrtNewSteerNode) < minCost) { minCostNode = node; minCost = node.CostFuncValue + MLineCostFunc(node, mRrtNewSteerNode); //记录父节点 mRrtNewSteerNode.ParentNode = minCostNode; //记录临时最优minCost参数 mRrtNewSteerNode.CostFuncValue = minCost; } } //更新父节点的childlist mRrtNewSteerNode.ParentNode.ChildNodes.Add(mRrtNewSteerNode); //Rewrite the tree! foreach (var node in nearNodes) { if (_isSafeLine(mRrtNewSteerNode.NodeLocation, node.NodeLocation) && _isSafePoint(mRrtNewSteerNode.NodeLocation) && mRrtNewSteerNode.CostFuncValue + MLineCostFunc(mRrtNewSteerNode, node) < node.CostFuncValue) { //新创立的节点可能会影响tree的最优性,所以需要重写局部的连接情况 //去掉与原父节点的联系 node.ParentNode.ChildNodes.Remove(node); //添加与新父节点的联系 node.ParentNode = mRrtNewSteerNode; mRrtNewSteerNode.ChildNodes.Add(node); //更新字节点的costfunc UpdateChildnodeCostFunc(node); } } }
public void BranchAndBound(ref HashSet <RrtStarNode> mFinalNodeSet, ref HashSet <RrtStarNode> mRrtStarTree) { var targetNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState); var minCost = mFinalNodeSet.Min(e => e.CostFuncValue + MLineCostFunc(e, targetNode)); RrtStarNode mOptimalNode = mFinalNodeSet.FirstOrDefault(e => e.CostFuncValue + MLineCostFunc(e, targetNode) == minCost); if (mOptimalNode == null) //default { return; } //foreach(var item in mRRTStarTree.Where(e => e.IsValid == true)) //寻找mFinalNodeSet相同内容 foreach (var item in mFinalNodeSet) { if (item.NodeIndex == mOptimalNode.NodeIndex) { continue; } //跳过最优值,剩下的都删了 //TODO //Step 1. Find out the GGGGGrandParent that should be abandoned. var topNodeParent = item; RrtStarNode topNode = item; //TopNode的子节点, item 一定是 abandoned 的节点。 while (topNodeParent.CostFuncValue + MLineCostFunc(topNodeParent, targetNode) > minCost) { if (topNodeParent.ParentNode != null) { topNode = topNodeParent; topNodeParent = topNodeParent.ParentNode; } else { break; } } //Step 2. Delete ChildNode reference if (topNode.ParentNode != null) { topNode.ParentNode.ChildNodes.Remove(topNode); } //Step 3. Set All child as abandoned SetDeleted(topNode); } //Step Finally. Delete! Them! All! mRrtStarTree.RemoveWhere(e => e.IsAbandoned); mFinalNodeSet.Clear(); mFinalNodeSet.Add(mOptimalNode); }
/// <summary> /// 在探测范围内随机生成一个节点 /// </summary> /// <returns>RRTStarNode</returns> private RrtStarNode RandomConfigurationOrigin() { RrtStarNode mRrtRandNode = new RrtStarNode(); mRrtRandNode.NodeLocation.X = _mRandom.NextDouble() * _mInput.Scenario.FlightScene.Coordinate.MaxX; mRrtRandNode.NodeLocation.Y = _mRandom.NextDouble() * _mInput.Scenario.FlightScene.Coordinate.MaxY; mRrtRandNode.NodeLocation.Z = _mInput.Scenario.UAVGroup.GetUAV(_mInput.UAVTask[ITaskIndex].Index).StartState.PointLocation.Z; //m_RRTParameter.MissionAltitude; mRrtRandNode.ParentNode = null; // return(mRrtRandNode); }
public void MarkingValid(RrtStarNode mRrtCurrentNode, ref HashSet <RrtStarNode> finalNodeSet) { var targetNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState); //路径连通而且距离不长 if (_isSafeLine(mRrtCurrentNode.NodeLocation, targetNode.NodeLocation)) //&& DistanceBetweenTwoNode(mRRTCurrentNode, TargetNode) <= RRTParameter.Error) { //打上 Valid标记(gradually模式用) mRrtCurrentNode.IsValid = true; finalNodeSet.Add(mRrtCurrentNode); } }
/// <summary> /// 计算新的节点 /// </summary> /// <param name="mRrtNearNode">距离mRRTRandNode最近的节点</param> /// <param name="mRrtRandNode">随机生成的节点</param> /// <returns></returns> public RrtStarNode Steer(RrtStarNode mRrtNearNode, RrtStarNode mRrtRandNode) { RrtStarNode mRrtNewNode = new RrtStarNode(); if (DistanceBetweenTwoNode(mRrtNearNode, mRrtRandNode) <= MRrtParameter.Step) { mRrtNewNode = mRrtRandNode; } else { //生成新点 mRrtNewNode = NewNode(MRrtParameter.Step, mRrtNearNode, mRrtRandNode); } return(mRrtNewNode); }
/// <summary> /// 计算新的节点 /// </summary> /// <param name="fStep">步长</param> /// <param name="mRrtNearNode">距离mRRTRandNode最近的节点</param> /// <param name="mRrtRandNode">随机生成的节点</param> /// <returns></returns> protected RrtStarNode NewNode(double fStep, RrtStarNode mRrtNearNode, RrtStarNode mRrtRandNode) { //Alex 2018.09.18 修复错误 //随便吐槽 //不知道和妹子还能在一起多久,不过还是有点心塞吧。 RrtStarNode mRrtNewNode = new RrtStarNode(); mRrtNewNode.NodeLocation.X = mRrtNearNode.NodeLocation.X + (fStep * (mRrtRandNode.NodeLocation.X - mRrtNearNode.NodeLocation.X)) / DistanceBetweenTwoNode(mRrtNearNode, mRrtRandNode); mRrtNewNode.NodeLocation.Y = mRrtNearNode.NodeLocation.Y + (fStep * (mRrtRandNode.NodeLocation.Y - mRrtNearNode.NodeLocation.Y)) / DistanceBetweenTwoNode(mRrtNearNode, mRrtRandNode); mRrtNewNode.NodeLocation.Z = _mInput.Scenario.UAVGroup.GetUAV(_mInput.UAVTask[ITaskIndex].Index).StartState.PointLocation.Z; //m_RRTParameter.MissionAltitude; //DirectionGenerationMethod(mRRTRandNode, mRRTNearNode, mRRTNewNode, fStep); return(mRrtNewNode); }
private RrtStarNode BiasRandomConfiguration() { //新节点 RrtStarNode mRrtNode = null; //是否直接把目标点当作新点 if (_mRandom.NextDouble() > MRrtParameter.ChooseTargetThreshold) { mRrtNode = RandomConfigurationOrigin(); } else { mRrtNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState); } // return(mRrtNode); }
/// <summary> /// 寻找树mRRTTree中距离mRRTRandNode最近的节点 /// </summary> /// <param name="mRrtTree">RRT树</param> /// <param name="mRrtRandNode">随机生成的节点</param> /// <returns></returns> public RrtStarNode NearestNeighbor(HashSet <RrtStarNode> mRrtTree, RrtStarNode mRrtRandNode) { RrtStarNode mRrtNearNode = new RrtStarNode(); double fMinDistance = double.MaxValue; double fDistance = 0; foreach (RrtStarNode mRrtNode in mRrtTree) { fDistance = DistanceBetweenTwoNode(mRrtRandNode, mRrtNode); if (fDistance <= fMinDistance) { mRrtNearNode = mRrtNode; fMinDistance = fDistance; } } // return(mRrtNearNode); }
/// <summary> /// 判断新结点到目标连线是否安全, 若安全则直接连接目标点 /// </summary> /// <param name="iTaskIndex">无人机/任务编号</param> /// <param name="iStageIndex">阶段编号</param> /// <param name="mRrtCurrentNode">当前节点</param> /// <param name="mRrtTree">RRT</param> /// <returns>1,是否有效(安全); 2,如果有效(安全),是否到达目标</returns> public bool DirectlyToTarget(RrtStarNode mRrtCurrentNode, ref HashSet <RrtStarNode> mRrtTree) { bool isReachTarget = false; //进一步判断新结点到目标连线是否安全, 若安全则直接连接目标点 if (_isSafeLine(mRrtCurrentNode.NodeLocation, _mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState.Location)) { //设置为到达 isReachTarget = true; //设置目标点为最后一个新结点, 并将当前节点设置为她的父节点 mRrtCurrentNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState, mRrtCurrentNode); //设节点编号 mRrtCurrentNode.NodeIndex = mRrtTree.Count; //增加新节点 mRrtTree.Add(mRrtCurrentNode); } return(isReachTarget); }
public void GraduallyToTarget(int count, ref HashSet <RrtStarNode> mRrtTree) { //当count < MaxNodeNumber 的木一个值时有可能之前被 continue掉,所以不能这么写 //所以应该取count == m_RRTParameter.MaxNodeNumber并在最终异常部分处理 //判断mRRTCurrentNode是不是有效的. var targetNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState); var finalCost = mRrtTree.Where(e => e.IsValid).Min(e => e.CostFuncValue + MLineCostFunc(e, targetNode)); RrtStarNode finalNode = mRrtTree.FirstOrDefault(e => e.CostFuncValue + MLineCostFunc(e, targetNode) == finalCost); /* * var TargetNode = RRTStarNode.ConvertUAVStateToNode(m_Input.UAVTask[iTaskIndex].Stages[iStageIndex].TargetState); * RRTStarNode FinalNode = null; * double FinalCost = double.MaxValue; * //寻找最短路径 * foreach (var tmpNode in mRRTTree) * { * if (tmpNode.IsValid) * { * var tmpCost = tmpNode.CostFuncValue + mLineCostFunc(tmpNode, TargetNode); * if (tmpCost < FinalCost) * { * FinalCost = tmpCost; * FinalNode = tmpNode; * } * } * }*/ if (finalNode == null) { ConstructFailedPath(ref mRrtTree); } else { //设置目标点为最后一个新结点, 并将当前节点设置为她的父节点 var mRrtFinalNode = RrtStarNode.ConvertUavStateToNode(_mInput.UAVTask[ITaskIndex].Stages[IStageIndex].TargetState, finalNode); //设节点编号 mRrtFinalNode.NodeIndex = count; //增加新节点 mRrtTree.Add(mRrtFinalNode); } }
private void UpdateTreeNode(RrtStarNode currentNode, ref List <MyTreeNode> resultList) { MyTreeNode tmp = new MyTreeNode(); tmp.NodeLocation = currentNode.NodeLocation; tmp.Direction = double.MinValue; tmp.CostFuncValue = currentNode.CostFuncValue; tmp.Index = currentNode.NodeIndex; if (currentNode.ParentNode == null) { tmp.ParentNode = null; } else { tmp.ParentNode = resultList.First(e => e.Index == currentNode.ParentNode.NodeIndex); } resultList.Add(tmp); foreach (var node in currentNode.ChildNodes) { UpdateTreeNode(node, ref resultList); } }
/// <summary> /// 本DEMO中给出的目标函数的定义,以最短距离为最优目标 /// </summary> /// <param name="lNode"></param> /// <param name="rNode"></param> /// <returns></returns> protected double CostFunc(RrtStarNode lNode, RrtStarNode rNode) { return(FPoint3.DistanceBetweenTwoSpacePointsXY(lNode.NodeLocation, rNode.NodeLocation)); }
/// <summary> /// 为单架无人机规划航迹 /// </summary> /// <param name="iTaskIndex">无人机/任务索引</param> /// <returns></returns> protected virtual MPath BuildPathForSingleUav(int iTaskIndex) { //实例化航路 MPath mPath = new MPath(); mPath.Index = AlgoInput.UAVTask[iTaskIndex].Index; mPath.Waypoints = new List <MWaypoint>(); int iWaypointIndex = 0; //基本RRT函数库 RrtStarHelper helper = null; //定义树 HashSet <RrtStarNode> mRrtStarTree = null; //定义航路 List <RrtStarNode> mRrtPath = null; //定义树节点 RrtStarNode mRrtNode = null; //定义树中间节点 RrtStarNode mRrtRandNode = null; RrtStarNode mRrtNearNode = null; RrtStarNode mRrtNewSteerNode = null; HashSet <RrtStarNode> mFinalNodeSet = null; //计数器 int nCount = 1; //对每一个阶段规划航路 for (int iStageIndex = 0; iStageIndex < AlgoInput.UAVTask[iTaskIndex].Stages.Count; ++iStageIndex) { //初始化函数库 helper = new RrtStarHelper(MRandom, MRrtParameter, iTaskIndex, iStageIndex, AlgoInput, IsSafePoint, IsSafeLine); //加载委托函数 helper.MLineCostFunc += CostFunc; //实例化 mRrtStarTree = new HashSet <RrtStarNode>(); mFinalNodeSet = new HashSet <RrtStarNode>(); //初始化计数器 nCount = 1; //加入开始点为第一个点 mRrtNode = new RrtStarNode(0, AlgoInput.UAVTask[iTaskIndex].Stages[iStageIndex].StartState.Location, nCount, null); mRrtStarTree.Add(mRrtNode); //是否到达目标 - 初始未到达 bool isReachTarget = false; //循环构建新点 - 到达目标时自动退出 while (!isReachTarget) { //-------------------------------随机生成节点--------------------------------// //随机生成节点 mRrtRandNode = helper.RandomConfiguration(mFinalNodeSet.Count == 0); //-----------------------------------end-------------------------------------// //----------------------------搜索距离最近的节点-----------------------------// mRrtNearNode = helper.NearestNeighbor(mRrtStarTree, mRrtRandNode); //-----------------------------------end-------------------------------------// //------------------------------延伸生成新节点-------------------------------// mRrtNewSteerNode = helper.Steer(mRrtNearNode, mRrtRandNode); //-----------------------------------end-------------------------------------// //计数器累加 nCount = nCount + 1; //-----------------------如果到达允许的搜索上限,则退出-----------------------// if (nCount >= MRrtParameter.MaxNodeNumber) { Console.WriteLine("MaxNodeNumber!"); break; } //-----------------------------------end-------------------------------------// //------------------------------扩展树 - 核心--------------------------------// if (IsSafeLine(mRrtNewSteerNode.NodeLocation, mRrtNearNode.NodeLocation) && IsSafePoint(mRrtNewSteerNode.NodeLocation)) { //此处SteerNode已经添加到Tree中 helper.ExpandTree(ref mRrtStarTree, mRrtNearNode, mRrtNewSteerNode, nCount); } else { continue; } //-----------------------------------end-------------------------------------// //------------判断新结点到目标连线是否安全, 若安全则直接连接目标点-----------// if (MRrtParameter.ReachMode == TargetReachMode.Direct) { isReachTarget = isReachTarget || helper.DirectlyToTarget(mRrtNewSteerNode, ref mRrtStarTree); } else if (MRrtParameter.ReachMode == TargetReachMode.Gradual) { helper.MarkingValid(mRrtNewSteerNode, ref mFinalNodeSet); } //-----------------------------------end-------------------------------------// //----------------------------Branch and Bound-------------------------------// if (mFinalNodeSet.Count > 10) { helper.BranchAndBound(ref mFinalNodeSet, ref mRrtStarTree); } //-----------------------------------end-------------------------------------// } if (nCount >= MRrtParameter.MaxNodeNumber) { if (MRrtParameter.ReachMode == TargetReachMode.Direct) { helper.ConstructFailedPath(ref mRrtStarTree); } else if (MRrtParameter.ReachMode == TargetReachMode.Gradual) { //GraduallyToTarget方法就是检查当 nCount == m_RRTParameter.MaxNodeNumber 时的结果 //所以在本部分需要为IsVailid添加标签。 helper.GraduallyToTarget(nCount, ref mRrtStarTree); } } mRrtPath = BuildPath(mRrtStarTree); //为可视化输出保存 _visualization.MPathForVisualizaition = mRrtStarTree.ToList(); if (!PathPlaningDataVisualization.PathPlaningDataVisualization.AlgoDataDict.ContainsKey(mPath.Index.ToString() + "-" + iStageIndex.ToString())) { //为ResultShowForm分析窗口保存数据 //3.30.2018 刘洋添加 PathPlaningDataVisualization.PathPlaningDataVisualization.AlgoDataDict.Add(mPath.Index.ToString() + "-" + iStageIndex.ToString(), _visualization.MyTreeNodeConverter(_visualization.MPathForVisualizaition)); } else { PathPlaningDataVisualization.PathPlaningDataVisualization.AlgoDataDict[mPath.Index.ToString() + "-" + iStageIndex.ToString()] = _visualization.MyTreeNodeConverter(_visualization.MPathForVisualizaition); } //添加当前阶段航路到总航路(起始航路点为当前阶段, 目标航路点为下一个阶段, 注意总航路的最后一个航路点属于最后一个阶段) for (int k = 0; k < mRrtPath.Count - 1; ++k) { mPath.Waypoints.Add(new MWaypoint(iWaypointIndex, RrtStarNode.ConvertNodeToUavState(mRrtPath[k]), iStageIndex)); iWaypointIndex = iWaypointIndex + 1; } } //增加最后的目标点 mPath.Waypoints.Add(new MWaypoint(iWaypointIndex, RrtStarNode.ConvertNodeToUavState(mRrtPath[mRrtPath.Count - 1]), AlgoInput.UAVTask[iTaskIndex].Stages.Count - 1)); //返回路径 return(mPath); }
/// <summary> /// 寻找SteerNode 的附近节点 /// </summary> /// <param name="mRrtStarTrees"></param> /// <param name="steerNode"></param> /// <returns></returns> public HashSet <RrtStarNode> NearNeighbors(ref HashSet <RrtStarNode> mRrtStarTrees, RrtStarNode steerNode) { double Tolerance = 10E-7; //原始算法测试结果 //double radiusConst = m_RRTParameter.Step*1.1; //double radius = Math.Max(m_RRTParameter.FixedNearDistanceRatio * Math.Pow(Math.Log(2, mRRTStarTrees.Count) / mRRTStarTrees.Count, 1.0 / 2), radiusConst); double radius = MRrtParameter.Step * MRrtParameter.FixedNearDistanceRatio; HashSet <RrtStarNode> resultSet = new HashSet <RrtStarNode>(); resultSet.Clear(); /* * //并行操作优化 * //貌似会慢1S左右。。。。。 * ResultSet = mRRTStarTrees.AsParallel().Where(node => DistanceBetweenTwoNode(node, SteerNode) <= radius && node != SteerNode).ToHashSet(); */ foreach (var node in mRrtStarTrees) { if (DistanceBetweenTwoNode(node, steerNode) <= radius && node != steerNode) { resultSet.Add(node); } } if (resultSet.Count > MRrtParameter.TriggerNum && MRrtParameter.NearNodesFilter) { var query = resultSet.GroupBy(e => e.ParentNode); var tmpResultSet = new HashSet <RrtStarNode>(); foreach (var group in query) { var minDis = group.Min(e => e.CostFuncValue + DistanceBetweenTwoNode(e, steerNode)); var minNode = group.First(e => Math.Abs((e.CostFuncValue + DistanceBetweenTwoNode(e, steerNode)) - minDis) <= Tolerance); tmpResultSet.Add(minNode); } // var tmpResultSet = new HashSet<RrtStarNode>(); // foreach (var item in resultSet) // { // if(item.ParentNode != null) // tmpResultSet.Add(item.ParentNode); // } // if(tmpResultSet.Count != 0) // resultSet = tmpResultSet; } return(resultSet); }