12#ifndef PATH_TRACER_2D_HPP
13#define PATH_TRACER_2D_HPP
15#include "../GeospatialOperations.hpp"
19#include <matplot/matplot.h>
65 m_mtRoverPathPlot = matplot::figure(
true);
66 m_mtRoverPathAxes = m_mtRoverPathPlot->current_axes();
67 m_szPlotTitle = szPlotTitle;
70 std::string szPlotSavePath = logging::g_szLoggingOutputPath +
"/path_plots/" + m_szPlotTitle;
71 m_szCurrentPlotSavePath = logging::g_szLoggingOutputPath +
"/path_plots/CurrentPlot.png";
73 while (std::filesystem::exists(szPlotSavePath + std::to_string(nFileNum) +
".png"))
78 szPlotSavePath = szPlotSavePath + std::to_string(nFileNum);
80 if (!std::filesystem::exists(logging::g_szLoggingOutputPath +
"/path_plots"))
82 std::filesystem::create_directory(logging::g_szLoggingOutputPath +
"/path_plots");
86 m_mtRoverPathPlot->backend()->output(szPlotSavePath +
".png");
89 if (m_szPlotTitle.empty())
92 LOG_WARNING(logging::g_qSharedLogger,
"Plot title is empty. Setting title to default.");
93 m_szPlotTitle =
"RoverPath";
97 m_mtRoverPathPlot->title(m_szPlotTitle);
98 m_mtRoverPathAxes->xlabel(
"Easting");
99 m_mtRoverPathAxes->ylabel(
"Northing");
166 bool CreatePathLayer(
const std::string& szLayerName,
const std::string& szStyleString =
"-o")
169 if (m_umPathMap.find(szLayerName) != m_umPathMap.end())
172 LOG_WARNING(logging::g_qSharedLogger,
"Layer already exists. Cannot create layer.");
177 m_umPathMap[szLayerName] = std::vector<std::pair<double, double>>();
178 m_umPathLineStyleMap[szLayerName] = szStyleString;
179 m_umLastPlotUpdateTimeMap[szLayerName] = std::chrono::system_clock::now();
205 bool CreateDotLayer(
const std::string& szLayerName,
const std::string& szColorString =
"blue",
const bool bFillMarkerFace =
true)
208 if (m_umDotMap.find(szLayerName) != m_umDotMap.end())
211 LOG_WARNING(logging::g_qSharedLogger,
"Layer already exists. Cannot create layer.");
216 m_umDotMap[szLayerName] = std::vector<std::tuple<double, double, double>>();
217 m_umDotLineStyleMap[szLayerName] = std::make_pair(szColorString, bFillMarkerFace);
218 m_umLastDotUpdateTimeMap[szLayerName] = std::chrono::system_clock::now();
236 if (m_umPathMap.find(szLayerName) == m_umPathMap.end() && m_umDotMap.find(szLayerName) == m_umDotMap.end())
239 LOG_WARNING(logging::g_qSharedLogger,
"Layer does not exist. Cannot delete layer.");
244 if (m_umPathMap.find(szLayerName) != m_umPathMap.end())
246 m_umPathMap.erase(szLayerName);
247 m_umPathLineStyleMap.erase(szLayerName);
248 m_umLastPlotUpdateTimeMap.erase(szLayerName);
250 if (m_umDotMap.find(szLayerName) != m_umDotMap.end())
252 m_umDotMap.erase(szLayerName);
253 m_umDotLineStyleMap.erase(szLayerName);
254 m_umLastDotUpdateTimeMap.erase(szLayerName);
273 if (m_umPathMap.find(szLayerName) == m_umPathMap.end() && m_umDotMap.find(szLayerName) == m_umDotMap.end())
276 LOG_WARNING(logging::g_qSharedLogger,
"Layer does not exist. Cannot clear layer.");
281 if (m_umPathMap.find(szLayerName) != m_umPathMap.end())
283 m_umPathMap[szLayerName].clear();
285 if (m_umDotMap.find(szLayerName) != m_umDotMap.end())
287 m_umDotMap[szLayerName].clear();
343 m_umPathMap[szLayerName].emplace_back(stCoordinate.dEasting, stCoordinate.dNorthing);
374 m_umPathMap[szLayerName].emplace_back(stUTMCoordinate.dEasting, stUTMCoordinate.dNorthing);
393 void AddPathPoints(
const std::vector<geoops::Waypoint>& stWaypoints,
const std::string& szLayerName,
const uint unMaxUpdatesPerSecond = 1)
405 m_umPathMap[szLayerName].emplace_back(stWaypoint.GetUTMCoordinate().dEasting, stWaypoint.GetUTMCoordinate().dNorthing);
425 void AddPathPoints(
const std::vector<geoops::UTMCoordinate>& vCoordinates,
const std::string& szLayerName,
const uint unMaxUpdatesPerSecond = 1)
437 m_umPathMap[szLayerName].emplace_back(stCoordinate.dEasting, stCoordinate.dNorthing);
457 void AddPathPoints(
const std::vector<geoops::GPSCoordinate>& vCoordinates,
const std::string& szLayerName,
const uint unMaxUpdatesPerSecond = 1)
470 m_umPathMap[szLayerName].emplace_back(stUTMCoordinate.dEasting, stUTMCoordinate.dNorthing);
501 if (stWaypoint.dRadius <= 0)
537 m_umDotMap[szLayerName].emplace_back(stCoordinate.dEasting, stCoordinate.dNorthing, dDotRadius);
569 m_umDotMap[szLayerName].emplace_back(stUTMCoordinate.dEasting, stUTMCoordinate.dNorthing, dDotRadius);
590 void AddDots(
const std::vector<geoops::Waypoint>& stWaypoints,
const std::string& szLayerName,
const uint unMaxUpdatesPerSecond = 1)
603 if (stWaypoint.dRadius <= 0)
605 m_umDotMap[szLayerName].emplace_back(stWaypoint.GetUTMCoordinate().dEasting, stWaypoint.GetUTMCoordinate().dNorthing, 5);
609 m_umDotMap[szLayerName].emplace_back(stWaypoint.GetUTMCoordinate().dEasting, stWaypoint.GetUTMCoordinate().dNorthing, stWaypoint.dRadius);
631 void AddDots(
const std::vector<geoops::UTMCoordinate>& vCoordinates,
632 const std::string& szLayerName,
633 const uint unMaxUpdatesPerSecond = 1,
634 const double dDotRadius = 5)
646 m_umDotMap[szLayerName].emplace_back(stCoordinate.dEasting, stCoordinate.dNorthing, dDotRadius);
667 void AddDots(
const std::vector<geoops::GPSCoordinate>& vCoordinates,
668 const std::string& szLayerName,
669 const uint unMaxUpdatesPerSecond = 1,
670 const double dDotRadius = 5)
683 m_umDotMap[szLayerName].emplace_back(stUTMCoordinate.dEasting, stUTMCoordinate.dNorthing, dDotRadius);
692 matplot::figure_handle m_mtRoverPathPlot;
693 matplot::axes_handle m_mtRoverPathAxes;
694 std::unordered_map<std::string, std::string> m_umPathLineStyleMap;
695 std::unordered_map<std::string, std::pair<std::string, bool>> m_umDotLineStyleMap;
696 std::unordered_map<std::string, std::chrono::system_clock::time_point> m_umLastPlotUpdateTimeMap;
697 std::unordered_map<std::string, std::chrono::system_clock::time_point> m_umLastDotUpdateTimeMap;
698 std::unordered_map<std::string, std::vector<std::pair<double, double>>> m_umPathMap;
699 std::unordered_map<std::string, std::vector<std::tuple<double, double, double>>> m_umDotMap;
700 std::string m_szPlotTitle;
701 std::string m_szCurrentPlotSavePath;
713 std::vector<std::string> vLayerNames;
716 m_mtRoverPathAxes->clear();
722 for (
const std::pair<const std::string, const std::string>& stdLayer : m_umPathLineStyleMap)
725 if (m_umPathMap[stdLayer.first].size() > 1)
728 vLayerNames.push_back(stdLayer.first);
731 std::vector<double> vEasting, vNorthing;
732 for (
const std::pair<double, double>& stCoordinate : m_umPathMap[stdLayer.first])
734 vEasting.push_back(stCoordinate.first);
735 vNorthing.push_back(stCoordinate.second);
739 m_mtRoverPathAxes->plot(vEasting, vNorthing, std::string_view(stdLayer.second));
741 m_mtRoverPathAxes->hold(
true);
749 for (
const std::pair<
const std::string,
const std::pair<std::string, bool>>& stdLayer : m_umDotLineStyleMap)
752 if (m_umDotMap[stdLayer.first].size() > 0)
755 vLayerNames.push_back(stdLayer.first);
758 std::vector<double> vEasting, vNorthing, vRadius;
759 for (
const std::tuple<double, double, double>& stCoordinate : m_umDotMap[stdLayer.first])
761 vEasting.push_back(std::get<0>(stCoordinate));
762 vNorthing.push_back(std::get<1>(stCoordinate));
763 vRadius.push_back(std::get<2>(stCoordinate));
767 matplot::line_handle mtLineHandle = m_mtRoverPathAxes->scatter(vEasting, vNorthing, vRadius);
768 mtLineHandle->color(stdLayer.second.first);
769 mtLineHandle->marker_face(stdLayer.second.second);
771 m_mtRoverPathAxes->hold(
true);
776 m_mtRoverPathAxes->legend(vLayerNames);
777 matplot::legend_handle mtLegend = m_mtRoverPathAxes->legend();
778 mtLegend->font_size(8);
779 mtLegend->num_columns(2);
781 m_mtRoverPathAxes->grid(
true);
782 m_mtRoverPathAxes->xtickangle(45);
783 m_mtRoverPathAxes->axis(matplot::square);
784 m_mtRoverPathAxes->xtickformat(
"%.0f");
785 m_mtRoverPathAxes->ytickformat(
"%.0f");
787 m_mtRoverPathAxes->hold(
false);
789 m_mtRoverPathPlot->draw();
790 m_mtRoverPathPlot->save(m_szCurrentPlotSavePath);
812 if (m_umLastPlotUpdateTimeMap.find(szLayerName) == m_umLastPlotUpdateTimeMap.end())
815 LOG_WARNING(logging::g_qSharedLogger,
"Layer does not exist. Cannot add waypoints.");
820 if (unMaxUpdatesPerSecond != 0 &&
821 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - m_umLastPlotUpdateTimeMap[szLayerName]).count() <
822 1.0 / unMaxUpdatesPerSecond)
829 m_umLastPlotUpdateTimeMap[szLayerName] = std::chrono::system_clock::now();
854 if (m_umLastDotUpdateTimeMap.find(szLayerName) == m_umLastDotUpdateTimeMap.end())
857 LOG_WARNING(logging::g_qSharedLogger,
"Layer does not exist. Cannot add waypoints.");
862 if (unMaxUpdatesPerSecond != 0 &&
863 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - m_umLastDotUpdateTimeMap[szLayerName]).count() <
864 1.0 / unMaxUpdatesPerSecond)
871 m_umLastDotUpdateTimeMap[szLayerName] = std::chrono::system_clock::now();
The PathTracer class is used to trace the path of the rover and plot the path on a 2D graph.
Definition PathTracer2D.hpp:53
bool CheckPathUpdateTime(const std::string &szLayerName, const uint unMaxUpdatesPerSecond)
Checks the unordered map of last update times for a given layer name and returns true if the time sin...
Definition PathTracer2D.hpp:809
~PathTracer()
Destroy the Path Tracer object.
Definition PathTracer2D.hpp:109
bool CreatePathLayer(const std::string &szLayerName, const std::string &szStyleString="-o")
Add a new draw layer to the plot.
Definition PathTracer2D.hpp:166
void AddPathPoints(const std::vector< geoops::Waypoint > &stWaypoints, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1)
Add a waypoint to the path and plot the path. This method has no limit to the number of waypoints tha...
Definition PathTracer2D.hpp:393
bool ClearLayer(const std::string &szLayerName)
Clear the path or dots of a layer.
Definition PathTracer2D.hpp:270
void AddDot(const geoops::UTMCoordinate &stCoordinate, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1, const double dDotRadius=5)
Add a waypoint as a dot to the path. This method has a limit to the number of waypoints that can be a...
Definition PathTracer2D.hpp:527
void AddDot(const geoops::Waypoint &stWaypoint, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1)
Add a waypoint as a dot to the path. This method has a limit to the number of waypoints that can be a...
Definition PathTracer2D.hpp:491
void UpdatePlot()
Update the plot with the new waypoints and redraw the plot.
Definition PathTracer2D.hpp:710
PathTracer(const std::string &szPlotTitle="Graph")
Construct a new Path Tracer object.
Definition PathTracer2D.hpp:62
void AddPathPoint(const geoops::UTMCoordinate &stCoordinate, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1)
Add a waypoint to the path and plot the path. This method has a limit to the number of waypoints that...
Definition PathTracer2D.hpp:333
void AddDots(const std::vector< geoops::UTMCoordinate > &vCoordinates, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1, const double dDotRadius=5)
Add a waypoint as a dot to the path. This method has no limit to the number of waypoints that can be ...
Definition PathTracer2D.hpp:631
void AddPathPoints(const std::vector< geoops::GPSCoordinate > &vCoordinates, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1)
Add a waypoint to the path and plot the path. This method has no limit to the number of waypoints tha...
Definition PathTracer2D.hpp:457
void AddDots(const std::vector< geoops::Waypoint > &stWaypoints, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1)
Add a waypoint as a dot to the path. This method has no limit to the number of waypoints that can be ...
Definition PathTracer2D.hpp:590
bool CheckDotUpdateTime(const std::string &szLayerName, const uint unMaxUpdatesPerSecond)
Checks the unordered map of last update times for a given layer name and returns true if the time sin...
Definition PathTracer2D.hpp:851
void AddPathPoint(const geoops::GPSCoordinate &stCoordinate, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1)
Add a waypoint to the path and plot the path. This method has a limit to the number of waypoints that...
Definition PathTracer2D.hpp:361
void AddDot(const geoops::GPSCoordinate &stCoordinate, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1, const double dDotRadius=5)
Add a waypoint as a dot to the path. This method has a limit to the number of waypoints that can be a...
Definition PathTracer2D.hpp:556
bool DeleteLayer(const std::string &szLayerName)
Delete a draw layer from the plot.
Definition PathTracer2D.hpp:233
void AddDots(const std::vector< geoops::GPSCoordinate > &vCoordinates, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1, const double dDotRadius=5)
Add a waypoint as a dot to the path. This method has no limit to the number of waypoints that can be ...
Definition PathTracer2D.hpp:667
void AddPathPoints(const std::vector< geoops::UTMCoordinate > &vCoordinates, const std::string &szLayerName, const uint unMaxUpdatesPerSecond=1)
Add a waypoint to the path and plot the path. This method has no limit to the number of waypoints tha...
Definition PathTracer2D.hpp:425
void AddPathPoint(const geoops::Waypoint &stWaypoint, const std::string &szLayerName, const uint nMaxWaypointsPerSecond=1)
Add a waypoint to the path and plot the path. This method has a limit to the number of waypoints that...
Definition PathTracer2D.hpp:305
bool CreateDotLayer(const std::string &szLayerName, const std::string &szColorString="blue", const bool bFillMarkerFace=true)
Add a new draw layer to the plot.
Definition PathTracer2D.hpp:205
UTMCoordinate ConvertGPSToUTM(const GPSCoordinate &stGPSCoord)
Given a GPS coordinate, convert to UTM and create a new UTMCoordinate object.
Definition GeospatialOperations.hpp:302
Namespace containing all global type/structs that will be used project wide for logging.
Definition AutonomyLogging.cpp:34
This struct stores/contains information about a GPS data.
Definition GeospatialOperations.hpp:99
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:195
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:392
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:477