Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
gnssSensor.cpp
Go to the documentation of this file.
2
3#include "quaternion.hpp"
4
6{
7 this->rate = rate;
8 this->lastSampleTime = 0.0;
9 this->deadTime = deadTime;
10 this->noiseSeed = 0;
11}
12
14{
15 config.getElement<std::string>(&this->name, "name");
16 config.getElement<std::string>(&this->frame_id, "name");
17 config.getElement<double>(&this->rate, "rate");
18 config["delay"].getElement<double>(&this->deadTime, "mean");
19 std::vector<double> position;
20 config["pose"].getElement<std::vector<double>>(&position, "position");
21 this->position = Eigen::Vector3d(position[0], position[1], position[2]);
22 std::vector<double> orientation;
23 config["pose"].getElement<std::vector<double>>(&orientation, "orientation");
24 this->orientation = Eigen::Vector3d(orientation[0], orientation[1], orientation[2]);
25
26 std::vector<double> sigmaPosition;
27 config["noise"]["position"].getElement<std::vector<double>>(&sigmaPosition, "sigma");
28 this->errorSigmaPosition = Eigen::Vector3d(sigmaPosition[0], sigmaPosition[1], sigmaPosition[2]);
29 std::vector<double> meanPosition;
30 config["noise"]["position"].getElement<std::vector<double>>(&meanPosition, "mean");
31 this->errorMeanPosition = Eigen::Vector3d(meanPosition[0], meanPosition[1], meanPosition[2]);
32
33 std::vector<double> sigmaVelocity;
34 config["noise"]["velocity"].getElement<std::vector<double>>(&sigmaVelocity, "sigma");
35 this->errorSigmaVelocity = Eigen::Vector3d(sigmaVelocity[0], sigmaVelocity[1], sigmaVelocity[2]);
36 std::vector<double> meanVelocity;
37 config["noise"]["velocity"].getElement<std::vector<double>>(&meanVelocity, "mean");
38 this->errorMeanVelocity = Eigen::Vector3d(meanVelocity[0], meanVelocity[1], meanVelocity[2]);
39
40 std::vector<double> sigmaOrientation;
41 config["noise"]["orientation"].getElement<std::vector<double>>(&sigmaOrientation, "sigma");
42 this->errorSigmaOrientation = Eigen::Vector3d(sigmaOrientation[0], sigmaOrientation[1], sigmaOrientation[2]);
43 std::vector<double> meanOrientation;
44 config["noise"]["orientation"].getElement<std::vector<double>>(&meanOrientation, "mean");
45 this->errorMeanOrientation = Eigen::Vector3d(meanOrientation[0], meanOrientation[1], meanOrientation[2]);
46
47 config["features"].getElement<bool>(&this->outputVelocity, "velocity");
48 config["features"].getElement<int>(&this->orientationMode, "orientation");
49
50 return;
51}
52
53Eigen::Vector3d wgs84toEcef(double lat, double lon, double alt)
54{
55 // https://en.wikipedia.org/wiki/Geographic_coordinate_conversion
56 double deg2rad = M_PI / 180.0;
57 double a = 6378137.0;
58 double b = 6356752.314;
59 double h = alt;
60 double esqr = 1 - std::pow(b / a, 2);
61 double N = a / (sqrt(1 - esqr * std::pow(std::sin(lat * deg2rad), 2)));
62 double X = (N + h) * std::cos(lat * deg2rad) * std::cos(lon * deg2rad);
63 double Y = (N + h) * std::cos(lat * deg2rad) * std::sin(lon * deg2rad);
64 double Z = std::sin(lat * deg2rad) * ((1 - esqr) * N + h);
65 return Eigen::Vector3d(X, Y, Z);
66}
67
68double getRn(double latitude)
69{
70 double a = 6378137.0;
71 double b = 6356752.314;
72 double esqr = 1 - std::pow(b / a, 2);
73
74 double N = a / (sqrt(1 - esqr * std::pow(std::sin(latitude), 2)));
75 return N;
76}
77
78Eigen::Vector3d ecefToWgs84(double x, double y, double z)
79{
80 // https://www.oc.nps.edu/oc2902w/coord/coordcvt.pdf
81 double lon = std::atan2(y, x);
82 double p = std::hypot(x, y);
83 double deg2rad = M_PI / 180.0;
84 double a = 6378137.0;
85 double b = 6356752.314;
86
87 double esqr = 1 - std::pow(b / a, 2);
88 // there exists no closed form solution
89 // iterative method to get height and latitude
90 double h = 0.0;
91 double lat = std::atan2(p, z);
92 // 7 iterarations gave me error which rounds to 0 on doubles
93 for (int i = 0; i < 7; ++i)
94 {
95 double rn = getRn(lat);
96 h = (p / std::cos(lat)) - rn;
97 lat = std::atan((z / p) / (1 - esqr * rn / (rn + h)));
98 }
99 lon = lon / deg2rad;
100 lat = lat / deg2rad;
101 return Eigen::Vector3d(lat, lon, h);
102}
103
104Eigen::Matrix3d getEnuToEcefRotMat(double lat, double lon)
105{
106 // https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_ENU_to_ECEF
107 double deg2rad = M_PI / 180.0;
108 lat = lat * deg2rad;
109 lon = lon * deg2rad;
110 Eigen::Matrix3d ret;
111 ret << -sin(lon), -sin(lat) * cos(lon), cos(lat) * cos(lon), cos(lon), -sin(lat) * sin(lon), cos(lat) * sin(lon),
112 0.0, cos(lat), sin(lat);
113 return ret;
114}
115
116std::string GnssSensor::getName() { return this->name; }
117
118std::string GnssSensor::getFrameId() { return this->frame_id; }
119
120bool GnssSensor::RunTick(Eigen::Vector3d& gnssOrigin, Eigen::Vector3d& enuToTrackRotation, Eigen::Vector3d& trans,
121 Eigen::Vector3d& rot, double time, Eigen::Vector3d velocity, Eigen::Vector3d omega, Eigen::Vector3d start_position,
122 Eigen::Vector3d start_orientation, bool trackPreTransformed)
123{
124
125 if (this->sampleReady(time))
126 {
127 double originLat = gnssOrigin.x();
128 double originLon = gnssOrigin.y();
129 double originAlt = gnssOrigin.z();
130 auto originEcef = wgs84toEcef(originLat, originLon, originAlt);
131 Eigen::Vector3d ecefRef = Eigen::Vector3d(originEcef.x(), originEcef.y(), originEcef.z());
132 auto rotEnuToEcef = getEnuToEcefRotMat(originLat, originLon);
133 Eigen::Vector3d rotTrackToENU(enuToTrackRotation.x(), enuToTrackRotation.y(), enuToTrackRotation.z());
134 Eigen::Matrix3d rotMatTrackToEnu = eulerAnglesToRotMat(rotTrackToENU).transpose();
135 Eigen::Vector3d actualTrackCar = start_position;
136 // if the track was transformed, we need to account for the changed track origin
137 if (trackPreTransformed)
138 {
139 actualTrackCar = eulerAnglesToRotMat(start_orientation).transpose() * trans + start_position;
140 }
141 Eigen::Vector3d enuCar = rotMatTrackToEnu * actualTrackCar;
142
143 std::default_random_engine generator(noiseSeed);
144
145 std::normal_distribution<double> distX(errorMeanPosition.x(), errorSigmaPosition.x());
146 std::normal_distribution<double> distY(errorMeanPosition.y(), errorSigmaPosition.y());
147 std::normal_distribution<double> distZ(errorMeanPosition.z(), errorSigmaPosition.z());
148
149 std::normal_distribution<double> distXOr(errorMeanOrientation.x(), errorSigmaOrientation.x());
150 std::normal_distribution<double> distYOr(errorMeanOrientation.y(), errorSigmaOrientation.y());
151 std::normal_distribution<double> distZOr(errorMeanOrientation.z(), errorSigmaOrientation.z());
152
153 std::normal_distribution<double> distXVel(errorMeanVelocity.x(), errorSigmaVelocity.x());
154 std::normal_distribution<double> distYVel(errorMeanVelocity.y(), errorSigmaVelocity.y());
155 std::normal_distribution<double> distZVel(errorMeanVelocity.z(), errorSigmaVelocity.z());
156
157 enuCar.x() += distX(generator);
158 enuCar.y() += distY(generator);
159 enuCar.z() += distZ(generator);
160 Eigen::Vector3d ecefCar = rotEnuToEcef * enuCar + ecefRef;
161
162 Eigen::Vector3d positionWgs = ecefToWgs84(ecefCar.x(), ecefCar.y(), ecefCar.z());
163
164 Eigen::Vector3d velENU
165 = rotMatTrackToEnu * eulerAnglesToRotMat(rot) * rigidBodyVelocity(velocity, this->position, omega);
166 if (trackPreTransformed)
167 {
168 velENU = rotMatTrackToEnu * eulerAnglesToRotMat(start_orientation) * eulerAnglesToRotMat(rot)
169 * rigidBodyVelocity(velocity, this->position, omega);
170 }
171
172 // sensor->car->track->enu
175 quaternion q11 = quatFromEulerAngles(start_orientation);
176 quaternion qCar = q1;
177 // if the track was transformed, we need to account for the changed track origin
178 if (trackPreTransformed)
179 {
180 qCar = quatMult(q11, q1);
181 }
182 quaternion q2 = quatFromEulerAngles(rotTrackToENU);
183 quaternion q3 = quatMult(q2, quatMult(qCar, q0));
184 // apply noise as additional rotation
185 quaternion q4
186 = quatFromEulerAngles(Eigen::Vector3d(distXOr(generator), distYOr(generator), distZOr(generator)));
187 quaternion q5 = quatMult(q4, q3);
188
189 quaternion outQuat = quatFromEulerAngles(Eigen::Vector3d(0.0, 0.0, 0.0));
190 if (this->orientationMode == 1)
191 {
192 Eigen::Matrix3d testMat = rotationMatrixFromQuaternion(q5);
193 Eigen::Vector3d testVec = testMat * Eigen::Vector3d(1, 0, 0);
194 double angleN = std::atan2(testVec.y(), testVec.x());
195 outQuat = quatFromEulerAngles(Eigen::Vector3d(0.0, 0.0, angleN));
196 }
197 else if (this->orientationMode == 2)
198 {
199 outQuat = q5;
200 }
201
202 GnssData value;
203 value.latitude = positionWgs.x();
204 value.longitude = positionWgs.y();
205 value.altitude = positionWgs.z();
206 value.position_covariance = this->errorSigmaPosition.asDiagonal();
207 value.position_covariance = value.position_covariance.array().square();
208
209 if (this->outputVelocity)
210 {
211 value.vel_east = velENU.x() + distXVel(generator);
212 value.vel_north = velENU.y() + distYVel(generator);
213 value.vel_up = velENU.z() + distZVel(generator);
214 value.velocity_covariance = this->errorSigmaVelocity.asDiagonal();
215 value.velocity_covariance = value.velocity_covariance.array().square();
216 }
217 else
218 {
219 value.vel_east = 0.0;
220 value.vel_north = 0.0;
221 value.vel_up = 0.0;
222 value.velocity_covariance(0, 0) = -1.0;
223 value.velocity_covariance(1, 1) = -1.0;
224 value.velocity_covariance(2, 2) = -1.0;
225 }
226
227 value.orientation = outQuat;
228 value.orientation_covariance = this->errorSigmaOrientation.asDiagonal();
229 value.orientation_covariance = value.orientation_covariance.array().square();
230
232
233 value.timestamp = time;
234 value.frame = this->frame_id;
235
236 noiseSeed += 1;
237
238 this->deadTimeQueue.push(value);
239 this->registerSampling();
240 }
241 return availableDeadTime(time);
242}
ConfigElement getElement(string elementName)
std::string frame_id
std::string name
std::string getName()
Eigen::Vector3d errorMeanVelocity
void readConfig(ConfigElement &config)
Eigen::Vector3d errorMeanPosition
Eigen::Vector3d errorMeanOrientation
Eigen::Vector3d errorSigmaVelocity
Eigen::Vector3d errorSigmaOrientation
bool outputVelocity
std::string getFrameId()
Eigen::Vector3d errorSigmaPosition
int orientationMode
bool RunTick(Eigen::Vector3d &gnssOrigin, Eigen::Vector3d &enuToTrackRotation, Eigen::Vector3d &trans, Eigen::Vector3d &rot, double time, Eigen::Vector3d velocity, Eigen::Vector3d omega, Eigen::Vector3d start_position, Eigen::Vector3d start_orientation, bool trackPreTransformed)
bool sampleReady(double time)
bool availableDeadTime(double time)
Eigen::Vector3d orientation
std::queue< GnssData > deadTimeQueue
Eigen::Vector3d position
Eigen::Vector3d ecefToWgs84(double x, double y, double z)
Eigen::Matrix3d getEnuToEcefRotMat(double lat, double lon)
Eigen::Vector3d wgs84toEcef(double lat, double lon, double alt)
double getRn(double latitude)
Eigen::Matrix3d rotationMatrixFromQuaternion(quaternion a)
quaternion quatMult(quaternion a, quaternion b)
quaternion quatFromEulerAngles(Eigen::Vector3d a)
double vel_up
Definition types.hpp:104
Eigen::Matrix3d velocity_covariance
Definition types.hpp:105
quaternion orientation
Definition types.hpp:107
double longitude
Definition types.hpp:98
double timestamp
Definition types.hpp:118
double vel_north
Definition types.hpp:103
double latitude
Definition types.hpp:97
Eigen::Matrix3d position_covariance
Definition types.hpp:100
double altitude
Definition types.hpp:99
FixStatus fix_status
Definition types.hpp:116
std::string frame
Definition types.hpp:119
Eigen::Matrix3d orientation_covariance
Definition types.hpp:108
double vel_east
Definition types.hpp:102
Eigen::Vector3d rigidBodyVelocity(Eigen::Vector3d v, Eigen::Vector3d r, Eigen::Vector3d omega)
Definition transform.cpp:3
Eigen::Matrix3d eulerAnglesToRotMat(Eigen::Vector3d &angles)
Definition transform.cpp:14