コード例 #1
0
        public static QuadraticSpeedDistanceCurve Build_A_Safe_Backward(AccelerationSpeedDistanceSurface A_V_D, FlatSpeedDistanceCurve MRSP)
        {
            if (debug)
            {
                Log.InfoFormat("#######################################################");
                Log.InfoFormat("## Build_A_Safe_Backward_Surface#######################");
                Log.InfoFormat("#######################################################");
            }

            int debugging_counter = 0;
            QuadraticSpeedDistanceCurve result = new QuadraticSpeedDistanceCurve();

            /***********************************************************
              The ending point is the first point in the MRSP
             ***********************************************************/
            SiDistance end_position = MRSP[0].X.X0;

            /***********************************************************
              Go forward in the MRSP until we find the point with
              minimal speed. This shall be our starting point
              **********************************************************/
            SiDistance current_position = SiDistance.Zero;
            SiSpeed current_speed = SiSpeed.MaxValue;

            if (debug)
                Log.DebugFormat("  Search the position of the minimal speed in the MRSP");
            for (int i = 0; i < MRSP.SegmentCount; i++)
            {
                ConstantCurveSegment<SiDistance, SiSpeed> segment = MRSP[i];
                if (segment.Y < current_speed)
                {
                    current_speed = segment.Y;
                    current_position = segment.X.X1;

                    if (debug)
                        Log.DebugFormat("    new start position V={0,7:F2} at={1,7:F2} ", current_speed.ToUnits(), current_position.ToUnits());
                }
            }

            if (debug)
                Log.DebugFormat("    end position is at={0,7:F2} ", end_position.ToUnits());

            /*************************************************************************/
            /* Starting from the right side of curves, go back to the left side.     */
            /* Build small curves arcs where the acceleration is constant on each one*/
            /*************************************************************************/
            while (current_position > end_position)
            {
                if (debug)
                {
                    Log.DebugFormat("#######################################################");
                    Log.DebugFormat("### Loop {0}  #########################################", debugging_counter);
                    Log.DebugFormat("#######################################################");
                }

                /************************************************************
                  Based on current speed and position, search on wich tile
                  of A_V_D tile we are
                  ***********************************************************/
                SurfaceTile current_tile = A_V_D.GetTileAt(current_speed + new SiSpeed(0.01), current_position - new SiDistance(0.1));
                SiAcceleration current_acceleration = current_tile.V.Y;

                /***************************************************************************/
                /* If at previous loop wi did 'hit' the vertical part of the MRSP,
                   we might have a speed above the current MRSP segment.*/
                /***************************************************************************/
                if (current_speed > MRSP.GetValueAt(current_position - new SiDistance(0.1)))
                {
                    current_speed = MRSP.GetValueAt(current_position - new SiDistance(0.1));
                }

                /*******************************************************************
                  We build a quadratic arc with current train position, speed
                  and acceleration. The arc domain [0..current_position] is not valid yet.
                  We must find out the domain left limit.
                 *****************************************************************/
                QuadraticCurveSegment current_curve = new QuadraticCurveSegment(SiDistance.Zero,
                                                                                 current_position,
                                                                                 current_acceleration,
                                                                                 current_speed,
                                                                                 current_position);

                if (debug)
                {
                    Log.DebugFormat("  current_acceleration = {0,7:F2} from a_tile {1}", current_acceleration.ToUnits(), current_tile.ToString());
                    Log.DebugFormat("  current_speed        = {0,7:F2} ", current_speed.ToUnits());
                    Log.DebugFormat("  current_position     = {0,7:F2} ", current_position.ToUnits());

                    Log.DebugFormat("  --> current_curve    = {0} ", current_curve.ToString());
                }

                /********************************************************************/
                /* The current_curve may 'hit' one of these 4 items:
                     1) The upper border of the tile (because of a new acceleration)
                     2) The left border of the tile (because of a gradient?)
                     3) A vertical segment of the MRSP
                     4) An horizontal segment of the MRSP
                   Text all of them and update the next_position accordingly.
                *************************************************************************/
                SiDistance next_position = SiDistance.Zero;

                /* 1) The distance at wich our temporary arc intersects the top (V2) segment of the AVD tile */
                {
                    SiDistance d = current_curve.IntersectAt(current_tile.V.X.X1);
                    if (debug)
                        Log.DebugFormat("  intersection with tile (V_TOP) at {0,7:F2} ", d.ToUnits());
                    if (d >= next_position)
                    {
                        if (debug)
                            Log.DebugFormat("  --> case_1  next_position {0,7:F2} -> {1,7:F2}", next_position.ToUnits(), d.ToUnits());
                        next_position = d;
                    }
                }

                /* 2) The distance at wich our temporary arc intersects the left (D0) segment of the AVD tile */
                {
                    SiDistance d = current_tile.D.X.X0;
                    if (debug)
                        Log.DebugFormat("  intersection with tile (D0)    at {0,7:F2} ", d.ToUnits());
                    if (d >= next_position)
                    {
                        if (debug)
                            Log.DebugFormat("  --> case_2  next_position {0,7:F2} -> {1,7:F2}", next_position.ToUnits(), d.ToUnits());
                        next_position = d;
                    }
                }

                /*Since the MRSP is continous, the following cannot fail. */
                ConstantCurveSegment<SiDistance, SiSpeed> speed_limit_here = MRSP.Intersect(current_position - new SiDistance(0.1), current_curve);
                if (debug)
                    Log.DebugFormat("  MRSP segment          {0} ", speed_limit_here.ToString());

                /* 3) Do we hit the vertical segment of the MRSP ? */
                {
                    if (speed_limit_here.X.X0 >= next_position)
                    {
                        if (debug)
                            Log.DebugFormat("  --> case_3  next_position {0,7:F2} -> {1,7:F2}", next_position.ToUnits(), speed_limit_here.X.X0.ToUnits());
                        next_position = speed_limit_here.X.X0;
                    }
                }

                /* 4) Do we hit the horizontal segment of the MRSP */
                {
                    if (current_speed + new SiSpeed(0.01) < speed_limit_here.Y)
                    {
                        SiDistance d = current_curve.IntersectAt(speed_limit_here.Y);
                        if (d >= next_position)
                        {
                            if (debug)
                                Log.DebugFormat("  --> case_4a next_d        {0,7:F2} -> {1,7:F2}", next_position.ToUnits(), d.ToUnits());
                            next_position = d;
                        }
                    }
                    else
                    {
                        if (debug)
                            Log.DebugFormat("  --> case_4b next_acc_0    {0,7:F2} -> {1,7:F2}", next_position.ToUnits(), speed_limit_here.X.X0.ToUnits());
                        current_acceleration = SiAcceleration.Zero;
                        next_position = speed_limit_here.X.X0;
                    }
                }

                /* Finally we can add the segment because next_position has been computed. */
                result.Add(next_position, current_position, current_acceleration, current_speed, current_position);

                result.Dump("result so far ");

                /* Next loop starts from our new position.
                   We do not need to update current_acceleration because
                   it is done at the beginning of the loop*/
                current_position = next_position;
                current_speed = result.GetValueAt(current_position);

                /*************************************************************/
                /* If this exception is thrown, you'd better call Juan       */
                /*************************************************************/
                if (debugging_counter++ > 200)
                {
                    throw new Exception("Algorithm is broken");
                }
            }

            return result;
        }
