Esempio n. 1
0
    // Update is called once per frame
    void Update()
    {
        if (isMoving)
        {
            // How long has it been since we last updated our position
            float distanceIncrement = this.moveRate * Time.deltaTime;
            // find out how far we should move
            // convert to T value 0...1
            this.currentDistanceAlongDubinPath += distanceIncrement;
            if (currentDistanceAlongDubinPath >= finalDistanceAlongDubinPath)
            {
                distanceIncrement             = currentDistanceAlongDubinPath - finalDistanceAlongDubinPath;
                currentDistanceAlongDubinPath = finalDistanceAlongDubinPath;
                isMoving = false;
            }
            else
            {
                this.CurrentMoveDistance -= distanceIncrement;
            }

            this.CurrentMoveDistance = Mathf.Max(0.0f, CurrentMoveDistance);

            DubinCSC currentDubin     = CurrentPath.path[this.currentDubinIdx];
            float    relativeDistance = currentDistanceAlongDubinPath - runningDubinDistanceTotal;

            if (relativeDistance > currentDubin.totalLength)
            {
                this.runningDubinDistanceTotal += currentDubin.totalLength;
                relativeDistance -= currentDubin.totalLength;

                currentDubinIdx++;
                currentDubin = this.currentPath.path[currentDubinIdx];
            }

            Vector3 nextPos;
            Vector3 nextDir;

            currentDubin.GetPositionAndHeadingFromDistance(relativeDistance, this.currentPath.turnRadius, out nextPos, out nextDir);

            // move to that spot.
            this.transform.position = nextPos;
            this.transform.forward  = this.CurrentPath.isReverse ? -nextDir : nextDir;

            gameEventSystem.RaiseEvent(GameEventType.ObjectPropertyChanged, this.gameObject, this.gameObject);

            // TODO:
            // Do something with tile grid?
            // Do we care for in motion stuff, or just the end position?

            if (!isMoving)
            {
                ////TODO: Do we really want to clear the entire, or just from the last point?
                //// in which case, we'd need to clip the dubin, basicaly....or repath
                //this.CurrentPath.path.Clear();
                this.CurrentPath.Clip(currentDistanceAlongDubinPath);
                gameEventSystem.RaiseEvent(GameEventType.PathChanged, this.gameObject, CurrentPath);
                gameEventSystem.RaiseEvent(GameEventType.MoveEnded, this.gameObject, CurrentPath);
            }
        }
    }
Esempio n. 2
0
    public void Clip(float startDistance)
    {
        // find the new starting dubin:
        float    pathDistance  = 0.0f;
        DubinCSC newStartDubin = DubinCSC.NullDubin;
        int      startIdx      = -1;

        // TODO make this into a function, though it's an awkward one
        // Figure out which Dubin in the list we should start on
        for (int i = 0; i < path.Count; ++i)
        {
            pathDistance += path[i].totalLength;
            if (startDistance < pathDistance)
            {
                newStartDubin = path[i];
                startIdx      = i;
                pathDistance -= path[i].totalLength;
                break; //Found our dubin
            }
        }

        if (startIdx == -1 || MyMath.IsNearZero(pathDistance))
        {
            this.path.Clear();
        }
        else
        {
            float relativeDistanceStart = startDistance - pathDistance;
            newStartDubin.Clip(relativeDistanceStart, turnRadius);

            // remove all previous dubins
            this.path.RemoveRange(0, startIdx);
        }
    }
