Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
perceptionSensor.cpp
Go to the documentation of this file.
2
4{
5 this->name = "";
6 this->frame_id = "";
7 this->maxRange = 0.0;
8 this->minRange = 0.0;
9 this->minAngleHorizontal = 0.0;
10 this->maxAngleHorizontal = 0.0;
11 this->rate = rate;
12 this->lastSampleTime = 0.0;
13 this->deadTime = deadTime;
14 this->position = Eigen::Vector3d(0.0, 0.0, 0.0);
15 this->orientation = Eigen::Vector3d(0.0, 0.0, 0.0);
16 this->errorMeanXYZ = Eigen::Vector3d::Zero();
17 this->errorSigmaXYZ = Eigen::Vector3d::Zero();
18 this->errorMeanRange = 0.0;
19 this->errorSigmaRange = 0.0;
20 this->errorMeanRangeRelative = 0.0;
21 this->errorSigmaRangeRelative = 0.0;
22 this->errorMeanAngle = Eigen::Vector2d::Zero();
23 this->errorSigmaAngle = Eigen::Vector2d::Zero();
24 this->numFrames = 0;
25 this->detection_prob_min_dist = 0.99;
28 this->min_detection_prob = 0.1;
29}
30
32{
33 config.getElement<std::string>(&this->name, "name");
34 config.getElement<std::string>(&this->frame_id, "name");
35 config.getElement<double>(&this->rate, "rate");
36 config["delay"].getElement<double>(&this->deadTime, "mean");
37 std::vector<double> position;
38 config["pose"].getElement<std::vector<double>>(&position, "position");
39 this->position = Eigen::Vector3d(position[0], position[1], position[2]);
40 std::vector<double> orientation;
41 config["pose"].getElement<std::vector<double>>(&orientation, "orientation");
42 this->orientation = Eigen::Vector3d(orientation[0], orientation[1], orientation[2]);
43 config["observation"].getElement<double>(&this->minRange, "min_range");
44 config["observation"].getElement<double>(&this->maxRange, "max_range");
45
46 config["observation"].getElement<double>(&this->minAngleHorizontal, "min_angle_horizontal");
47 config["observation"].getElement<double>(&this->maxAngleHorizontal, "max_angle_horizontal");
48 config["observation"].getElement<double>(&this->minAngleVertical, "min_angle_vertical");
49 config["observation"].getElement<double>(&this->maxAngleVertical, "max_angle_vertical");
50
51 std::vector<double> meanErrorXYZ;
52 config["noise"]["cartesian"].getElement<std::vector<double>>(&meanErrorXYZ, "mean");
53 this->errorMeanXYZ = Eigen::Vector3d(meanErrorXYZ[0], meanErrorXYZ[1], meanErrorXYZ[2]);
54
55 std::vector<double> sigmaErrorXYZ;
56 config["noise"]["cartesian"].getElement<std::vector<double>>(&sigmaErrorXYZ, "sigma");
57 this->errorSigmaXYZ = Eigen::Vector3d(sigmaErrorXYZ[0], sigmaErrorXYZ[1], sigmaErrorXYZ[2]);
58
59 std::vector<double> meanErrorAngle;
60 config["noise"]["angle"].getElement<std::vector<double>>(&meanErrorAngle, "mean");
61 this->errorMeanAngle = Eigen::Vector2d(meanErrorAngle[0], meanErrorAngle[1]);
62
63 std::vector<double> sigmaErrorAngle;
64 config["noise"]["angle"].getElement<std::vector<double>>(&sigmaErrorAngle, "sigma");
65 this->errorSigmaAngle = Eigen::Vector2d(sigmaErrorAngle[0], sigmaErrorAngle[1]);
66
67 config["noise"]["range"].getElement<double>(&this->errorMeanRange, "mean");
68 config["noise"]["range"].getElement<double>(&this->errorSigmaRange, "sigma");
69 config["noise"]["range_relative"].getElement<double>(&this->errorMeanRangeRelative, "mean");
70 config["noise"]["range_relative"].getElement<double>(&this->errorSigmaRangeRelative, "sigma");
71
72 config["detection"].getElement<double>(&this->detection_prob_min_dist, "prob_min_dist");
73 config["detection"].getElement<double>(&this->detection_prob_decrease_dist_linear, "prob_decrease_dist_linear");
74 config["detection"].getElement<double>(
75 &this->detection_prob_decrease_dist_quadratic, "prob_decrease_dist_quadratic");
76 config["detection"].getElement<double>(&this->min_detection_prob, "min_prob");
77
78 config["classification"].getElement<double>(&this->classification_max_distance, "max_dist");
79 config["classification"].getElement<double>(&this->classification_prob_min_dist, "prob_min_dist");
80 config["classification"].getElement<double>(
81 &this->classification_prob_decrease_dist_linear, "prob_decrease_dist_linear");
82 config["classification"].getElement<double>(
83 &this->classification_prob_decrease_dist_quadratic, "prob_decrease_dist_quadratic");
84 config["classification"].getElement<double>(&this->min_classification_prob, "min_prob");
85}
86
87LandmarkList PerceptionSensor::process(LandmarkList& in, Eigen::Vector3d& trans, Eigen::Vector3d& rot, double time)
88{
89 LandmarkList transformedLmsVehicle = transformLmList(in, trans, rot);
90 LandmarkList transformedLms = transformLmList(transformedLmsVehicle, this->position, this->orientation);
91 std::vector<Landmark> listNew = this->filterFoV(transformedLms.list);
92 listNew = this->filterTypeAndDOO(listNew);
93 listNew = this->handleFalsePositivesAndNegatives(listNew);
94 listNew = this->addClassProbailities(listNew);
95 listNew = this->addNoise(listNew);
96 LandmarkList ret;
97 ret.list = listNew;
98 ret.timestamp = time;
99 ret.frame_id = frame_id;
100 numFrames += 1;
101 return ret;
102}
103
104std::vector<Landmark> PerceptionSensor::filterFoV(std::vector<Landmark>& in)
105{
106 std::vector<Landmark> listNew;
107 for (Landmark& lm : in)
108 {
109 double dist = lm.position.norm();
110 double angleHorizontal = std::atan2(lm.position.y(), lm.position.x());
111 // double angleVertical = std::asin(lm.position.z() / dist);
112 // if (dist >= minRange && dist <= maxRange && angleHorizontal >= minAngleHorizontal
113 // && angleHorizontal <= maxAngleHorizontal && angleVertical >= minAngleVertical,
114 // angleVertical <= maxAngleVertical)
115 if (dist >= minRange && dist <= maxRange && angleHorizontal >= minAngleHorizontal
116 && angleHorizontal <= maxAngleHorizontal)
117 {
118 listNew.push_back(lm);
119 }
120 }
121 return listNew;
122}
123
124std::vector<Landmark> PerceptionSensor::filterTypeAndDOO(std::vector<Landmark>& in)
125{
126 std::vector<Landmark> listNew;
127 for (Landmark& lm : in)
128 {
129 if (lm.type != LandmarkType::INVISIBLE && (!lm.beenHit))
130 {
131 listNew.push_back(lm);
132 }
133 }
134 return listNew;
135}
136
137std::vector<Landmark> PerceptionSensor::addNoise(std::vector<Landmark>& in)
138{
139 std::vector<Landmark> listNew;
140 // provide numFrames as seed because the pseudo random generator would otherwise output the same values in
141 // standstill and the noise would be constant
142 std::default_random_engine generator(numFrames);
143 std::normal_distribution<double> distX(errorMeanXYZ.x(), errorSigmaXYZ.x());
144 std::normal_distribution<double> distY(errorMeanXYZ.y(), errorSigmaXYZ.y());
145 std::normal_distribution<double> distZ(errorMeanXYZ.z(), errorSigmaXYZ.z());
146
147 std::normal_distribution<double> distRange(errorMeanRange, errorSigmaRange);
148 std::normal_distribution<double> distRangeRelative(errorMeanRangeRelative, errorSigmaRangeRelative);
149
150 std::normal_distribution<double> distTheta(errorMeanAngle.x(), errorSigmaAngle.x());
151 std::normal_distribution<double> distPhi(errorMeanAngle.y(), errorSigmaAngle.y());
152
153 Eigen::Matrix3d rotationJacobian;
154
155 for (Landmark& lm : in)
156 {
157 double dist = lm.position.norm();
158 double theta = std::acos(lm.position.z() / dist);
159 double phi = std::atan2(lm.position.y(), lm.position.x());
160
161 Eigen::Matrix3d covSpherical = Eigen::Matrix3d::Zero();
162 covSpherical(0, 0) = errorSigmaAngle.x() * errorSigmaAngle.x();
163 covSpherical(1, 1) = errorSigmaAngle.y() * errorSigmaAngle.y();
164 covSpherical(2, 2)
166
167 rotationJacobian(0, 0) = dist * std::cos(theta) * std::cos(phi);
168 rotationJacobian(0, 1) = dist * std::sin(theta) * -std::sin(phi);
169 rotationJacobian(0, 2) = std::sin(theta) * std::cos(phi);
170
171 rotationJacobian(1, 0) = dist * std::cos(theta) * std::sin(phi);
172 rotationJacobian(1, 1) = dist * std::sin(theta) * std::cos(phi);
173 rotationJacobian(1, 2) = std::sin(theta) * std::sin(phi);
174
175 rotationJacobian(2, 0) = -dist * std::sin(theta);
176 rotationJacobian(2, 1) = 0.0;
177 rotationJacobian(2, 2) = std::cos(theta);
178
179 theta += distTheta(generator);
180 phi += distPhi(generator);
181
182 dist += dist * distRangeRelative(generator);
183 dist += distRange(generator);
184
185 lm.position.x() = dist * std::sin(theta) * std::cos(phi);
186 lm.position.y() = dist * std::sin(theta) * std::sin(phi);
187 lm.position.z() = dist * std::cos(theta);
188
189 lm.position.x() += distX(generator);
190 lm.position.y() += distY(generator);
191 lm.position.z() += distZ(generator);
192
193 lm.cov = rotationJacobian * covSpherical * rotationJacobian.transpose();
194 lm.cov(0, 0) += errorSigmaXYZ.x() * errorSigmaXYZ.x();
195 lm.cov(1, 1) += errorSigmaXYZ.y() * errorSigmaXYZ.y();
196 lm.cov(2, 2) += errorSigmaXYZ.z() * errorSigmaXYZ.z();
197
198 listNew.push_back(lm);
199 }
200 return listNew;
201}
202
203std::vector<Landmark> PerceptionSensor::addClassProbailities(std::vector<Landmark>& in)
204{
205 std::vector<Landmark> listNew;
206 bool detect_big_orange = true;
207 bool detect_timekeeping = true;
208 std::default_random_engine random_generator(this->numFrames);
209 std::uniform_real_distribution<double> unif(0, 1.0);
210
211 std::vector<int> detectionClasses = { LandmarkType::UNKNOWN, LandmarkType::BLUE, LandmarkType::YELLOW,
213 for (Landmark& lm : in)
214 {
215 double dist = lm.position.norm();
216 double prob = this->classification_prob_min_dist
218 - std::pow((dist - this->minRange), 2) * this->classification_prob_decrease_dist_quadratic;
219 prob = std::max(prob, min_classification_prob);
220 if (dist > this->classification_max_distance)
221 {
222 prob = 1.0;
223 lm.type = LandmarkType::UNKNOWN;
224 }
225 // if it's some weird class (like timekeeping), just set as unknown
226 if (std::find(detectionClasses.begin(), detectionClasses.end(), lm.type) == detectionClasses.end())
227 {
228 lm.type = LandmarkType::UNKNOWN;
229 }
230 std::fill(lm.typeWeights, lm.typeWeights + LandmarkType::UNKNOWN, 0);
231 lm.typeWeights[lm.type] = prob;
232 for (auto i : detectionClasses)
233 {
234 if (i != lm.type)
235 {
236 lm.typeWeights[i] = (1 - prob) / ((double)detectionClasses.size() - 1);
237 }
238 }
239 // randomly swap some class with p = prob
240 double randomNum = unif(random_generator);
241 double acc = 0;
242 for (int i = 0; i < (LandmarkType::UNKNOWN + 1); ++i)
243 {
244 acc += lm.typeWeights[i];
245 if (acc > randomNum)
246 {
247 double tmp = lm.typeWeights[i];
248 lm.typeWeights[i] = lm.typeWeights[lm.type];
249 lm.typeWeights[lm.type] = tmp;
250 lm.type = static_cast<LandmarkType>(i);
251 break;
252 }
253 }
254
255 listNew.push_back(lm);
256 }
257 return listNew;
258}
259
260std::vector<Landmark> PerceptionSensor::handleFalsePositivesAndNegatives(std::vector<Landmark>& in)
261{
262 std::vector<Landmark> listNew;
263
264 std::default_random_engine random_generator(this->numFrames);
265 std::uniform_real_distribution<double> unif(0, 1.0);
266
267 for (Landmark& lm : in)
268 {
269 double dist = lm.position.norm();
270 double detection_prob = this->detection_prob_min_dist
271 - (dist - this->minRange) * this->detection_prob_decrease_dist_linear
272 - std::pow((dist - this->minRange), 2) * this->detection_prob_decrease_dist_quadratic;
273 detection_prob = std::max(this->min_detection_prob, detection_prob);
274 double random = unif(random_generator);
275 if (random < detection_prob)
276 {
277 lm.detection_probability = detection_prob;
278 listNew.push_back(lm);
279 }
280 }
281 return listNew;
282}
283
284std::string PerceptionSensor::getName() { return this->name; }
285
286std::string PerceptionSensor::getFrameId() { return this->frame_id; }
287
288bool PerceptionSensor::RunTick(LandmarkList& in, Eigen::Vector3d& trans, Eigen::Vector3d& rot, double time)
289{
290 if (this->sampleReady(time))
291 {
292 LandmarkList value = this->process(in, trans, rot, time);
293 this->deadTimeQueue.push(value);
294 this->registerSampling();
295 }
296 return availableDeadTime(time);
297}
ConfigElement getElement(string elementName)
std::vector< Landmark > addClassProbailities(std::vector< Landmark > &in)
LandmarkList process(LandmarkList &in, Eigen::Vector3d &trans, Eigen::Vector3d &rot, double time)
std::vector< Landmark > filterFoV(std::vector< Landmark > &in)
std::vector< Landmark > addNoise(std::vector< Landmark > &in)
double classification_prob_min_dist
std::string getFrameId()
std::vector< Landmark > handleFalsePositivesAndNegatives(std::vector< Landmark > &in)
double detection_prob_decrease_dist_quadratic
double detection_prob_decrease_dist_linear
Eigen::Vector3d errorSigmaXYZ
Eigen::Vector2d errorMeanAngle
bool RunTick(LandmarkList &in, Eigen::Vector3d &trans, Eigen::Vector3d &rot, double time)
double classification_prob_decrease_dist_quadratic
std::vector< Landmark > filterTypeAndDOO(std::vector< Landmark > &in)
Eigen::Vector2d errorSigmaAngle
Eigen::Vector3d errorMeanXYZ
void readConfig(ConfigElement &config)
double classification_prob_decrease_dist_linear
bool sampleReady(double time)
bool availableDeadTime(double time)
Eigen::Vector3d orientation
std::queue< LandmarkList > deadTimeQueue
double timestamp
Definition types.hpp:56
std::string frame_id
Definition types.hpp:55
std::vector< Landmark > list
Definition types.hpp:51
LandmarkList transformLmList(LandmarkList &in, Eigen::Vector3d trans, Eigen::Vector3d rot)
Definition transform.cpp:34
LandmarkType
Definition types.hpp:9
@ BLUE
Definition types.hpp:10
@ INVISIBLE
Definition types.hpp:15
@ BIG_ORANGE
Definition types.hpp:13
@ UNKNOWN
Definition types.hpp:17
@ ORANGE
Definition types.hpp:12
@ YELLOW
Definition types.hpp:11