コード例 #2
0
        /// <summary>
        ///     Finds the tile edge that is intersected in the chosen direction
        /// </summary>
        /// <param name="current_tile"></param>
        /// <param name="current_curve"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static SiDistance Tile_Intersect(SiDistance current_position, SurfaceTile current_tile,
            QuadraticCurveSegment current_curve, BrakingCurveDirectionEnum dir)
        {
            SiDistance result = SiDistance.Zero;

            SiDistance SpdEdge = Speed_Edge_Location(current_tile, current_curve, dir);
            SiDistance DistEdge = Distance_Edge(current_tile, dir);

            result = Closest_To(current_position, DistEdge, SpdEdge);

            return result;
        }
コード例 #3
0
        /******************************************************************************************************/
        protected void Emit_Quadratic_Segment(StreamWriter swd, QuadraticCurveSegment aSegment, SiSpeed v_offset, SiDistance d_offset)
        {
            SiDistance d0 = aSegment.X.X0;
            SiDistance d1 = aSegment.X.X1;

            Emit_d_V(swd, d0 + d_offset, aSegment.Get(d0) + v_offset);

            if (d1 - d0 > SiDistance.One)
            {
                SiDistance delta = SiDistance.One;
                SiDistance d = d0 + delta;
                do
                {
                    Emit_d_V(swd, d + d_offset, aSegment.Get(d) + v_offset);

                    d += delta;
                } while (d < d1);
            }

            Emit_d_V(swd, d1 + d_offset, aSegment.Get(d1) + v_offset);
        }