Esempio n. 3
0
    // Generates four dubins
    static public DubinCSC FindDubins(DirectionalCircle orgLeft,
                                      DirectionalCircle orgRight,
                                      DirectionalCircle dstLeft,
                                      DirectionalCircle dstRight,
                                      Vector2 ptStart,
                                      Vector2 ptDest,
                                      float turnRadius,
                                      DubinCSC[] dubins)
    {
        dubins = new DubinCSC[4];
        // RSR
        ///////
        DubinCSC shortestDubins = dubins[0] = DubinCSC.RSRCourse(orgRight, dstRight, ptStart, ptDest, turnRadius);

        // LSL
        ////////
        dubins[1]      = DubinCSC.LSLCourse(orgLeft, dstLeft, ptStart, ptDest, turnRadius);
        shortestDubins = DubinCSC.TakeShortest(shortestDubins, dubins[1]);

        // RSL
        ////////
        dubins[2]      = DubinCSC.RSLCourse(orgRight, dstLeft, ptStart, ptDest, turnRadius);
        shortestDubins = DubinCSC.TakeShortest(shortestDubins, dubins[2]);

        // LSR
        ///////
        dubins[3]      = DubinCSC.LSRCourse(orgLeft, dstRight, ptStart, ptDest, turnRadius);
        shortestDubins = DubinCSC.TakeShortest(shortestDubins, dubins[3]);

        return(shortestDubins);
    }
Esempio n. 4
0
    static public DubinCSC LSRCourse(
        DirectionalCircle orgLeft,
        DirectionalCircle dstRight,
        Vector2 ptStart,
        Vector2 ptDest,
        float turnRadius)
    {
        float x1 = orgLeft.center.x;
        float y1 = orgLeft.center.y;

        float x2 = dstRight.center.x;
        float y2 = dstRight.center.y;

        Vector2 v = dstRight.center - orgLeft.center;

        float dSqr = v.sqrMagnitude;

        if (dSqr < turnRadius)
        {
            // Circles overlap
            return(NullDubin);
        }

        float d = Mathf.Sqrt(dSqr);

        v /= d;

        // For Sign1 = -1
        float c = (turnRadius + turnRadius) / d;

        if (c * c > 1.0f)
        {
            return(NullDubin);
        }

        float h = Mathf.Sqrt(1.0f - c * c);

        // Sign1 = -1, Sign2 = -1
        float nx = (v.x * c + h * v.y) * turnRadius;
        float ny = (v.y * c - h * v.x) * turnRadius;

        DubinCSC course = new DubinCSC();

        course.line = (new Line2D()
        {
            start = new Vector2(x1 + nx, y1 + ny),
            end = new Vector2(x2 - nx, y2 - ny)
        });
        course.sLength = d;

        course.startArc = new Arc(orgLeft, orgLeft.startTheta, course.line.start, turnRadius);
        course.endArc   = new Arc(dstRight, course.line.end, ptDest, turnRadius);

        course.totalLength = course.sLength + course.startArc.length + course.endArc.length;

        return(course);
    }
Esempio n. 5
0
    static public DubinCSC RSRCourse(
        DirectionalCircle orgRight,
        DirectionalCircle dstRight,
        Vector2 ptStart,
        Vector2 ptDest,
        float turnRadius)
    {
        // Compute tangent line
        float x1 = orgRight.center.x;
        float y1 = orgRight.center.y;

        float x2 = dstRight.center.x;
        float y2 = dstRight.center.y;

        Vector2 v = dstRight.center - orgRight.center;

        float dSqr = v.sqrMagnitude;

        if (dSqr < turnRadius)
        {
            // Circles overlap
            return(NullDubin);
        }

        float d = Mathf.Sqrt(dSqr);

        v /= d;         // note to self, i believe this is overkill, and just there for circles of different radius, normal doesn't need to be computed.
        // and i could get away with a simple x1,y1 + -vy,vx
        // And I might be able to get away with checking each individial arc/line/arc distance separately

        // Sign1 = 1, Sign2 = 1
        float nx = /*v.x * c*/ -v.y;
        float ny = /*v.y * c*/ +v.x;

        nx *= turnRadius;
        ny *= turnRadius;

        DubinCSC course = new DubinCSC();

        course.line = new Line2D()
        {
            start = new Vector2(x1 + nx, y1 + ny),
            end   = new Vector2(x2 + nx, y2 + ny)
        };

        course.sLength = d;

        course.startArc    = new Arc(orgRight, orgRight.startTheta, course.line.start, turnRadius);
        course.endArc      = new Arc(dstRight, course.line.end, ptDest, turnRadius);
        course.totalLength = course.sLength + course.startArc.length + course.endArc.length;

        return(course);
    }
