/// <summary> /// Get the closest points on 2 paths /// </summary> /// <param name="path1"></param> /// <param name="path2"></param> /// <param name="p1"></param> /// <param name="p2"></param> public static void GetClosestPoints(Path path1, Path path2, out PointOnPath p1, out PointOnPath p2, out double distance) { PointOnPath closest1 = path1.StartPoint; PointOnPath closest2 = path2.StartPoint; double dist = Double.MaxValue; PointOnPath current = path1.StartPoint; double increment = 1; double tmpIncrement = 0; while (tmpIncrement == 0) { PointOnPath test = path2.GetClosest(current.pt); double tmpDist = test.pt.DistanceTo(current.pt); if (tmpDist < dist) { closest1 = current; closest2 = test; dist = tmpDist; } tmpIncrement = increment; current = path1.AdvancePoint(current, ref tmpIncrement); } p1 = closest1; p2 = closest2; distance = dist; }
/// <summary> /// Reason about changing lanes /// </summary> /// <param name="previousChangeLanePath">previous change lane path</param> /// <param name="initialLanePath">lane path that vehicle is changing from</param> /// <param name="targetLanePath"> lane path that vehicle is changing to</param> /// <param name="targetType"> type for target lane, left or right</param> /// <param name="observedObstacles">static obstacles</param> /// <param name="observedVehicles">observed vehicles</param> /// <param name="lowerBound"> lower bound point on initial lane (similar to obstacle on target lane)</param> /// <param name="upperBound"> upper bound point on initial lane (similar to obstacle on initial lane)</param> /// <param name="position"> vehicle absolute position in m</param> /// <param name="heading"> vehicle heading as a vector</param> /// <param name="speed"> vehicle speed in m/s</param> /// <param name="aboutPath"> type of path being returned</param> /// <param name="currentChangeLanePath">change lane path</param> public void LaneChangePlanAdvance(Path previousChangeLanePath, Path initialLanePath, Path targetLanePath, TargetLaneChangeType targetType, ObservedObstacles observedObstacles, ObservedVehicle[] observedVehicles, PointOnPath initialLaneLowerBound, PointOnPath initialLaneUpperBound, Coordinates position, Coordinates heading, double speed, out AboutPath aboutPath, out Path currentChangeLanePath) { // check if target lane is to the left or right if (targetType == TargetLaneChangeType.Left) { // set up vehicle and lane information InitialiseInformation(position, heading, speed, null, targetLanePath, initialLanePath); // manage static and dynamic dynamic obstacles InitialiseObstacles(null, targetLanePath, initialLanePath, observedObstacles, observedVehicles); } else { // set up vehicle and lane information InitialiseInformation(position, heading, speed, initialLanePath, targetLanePath, null); // manage static and dynamic dynamic obstacles InitialiseObstacles(initialLanePath, targetLanePath, null, observedObstacles, observedVehicles); } // determine risk of previous spline path, if provided double pathRisk, pathRiskDist, pathSepDist; if (previousChangeLanePath != null) { // check risk of previous spline path CheckPathRisk(previousChangeLanePath, out pathRisk, out pathRiskDist, out pathSepDist); if (pathRisk == 0) { // no risk was found, return previous spline path currentChangeLanePath = previousChangeLanePath; aboutPath = AboutPath.Normal; return; } } PointOnPath targetLaneLowerBound = targetLanePath.GetClosest(initialLaneLowerBound.pt); PointOnPath targetLaneUpperBound = targetLanePath.GetClosest(initialLaneUpperBound.pt); double targetLaneLowerBoundDist = Math.Round(targetLanePath.DistanceBetween(currentLanePosition, targetLaneLowerBound),1); double targetLaneUpperBoundDist = Math.Round(targetLanePath.DistanceBetween(currentLanePosition, targetLaneUpperBound),1); // generate obstacles for lower and upper bound points Coordinates lowerBoundObstacle = targetLaneLowerBound.pt; Coordinates upperBoundObstacle = initialLaneUpperBound.pt; if (targetType == TargetLaneChangeType.Left) { lowerBoundObstacle += targetLaneLowerBound.segment.Tangent(targetLaneLowerBound).RotateM90().Normalize(0.5 * currentLaneWidth - 1.0); upperBoundObstacle += initialLaneUpperBound.segment.Tangent(initialLaneUpperBound).Rotate90().Normalize(0.5 * rightLaneWidth - 1.0); } else { lowerBoundObstacle += targetLaneLowerBound.segment.Tangent(targetLaneLowerBound).Rotate90().Normalize(0.5 * currentLaneWidth - 1.0); upperBoundObstacle += initialLaneUpperBound.segment.Tangent(initialLaneUpperBound).RotateM90().Normalize(0.5 * leftLaneWidth - 1.0); } staticObstaclesFake.Add(lowerBoundObstacle); staticObstaclesFake.Add(upperBoundObstacle); // path projection distance double projectionDist = Math.Max(targetLaneLowerBoundDist, TahoeParams.VL + TahoeParams.FL); double origProjectionDist = projectionDist; do { // lookahead point double lookaheadDist = projectionDist; PointOnPath lookaheadPt = targetLanePath.AdvancePoint(currentLanePosition, ref lookaheadDist); // extend point if at end of path Coordinates offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(lookaheadDist); // prepare ctrl points for spline path Coordinates startPoint = vehiclePosition; Coordinates endPoint = lookaheadPt.pt + offsetVec; Coordinates startVec = new Coordinates(1, 0).Rotate(vehicleHeading).Normalize(Math.Max(vehicleSpeed, 2.0)); Coordinates endVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(Math.Max(vehicleSpeed, 2.0)); // generate spline path currentChangeLanePath = GenerateBezierPath(startPoint, endPoint, startVec, endVec); // determine risk of spline path CheckPathRisk(currentChangeLanePath, out pathRisk, out pathRiskDist, out pathSepDist); // project further if current spline path has risk if (pathRisk != 0) { if (projectionDist == targetLaneUpperBoundDist + TahoeParams.RL) break; projectionDist = Math.Min(projectionDist + TahoeParams.VL / 2, targetLaneUpperBoundDist + TahoeParams.RL); } } while (pathRisk != 0 && projectionDist <= targetLaneUpperBoundDist + TahoeParams.RL); // check if path without risk was found if (pathRisk == 0) aboutPath = AboutPath.Normal; else aboutPath = AboutPath.Null; }
/// <summary> /// Reason about changing lanes (simple version) /// </summary> public void LaneChangePlan(Path changeLanesPath, Path initialLane, Path targetLane, ObservedObstacles observedObstacles, ObservedVehicle[] initialLaneObservedVehicles, ObservedVehicle[] targetLaneObservedVehicles, PointOnPath lowerBound, PointOnPath upperBound, Coordinates position, Coordinates heading, double speed, out AboutPath aboutPath, out Path laneChangePath) { // set up vehicle states vehiclePosition = position; vehicleSpeed = speed; vehicleHeading = heading.ArcTan; currentLanePosition = targetLane.GetClosest(vehiclePosition); leftLanePosition = initialLane != null ? initialLane.GetClosest(vehiclePosition) : new PointOnPath(); rightLanePosition = initialLane != null ? initialLane.GetClosest(vehiclePosition) : new PointOnPath(); //// set up lane information leftLaneWidth = initialLane != null ? leftLanePosition.pt.DistanceTo(currentLanePosition.pt) : double.NaN; rightLaneWidth = initialLane != null ? rightLanePosition.pt.DistanceTo(currentLanePosition.pt) : double.NaN; if (double.IsNaN(leftLaneWidth)) if (double.IsNaN(rightLaneWidth)) currentLaneWidth = 3; else currentLaneWidth = rightLaneWidth; else currentLaneWidth = leftLaneWidth; //// manage static and dynamic dynamic obstacles //ManageObstacles(targetLane, observedObstacles, // initialLaneObservedVehicles, targetLaneObservedVehicles); double projectionDist = 15; double origProjDist = projectionDist; double pathRisk, pathRiskDist, pathSepDist; // lookahead point double lookaheadDist = projectionDist; PointOnPath lookaheadPt = targetLane.AdvancePoint(currentLanePosition, ref lookaheadDist); // extend point if at end of path Coordinates offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(lookaheadDist); PointOnPath targetUpperBound = targetLane.GetClosest(upperBound.pt); // prepare ctrl points for spline path Coordinates startPoint = vehiclePosition; //Coordinates rVec = lookaheadPt.segment.Tangent(lookaheadPt).Rotate90().Normalize(endOffset); Coordinates endPoint = targetUpperBound.pt; // lookaheadPt.pt + offsetVec + rVec; Coordinates startVec = new Coordinates(1, 0).Rotate(vehicleHeading).Normalize(Math.Max(vehicleSpeed, 2.0)); Coordinates endVec = targetLane.GetClosest(targetUpperBound.pt).segment.Tangent(targetUpperBound).Normalize(Math.Max(vehicleSpeed, 2.0)); //Coordinates endVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(Math.Max(vehicleSpeed, 2.0)); // generate spline path laneChangePath = GenerateBezierPath(startPoint, endPoint, startVec, endVec); // determine risk of spline path CheckPathRisk(laneChangePath, out pathRisk, out pathRiskDist, out pathSepDist); if (pathRisk == 0) aboutPath = AboutPath.Normal; else aboutPath = AboutPath.Stop; }
/// <summary> /// Reason about changing lanes /// </summary> /// <param name="previousChangeLanePath">previous change lane path</param> /// <param name="initialLanePath">lane path that vehicle is changing from</param> /// <param name="targetLanePath"> lane path that vehicle is changing to</param> /// <param name="targetType">type for target lane, left or right</param> /// <param name="initialLaneVehicles">observed vehicles on initial lane</param> /// <param name="initialLaneLowerBound">lower bound point on initial lane (similar to obstacle on target lane)</param> /// <param name="initialLaneUpperBound">upper bound point on initial lane (similar to obstacle on initial lane)</param> /// <param name="vehicleState">vehicle state</param> public Path LaneChangeObstacleReasoning(Path previousChangeLanePath, Path initialLanePath, Path targetLanePath, TargetLaneChangeType targetType, ObservedVehicle[] initialLaneVehicles, PointOnPath initialLaneLowerBound, PointOnPath initialLaneUpperBound, VehicleState vehicleState) { // check if target lane is to the left or right if (targetType == TargetLaneChangeType.Left) { // set up vehicle and lane information InitialiseInformation(vehicleState.xyPosition, vehicleState.heading, vehicleState.speed, null, targetLanePath, initialLanePath); } else { // set up vehicle and lane information InitialiseInformation(vehicleState.xyPosition, vehicleState.heading, vehicleState.speed, initialLanePath, targetLanePath, null); } // set up static obstacles (none for now) staticObstaclesIn.Clear(); staticObstaclesOut.Clear(); staticObstaclesFake.Clear(); // set up dynamic obstacles dynamicObstacles.Clear(); dynamicObstaclesPaths.Clear(); SetDynamicObstacles(initialLanePath, initialLaneVehicles); // determine risk of previous spline path, if provided double pathRisk, pathRiskDist, pathSepDist; if (previousChangeLanePath != null) { // check risk of previous spline path CheckPathRisk(previousChangeLanePath, out pathRisk, out pathRiskDist, out pathSepDist); // if no risk was found, return previous spline path if (pathRisk == 0) return previousChangeLanePath; } // set up number of paths based on lane width double spacing = 0.25; int numPaths = (int)Math.Round(currentLaneWidth / spacing); if ((int)Math.IEEERemainder((double)numPaths, 2.0) == 0) numPaths -= 1; // increase number of drift paths int midPathIndex; numPaths += 12; midPathIndex = (numPaths - 1) / 2; double[] pathsRisk, pathsRiskDist, pathsSepDist, pathsCost; Path[] paths = new Path[numPaths]; int selectedPathIndex; PointOnPath targetLaneLowerBound = targetLanePath.GetClosest(initialLaneLowerBound.pt); PointOnPath targetLaneUpperBound = targetLanePath.GetClosest(initialLaneUpperBound.pt); double targetLaneLowerBoundDist = Math.Round(targetLanePath.DistanceBetween(currentLanePosition, targetLaneLowerBound), 1); double targetLaneUpperBoundDist = Math.Round(targetLanePath.DistanceBetween(currentLanePosition, targetLaneUpperBound), 1); // generate obstacles for lower and upper bound points Coordinates lowerBoundObstacle = targetLaneLowerBound.pt; Coordinates upperBoundObstacle = initialLaneUpperBound.pt; if (targetType == TargetLaneChangeType.Left) { lowerBoundObstacle += targetLaneLowerBound.segment.Tangent(targetLaneLowerBound).RotateM90().Normalize(0.5 * currentLaneWidth - 1.0); upperBoundObstacle += initialLaneUpperBound.segment.Tangent(initialLaneUpperBound).Rotate90().Normalize(0.5 * rightLaneWidth - 1.0); } else { lowerBoundObstacle += targetLaneLowerBound.segment.Tangent(targetLaneLowerBound).Rotate90().Normalize(0.5 * currentLaneWidth - 1.0); upperBoundObstacle += initialLaneUpperBound.segment.Tangent(initialLaneUpperBound).RotateM90().Normalize(0.5 * leftLaneWidth - 1.0); } staticObstaclesFake.Add(lowerBoundObstacle); staticObstaclesFake.Add(upperBoundObstacle); // path projection distance double projectionDist = Math.Max(targetLaneLowerBoundDist, TahoeParams.VL + TahoeParams.FL); double origProjectionDist = projectionDist; Path currentChangeLanePath = new Path(); do { // lookahead point double lookaheadDist = projectionDist; PointOnPath lookaheadPt = targetLanePath.AdvancePoint(currentLanePosition, ref lookaheadDist); // extend point if at end of path Coordinates offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(lookaheadDist); // prepare ctrl points for first part of spline path Coordinates startPoint = vehiclePosition; Coordinates midPoint = lookaheadPt.pt + offsetVec; Coordinates startVec = new Coordinates(1, 0).Rotate(vehicleHeading).Normalize(Math.Max(vehicleSpeed, 2.0)); Coordinates midVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(Math.Max(vehicleSpeed, 2.0)); // lookahead point (for end point) lookaheadDist = projectionDist + 10; lookaheadPt = targetLanePath.AdvancePoint(currentLanePosition, ref lookaheadDist); // extend point if at end of path (for end point) offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(lookaheadDist); // prepare ctrl points for second part of spline path Coordinates endPoint = lookaheadPt.pt + offsetVec; Coordinates endVec = lookaheadPt.segment.Tangent(lookaheadPt).Normalize(Math.Max(vehicleSpeed, 2.0)); ///////////////////////////////// Coordinates shiftedMidPoint, shiftedEndPoint; Coordinates shiftMidVec = midVec.Rotate90(); Coordinates shiftEndVec = endVec.Rotate90(); // generate multiple spline paths for (int i = 0; i < numPaths; i++) { shiftedMidPoint = midPoint - shiftMidVec.Normalize((i - midPathIndex) * spacing); shiftedEndPoint = endPoint - shiftEndVec.Normalize((i - midPathIndex) * spacing); // generate spline path paths[i] = GenerateBezierPath(startPoint, shiftedMidPoint, startVec, midVec); // generate extension to spline path Path extPath = GenerateBezierPath(shiftedMidPoint, shiftedEndPoint, midVec, endVec); // add extension to path paths[i].Add((BezierPathSegment)extPath[0]); } // evaluate paths and select safest path selectedPathIndex = EvaluatePaths(paths, midPathIndex, out pathsRisk, out pathsRiskDist, out pathsSepDist, out pathsCost); // project further if current spline path has risk if (pathsRisk[selectedPathIndex] != 0) { if (projectionDist == targetLaneUpperBoundDist + TahoeParams.RL) break; projectionDist = Math.Min(projectionDist + TahoeParams.VL / 2, targetLaneUpperBoundDist + TahoeParams.RL); } } while (pathsRisk[selectedPathIndex] != 0 && projectionDist <= targetLaneUpperBoundDist + TahoeParams.RL); // check if path without risk was found if (pathsRisk[selectedPathIndex] == 0) return paths[selectedPathIndex]; else return null; }
/// <summary> /// Initialise vehicle and lane information /// </summary> private void InitialiseInformation(Coordinates position, Coordinates heading, double speed, Path leftLanePath, Path currentLanePath, Path rightLanePath) { // set up vehicle information vehiclePosition = position; vehicleSpeed = speed; vehicleHeading = heading.ArcTan; // set up lane valid flags leftLaneValid = leftLanePath != null ? true : false; rightLaneValid = rightLanePath != null ? true : false; // set up positions on lanes currentLanePosition = currentLanePath.GetClosest(vehiclePosition); leftLanePosition = leftLaneValid ? leftLanePath.GetClosest(vehiclePosition) : new PointOnPath(); rightLanePosition = rightLaneValid ? rightLanePath.GetClosest(vehiclePosition) : new PointOnPath(); // set up lane information leftLaneWidth = leftLaneValid ? leftLanePosition.pt.DistanceTo(currentLanePosition.pt) : double.NaN; rightLaneWidth = rightLaneValid ? rightLanePosition.pt.DistanceTo(currentLanePosition.pt) : double.NaN; if (leftLaneValid) currentLaneWidth = leftLaneWidth; else if (rightLaneValid) currentLaneWidth = rightLaneWidth; else currentLaneWidth = TahoeParams.T + 1.0; }
/// <summary> /// Set dynamic obstacles given in absolute coordinates (Version 1) /// </summary> /// <param name="obstacles"></param> public void SetDynamicObstaclesVer1(Path observedVehiclePath, ObservedVehicle[] observedVehicles) { // generate paths for for (int i = 0; i < observedVehicles.Length; i++) { // add observed vehicle dynamicObstacles.Add(observedVehicles[i]); // lane position PointOnPath observedVehiclePosition = observedVehiclePath.GetClosest(observedVehicles[i].AbsolutePosition); // lookahead point double projectionDist = Math.Max(vehicleSpeed * 3, 10) + TahoeParams.FL; double lookaheadDist = projectionDist; PointOnPath projectionPoint = observedVehiclePath.AdvancePoint(observedVehiclePosition, ref lookaheadDist); // extend point if at end of path Coordinates offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = projectionPoint.segment.Tangent(projectionPoint).Normalize(lookaheadDist); // prepare ctrl points for spline path Coordinates startPoint = observedVehicles[i].AbsolutePosition; Coordinates endPoint = projectionPoint.pt + offsetVec; Coordinates startVec = observedVehiclePosition.segment.Tangent(observedVehiclePosition).Normalize(Math.Max(observedVehicles[i].Speed, 2.0)); Coordinates endVec = projectionPoint.segment.Tangent(projectionPoint).Normalize(Math.Max(observedVehicles[i].Speed, 2.0)); // generate spline path dynamicObstaclesPaths.Add(GenerateBezierPath(startPoint, endPoint, startVec, endVec)); // generate static obstacles if speed is close to zero if (observedVehicles[i].Speed < 1.0) { Coordinates tVec = observedVehiclePosition.segment.Tangent(observedVehiclePosition).Normalize(observedVehicles[i].Length / 2); Coordinates rVec = observedVehiclePosition.segment.Tangent(observedVehiclePosition).Rotate90().Normalize(observedVehicles[i].Width / 2); staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition + tVec + rVec); // front left staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition + tVec - rVec); // front right staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition - tVec + rVec); // rear left staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition - tVec - rVec); // rear right } } }
/// <summary> /// Set dynamic obstacles given in absolute coordinates (Version 2a) /// </summary> /// <param name="obstacles"></param> public void SetDynamicObstacles(Path observedVehiclePath, ObservedVehicle[] observedVehicles) { // generate paths for for (int i = 0; i < observedVehicles.Length; i++) { // add observed vehicle dynamicObstacles.Add(observedVehicles[i]); // lane position PointOnPath observedVehicleLanePosition = observedVehiclePath.GetClosest(observedVehicles[i].AbsolutePosition); // lookahead point double projectionDist = Math.Max(observedVehicles[i].Speed * 5, 10) + 0.5 * TahoeParams.VL; double lookaheadDist = projectionDist; PointOnPath projectionPoint = observedVehiclePath.AdvancePoint(observedVehicleLanePosition, ref lookaheadDist); // extend point if at end of path Coordinates offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = projectionPoint.segment.Tangent(projectionPoint).Normalize(lookaheadDist); // prepare ctrl points for spline path Coordinates startPoint = observedVehicles[i].AbsolutePosition; Coordinates endPoint = projectionPoint.pt + offsetVec; Coordinates startVec = observedVehicleLanePosition.segment.Tangent(observedVehicleLanePosition).Normalize(Math.Max(observedVehicles[i].Speed, 2.0)); Coordinates endVec = projectionPoint.segment.Tangent(projectionPoint).Normalize(Math.Max(observedVehicles[i].Speed, 2.0)); // generate mid points of path int midPointsTotal = (int)Math.Round(projectionDist / 5.0) - 1; double midPointStepDist = projectionDist / (midPointsTotal + 1); Coordinates[] midPoints = new Coordinates[midPointsTotal]; Coordinates[] midVecs = new Coordinates[midPointsTotal]; Coordinates[] midShiftVecs = new Coordinates[midPointsTotal]; for (int j = 0; j < midPointsTotal; j++) { // lookahead point lookaheadDist = projectionDist * (j + 1) / (midPointsTotal + 1); projectionPoint = observedVehiclePath.AdvancePoint(observedVehicleLanePosition, ref lookaheadDist); // extend point if at end of path offsetVec = new Coordinates(0, 0); if (lookaheadDist > 0.5) offsetVec = projectionPoint.segment.Tangent(projectionPoint).Normalize(lookaheadDist); // prepare ctrl points for spline path midPoints[j] = projectionPoint.pt + offsetVec; midVecs[j] = projectionPoint.segment.Tangent(projectionPoint).Normalize(Math.Max(vehicleSpeed, 2.0)); midShiftVecs[j] = midVecs[j].Rotate90(); } // vehicle vector with respect to segment closest point Coordinates carVec = observedVehicles[i].AbsolutePosition - observedVehicleLanePosition.pt; // segment tangent vector Coordinates pathVec = observedVehicleLanePosition.segment.Tangent(observedVehicleLanePosition); // compute offtrack error double offtrackError = Math.Sign(carVec.Cross(pathVec)) * observedVehicleLanePosition.pt.DistanceTo(observedVehicles[i].AbsolutePosition); // path points Coordinates[] pathPoints = new Coordinates[midPointsTotal + 2]; pathPoints[0] = startPoint; pathPoints[midPointsTotal + 1] = endPoint; for (int j = 0; j < midPointsTotal; j++) { double control = 0.0; if (j == 0) control = 0.35; else if (j == midPointsTotal - 1) control = -0.35; pathPoints[j + 1] = midPoints[j] - midShiftVecs[j].Normalize(offtrackError * (midPointsTotal - j + control) / (midPointsTotal + 1)); } // generate spline path with points Path projectedPath = new Path(); CubicBezier[] beziers = SmoothingSpline.BuildC2Spline(pathPoints, startVec.Normalize(0.5 * midPointStepDist), endVec.Normalize(0.5 * midPointStepDist), 0.5); for (int j = 0; j < beziers.Length; j++) { projectedPath.Add(new BezierPathSegment(beziers[j], (double?)null, false)); } // generate spline path dynamicObstaclesPaths.Add(projectedPath); // generate static obstacles if speed is close to zero if (observedVehicles[i].Speed < 1.0) { Coordinates tVec = observedVehicleLanePosition.segment.Tangent(observedVehicleLanePosition).Normalize(observedVehicles[i].Length / 2); Coordinates rVec = observedVehicleLanePosition.segment.Tangent(observedVehicleLanePosition).Rotate90().Normalize(observedVehicles[i].Width / 2); staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition + tVec + rVec); // front left staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition + tVec - rVec); // front right staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition - tVec + rVec); // rear left staticObstaclesIn.Add(observedVehicles[i].AbsolutePosition - tVec - rVec); // rear right } } }
/// <summary> /// Check if the other line path intersects this line path /// </summary> /// <param name="other"></param> /// <param name="tol"></param> /// <returns></returns> public bool Intersects(Path other, double tol) { // start point want to be outside of this lane PointOnPath current = this.PartitionPath.StartPoint; double increment = tol / 2.0; double dist = 0; while (dist == 0) { Coordinates pt = this.PartitionPath.GetClosest(current.pt).pt; PointOnPath tmp = other.GetClosest(pt); if (tmp.pt.DistanceTo(pt) <= tol) { return true; } dist = increment; current = this.PartitionPath.AdvancePoint(current, ref dist); } return false; }
/// <summary> /// Generates adjacency of a partition to another lane /// </summary> /// <param name="alp"></param> /// <param name="al"></param> private void GenerateSinglePartitionAdjacency(ArbiterLanePartition alp, ArbiterLane al) { // fake path List<IPathSegment> fakePathSegments = new List<IPathSegment>(); fakePathSegments.Add(new LinePathSegment(alp.Initial.Position, alp.Final.Position)); Path fakePath = new Path(fakePathSegments); // partitions adjacent List<ArbiterLanePartition> adjacent = new List<ArbiterLanePartition>(); // tracks PointOnPath current = fakePath.StartPoint; double increment = 0.5; double tmpInc = 0; // increment along while (tmpInc == 0) { // loop over partitions foreach (ArbiterLanePartition alpar in al.Partitions) { // get fake path for partition List<IPathSegment> ips = new List<IPathSegment>(); ips.Add(new LinePathSegment(alpar.Initial.Position, alpar.Final.Position)); Path alpPath = new Path(ips); // get closest point on tmp partition to current PointOnPath closest = alpPath.GetClosest(current.pt); // check general distance if (closest.pt.DistanceTo(current.pt) < 20) { // check not start or end if (!closest.Equals(alpPath.StartPoint) && !closest.Equals(alpPath.EndPoint)) { // check not already added if (!adjacent.Contains(alpar)) { // add adjacent.Add(alpar); } } } } // set inc tmpInc = increment; // increment point current = fakePath.AdvancePoint(current, ref tmpInc); } // add adjacent alp.NonLaneAdjacentPartitions.AddRange(adjacent); }