コード例 #4
0
        /// <summary>
        ///     Provides the distance at which the curve intersects the horizontal edge of the tile in the given direction
        /// </summary>
        /// <param name="current_tile"></param>
        /// <param name="current_curve"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static SiDistance Speed_Edge_Location(SurfaceTile current_tile, QuadraticCurveSegment current_curve,
            BrakingCurveDirectionEnum dir)
        {
            SiDistance result = SiDistance.Zero;

            SiSpeed limit = SiSpeed.Zero;

            switch (dir)
            {
                case BrakingCurveDirectionEnum.Backwards:
                    limit = current_tile.V.X.X1;
                    break;
                case BrakingCurveDirectionEnum.Forwards:
                    limit = current_tile.V.X.X0;
                    break;
            }
            result = current_curve.IntersectAt(limit);

            return result;
        }
コード例 #5
0
        /// <summary>
        ///     Provides the distance limit of a tile in the requested direction
        /// </summary>
        /// <param name="current_tile"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static SiDistance Distance_Edge(QuadraticCurveSegment current_curve, BrakingCurveDirectionEnum dir)
        {
            SiDistance result = SiDistance.Zero;

            switch (dir)
            {
                case BrakingCurveDirectionEnum.Backwards:
                    result = current_curve.X.X0;
                    break;
                case BrakingCurveDirectionEnum.Forwards:
                    result = current_curve.X.X1;
                    break;
            }

            return result;
        }
コード例 #6
0
        /// <summary>
        ///     Method to return the curve segment at the current location and speed, going in the specified direction.
        /// </summary>
        /// <param name="current_tile"></param>
        /// <param name="current_position"></param>
        /// <param name="current_speed"></param>
        /// <param name="MRSP"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static QuadraticCurveSegment Build_One_Curve_Segment(SurfaceTile current_tile,
            SiDistance current_position,
            SiSpeed current_speed,
            FlatSpeedDistanceCurve MRSP,
            BrakingCurveDirectionEnum dir)
        {
            SiAcceleration current_acceleration = current_tile.V.Y;
            SiDistance MRSP_end = MRSP[MRSP.SegmentCount - 1].X.X1;

            SiDistance curve_start = new SiDistance();
            SiDistance curve_end = new SiDistance();
            switch (dir)
            {
                case BrakingCurveDirectionEnum.Backwards:
                    curve_start = SiDistance.Zero;
                    curve_end = current_position;
                    break;
                case BrakingCurveDirectionEnum.Forwards:
                    curve_start = current_position;
                    curve_end = MRSP_end;
                    break;
            }

            QuadraticCurveSegment current_curve = new QuadraticCurveSegment(curve_start,
                curve_end,
                current_acceleration,
                current_speed,
                current_position);

            if (debug)
            {
                Log.DebugFormat("  current_acceleration = {0,7:F2} from a_tile {1}", current_acceleration.ToUnits(),
                    current_tile.ToString());
                Log.DebugFormat("  current_speed        = {0,7:F2} ", current_speed.ToUnits());
                Log.DebugFormat("  current_position     = {0,7:F2} ", current_position.ToUnits());

                Log.DebugFormat("  --> current_curve    = {0} ", current_curve.ToString());
            }

            /********************************************************************/
            /* The current_curve may 'hit' one of these 4 items:
                    1) The upper border of the tile (because of a new acceleration)
                    2) The left border of the tile (because of a gradient?)
                    3) A vertical segment of the MRSP
                    4) An horizontal segment of the MRSP
                Text all of them and update the next_position accordingly.
            *************************************************************************/
            SiDistance next_position = SiDistance.Zero;

            /* The distance at which our temporary arc intersects a segment of the AVD tile */
            {
                next_position = Tile_Intersect(current_position, current_tile, current_curve, dir);
            }

            /* The MRSP checks only need to be performed if the curve is being computed backwards */
            if (dir == BrakingCurveDirectionEnum.Backwards)
            {
                /*Since the MRSP is continous, the following cannot fail. */
                ConstantCurveSegment<SiDistance, SiSpeed> speed_limit_here =
                    MRSP.Intersect(current_position - new SiDistance(0.1), current_curve);
                if (debug)
                    Log.DebugFormat("  MRSP segment          {0} ", speed_limit_here.ToString());

                /* 3) Do we hit the vertical segment of the MRSP ? */
                {
                    next_position = IntersectMRSPSpeed(next_position, speed_limit_here);
                }

                /* 4) Do we hit the horizontal segment of the MRSP */
                {
                    if (current_speed + new SiSpeed(0.01) < speed_limit_here.Y)
                    {
                        SiDistance d = current_curve.IntersectAt(speed_limit_here.Y);
                        if (d >= next_position)
                        {
                            if (debug)
                                Log.DebugFormat("  --> case_4a next_d        {0,7:F2} -> {1,7:F2}",
                                    next_position.ToUnits(), d.ToUnits());
                            next_position = d;
                        }
                    }
                    else
                    {
                        if (debug)
                            Log.DebugFormat("  --> case_4b next_acc_0    {0,7:F2} -> {1,7:F2}", next_position.ToUnits(),
                                speed_limit_here.X.X0.ToUnits());
                        current_acceleration = SiAcceleration.Zero;
                        next_position = speed_limit_here.X.X0;
                    }
                }
            }

            SiDistance result_start = new SiDistance();
            SiDistance result_end = new SiDistance();

            switch (dir)
            {
                case BrakingCurveDirectionEnum.Backwards:
                    result_start = next_position;
                    result_end = current_position;
                    break;
                case BrakingCurveDirectionEnum.Forwards:
                    result_start = current_position;
                    result_end = next_position;
                    break;
            }

            QuadraticCurveSegment result = new QuadraticCurveSegment(result_start,
                result_end,
                current_acceleration,
                current_speed,
                current_position);

            return result;
        }