Esempio n. 6
0
    static public DubinCSC LSLCourse(
        DirectionalCircle orgLeft,
        DirectionalCircle dstLeft,
        Vector2 ptStart,
        Vector2 ptDest,
        float turnRadius)
    {
        float x1 = orgLeft.center.x;
        float y1 = orgLeft.center.y;

        float x2 = dstLeft.center.x;
        float y2 = dstLeft.center.y;

        Vector2 v = dstLeft.center - orgLeft.center;

        float dSqr = v.sqrMagnitude;

        if (dSqr < turnRadius)
        {
            // Circles overlap
            return(NullDubin);
        }

        float d = Mathf.Sqrt(dSqr);

        v /= d;

        float nx = /*v.x * c*/ -v.y;
        float ny = /*v.y * c*/ +v.x;

        // Sign1 = 1, Sign2 = -1
        nx = -nx * turnRadius;
        ny = -ny * turnRadius;

        DubinCSC course = new DubinCSC();

        course.line = (new Line2D()
        {
            start = new Vector2(x1 + nx, y1 + ny),
            end = new Vector2(x2 + nx, y2 + ny)
        });

        course.sLength = d;

        course.startArc = new Arc(orgLeft, orgLeft.startTheta, course.line.start, turnRadius);
        course.endArc   = new Arc(dstLeft, course.line.end, ptDest, turnRadius);

        course.totalLength = course.sLength + course.startArc.length + course.endArc.length;

        return(course);
    }
Esempio n. 7
0
    static public DubinCSC Translate(DubinCSC dubin, Vector2 transVec)
    {
        // Lengths remain the same, just the positions change
        DubinCSC transDubin = new DubinCSC()
        {
            startArc    = dubin.startArc,
            line        = dubin.line,
            endArc      = dubin.endArc,
            sLength     = dubin.sLength,
            totalLength = dubin.totalLength
        };

        transDubin.line.start             += transVec;
        transDubin.line.end               += transVec;
        transDubin.startArc.circle.center += transVec;
        transDubin.endArc.circle.center   += transVec;

        return(transDubin);
    }
Esempio n. 8
0
    public void GetEndDirAndPos(out Vector3 dir, out Vector3 pos)
    {
        DubinCSC lastDubin = path[path.Count - 1];

        if (isDirectional)
        {
            lastDubin.endArc.GetPositionAndHeadingFromDistance(
                lastDubin.endArc.length,
                turnRadius,
                out pos,
                out dir);
        }
        else
        {
            Vector2 normDir2D = (lastDubin.line.end - lastDubin.line.start).normalized;
            dir = new Vector3(normDir2D.x, 0.0f, normDir2D.y);
            pos = new Vector3(lastDubin.line.end.x, 0.0f, lastDubin.line.end.y);
        }

        if (isReverse)
        {
            dir = -dir;
        }
    }
Esempio n. 9
0
    static public DubinCSC FindDubin(DirectionalCircle orgLeft,
                                     DirectionalCircle orgRight,
                                     Vector2 ptStart,
                                     Vector2 ptDest,
                                     float turnRadius,
                                     DirectionalCircle dstLeft,
                                     DirectionalCircle dstRight)
    {
        // RSR
        ///////
        DubinCSC shortestDubins = DubinCSC.RSRCourse(orgRight, dstRight, ptStart, ptDest, turnRadius);

        // LSL
        ////////
        shortestDubins = DubinCSC.TakeShortest(shortestDubins, DubinCSC.LSLCourse(orgLeft, dstLeft, ptStart, ptDest, turnRadius));

        // RSL
        ////////
        shortestDubins = DubinCSC.TakeShortest(shortestDubins, DubinCSC.RSLCourse(orgRight, dstLeft, ptStart, ptDest, turnRadius));

        // LSR
        ///////
        return(DubinCSC.TakeShortest(shortestDubins, DubinCSC.LSRCourse(orgLeft, dstRight, ptStart, ptDest, turnRadius)));
    }
