public override void Process(object param) { try { Trace.CorrelationManager.StartLogicalOperation("ChangeLanes"); if (!base.BeginProcess()) { return; } // check if we were given a parameter if (param != null && param is ChangeLaneBehavior) { ChangeLaneBehavior clParam = (ChangeLaneBehavior)param; HandleBehavior(clParam); BehaviorManager.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "got new param -- speed {0}, dist {1}, dist timestamp {2}", clParam.SpeedCommand, clParam.MaxDist, clParam.TimeStamp); } // project the lane paths up to the current time RelativeTransform relTransform = Services.RelativePose.GetTransform(behaviorTimestamp, curTimestamp); LinePath curStartingPath = startingLanePath.Transform(relTransform); LinePath curEndingPath = endingLanePath.Transform(relTransform); // get the starting and ending lane models ILaneModel startingLaneModel, endingLaneModel; Services.RoadModelProvider.GetLaneChangeModels(curStartingPath, startingLaneWidth, startingNumLanesLeft, startingNumLanesRight, curEndingPath, endingLaneWidth, changeLeft, behaviorTimestamp, out startingLaneModel, out endingLaneModel); // calculate the max speed // TODO: make this look ahead for slowing down settings.maxSpeed = GetMaxSpeed(endingLanePath, endingLanePath.ZeroPoint); // get the remaining lane change distance double remainingDist = GetRemainingLaneChangeDistance(); BehaviorManager.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "remaining distance is {0}", remainingDist); if (cancelled) { return; } // check if we're done if (remainingDist <= 0) { // create a new stay in lane behavior int deltaLanes = changeLeft ? -1 : 1; StayInLaneBehavior stayInLane = new StayInLaneBehavior(endingLaneID, speedCommand, null, endingLanePath, endingLaneWidth, startingNumLanesLeft + deltaLanes, startingNumLanesRight - deltaLanes); stayInLane.TimeStamp = behaviorTimestamp.ts; Services.BehaviorManager.Execute(stayInLane, null, false); // send completion report ForwardCompletionReport(new SuccessCompletionReport(typeof(ChangeLaneBehavior))); return; } // calculate the planning distance double planningDist = GetPlanningDistance(); if (planningDist < remainingDist + TahoeParams.VL) { planningDist = remainingDist + TahoeParams.VL; } BehaviorManager.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "planning dist {0}", planningDist); // create a linearization options structure LinearizationOptions laneOpts = new LinearizationOptions(); laneOpts.Timestamp = curTimestamp; // get the center line of the target lane starting at the distance we want to enter into it laneOpts.StartDistance = remainingDist; laneOpts.EndDistance = planningDist; LinePath centerLine = endingLaneModel.LinearizeCenterLine(laneOpts); // add the final center line as a weighting AddTargetPath(centerLine.Clone(), default_lane_alpha_w); // pre-pend (0,0) as our position centerLine.Insert(0, new Coordinates(0, 0)); LinePath leftBound = null; LinePath rightBound = null; // figure out if the lane is to the right or left of us laneOpts.EndDistance = planningDist; double leftEndingStartDist, rightEndingStartDist; GetLaneBoundStartDists(curEndingPath, endingLaneWidth, out leftEndingStartDist, out rightEndingStartDist); if (changeLeft) { // we're the target lane is to the left // get the left bound of the target lane laneOpts.StartDistance = Math.Max(leftEndingStartDist, TahoeParams.FL); leftBound = endingLaneModel.LinearizeLeftBound(laneOpts); } else { // we're changing to the right, get the right bound of the target lane laneOpts.StartDistance = Math.Max(rightEndingStartDist, TahoeParams.FL); rightBound = endingLaneModel.LinearizeRightBound(laneOpts); } // get the other bound as the starting lane up to 5m before the remaining dist laneOpts.StartDistance = TahoeParams.FL; laneOpts.EndDistance = Math.Max(0, remainingDist - 5); if (changeLeft) { if (laneOpts.EndDistance > 0) { rightBound = startingLaneModel.LinearizeRightBound(laneOpts); } else { rightBound = new LinePath(); } } else { if (laneOpts.EndDistance > 0) { leftBound = startingLaneModel.LinearizeLeftBound(laneOpts); } else { leftBound = new LinePath(); } } // append on the that bound of the target lane starting at the remaining dist laneOpts.StartDistance = Math.Max(remainingDist, TahoeParams.FL); laneOpts.EndDistance = planningDist; if (changeLeft) { rightBound.AddRange(endingLaneModel.LinearizeRightBound(laneOpts)); } else { leftBound.AddRange(endingLaneModel.LinearizeLeftBound(laneOpts)); } // set up the planning smootherBasePath = centerLine; AddLeftBound(leftBound, !changeLeft); AddRightBound(rightBound, changeLeft); Services.UIService.PushLineList(centerLine, curTimestamp, "subpath", true); Services.UIService.PushLineList(leftBound, curTimestamp, "left bound", true); Services.UIService.PushLineList(rightBound, curTimestamp, "right bound", true); if (cancelled) { return; } // set auxillary options settings.endingHeading = centerLine.EndSegment.UnitVector.ArcTan; // smooth and track that stuff SmoothAndTrack(commandLabel, true); } finally { Trace.CorrelationManager.StopLogicalOperation(); } }
public LocalLaneModel Clone() { double[] varianceClone = new double[laneYVariance.Length]; Array.Copy(laneYVariance, varianceClone, laneYVariance.Length); return(new LocalLaneModel(lanePath.Clone(), varianceClone, width, widthVariance, probability)); }
private void DoInitialPlan() { InitializePlanningSettings(); curTimestamp = Services.RelativePose.CurrentTimestamp; vs = Services.StateProvider.GetVehicleState(); LinePath curTargetPath = targetPath.Clone(); LinePath curLeftBound = null; if (leftBound != null) { curLeftBound = leftBound.Clone(); } LinePath curRightBound = null; if (rightBound != null) { curRightBound = rightBound.Clone(); } // get the distance between our current location and the start point double distToStart = Coordinates.Zero.DistanceTo(curTargetPath[0]); // extract off the first 5 m of the target path LinePath.PointOnPath endTarget = curTargetPath.AdvancePoint(curTargetPath.StartPoint, 12); curTargetPath = curTargetPath.SubPath(curTargetPath.StartPoint, endTarget); AddTargetPath(curTargetPath.Clone(), 0.005); // adjust the left bound and right bounds starting distance if (curLeftBound != null) { LinePath.PointOnPath leftBoundStart = curLeftBound.AdvancePoint(curLeftBound.StartPoint, 2); curLeftBound = curLeftBound.SubPath(leftBoundStart, curLeftBound.EndPoint); AddLeftBound(curLeftBound, false); } if (curRightBound != null) { LinePath.PointOnPath rightBoundStart = curRightBound.AdvancePoint(curRightBound.StartPoint, 2); curRightBound = curRightBound.SubPath(rightBoundStart, curRightBound.EndPoint); AddRightBound(curRightBound, false); } // add the intersection pull path LinePath intersectionPullPath = new LinePath(); double pullWeight = 0; AbsoluteTransformer trans = Services.StateProvider.GetAbsoluteTransformer(curTimestamp); GetIntersectionPullPath(pseudoStartLane.Transform(trans), curTargetPath, intersectionPolygon, true, true, intersectionPullPath, ref pullWeight); if (intersectionPullPath.Count > 0) { AddTargetPath(intersectionPullPath, pullWeight); } // set up planning details // add our position to the current target path curTargetPath.Insert(0, new Coordinates(0, 0)); smootherBasePath = curTargetPath; // add the bounds // calculate max speed settings.maxSpeed = GetMaxSpeed(null, LinePath.PointOnPath.Invalid); // fill in auxiliary settings if (curLeftBound != null || curRightBound != null) { settings.endingHeading = curTargetPath.EndSegment.UnitVector.ArcTan; } disablePathAngleCheck = true; settings.Options.w_diff = 4; // do the planning PlanningResult planningResult = Smooth(false); // if the planning was a success, store the result if (!planningResult.dynamicallyInfeasible) { // transform to absolute coordinates AbsoluteTransformer absTransform = Services.StateProvider.GetAbsoluteTransformer(curTimestamp); turnBasePath = planningResult.smoothedPath.Transform(absTransform.Invert()); } }
public override void Process(object param) { if (!base.BeginProcess()) { return; } // check if we're given a param if (param != null && param is TurnBehavior) { TurnBehavior turnParam = (TurnBehavior)param; HandleTurnBehavior(turnParam); BehaviorManager.TraceSource.TraceEvent(TraceEventType.Information, 0, "turn behavior - got new param, speed command {0}", turnParam.SpeedCommand); } LinePath curTargetPath = targetPath.Clone(); LinePath curLeftBound = null; if (leftBound != null) { curLeftBound = leftBound.Clone(); } LinePath curRightBound = null; if (rightBound != null) { curRightBound = rightBound.Clone(); } // transform the path into the current timestamp if (behaviorTimestamp != curTimestamp) { // get the relative transform RelativeTransform relTransform = Services.RelativePose.GetTransform(behaviorTimestamp, curTimestamp); BehaviorManager.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "in turn behavior, transforming from {0}->{1}, wanted {2}->{3}", relTransform.OriginTimestamp, relTransform.EndTimestamp, behaviorTimestamp, curTimestamp); curTargetPath.TransformInPlace(relTransform); if (curLeftBound != null) { curLeftBound.TransformInPlace(relTransform); } if (curRightBound != null) { curRightBound.TransformInPlace(relTransform); } } // get the distance between our current location and the start point double distToStart = Coordinates.Zero.DistanceTo(curTargetPath[0]); double startDist = Math.Max(0, TahoeParams.FL - distToStart); // extract off the first 5 m of the target path LinePath.PointOnPath endTarget = curTargetPath.AdvancePoint(curTargetPath.StartPoint, TahoeParams.VL); curTargetPath = curTargetPath.SubPath(curTargetPath.StartPoint, endTarget); curTargetPath = curTargetPath.RemoveZeroLengthSegments(); // adjust the left bound and right bounds starting distance if (curLeftBound != null) { LinePath.PointOnPath leftBoundStart = curLeftBound.AdvancePoint(curLeftBound.StartPoint, 2); curLeftBound = curLeftBound.SubPath(leftBoundStart, curLeftBound.EndPoint); AddLeftBound(curLeftBound, false); Services.UIService.PushLineList(curLeftBound, curTimestamp, "left bound", true); } if (curRightBound != null) { LinePath.PointOnPath rightBoundStart = curRightBound.AdvancePoint(curRightBound.StartPoint, 2); curRightBound = curRightBound.SubPath(rightBoundStart, curRightBound.EndPoint); AddRightBound(curRightBound, false); Services.UIService.PushLineList(curRightBound, curTimestamp, "right bound", true); } if (cancelled) { return; } BehaviorManager.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "in turn behavior, dist to start: {0}", distToStart); if (distToStart < TahoeParams.FL * 0.75) { BehaviorManager.TraceSource.TraceEvent(TraceEventType.Information, 0, "in turn behavior, past start point of target path"); // return a completion report ForwardCompletionReport(new SuccessCompletionReport(typeof(TurnBehavior))); } AddTargetPath(curTargetPath.Clone(), 0.005); // transform the pseudo start lane to the current timestamp AbsoluteTransformer trans = Services.StateProvider.GetAbsoluteTransformer(curTimestamp); LinePath curStartPath = pseudoStartLane.Transform(trans); // add the intersection pull path LinePath intersectionPullPath = new LinePath(); double pullWeight = 0; GetIntersectionPullPath(curStartPath, curTargetPath, intersectionPolygon, true, true, intersectionPullPath, ref pullWeight); if (intersectionPullPath.Count > 0) { AddTargetPath(intersectionPullPath, pullWeight); } // set up planning details // add our position to the current target path LinePath origTargetPath = curTargetPath.Clone(); curTargetPath.Insert(0, new Coordinates(0, 0)); //curTargetPath.Insert(1, new Coordinates(1, 0)); smootherBasePath = curTargetPath; // add the bounds // calculate max speed settings.maxSpeed = GetMaxSpeed(null, LinePath.PointOnPath.Invalid); settings.Options.w_diff = 4; BehaviorManager.TraceSource.TraceEvent(TraceEventType.Information, 0, "max speed set to {0}", settings.maxSpeed); if (cancelled) { return; } Services.UIService.PushLineList(curTargetPath, curTimestamp, "subpath", true); // set the avoidance path to the previously planned path // transform to the current timestamp disablePathAngleCheck = true; if (turnBasePath != null) { avoidanceBasePath = turnBasePath.Transform(trans); avoidanceBasePath = avoidanceBasePath.SubPath(avoidanceBasePath.GetClosestPoint(Coordinates.Zero), avoidanceBasePath.EndPoint); maxAvoidanceBasePathAdvancePoint = avoidanceBasePath.GetPointOnPath(1); if (avoidanceBasePath.PathLength > 7.5) { smootherBasePath = avoidanceBasePath.SubPath(avoidanceBasePath.StartPoint, avoidanceBasePath.AdvancePoint(avoidanceBasePath.EndPoint, -7.5)); } else { smootherBasePath = avoidanceBasePath.Clone(); } disablePathAngleCheck = false; } // fill in auxiliary settings if (curLeftBound != null || curRightBound != null) { settings.endingHeading = curTargetPath.EndSegment.UnitVector.ArcTan; } settings.endingPositionFixed = false; settings.endingPositionMax = 16; settings.endingPositionMin = -16; if (curLeftBound != null && curLeftBound.Count > 0 && curTargetPath.Count > 0) { double leftWidth = curLeftBound[0].DistanceTo(origTargetPath[0]) - TahoeParams.T / 2; settings.endingPositionMax = leftWidth; settings.endingPositionFixed = true; } if (curRightBound != null && curRightBound.Count > 0 && curTargetPath.Count > 0) { double rightWidth = curRightBound[0].DistanceTo(origTargetPath[0]) - TahoeParams.T / 2; settings.endingPositionFixed = true; settings.endingPositionMin = -rightWidth; } //disablePathAngleCheck = true; //useAvoidancePath = true; // do the planning SmoothAndTrack(commandLabel, true); }
private LinePath ReplaceFirstPoint(LinePath path, LinePath.PointOnPath maxAdvancePoint, Coordinates pt) { LinePath ret; if (!disablePathAngleCheck) { // start walking down the path until the angle is cool double angle_threshold = pathAngleMax; LinePath.PointOnPath newPoint = new LinePath.PointOnPath(); for (double dist = 0; dist < pathAngleCheckMax; dist += 1) { // get the point advanced from the 2nd point on the base path by dist double distTemp = dist; newPoint = path.AdvancePoint(path.GetPointOnPath(1), ref distTemp); // check if we're past the end if (distTemp > 0) { break; } else if (maxAdvancePoint.Valid && newPoint >= maxAdvancePoint) { newPoint = maxAdvancePoint; break; } // check if the angle is coolness or not double angle = Math.Acos((newPoint.Location-pt).Normalize().Dot(path.GetSegment(newPoint.Index).UnitVector)); if (angle < angle_threshold) { break; } } // create a new version of the base path with the stuff section removed ret = path.RemoveBetween(path.StartPoint, newPoint); ret[0] = pt; } else { ret = path.Clone(); ret[0] = pt; } return ret; }