コード例 #7
0
        /// <summary>
        /// Provides the graph of this function if it has been statically defined
        /// </summary>
        /// <param name="context">the context used to create the graph</param>
        /// <returns></returns>
        public override Graph createGraph(Interpreter.InterpretationContext context, Parameter parameter)
        {
            Graph retVal = null;

            Graph    MRSPGraph        = null;
            Function speedRestriction = context.findOnStack(SpeedRestrictions).Value as Function;

            if (speedRestriction != null)
            {
                Parameter p = (Parameter)speedRestriction.FormalParameters[0];

                int token = context.LocalScope.PushContext();
                context.LocalScope.setGraphParameter(p);
                MRSPGraph = createGraphForValue(context, context.findOnStack(SpeedRestrictions).Value, p);
                context.LocalScope.PopContext(token);
            }

            if (MRSPGraph != null)
            {
                Function deceleratorFactor = context.findOnStack(DecelerationFactor).Value as Function;
                if (deceleratorFactor != null)
                {
                    Surface DecelerationSurface = deceleratorFactor.createSurface(context);
                    if (DecelerationSurface != null)
                    {
                        FlatSpeedDistanceCurve           MRSPCurve           = MRSPGraph.FlatSpeedDistanceCurve(MRSPGraph.ExpectedEndX());
                        AccelerationSpeedDistanceSurface accelerationSurface = DecelerationSurface.createAccelerationSpeedDistanceSurface(double.MaxValue, double.MaxValue);
                        QuadraticSpeedDistanceCurve      BrakingCurve        = null;
                        try
                        {
                            BrakingCurve = EtcsBrakingCurveBuilder.Build_A_Safe_Backward(accelerationSurface, MRSPCurve);
                        }
                        catch (System.Exception e)
                        {
                            retVal = new Graph();
                            retVal.addSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, 0, 0)));
                        }

                        if (BrakingCurve != null)
                        {
                            retVal = new Graph();

                            // TODO : Remove the distinction between linear curves and quadratic curves
                            bool isLinear = true;
                            for (int i = 0; i < BrakingCurve.SegmentCount; i++)
                            {
                                QuadraticCurveSegment segment = BrakingCurve[i];
                                if (segment.A.ToUnits() != 0.0 || segment.V0.ToUnits() != 0.0)
                                {
                                    isLinear = false;
                                    break;
                                }
                            }

                            for (int i = 0; i < BrakingCurve.SegmentCount; i++)
                            {
                                QuadraticCurveSegment segment = BrakingCurve[i];

                                Graph.Segment newSegment;
                                if (isLinear)
                                {
                                    newSegment = new Graph.Segment(
                                        segment.X.X0.ToUnits(),
                                        segment.X.X1.ToUnits(),
                                        new Graph.Segment.Curve(0.0, segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour), 0.0));
                                }
                                else
                                {
                                    newSegment = new Graph.Segment(
                                        segment.X.X0.ToUnits(),
                                        segment.X.X1.ToUnits(),
                                        new Graph.Segment.Curve(
                                            segment.A.ToSubUnits(SiAcceleration_SubUnits.Meter_per_SecondSquare),
                                            segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour),
                                            segment.D0.ToSubUnits(SiDistance_SubUnits.Meter)
                                            )
                                        );
                                }
                                retVal.addSegment(newSegment);
                            }
                        }
                    }
                    else
                    {
                        Log.Error("Cannot create surface for " + DecelerationFactor.ToString());
                    }
                }
                else
                {
                    Log.Error("Cannot evaluate " + DecelerationFactor.ToString() + " as a function");
                }
            }
            else
            {
                Log.Error("Cannot create graph for " + SpeedRestrictions.ToString());
            }

            return(retVal);
        }