Esempio n. 10
0
    public List <HeadingPositionPair> AsPointsList(LineRenderArgs args, float distInc)
    {
        Vector3 nextPos = Vector3.zero;
        Vector3 nextDir;
        int     dubinIndex = path.Count - 1;

        float totalLength = this.CalculateTotalDistance();

        float    pathDistance = 0.0f;
        DubinCSC currentDubin = path[path.Count - 1];

        // Figure out which Dubin in the list we should start on
        for (int i = 0; i < path.Count; ++i)
        {
            pathDistance += path[i].totalLength;
            if (args.StartDistance <= pathDistance)
            {
                currentDubin  = path[i];
                dubinIndex    = i;
                pathDistance -= path[i].totalLength;
                break; //Found our dubin
            }
        }

        // const int numSegmentsPerDubin = 100;
        // int totalNumSegments = numSegmentsPerDubin * (path.Count - dubinIndex);
        //float distInc = Mathf.Ceil(currentDubin.totalLength / numSegmentsPerDubin);
        int numPairs = (int)(totalLength / distInc);
        List <HeadingPositionPair> pathLines = new List <HeadingPositionPair>(numPairs);

        for (float distance = args.StartDistance; distance < args.EndDistance;)
        {
            float relativeDistanceStart = distance - pathDistance;
            float relativeDistanceEnd   = Mathf.Min(currentDubin.totalLength, args.EndDistance - pathDistance);
            //float distInc = Mathf.Ceil(currentDubin.totalLength / numSegmentsPerDubin);

            for (float relativeDistance = relativeDistanceStart;
                 relativeDistance <= relativeDistanceEnd;
                 relativeDistance += distInc)
            {
                currentDubin.GetPositionAndHeadingFromDistance(relativeDistance, turnRadius, out nextPos, out nextDir);
                pathLines.Add(new HeadingPositionPair(nextPos, nextDir));
            }

            // ensure that the last spot is included
            currentDubin.GetPositionAndHeadingFromDistance(relativeDistanceEnd, turnRadius, out nextPos, out nextDir);
            pathLines.Add(new HeadingPositionPair(nextPos, nextDir));

            distance     += currentDubin.totalLength;
            pathDistance += currentDubin.totalLength;

            dubinIndex++;
            if (dubinIndex >= path.Count)
            {
                break;
            }

            currentDubin = path[dubinIndex];
        }

        return(pathLines);
    }
