예제 #1
0
    /// <summary>
    /// Get an estimate of the future state based on the current state, redirector's action and the path to be followed.
    /// ATTENTION: This method is only used for simulation(planning)! A user's actual state is only updated by the tracking system.
    /// </summary>
    /// <param name="s"></param> the current state of the environment.
    /// <param name="a"></param> action to be taken by the redirector.
    /// <param name="seg"></param> the path that the user is walking on in the current stage.
    public RedirectionManager.State ApplyStateUpdate(RedirectionManager.State state, Action a, Segment seg)
    {
        RedirectionManager.State newState = new RedirectionManager.State();
        if (seg is LineSegment)
        {
            LineSegment segment    = (LineSegment)seg;
            Vector2     tangentDir = (segment.endPos - Utilities.FlattenedPos2D(state.pos)).normalized;
            Vector2     delta_p    = this.redirectionManager.speedReal * this.stageDuration * tangentDir;

            // update virtual position and direction
            newState.pos = state.pos + Utilities.UnFlatten(delta_p);
            newState.dir = state.dir;

            // update the real world state according to the action
            if (a.type == ActionType.CURVATURE)
            {
                float s = delta_p.magnitude;
                //Debug.Log("s=" + s);
                float kr    = a.gain; // the curvature gain rou(c)
                float ori_0 = Vector2.SignedAngle(Vector2.right, Utilities.FlattenedDir2D(state.dirReal)) * Mathf.Deg2Rad;
                //Debug.Log("angle:"+ Vector2.SignedAngle(Vector2.right, Utilities.FlattenedDir2D(state.dirReal))+" ori_0:" + ori_0);
                // The new real position depends on user's real orientation
                newState.posReal.x = (Mathf.Sin(ori_0 + kr * s) - Mathf.Sin(ori_0)) / kr + state.posReal.x;
                newState.posReal.z = (Mathf.Cos(ori_0) - Mathf.Cos(ori_0 + kr * s)) / kr + state.posReal.z;
                newState.dirReal   = Utilities.UnFlatten(Utilities.RotateVector(Utilities.FlattenedDir2D(state.dirReal), s * kr * Mathf.Rad2Deg));
                //Debug.Log("ppp " + newState.posReal);
                //Debug.Log("ddd " + newState.dirReal);
            }
            else if (a.type == ActionType.ZERO)
            {
                newState.posReal = state.posReal + state.dirReal * this.redirectionManager.speedReal * this.stageDuration;
                newState.dirReal = state.dirReal;
            }
            else if (a.type == ActionType.RESET)
            {
                newState.posReal = state.posReal - state.dirReal * this.redirectionManager.speedReal * this.stageDuration;
                newState.dirReal = -state.dirReal;
            }
        }
        else if (seg is ArcSegment)
        {
            ArcSegment segment = (ArcSegment)seg;

            // update virtual position and direction
            float s      = this.redirectionManager.speedReal * this.stageDuration;
            float ori_v0 = Vector2.SignedAngle(Vector2.right, Utilities.FlattenedDir2D(state.dir)) * Mathf.Deg2Rad;
            newState.pos.x = (Mathf.Sin(ori_v0 + s / segment.radius) - Mathf.Sin(ori_v0)) * segment.radius + state.pos.x;
            newState.pos.z = (Mathf.Cos(ori_v0) - Mathf.Cos(ori_v0 + s / segment.radius)) / segment.radius + state.pos.z;
            newState.dir   = Utilities.UnFlatten(Utilities.RotateVector(state.dir, s / segment.radius));

            // update the real world state according to the action
            float ori_r0 = Vector2.SignedAngle(Vector2.right, Utilities.FlattenedDir2D(state.dirReal)) * Mathf.Deg2Rad;

            if (a.type == ActionType.CURVATURE)
            {
                float kr = 1 / segment.radius + a.gain; // the compound curvature gain 1/r + rou(c)
                // The new real position depends on user's real orientation
                newState.posReal.x = (Mathf.Sin(ori_r0 + kr * s) - Mathf.Sin(ori_r0)) / kr + state.posReal.x;
                newState.posReal.z = (Mathf.Cos(ori_r0) - Mathf.Cos(ori_r0 + kr * s)) / kr + state.posReal.z;
                newState.dirReal   = Utilities.UnFlatten(Utilities.RotateVector(state.dirReal, s * kr));
            }
            else if (a.type == ActionType.ZERO)
            {
                newState.posReal.x = (Mathf.Sin(ori_r0 + s / segment.radius) - Mathf.Sin(ori_r0)) * segment.radius + state.posReal.x;
                newState.posReal.z = (Mathf.Cos(ori_r0) - Mathf.Cos(ori_r0 + s / segment.radius)) / segment.radius + state.posReal.z;
                newState.dirReal   = Utilities.UnFlatten(Utilities.RotateVector(state.dirReal, s / segment.radius));
            }
            else if (a.type == ActionType.RESET)
            {
                ori_r0             = Vector2.SignedAngle(Vector2.right, Utilities.FlattenedDir2D(-state.dirReal)) * Mathf.Deg2Rad;
                newState.posReal.x = (Mathf.Sin(ori_r0 + s / segment.radius) - Mathf.Sin(ori_r0)) * segment.radius + state.posReal.x;
                newState.posReal.z = (Mathf.Cos(ori_r0) - Mathf.Cos(ori_r0 + s / segment.radius)) / segment.radius + state.posReal.z;
                newState.dirReal   = Utilities.UnFlatten(Utilities.RotateVector(-state.dirReal, s / segment.radius));
            }
        }
        else if (seg is RotationSegment)
        {
            RotationSegment segment = (RotationSegment)seg;

            // update virtual position and direction
            newState.pos = state.pos;
            float rotatedAngle = this.redirectionManager.angularSpeedReal * this.stageDuration * Mathf.Sign(segment.angle);
            newState.dir = Utilities.RotateVector(state.dir, rotatedAngle);

            if (a.type == ActionType.ROTATION)
            {
                newState.posReal = state.posReal;
                rotatedAngle     = rotatedAngle * a.gain;
                newState.dirReal = Utilities.RotateVector(state.dirReal, rotatedAngle);
            }
            else if (a.type == ActionType.ZERO)
            {
                newState.posReal = state.posReal;
                newState.dirReal = Utilities.RotateVector(state.dirReal, rotatedAngle);
            }
        }

        return(newState);
    }