コード例 #8
0
        /// <summary>
        ///     Creates a graph for the function
        /// </summary>
        /// <param name="context"></param>
        /// <param name="parameter"></param>
        /// <param name="explain"></param>
        /// <returns></returns>
        public override Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain)
        {
            Graph retVal = new Graph();

            StructureValue LocationStruct = context.FindOnStack(Target).Value as StructureValue;

            SiDistance location;
            SiSpeed    speed;

            if (LocationStruct != null)
            {
                IVariable locationField = LocationStruct.Val["Location"] as IVariable;
                location = new SiDistance((locationField.Value as DoubleValue).Val);
                IVariable speedField = LocationStruct.Val["Speed"] as IVariable;
                speed = new SiSpeed((speedField.Value as DoubleValue).Val, SiSpeed_SubUnits.KiloMeter_per_Hour);

                Function decelerationFactor = context.FindOnStack(DecelerationFactor).Value as Function;
                if (decelerationFactor != null)
                {
                    Surface DecelerationSurface = decelerationFactor.CreateSurface(context, explain);
                    if (DecelerationSurface != null)
                    {
                        AccelerationSpeedDistanceSurface accelerationSurface =
                            DecelerationSurface.createAccelerationSpeedDistanceSurface(double.MaxValue, double.MaxValue);

                        QuadraticSpeedDistanceCurve BrakingCurve = null;

                        try
                        {
                            BrakingCurve = EtcsBrakingCurveBuilder.Build_Deceleration_Curve(accelerationSurface, speed,
                                                                                            location);
                        }
                        catch (Exception e)
                        {
                            retVal.AddSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, 0, 0)));
                        }

                        SiSpeed finalSpeed = new SiSpeed(GetDoubleValue(context.FindOnStack(EndSpeed).Value),
                                                         SiSpeed_SubUnits.KiloMeter_per_Hour);
                        for (int i = 0; i < BrakingCurve.SegmentCount; i++)
                        {
                            QuadraticCurveSegment segment = BrakingCurve[i];

                            SiSpeed endSpeed = Max(finalSpeed, segment.Get(segment.X.X1));

                            SiDistance endDistance;
                            if (endSpeed == finalSpeed)
                            {
                                // Ensures that a braking curve is calculated until the finalSpeed
                                // but not further than the end of the curve segment
                                SiSpeed tmp = Max(segment.Get(segment.X.X1),
                                                  endSpeed - new SiSpeed(0.001));
                                endDistance = segment.IntersectAt(tmp);
                            }
                            else
                            {
                                endDistance = segment.X.X1;
                            }

                            Graph.Segment newSegment = new Graph.Segment(
                                segment.X.X0.ToUnits(),
                                endDistance.ToUnits(),
                                new Graph.Segment.Curve(
                                    segment.A.ToSubUnits(SiAcceleration_SubUnits.Meter_per_SecondSquare),
                                    segment.V0.ToSubUnits(SiSpeed_SubUnits.KiloMeter_per_Hour),
                                    segment.D0.ToSubUnits(SiDistance_SubUnits.Meter)
                                    )
                                );
                            retVal.AddSegment(newSegment);

                            if (endSpeed == finalSpeed)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            return(retVal);
        }