Beispiel #1
0
        /// <summary>
        /// calculate vmc and vmg values if possible with current state
        /// </summary>
        /// <param name="state">current race state</param>
        public void Calculate(State state)
        {
            if (state.Location != null && state.TargetMark != null && state.TargetMark.Location != null && state.Course is CourseByMarks)
            {
                double meters = CoordinatePoint.HaversineDistance(state.Location, state.TargetMark.Location);
                if (meters < _distanceCutoff)//if the reported distance is more than this threshold, it's probably garbage data
                {
                    state.StateValues[StateValue.DistanceToTargetMarkInYards] = meters * MetersToYards;
                }

                var calculation = new MarkCalculation();
                calculation.Location = state.Location;
                calculation.Time     = state.BestTime;

                _previousCalculations.Add(calculation);
                while (_previousCalculations.Count > _previousCalculationCount)
                {
                    _previousCalculations.RemoveAt(0);
                }

                if (_previousCalculations.Count > 1)
                {
                    var previous = _previousCalculations[_previousCalculations.Count - 2];
                    var duration = calculation.Time - previous.Time;

                    //calculate vmc
                    var previousDistanceMeters = CoordinatePoint.HaversineDistance(previous.Location,
                                                                                   state.TargetMark.Location);
                    var distanceDelta      = previousDistanceMeters - meters;
                    var vmcMetersPerSecond = distanceDelta / duration.TotalSeconds;
                    var vmcKnots           = MetersPerSecondToKnots * vmcMetersPerSecond;
                    calculation.VelocityMadeGoodOnCourse = vmcKnots;
                    state.StateValues[StateValue.VelocityMadeGoodOnCourse] = vmcKnots;                    //_previousCalculations.Average(x => x.VelocityMadeGoodOnCourse);

                    state.StateValues[StateValue.VelocityMadeGoodOnCoursePercent] = vmcKnots / state.StateValues[StateValue.SpeedInKnots] * 100;

                    //TODO: calculate vmg
                    if (state.PreviousMark != null && state.StateValues.ContainsKey(StateValue.SpeedInKnots))
                    {
                        calculation.VelocityMadeGood = VelocityMadeGood(state.TargetMark, state.PreviousMark,
                                                                        calculation.Location, previous.Location, state.StateValues[StateValue.SpeedInKnots]);

                        state.StateValues[StateValue.VelocityMadeGoodPercent] = calculation.VelocityMadeGood.Value / state.StateValues[StateValue.SpeedInKnots] * 100;

                        var relativeAngle = RelativeAngleToCourse(state.TargetMark, state.PreviousMark, calculation.Location, previous.Location);
                        state.StateValues[StateValue.CourseOverGroundRelativeToCourse] = AngleUtilities.RadiansToDegrees(relativeAngle);
                    }
                }
            }
            else if (state.Course is CourseByAngle && state.StateValues.ContainsKey(StateValue.CourseOverGroundDirection) && state.StateValues.ContainsKey(StateValue.SpeedInKnots))
            {
                state.StateValues[StateValue.VelocityMadeGood]        = VelocityMadeGood((state.Course as CourseByAngle).CourseAngle, state.StateValues[StateValue.CourseOverGroundDirection], state.StateValues[StateValue.SpeedInKnots]);
                state.StateValues[StateValue.VelocityMadeGoodPercent] = state.StateValues[StateValue.VelocityMadeGood] / state.StateValues[StateValue.SpeedInKnots] * 100;

                var relativeAngle = AngleUtilities.AngleDifference(AngleUtilities.DegreestoRadians((state.Course as CourseByAngle).CourseAngle), AngleUtilities.DegreestoRadians(state.StateValues[StateValue.CourseOverGroundDirection]));
                state.StateValues[StateValue.CourseOverGroundRelativeToCourse] = AngleUtilities.RadiansToDegrees(relativeAngle);
            }
        }
Beispiel #2
0
        /// <inheritdoc />
        public void ProcessMarkRoundings()
        {
            if (_state.Course is CourseByMarks)
            {
                var course = _state.Course as CourseByMarks;
                //if the race just started, set the line
                if (DetectRaceStart())
                {
                    var line = course.Marks.FirstOrDefault(x => x.MarkType == MarkType.Line);
                    if (line == null)
                    {
                        line = new Mark()
                        {
                            MarkType      = MarkType.Line,
                            CaptureMethod = MarkCaptureMethod.Location,
                            Location      = _state.Location
                        };
                        course.Marks.Insert(0, line);
                    }
                    _state.PreviousMark = line;

                    if (course.Marks.Any(x => x.MarkType == MarkType.Windward))
                    {
                        State.TargetMark = course.Marks.Where(x => x.MarkType == MarkType.Windward).Last();
                    }
                    else
                    {
                        State.TargetMark = null;
                    }
                }
                else if (_state.StartTime.HasValue && _state.BestTime > _state.StartTime && _state.TargetMark != null &&
                         _state.TargetMark.Location != null && _autoRoundMarkDistanceMeters.HasValue)
                {
                    var nextMark = GetNextMark(_state.TargetMark);
                    if (nextMark != null)
                    {
                        var distanceToMark = CoordinatePoint.HaversineDistance(_state.Location, _state.TargetMark.Location);
                        if (distanceToMark < _autoRoundMarkDistanceMeters)
                        {
                            _logger.Info("Distance to " + _state.TargetMark.MarkType + " is " + string.Format("{0:0.0}m") +
                                         ", advancing to next mark");
                            NextMark();
                        }
                    }
                }
            }
            else
            {
                DetectRaceStart();
            }
        }