Esempio n. 11
0
    static public DubinCSC FindDegenerateDubins(
        DirectionalCircle orgLeft,
        DirectionalCircle orgRight,
        Vector2 ptStart,
        Vector2 ptDest,
        float turnRadius)
    {
        Vector2 vLeft  = orgLeft.center - ptDest;
        Vector2 vRight = orgRight.center - ptDest;

        DubinCSC dubinLS = new DubinCSC();
        DubinCSC dubinRS = new DubinCSC();

        float rSq = turnRadius * turnRadius;

        if (rSq < vLeft.sqrMagnitude)
        {
            float a = Mathf.Asin(turnRadius / vLeft.magnitude);
            float b = Mathf.Atan2(vLeft.y, vLeft.x);

            float   t = b + a;
            Vector2 Q = new Vector2(orgLeft.center.x + turnRadius * -Mathf.Sin(t),
                                    orgLeft.center.y + turnRadius * Mathf.Cos(t));


            // TODO:  I think I'm doing one too many Atan2s here....
            dubinLS.startArc   = new Arc(orgLeft, orgLeft.startTheta, Q, turnRadius);
            dubinLS.line.start = Q;
            dubinLS.line.end   = ptDest;
            dubinLS.sLength    = (dubinLS.line.end - dubinLS.line.start).magnitude;

            dubinLS.endArc.startTheta = 0.0f;
            dubinLS.endArc.endTheta   = 0.0f;
            dubinLS.endArc.length     = 0.0f;

            dubinLS.totalLength = dubinLS.startArc.length + dubinLS.sLength;
        }
        else
        {
            dubinLS.totalLength = NullDubin.totalLength;
        }

        if (rSq < vRight.sqrMagnitude)
        {
            float   a = Mathf.Asin(turnRadius / vRight.magnitude);
            float   b = Mathf.Atan2(vRight.y, vRight.x);
            float   t = b - a;
            Vector2 Q = new Vector2(orgRight.center.x + turnRadius * Mathf.Sin(t),
                                    orgRight.center.y + turnRadius * -Mathf.Cos(t));

            dubinRS.startArc   = new Arc(orgRight, orgRight.startTheta, Q, turnRadius);
            dubinRS.line.start = Q;
            dubinRS.line.end   = ptDest;
            dubinRS.sLength    = (dubinRS.line.end - dubinRS.line.start).magnitude;

            dubinRS.endArc.startTheta = 0.0f;
            dubinRS.endArc.endTheta   = 0.0f;
            dubinRS.endArc.length     = 0.0f;

            dubinRS.totalLength = dubinRS.startArc.length + dubinRS.sLength;
        }
        else
        {
            dubinRS.totalLength = NullDubin.totalLength;
        }

        return(DubinCSC.TakeShortest(dubinLS, dubinRS));
    }
Esempio n. 12
0
    // note:  This form doesn't care about ending direction, just tries to get to the point
    // Generates two dubins
    static public DubinCSC FindDegenerateDubins(
        DirectionalCircle orgLeft,
        DirectionalCircle orgRight,
        Vector2 ptStart,
        Vector2 ptDest,
        float turnRadius,
        DubinCSC[] dubins)
    {
        Vector2 vLeft  = orgLeft.center - ptDest;           // lines from center of circle to destination
        Vector2 vRight = orgRight.center - ptDest;

        DubinCSC dubinLS = NullDubin;
        DubinCSC dubinRS = NullDubin;

        float rSq = turnRadius * turnRadius;          // this could probably be pulled out to a member or argument

        if (rSq < vLeft.sqrMagnitude)
        {
            float a = Mathf.Asin(turnRadius / vLeft.magnitude);             // vLeft.Mag = h
            float b = Mathf.Atan2(vLeft.y, vLeft.x);

            float   t = b + a;
            Vector2 Q = new Vector2(orgLeft.center.x + turnRadius * -Mathf.Sin(t),
                                    orgLeft.center.y + turnRadius * Mathf.Cos(t));
            dubinLS            = new DubinCSC();
            dubinLS.startArc   = new Arc(orgLeft, orgLeft.startTheta, Q, turnRadius);
            dubinLS.line.start = Q;
            dubinLS.line.end   = ptDest;
            dubinLS.sLength    = (dubinLS.line.end - dubinLS.line.start).magnitude;

            dubinLS.endArc.startTheta = 0.0f;
            dubinLS.endArc.endTheta   = 0.0f;
            dubinLS.endArc.length     = 0.0f;

            dubinLS.totalLength = dubinLS.startArc.length + dubinLS.sLength;
        }

        if (rSq < vRight.sqrMagnitude)
        {
            float   a = Mathf.Asin(turnRadius / vRight.magnitude);
            float   b = Mathf.Atan2(vRight.y, vRight.x);
            float   t = b - a;
            Vector2 Q = new Vector2(orgRight.center.x + turnRadius * Mathf.Sin(t),
                                    orgRight.center.y + turnRadius * -Mathf.Cos(t));
            dubinRS            = new DubinCSC();
            dubinRS.startArc   = new Arc(orgRight, orgRight.startTheta, Q, turnRadius);
            dubinRS.line.start = Q;
            dubinRS.line.end   = ptDest;
            dubinRS.sLength    = (dubinRS.line.end - dubinRS.line.start).magnitude;

            dubinRS.endArc.startTheta = 0.0f;
            dubinRS.endArc.endTheta   = 0.0f;
            dubinRS.endArc.length     = 0.0f;

            dubinRS.totalLength = dubinRS.startArc.length + dubinRS.sLength;
        }


        DubinCSC shortDubin = DubinCSC.TakeShortest(dubinLS, dubinRS);

        dubins[0] = dubinLS;
        dubins[1] = dubinRS;


        return(shortDubin);
    }