예제 #2
0
        public void TestGenericShift()
        {
            // regular work week with holidays and breaks
            schedule = new WorkSchedule("Regular 40 hour work week", "9 to 5");

            // holidays
            NonWorkingPeriod memorialDay = schedule.CreateNonWorkingPeriod("MEMORIAL DAY", "Memorial day", new LocalDateTime(2016, 5, 30, 0, 0, 0),
                                                                           Duration.FromHours(24));

            schedule.CreateNonWorkingPeriod("INDEPENDENCE DAY", "Independence day", new LocalDateTime(2016, 7, 4, 0, 0, 0),
                                            Duration.FromHours(24));
            schedule.CreateNonWorkingPeriod("LABOR DAY", "Labor day", new LocalDateTime(2016, 9, 5, 0, 0, 0),
                                            Duration.FromHours(24));
            schedule.CreateNonWorkingPeriod("THANKSGIVING", "Thanksgiving day and day after",
                                            new LocalDateTime(2016, 11, 24, 0, 0, 0), Duration.FromHours(48));
            schedule.CreateNonWorkingPeriod("CHRISTMAS SHUTDOWN", "Christmas week scheduled maintenance",
                                            new LocalDateTime(2016, 12, 25, 0, 30, 0), Duration.FromHours(168));

            // each shift duration
            Duration  shiftDuration = Duration.FromHours(8);
            LocalTime shift1Start   = new LocalTime(7, 0, 0);
            LocalTime shift2Start   = new LocalTime(15, 0, 0);

            // shift 1
            Shift shift1 = schedule.CreateShift("Shift1", "Shift #1", shift1Start, shiftDuration);

            // breaks
            shift1.CreateBreak("10AM", "10 am break", new LocalTime(10, 0, 0), Duration.FromMinutes(15));
            shift1.CreateBreak("LUNCH", "lunch", new LocalTime(12, 0, 0), Duration.FromHours(1));
            shift1.CreateBreak("2PM", "2 pm break", new LocalTime(14, 0, 0), Duration.FromMinutes(15));

            // shift 2
            Shift shift2 = schedule.CreateShift("Shift2", "Shift #2", shift2Start, shiftDuration);

            // shift 1, 5 days ON, 2 OFF
            Rotation rotation1 = new Rotation("Shift1", "Shift1");

            rotation1.AddSegment(shift1, 5, 2);

            // shift 2, 5 days ON, 2 OFF
            Rotation rotation2 = new Rotation("Shift2", "Shift2");

            rotation2.AddSegment(shift2, 5, 2);

            LocalDate startRotation = new LocalDate(2016, 1, 1);
            Team      team1         = schedule.CreateTeam("Team1", "Team #1", rotation1, startRotation);
            Team      team2         = schedule.CreateTeam("Team2", "Team #2", rotation2, startRotation);

            // same day
            LocalDateTime from = startRotation.PlusDays(7).At(shift1Start);
            LocalDateTime to;

            Duration totalWorking = Duration.Zero;

            // 21 days, team1
            Duration d = Duration.Zero;

            for (int i = 0; i < 21; i++)
            {
                to           = from.PlusDays(i);
                totalWorking = team1.CalculateWorkingTime(from, to);
                int dir = team1.GetDayInRotation(to.Date);

                Assert.IsTrue(totalWorking.Equals(d));

                TimePeriod period = rotation1.GetPeriods()[dir - 1];
                if (period is Shift)
                {
                    d = d.Plus(shiftDuration);
                }
            }
            Duration totalSchedule = totalWorking;

            // 21 days, team2
            from = startRotation.PlusDays(7).At(shift2Start);
            d    = Duration.Zero;

            for (int i = 0; i < 21; i++)
            {
                to           = from.PlusDays(i);
                totalWorking = team2.CalculateWorkingTime(from, to);
                int dir = team2.GetDayInRotation(to.Date);

                Assert.IsTrue(totalWorking.Equals(d));

                if (rotation1.GetPeriods()[dir - 1] is Shift)
                {
                    d = d.Plus(shiftDuration);
                }
            }
            totalSchedule = totalSchedule.Plus(totalWorking);

            Duration scheduleDuration   = schedule.CalculateWorkingTime(from, from.PlusDays(21));
            Duration nonWorkingDuration = schedule.CalculateNonWorkingTime(from, from.PlusDays(21));

            Assert.IsTrue(scheduleDuration.Plus(nonWorkingDuration).Equals(totalSchedule));

            // breaks
            Duration allBreaks = Duration.FromMinutes(90);

            Assert.IsTrue(shift1.CalculateBreakTime().Equals(allBreaks));

            // misc
            WorkSchedule schedule2 = new WorkSchedule();

            Shift shift3 = new Shift();

            shift3.Name = "Shift3";
            Assert.IsTrue(shift3.WorkSchedule == null);
            Assert.IsTrue(shift3.CompareTo(shift3) == 0);

            Team team3 = new Team();

            Assert.IsTrue(team3.WorkSchedule == null);

            RotationSegment segment = new RotationSegment();

            segment.Sequence      = 1;
            segment.StartingShift = shift2;
            segment.DaysOn        = 5;
            segment.DaysOff       = 2;
            Assert.IsTrue(segment.Rotation == null);

            Rotation rotation3 = new Rotation();

            rotation3.Name = "Rotation3";
            Assert.IsTrue(rotation3.CompareTo(rotation3) == 0);
            Assert.IsTrue(rotation3.RotationSegments.Count == 0);

            NonWorkingPeriod nwp = new NonWorkingPeriod();

            Assert.IsTrue(nwp.WorkSchedule == null);


            Assert.IsTrue(team1.WorkSchedule.Equals(schedule));


            Assert.IsTrue(!team1.IsDayOff(startRotation));


            Assert.IsTrue(team1.CompareTo(team1) == 0);
            team3.Rotation = rotation1;


            Assert.IsTrue(!memorialDay.IsInPeriod(new LocalDate(2016, 1, 1)));

            runBaseTest(schedule, Duration.FromHours(40), Duration.FromDays(7), new LocalDate(2016, 1, 1));
        }
예제 #3
0
 public RotationCommand(Orientation rotationAxis, RotationSegment segment, int turnovers = 1)
 {
     RotationAxis = rotationAxis;
     Segment      = segment;
     Turnovers    = turnovers % 4;
 }