9#ifndef _DOVES_LAP_TIMER_H
10#define _DOVES_LAP_TIMER_H
12#include "ArxTypeTraits.h"
15#define CROSSING_LINE_SIDE_A -1
16#define CROSSING_LINE_SIDE_EXACT 0
17#define CROSSING_LINE_SIDE_B 1
20#define COURSE_DETECT_SPEED_THRESHOLD_MPH 20
21#define COURSE_DETECT_WAYPOINT_PROXIMITY_METERS 10.0
22#define COURSE_DETECT_MIN_DISTANCE_METERS 200.0
23#define COURSE_DETECT_DISTANCE_TOLERANCE_PCT 0.25
24#define COURSE_DETECT_MAX_REJECTIONS 3
25#define METERS_TO_FEET 3.28084
28#define WAYPOINT_LAP_MIN_DISTANCE_METERS 100.0
29#define WAYPOINT_LAP_PROXIMITY_METERS 30.0
30#define WAYPOINT_LAP_BUFFER_SIZE 50
38#define DETECT_STATE_IDLE 0
39#define DETECT_STATE_WAITING_FOR_SPEED 1
40#define DETECT_STATE_WAYPOINT_SET 2
41#define DETECT_STATE_CANDIDATES_READY 3
42#define DETECT_STATE_DETECTED 4
88 DovesLapTimer(
double crossingThresholdMeters = 7, Stream *debugSerial = NULL);
101 int loop(
double currentLat,
double currentLng,
float currentAltitudeMeters,
float currentSpeedKnots);
116 bool isObtuseTriangle(
double lat1,
double lon1,
double lat2,
double lon2,
double lat3,
double lon3);
148 int pointOnSideOfLine(
double driverLat,
double driverLng,
double pointALat,
double pointALng,
double pointBLat,
double pointBLng);
166 double pointLineSegmentDistance(
double pointX,
double pointY,
double startX,
double startY,
double endX,
double endY);
182 double haversine(
double lat1,
double lon1,
double lat2,
double lon2);
198 double haversine3D(
double prevLat,
double prevLng,
double prevAlt,
double currentLat,
double currentLng,
double currentAlt);
214 void setStartFinishLine(
double pointALat,
double pointALng,
double pointBLat,
double pointBLng);
223 void setSector2Line(
double pointALat,
double pointALng,
double pointBLat,
double pointBLng);
232 void setSector3Line(
double pointALat,
double pointALng,
double pointBLat,
double pointBLng);
448 template<
typename... Args>
449 void debug_print(Args&&... args) {
451 _serial->print(std::forward<Args>(args)...);
454 template<
typename... Args>
455 void debug_println(Args&&... args) {
457 _serial->println(std::forward<Args>(args)...);
474 bool checkStartFinish(
double currentLat,
double currentLng);
488 bool checkSectorLine(
double currentLat,
double currentLng,
double pointALat,
double pointALng,
double pointBLat,
double pointBLng,
bool& crossingFlag,
int sectorNumber);
504 double currentLat,
double currentLng,
505 double pointALat,
double pointALng,
506 double pointBLat,
double pointBLng,
509 double& outLat,
double& outLng,
510 unsigned long& outTime,
511 double& outOdometer);
518 void handleLineCrossing(
unsigned long crossingTime,
int sectorNumber);
522 void updateBestSectors();
533 double catmullRom(
double p0,
double p1,
double p2,
double p3,
double t);
543 double interpolateWeight(
double distA,
double distB,
float speedA,
float speedB);
560 void interpolateCrossingPoint(
double& crossingLat,
double& crossingLng,
unsigned long& crossingTime,
double& crossingOdometer,
double pointALat,
double pointALng,
double pointBLat,
double pointBLng);
565 unsigned long millisecondsSinceMidnight = 0;
567 double crossingThresholdMeters;
568 bool raceStarted =
false;
569 bool crossing =
false;
570 bool forceLinear =
true;
571 unsigned long currentLapStartTime = 0;
572 unsigned long lastLapTime = 0;
573 unsigned long bestLapTime = 0;
574 float currentLapOdometerStart = 0.0;
575 float lastLapDistance = 0.0;
576 float bestLapDistance = 0.0;
577 float currentSpeedkmh = 0.0;
578 int bestLapNumber = 0;
582 int currentSector = 0;
583 unsigned long currentSectorStartTime = 0;
584 bool crossingSector2 =
false;
585 bool crossingSector3 =
false;
588 unsigned long currentLapSector1Time = 0;
589 unsigned long currentLapSector2Time = 0;
590 unsigned long currentLapSector3Time = 0;
593 unsigned long bestSector1Time = 0;
594 unsigned long bestSector2Time = 0;
595 unsigned long bestSector3Time = 0;
598 int bestSector1LapNumber = 0;
599 int bestSector2LapNumber = 0;
600 int bestSector3LapNumber = 0;
602 float totalDistanceTraveled = 0;
603 float positionPrevAlt = 0.00;
604 double positionPrevLat = 0.00;
605 double positionPrevLng = 0.00;
606 bool firstPositionReceived =
false;
609 double prevFixLat = 0;
610 double prevFixLng = 0;
611 unsigned long prevFixTime = 0;
612 float prevFixOdometer = 0;
613 float prevFixSpeedKmh = 0;
614 bool hasPrevFix =
false;
616 double startFinishPointALat;
617 double startFinishPointALng;
618 double startFinishPointBLat;
619 double startFinishPointBLng;
622 double sector2PointALat;
623 double sector2PointALng;
624 double sector2PointBLat;
625 double sector2PointBLng;
628 double sector3PointALat;
629 double sector3PointALng;
630 double sector3PointBLat;
631 double sector3PointBLng;
634 bool sector2LineConfigured =
false;
635 bool sector3LineConfigured =
false;
638 static constexpr double radiusEarth = 6371.0 * 1000;
644 #if defined(RAMEND) && defined(RAMSTART)
645 #if ((RAMEND - RAMSTART) > 3000)
646 static const int crossingPointBufferSize = 100;
648 static const int crossingPointBufferSize = 25;
651 static const int crossingPointBufferSize = 100;
655 int crossingPointBufferIndex = 0;
656 bool crossingPointBufferFull =
false;
double TRITYPE
Definition DovesLapTimer.h:13
#define DIR_REVERSE
Definition DovesLapTimer.h:35
#define DIR_UNKNOWN
Definition DovesLapTimer.h:33
LineDetectResult
Definition DovesLapTimer.h:48
@ LINE_DETECT_IN_ZONE
Definition DovesLapTimer.h:50
@ LINE_DETECT_NONE
Definition DovesLapTimer.h:49
@ LINE_DETECT_COMPLETED
Definition DovesLapTimer.h:51
const double crossingPointBLat
Definition basic_oled_example.ino:21
const double crossingPointALat
Definition basic_oled_example.ino:19
void loop()
Definition basic_oled_example.ino:116
Definition DovesLapTimer.h:86
unsigned long getBestSector2Time() const
Gets the best sector 2 time.
Definition DovesLapTimer.cpp:849
unsigned long getLastLapTime() const
Gets the last lap time.
Definition DovesLapTimer.cpp:792
unsigned long getCurrentLapStartTime() const
Gets the current lap start time.
Definition DovesLapTimer.cpp:786
double pointLineSegmentDistance(double pointX, double pointY, double startX, double startY, double endX, double endY)
Calculate the shortest distance between a point and a line segment.
Definition DovesLapTimer.cpp:336
void updateCurrentTime(unsigned long currentTimeMilliseconds)
Updates the current GPS time since midnight.
Definition DovesLapTimer.cpp:771
unsigned long getOptimalLapTime() const
Gets the optimal lap time calculated from best sector times.
Definition DovesLapTimer.cpp:864
float getTotalDistanceTraveled() const
Gets the total distance traveled.
Definition DovesLapTimer.cpp:810
void forceLinearInterpolation()
forces linear interpolation when checking crossing line
Definition DovesLapTimer.cpp:774
float getCurrentSpeedMph() const
Gets the current speed in miles per hour.
Definition DovesLapTimer.cpp:840
float getLastLapDistance() const
Gets the last lap distance.
Definition DovesLapTimer.cpp:804
int getBestSector1LapNumber() const
Gets the lap number that achieved the best sector 1 time.
Definition DovesLapTimer.cpp:871
unsigned long getCurrentLapTime() const
Gets the current lap time.
Definition DovesLapTimer.cpp:789
float getPaceDifference() const
Calculates the pace difference between the current lap and the best lap in milliseconds.
Definition DovesLapTimer.cpp:819
bool getRaceStarted() const
Gets the race started status (passed the line one time).
Definition DovesLapTimer.cpp:780
int getDirection() const
Gets the detected driving direction.
Definition DovesLapTimer.cpp:889
unsigned long getCurrentLapSector2Time() const
Gets the current lap sector 2 time.
Definition DovesLapTimer.cpp:858
void reset()
Reset all parameters back to 0.
Definition DovesLapTimer.cpp:698
void setSector2Line(double pointALat, double pointALng, double pointBLat, double pointBLng)
Sets the sector 2 line using two points (A and B).
Definition DovesLapTimer.cpp:757
int getBestSector3LapNumber() const
Gets the lap number that achieved the best sector 3 time.
Definition DovesLapTimer.cpp:877
bool isObtuseTriangle(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3)
Checks if the triangle formed by the given coordinates is an obtuse triangle.
Definition DovesLapTimer.cpp:288
bool insideLineThreshold(double driverLat, double driverLon, double crossingPointALat, double crossingPointALon, double crossingPointBLat, double crossingPointBLon)
Check if a driver is within a threshold distance of the line formed by the two crossing points.
Definition DovesLapTimer.cpp:262
bool getCrossing() const
Gets the crossing status.
Definition DovesLapTimer.cpp:783
float getCurrentSpeedKmh() const
Gets the current speed in kilometers per hour.
Definition DovesLapTimer.cpp:837
int pointOnSideOfLine(double driverLat, double driverLng, double pointALat, double pointALng, double pointBLat, double pointBLng)
Determines which side of a line a driver is on.
Definition DovesLapTimer.cpp:318
unsigned long getBestSector1Time() const
Gets the best sector 1 time.
Definition DovesLapTimer.cpp:846
void setSector3Line(double pointALat, double pointALng, double pointBLat, double pointBLng)
Sets the sector 3 line using two points (A and B).
Definition DovesLapTimer.cpp:764
int getBestLapNumber() const
Gets the best lap number.
Definition DovesLapTimer.cpp:813
unsigned long getBestSector3Time() const
Gets the best sector 3 time.
Definition DovesLapTimer.cpp:852
float getCurrentLapOdometerStart() const
Gets the current lap odometer start.
Definition DovesLapTimer.cpp:798
unsigned long getCurrentLapSector1Time() const
Gets the current lap sector 1 time.
Definition DovesLapTimer.cpp:855
void setStartFinishLine(double pointALat, double pointALng, double pointBLat, double pointBLng)
Sets the start/finish line using two points (A and B).
Definition DovesLapTimer.cpp:751
bool isDirectionResolved() const
Checks if the driving direction has been resolved.
Definition DovesLapTimer.cpp:892
unsigned long getBestLapTime() const
Gets the best lap time.
Definition DovesLapTimer.cpp:795
void forceCatmullRomInterpolation()
Forces Catmull-Rom spline interpolation when checking crossing line.
Definition DovesLapTimer.cpp:777
float getBestLapDistance() const
Gets the best lap distance.
Definition DovesLapTimer.cpp:807
float getCurrentLapDistance() const
Gets the current lap distance.
Definition DovesLapTimer.cpp:801
double haversine3D(double prevLat, double prevLng, double prevAlt, double currentLat, double currentLng, double currentAlt)
Calculates the distance between two GPS points, including altitude difference.
Definition DovesLapTimer.cpp:371
unsigned long getCurrentLapSector3Time() const
Gets the current lap sector 3 time.
Definition DovesLapTimer.cpp:861
bool areSectorLinesConfigured() const
Checks if sector lines are configured.
Definition DovesLapTimer.cpp:883
int getLaps() const
Gets the total number of laps completed.
Definition DovesLapTimer.cpp:816
int getBestSector2LapNumber() const
Gets the lap number that achieved the best sector 2 time.
Definition DovesLapTimer.cpp:874
double haversine(double lat1, double lon1, double lat2, double lon2)
Calculates the great-circle distance between two points on the Earth's surface using the Haversine fo...
Definition DovesLapTimer.cpp:367
int getCurrentSector() const
Gets the current sector the driver is in.
Definition DovesLapTimer.cpp:880
Definition DovesLapTimer.h:63
DirectionDetector()
Definition DovesLapTimer.h:72
void reset()
Definition DovesLapTimer.h:75
unsigned long lapS2CrossingTime
Definition DovesLapTimer.h:69
void onLineCrossing(int sectorNumber, unsigned long crossingTime)
Definition DovesLapTimer.cpp:524
bool isReverse() const
Definition DovesLapTimer.h:82
bool raceSeen
Definition DovesLapTimer.h:65
unsigned long lapS3CrossingTime
Definition DovesLapTimer.h:70
int direction
Definition DovesLapTimer.h:64
bool isResolved() const
Definition DovesLapTimer.h:83
Definition DovesLapTimer.h:55
double lng
Definition DovesLapTimer.h:57
float speedKmh
Definition DovesLapTimer.h:60
unsigned long time
Definition DovesLapTimer.h:58
float odometer
Definition DovesLapTimer.h:59
double lat
Definition DovesLapTimer.h:56