Esempio n. 13
0
    public void DrawDubin(AccessibleLineRenderer lineRenderer, LineRenderArgs args)
    {
        if (path == null || path.Count == 0)
        {
            //TEMP
            lineRenderer.enabled = false;
            return;
        }

        lineRenderer.UnderlyingLineRenderer.SetWidth(args.LineWidth, args.LineWidth);

        //TEMP
        if (lineRenderer.enabled == false)
        {
            lineRenderer.enabled = true;
        }

        Vector3 nextPos = Vector3.zero;
        Vector3 nextDir;
        int     dubinIndex = path.Count - 1;

        float totalLength = this.CalculateTotalDistance();

        float    pathDistance = 0.0f;
        DubinCSC currentDubin = path[path.Count - 1];

        // Figure out which Dubin in the list we should start on
        for (int i = 0; i < path.Count; ++i)
        {
            pathDistance += path[i].totalLength;
            if (args.StartDistance <= pathDistance)
            {
                currentDubin  = path[i];
                dubinIndex    = i;
                pathDistance -= path[i].totalLength;
                break; //Found our dubin
            }
        }

        const int numSegmentsPerDubin = 100;
        int       totalNumSegments    = numSegmentsPerDubin * (path.Count - dubinIndex);

        lineRenderer.SetVertexCount(totalNumSegments); //hackery
        int idx = totalNumSegments - 1;

        for (float distance = args.StartDistance; distance < args.EndDistance;)
        {
            float relativeDistanceStart = distance - pathDistance;
            float relativeDistanceEnd   = Mathf.Min(currentDubin.totalLength, args.EndDistance - pathDistance);
            float distInc = Mathf.Ceil(currentDubin.totalLength / numSegmentsPerDubin);

            for (float relativeDistance = relativeDistanceStart;
                 relativeDistance <= relativeDistanceEnd;
                 relativeDistance += distInc)
            {
                currentDubin.GetPositionAndHeadingFromDistance(relativeDistance, turnRadius, out nextPos, out nextDir);
                nextPos.y += 1.0f;
                lineRenderer.SetPosition(idx--, nextPos);
            }

            // ensure that the last spot is included
            currentDubin.GetPositionAndHeadingFromDistance(relativeDistanceEnd, turnRadius, out nextPos, out nextDir);
            nextPos.y += 1.0f;
            lineRenderer.SetPosition(idx, nextPos);

            distance     += currentDubin.totalLength;
            pathDistance += currentDubin.totalLength;

            dubinIndex++;
            if (dubinIndex >= path.Count)
            {
                break;
            }

            currentDubin = path[dubinIndex];
        }

        int badMath = 0;

        //for (int i = idx; i < totalNumSegments; i++)
        for (int i = idx; i >= 0; --i)
        {
            badMath++;
            lineRenderer.SetPosition(i, nextPos);
        }



        //      Debug.Log("BadMath: " + badMath);
    }
Esempio n. 14
0
 public static DubinCSC TakeShortest(DubinCSC du1, DubinCSC du2)
 {
     return(du1.totalLength > du2.totalLength ? du2 : du1);
 }