Communication Library for Autonomous Systems v1.0
Reliable and secure communication library for autonomous vehicle systems
Loading...
Searching...
No Matches
location_service.h
Go to the documentation of this file.
1#ifndef LOCATION_SERVICE_H
2#define LOCATION_SERVICE_H
3
4// Enhanced LocationService that reads trajectory data from CSV files
5// as described in IdeaP5Enzo.md. Falls back to manual coordinates if no trajectory file is loaded.
6
7#include <mutex>
8#include <vector>
9#include <string>
10#include <fstream>
11#include <sstream>
12#include <chrono>
13#include <algorithm>
14
16 double x;
17 double y;
18 double radius;
19};
20
22 std::chrono::milliseconds timestamp;
23 double x;
24 double y;
25
26 TrajectoryPoint(long long ts_ms, double x_coord, double y_coord) : timestamp(ts_ms), x(x_coord), y(y_coord) {}
27};
28
30 public:
31
32 // Load trajectory from CSV file for time-based positioning
33 static bool loadTrajectory(const std::string& csv_filename);
34
35 // Get coordinates at specific timestamp (reads from trajectory if loaded)
36 static void getCoordinates(double& x, double& y, std::chrono::milliseconds timestamp = std::chrono::milliseconds::zero());
37
38 // Backward compatibility: get coordinates at current system time
39 static void getCurrentCoordinates(double& x, double& y);
40
41 // Set manual coordinates (used when no trajectory is loaded)
42 static void setCurrentCoordinates(double x, double y);
43
44 // Check if trajectory is loaded
45 static bool hasTrajectory();
46
47 // Get trajectory duration
48 static std::chrono::milliseconds getTrajectoryDuration();
49
50 private:
51
52 static bool loadTrajectoryFromCSV(const std::string& filename);
53
54 static void getCoordinatesAtTime(std::chrono::milliseconds timestamp, double& x, double& y);
55
56 private:
57 static std::vector<TrajectoryPoint> _trajectory;
58 static double _manual_x, _manual_y;
59 static std::mutex _mutex;
60 static std::chrono::milliseconds _start_time;
61};
62
63std::mutex LocationService::_mutex;
64std::vector<TrajectoryPoint> LocationService::_trajectory;
65double LocationService::_manual_x = 0;
66double LocationService::_manual_y = 0;
67std::chrono::milliseconds LocationService::_start_time = std::chrono::milliseconds::zero();
68
70 std::lock_guard<std::mutex> lock(_mutex);
71 if(loadTrajectoryFromCSV(csv_filename)){
72 _start_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
73 return true;
74 };
75 return false;
76}
77
78void LocationService::getCoordinates(double& x, double& y, std::chrono::milliseconds timestamp) {
79 std::lock_guard<std::mutex> lock(_mutex);
80
81 if (_trajectory.empty() || timestamp == std::chrono::milliseconds::zero()) {
82 // Use manual coordinates if no trajectory or no timestamp provided
83 x = _manual_x;
84 y = _manual_y;
85 return;
86 }
87
88 getCoordinatesAtTime(timestamp, x, y);
89}
90
91void LocationService::getCurrentCoordinates(double& x, double& y) {
92 auto now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
93 getCoordinates(x, y, now - _start_time);
94}
95
97 std::lock_guard<std::mutex> lock(_mutex);
98 _manual_x = x;
99 _manual_y = y;
100}
101
103 std::lock_guard<std::mutex> lock(_mutex);
104 return !_trajectory.empty();
105}
106
107std::chrono::milliseconds LocationService::getTrajectoryDuration() {
108 std::lock_guard<std::mutex> lock(_mutex);
109 if (_trajectory.empty()) return std::chrono::milliseconds::zero();
110 return _trajectory.back().timestamp - _trajectory.front().timestamp;
111}
112
113bool LocationService::loadTrajectoryFromCSV(const std::string& filename) {
114 std::ifstream file(filename);
115 if (!file.is_open()) {
116 return false;
117 }
118
119 _trajectory.clear();
120 std::string line;
121
122 // Skip header if present
123 if (std::getline(file, line) && line.find("timestamp") != std::string::npos) {
124 // Header detected, continue to next line
125 } else {
126 // No header, reset to beginning
127 file.clear();
128 file.seekg(0);
129 }
130
131 while (std::getline(file, line)) {
132 if (line.empty()) continue;
133
134 std::stringstream ss(line);
135 std::string cell;
136 std::vector<std::string> values;
137
138 // Parse CSV line
139 while (std::getline(ss, cell, ',')) {
140 values.push_back(cell);
141 }
142
143 if (values.size() >= 3) {
144 try {
145 long long timestamp_ms = std::stoll(values[0]);
146 double x_coord = std::stod(values[1]);
147 double y_coord = std::stod(values[2]);
148
149 _trajectory.emplace_back(timestamp_ms, x_coord, y_coord);
150 } catch (const std::exception&) {
151 // Skip malformed lines
152 continue;
153 }
154 }
155 }
156
157 // Sort trajectory by timestamp
158 std::sort(_trajectory.begin(), _trajectory.end(),
159 [](const TrajectoryPoint& a, const TrajectoryPoint& b) {
160 return a.timestamp < b.timestamp;
161 });
162
163 return !_trajectory.empty();
164}
165
166void LocationService::getCoordinatesAtTime(std::chrono::milliseconds timestamp, double& x, double& y) {
167 if (_trajectory.empty()) {
168 x = _manual_x;
169 y = _manual_y;
170 return;
171 }
172
173 // Find the first timestamp that is higher than the given one
174 auto it = std::upper_bound(_trajectory.begin(), _trajectory.end(), timestamp,
175 [](std::chrono::milliseconds ts, const TrajectoryPoint& point) {
176 return ts < point.timestamp;
177 });
178
179 if (it == _trajectory.begin()) {
180 // Timestamp is before trajectory start - use first point
181 x = _trajectory.front().x;
182 y = _trajectory.front().y;
183 } else if (it == _trajectory.end()) {
184 // Timestamp is after trajectory end - use last point
185 x = _trajectory.back().x;
186 y = _trajectory.back().y;
187 } else {
188 // Interpolate between two points for smoother movement
189 auto curr = it;
190 auto prev = it - 1;
191
192 auto dt_total = curr->timestamp - prev->timestamp;
193 auto dt_elapsed = timestamp - prev->timestamp;
194
195 if (dt_total.count() == 0) {
196 // Same timestamp, use current point
197 x = curr->x;
198 y = curr->y;
199 } else {
200 // Linear interpolation
201 double ratio = static_cast<double>(dt_elapsed.count()) / dt_total.count();
202 x = prev->x + ratio * (curr->x - prev->x);
203 y = prev->y + ratio * (curr->y - prev->y);
204 }
205 }
206}
207
208#endif // LOCATION_SERVICE_H
Definition location_service.h:29
static void getCurrentCoordinates(double &x, double &y)
Definition location_service.h:91
static void setCurrentCoordinates(double x, double y)
Definition location_service.h:96
static bool loadTrajectory(const std::string &csv_filename)
Definition location_service.h:69
static std::chrono::milliseconds getTrajectoryDuration()
Definition location_service.h:107
static bool hasTrajectory()
Definition location_service.h:102
static void getCoordinates(double &x, double &y, std::chrono::milliseconds timestamp=std::chrono::milliseconds::zero())
Definition location_service.h:78
Select_Debug<(Traits< T >::debugged &&Traits< Debug >::error)> db(Debug_Error l)
Definition debug.h:166
Definition location_service.h:15
double x
Definition location_service.h:16
double radius
Definition location_service.h:18
double y
Definition location_service.h:17
Definition location_service.h:21
TrajectoryPoint(long long ts_ms, double x_coord, double y_coord)
Definition location_service.h:26
double y
Definition location_service.h:24
double x
Definition location_service.h:23
std::chrono::milliseconds timestamp
Definition location_service.h:22