Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
LaneDetectionGT.cpp
Go to the documentation of this file.
3 
4 #include <iostream>
5 #include <stdio.h>
6 
7 #include <utils/logger.hpp>
8 #include <utils/file.hpp>
10 #include <unistd.h>
11 #include <thread>
12 
14 
15 #include <sensor_msgs/image_encodings.hpp>
16 
17 using namespace galaxis::ros;
18 using namespace galaxis::utils;
19 
20 using namespace galaxis::map::data;
21 
22 
23 constexpr double MATH_PI_DOUBLE = 3.141592653589793238;
24 
25 
27  rclcpp::Node("LaneDetectionGTNode"), m_mapDataLayer(1) {
28  log("Initializing LaneDetectionGT-Node...");
29 
30  // Read configuration
31  std::string configPath = "settings/onstartup_simulation_lanedetection_config.conf";
32  auto configMap = read_configuration(configPath);
33  m_simulatedLDFPSWaitingTimeMicroseconds = static_cast<int>(1000000 / std::stof(configMap->at("simulatedFPS")));
34  int configGTKeepLast = std::stoi(configMap->at("groundtruthKeepLast"));
35  m_lineImageWindowSize = Vector2i(std::stoi(configMap->at("imageWindowWidth")), std::stoi(configMap->at("imageWindowHeight")));
36  m_obstacleDetectionDistanceCM = std::stof(configMap->at("obstacleDetectionDistanceCM"));
37  log("Configuration (", configPath, "):", "\n",
38  " - SimulatedFPS: ", configMap->at("simulatedFPS"), " (WaitTimeMicroS: ", m_simulatedLDFPSWaitingTimeMicroseconds, ")\n",
39  " - GroundtruthKeepLast: ", configGTKeepLast, "\n",
40  " - Image Size (Window Size for Lookup): ", m_lineImageWindowSize[0], "cm x ", m_lineImageWindowSize[1], "cm");
41 
42  // Subsciber
43  rclcpp::QoS qos_params = rclcpp::QoS(rclcpp::KeepLast(configGTKeepLast), qos_profile_default);
44  m_subscriberLeftLineSPtr = this->create_subscription<visualization_msgs::msg::Marker>("/simulation/visualization/groundtruth/left_line", qos_params, std::bind(&LaneDetectionGT::groundtruthLeftLineCallback, this, std::placeholders::_1));
45  m_subscriberMiddleLineSPtr = this->create_subscription<visualization_msgs::msg::Marker>("/simulation/visualization/groundtruth/middle_line", qos_params, std::bind(&LaneDetectionGT::groundtruthCenterLineCallback, this, std::placeholders::_1));
46  m_subscriberRightLineSPtr = this->create_subscription<visualization_msgs::msg::Marker>("/simulation/visualization/groundtruth/right_line", qos_params, std::bind(&LaneDetectionGT::groundtruthRightLineCallback, this, std::placeholders::_1));
47 
48  m_subscriberObstacleSPtr = this->create_subscription<visualization_msgs::msg::Marker>("/simulation/visualization/groundtruth/obstacle", qos_params, std::bind(&LaneDetectionGT::groundtruthObstacleCallback, this, std::placeholders::_1));
49 
50  qos_params = get_qos_profile(QOS_BEST_EFFORT);
51  m_subscriberCarPoseSPtr = this->create_subscription<geometry_msgs::msg::Pose>("/simulation/gazebo/model/dr_drift/pose", qos_params, std::bind(&LaneDetectionGT::carPoseCallback, this, std::placeholders::_1));
52 
53  m_imgtransPub = image_transport::create_publisher(this, TOPIC_VCI_LANE_IMAGE_SIMULATION);
54 
55  // obstacle Publisher
56  galaxis::ros::create_publisher(this, m_publisherObstacleSPtr);
57  log("Waiting for messages...");
58 
59  // starting background thread for line detection image publishing
60  std::thread(&LaneDetectionGT::loop, this).detach();
61 }
62 
64 
65 
66 // Callback functions for ROS Subscriber
67 void LaneDetectionGT::groundtruthLeftLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message) {
69 }
70 
71 void LaneDetectionGT::groundtruthCenterLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message) {
73 }
74 
75 void LaneDetectionGT::groundtruthRightLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message) {
77 }
78 
79 void LaneDetectionGT::groundtruthCallback(visualization_msgs::msg::Marker::SharedPtr p_message, LINE_TYPE type) {
80  if (m_ready) return;
81 
82  int* groundtruthTileIterator;
83  char laneType;
84  if (type == LINE_TYPE::LEFT_LINE){
85  groundtruthTileIterator = &m_groundtruthTileIteratorLeftLine;
86  laneType = 'l';
87  }
88  else if (type == LINE_TYPE::CENTER_LINE) {
89  groundtruthTileIterator = &m_groundtruthTileIteratorCenterLine;
90  laneType = 'c';
91  }
92  else if (type == LINE_TYPE::RIGHT_LINE) {
93  groundtruthTileIterator = &m_groundtruthTileIteratorRightLine;
94  laneType = 'r';
95  }
96  else {
97  log_warning("Failure (Lane Type)");
98  return;
99  }
100 
101  // check if already all tiles received and inserted in map
102  if (p_message->id != *groundtruthTileIterator) {
103  if(p_message->id == 1 && *groundtruthTileIterator != -1) {
104  *groundtruthTileIterator = -1;
105  }
106  else {
107  return;
108  }
109  }
110 
111  if (type == LINE_TYPE::LEFT_LINE){
112  log("Left Line Groundtruth Message Received (", p_message->id, ")");
113  }
114  else if (type == LINE_TYPE::CENTER_LINE) {
115  log("Center Line Groundtruth Message Received (", p_message->id, ")");
116  }
117  else if (type == LINE_TYPE::RIGHT_LINE) {
118  log("Right Line Groundtruth Message Received (", p_message->id, ")");
119  }
120  else {
121  log_warning("Failure (Lane Type)");
122  return;
123  }
124 
125  // insert tile into map
126  m_mapDataLayer.updateMap(p_message, laneType);
127 
128  checkReady();
129 
130  // wait for next tile to insert into map
131  if (*groundtruthTileIterator != -1) {
132  *groundtruthTileIterator += 1;
133  }
134 }
135 
136 void LaneDetectionGT::groundtruthObstacleCallback(visualization_msgs::msg::Marker::SharedPtr p_message) {
137 
138  if(m_obstacleMap.find(p_message->id) == m_obstacleMap.end()) { // check if obstacle already inserted
139 
140  // calc center point of obstacle
141  Vector2f centerPoint = Vector2f(p_message->points[0].x - p_message->points[2].x, p_message->points[0].y - p_message->points[2].y) / 2;
142  centerPoint[0] += p_message->points[2].x;
143  centerPoint[1] += p_message->points[2].y;
144 
145  float width = std::fabs(p_message->points[0].x - p_message->points[1].x);
146  if (width <= 0.0001) {
147  width = std::fabs(p_message->points[0].y - p_message->points[1].y);
148  }
149 
150  Obstacle obstacle;
151  obstacle.positionCM = centerPoint * 100;
152  obstacle.widthCM = width * 100;
153 
154  m_obstacleMap.insert(std::pair<int, Obstacle>(p_message->id, obstacle));
155 
156  log("Obstacle Message Received (", p_message->id, ") with Center Point [m] (x y): ", centerPoint[0], " ", centerPoint[1], " and Width [m]: ", width);
157  }
158 
159 }
160 
161 
162 void LaneDetectionGT::carPoseCallback(geometry_msgs::msg::Pose::SharedPtr p_message) {
163  if(m_carPoseMtx.try_lock()) {
164  m_currentCarPoseTimestamp = this->get_clock()->now(); // WARNING Pose has no header!
165 
166  // Copied from https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
167  // yaw (z-axis rotation)
168  double siny_cosp = 2 * (p_message->orientation.w * p_message->orientation.z + p_message->orientation.x * p_message->orientation.y);
169  double cosy_cosp = 1 - 2 * (p_message->orientation.y * p_message->orientation.y + p_message->orientation.z * p_message->orientation.z);
170  double yaw = std::atan2(siny_cosp, cosy_cosp);
171 
173 
174  // fix orientation from simulation to internal galaxis representation
177 
178  // POSITION
179  m_currentCarPositionCM[0] = p_message->position.x * 100;
180  m_currentCarPositionCM[1] = p_message->position.y * 100;
181 
182  // Shift Position to Front Axis
184  Eigen::Rotation2Df rotationMat(-m_currentAbsoluteOrientation);
185  carPosOffToFrontAx = rotationMat * carPosOffToFrontAx;
186  m_currentCarPositionCM += carPosOffToFrontAx * 100;
187 
188  m_carPoseMtx.unlock();
189  // log("CarPose updated. [(X: ", m_currentCarPositionCM[0], ", Y: ", m_currentCarPositionCM[1],")cm, Yaw: ", m_currentAbsoluteOrientation, "Rad]");
190  }
191 }
192 
193 
194 // checks if all tiles for all lanes received as well as carPose -> then LaneDetectionGT::loop()
197  m_ready = true;
198  log("Ready to start loop.");
199  }
200  else {
201  m_ready = false;
202  }
203 }
204 
205 // main loop: running
207  while(1) {
209  if(!m_ready) continue;
210 
211  Vector2i effectiveWindowSize = Vector2i(-1,-1);
212  std::shared_ptr<sensor_msgs::msg::Image> lineMessageUPtr = std::make_unique<sensor_msgs::msg::Image>();
213 
214  m_carPoseMtx.lock();
215  lineMessageUPtr->header.stamp = m_currentCarPoseTimestamp;
216  std::shared_ptr<LinesObject<int16_t>> lineObj = m_mapDataLayer.getLineObject(m_currentCarPositionCM, m_currentAbsoluteOrientation, m_lineImageWindowSize, effectiveWindowSize);
217  m_carPoseMtx.unlock();
218 
219  // publish lane image
220  if (effectiveWindowSize[0] < 0 || effectiveWindowSize[1] < 0) log_warning("Effective Window Size not correct!");
221 
222  lineMessageUPtr->width = m_lineImageWindowSize[0];
223  lineMessageUPtr->height = m_lineImageWindowSize[1];
224  lineMessageUPtr->encoding = sensor_msgs::image_encodings::RGB8;
225  lineMessageUPtr->is_bigendian = 0;
226  lineMessageUPtr->step = lineMessageUPtr->width * 3;
227 
228  lineMessageUPtr->data.clear();
229  lineMessageUPtr->data.resize(lineMessageUPtr->step * lineMessageUPtr->height);
230 
231  int linePointsAmountOnImage = 0;
232 
233  // extract left line points
234  LinePoints<int16_t>* lineMapObjPtr = &lineObj->leftLine;
236 
237  for (int i = 0; i < 3; ++i) { // for all 3 lines
238  for(auto& [pointXRaw, pointsYVec] : lineMapObjPtr->getPointsXY()) {
239  for (auto& pointYRaw : pointsYVec) {
240  // rotate point
241  Vector2f vec = Vector2f(pointXRaw, pointYRaw);
242  vec = lineObj->reverseRotationMatrix * vec;
243 
244  // to integer
245  int pointX = std::round(vec[0]) + lineMessageUPtr->width / 2;
246  int pointY = lineMessageUPtr->height - std::round(vec[1]);
247 
248  //skip if behind car
249  if (pointX < 0 || pointY < 0 || pointX >= lineMessageUPtr->width || pointY >= lineMessageUPtr->height) {
250  continue;
251  }
252 
253  try {
254  int index = lineMessageUPtr->step * pointY + pointX * 3 + pixelByteIndex;
255  if(index >= static_cast<int>(lineMessageUPtr->data.size())) continue;
256 
257  lineMessageUPtr->data[index] = 255;
258 
259  linePointsAmountOnImage++;
260  }
261  catch (const std::exception& ex) {
262  log_warning("Exception thrown: ", ex.what());
263  }
264  }
265  }
266  // switch to next line (l->c->r)
267  if (pixelByteIndex == galaxis::autopilot::imageLLinePixelByteIndex) {
268  lineMapObjPtr = &lineObj->centerLine;
270  }
271  else if (pixelByteIndex == galaxis::autopilot::imageCLinePixelByteIndex) {
272  lineMapObjPtr = &lineObj->rightLine;
274  }
275  else {
276  // break;
277  }
278 
279  }
280 
281  // publish message
282  m_imgtransPub.publish(lineMessageUPtr);
283  log("LineDetection Top View Image Message sent! LinePointsAmountOnImage: ", linePointsAmountOnImage);
284 
285  m_carPoseMtx.lock();
286 
287  // obstacle message
288  std::unique_ptr<ObstacleListType> obstacleListUPtr = std::make_unique<ObstacleListType>();
289  obstacleListUPtr->header.stamp = m_currentCarPoseTimestamp; // this->get_clock()->now();
290 
291  bool obstacleFound = false;
292  for(auto& [id, obstacle] : m_obstacleMap) {
293  Vector2f distanceToObstacleVec = obstacle.positionCM - m_currentCarPositionCM;
294  if(distanceToObstacleVec.norm() <= m_obstacleDetectionDistanceCM) {
295 
296  Eigen::Rotation2Df rotationMat(m_currentAbsoluteOrientation);
297  distanceToObstacleVec = rotationMat * distanceToObstacleVec;
298 
299  if(distanceToObstacleVec[1] >= 0) {
300  // obstacle is in 180deg FOV -> add to object list
301  ObstacleType obstacleListElt;
302  obstacleListElt.pos_x = distanceToObstacleVec[0];
303  obstacleListElt.pos_x /= 100; // to m
304  obstacleListElt.pos_y = distanceToObstacleVec[1];
305  obstacleListElt.pos_y /= 100; // to m
306  obstacleListElt.width = obstacle.widthCM;
307  obstacleListElt.width /= 100; // to m
308 
309  obstacleListUPtr->obstacles.push_back(obstacleListElt);
310 
311  log("[OBSTACLE] Found in FOV. Distance: ", distanceToObstacleVec.norm(), " - Position x,y: ", distanceToObstacleVec[0], ",", distanceToObstacleVec[1]);
312  obstacleFound = true;
313  }
314  }
315  }
316 
317  m_carPoseMtx.unlock();
318 
319  if(obstacleFound) {
320  m_publisherObstacleSPtr->publish(std::move(obstacleListUPtr));
321  log("Obstacle Detection Message sent!");
322  }
323 
324  }
325 }
LaneDetectionGT::groundtruthRightLineCallback
void groundtruthRightLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message)
Definition: LaneDetectionGT.cpp:75
LEFT_LINE
@ LEFT_LINE
Definition: LaneDetectionGT.hpp:21
LaneDetectionGT::groundtruthCenterLineCallback
void groundtruthCenterLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message)
Definition: LaneDetectionGT.cpp:71
LaneDetectionGT::LaneDetectionGT
LaneDetectionGT()
Definition: LaneDetectionGT.cpp:26
ObstacleType
messages::msg::Obstacle ObstacleType
Definition: messages.hpp:59
node_ros_pubsub_wrapper.hpp
Obstacle::widthCM
float widthCM
Definition: LaneDetectionGT.hpp:29
LaneDetectionGT::m_currentCarPositionCM
Vector2f m_currentCarPositionCM
Definition: LaneDetectionGT.hpp:49
LaneDetectionGT::m_groundtruthTileIteratorRightLine
int m_groundtruthTileIteratorRightLine
Definition: LaneDetectionGT.hpp:44
LaneDetectionGT::m_carPoseMtx
std::mutex m_carPoseMtx
Definition: LaneDetectionGT.hpp:48
galaxis::autopilot::imageCLinePixelByteIndex
constexpr int imageCLinePixelByteIndex
Definition: AutopilotSettings.hpp:30
LaneDetectionGT::m_mapDataLayer
MapDataLayer m_mapDataLayer
Definition: LaneDetectionGT.hpp:36
LINE_TYPE
LINE_TYPE
Definition: LaneDetectionGT.hpp:20
LaneDetectionGT::m_obstacleDetectionDistanceCM
float m_obstacleDetectionDistanceCM
Definition: LaneDetectionGT.hpp:40
galaxis::ros
Definition: node_ros_pubsub_wrapper.hpp:15
galaxis::utils::log_warning
void log_warning(const Args &... args)
Definition: logger.hpp:41
MapDataLayer::getLineObject
std::shared_ptr< LinesObject< int16_t > > getLineObject(Vector2f absolutePositionCM, float lookBehindPosOffsetCM, double absoluteOrientation, Vector2i windowSize)
Definition: MapDataLayer.cpp:250
MapClasses.hpp
LaneDetectionGT::m_imgtransPub
image_transport::Publisher m_imgtransPub
Definition: LaneDetectionGT.hpp:63
LaneDetectionGT::m_subscriberRightLineSPtr
rclcpp::Subscription< visualization_msgs::msg::Marker >::SharedPtr m_subscriberRightLineSPtr
Definition: LaneDetectionGT.hpp:56
LaneDetectionGT::m_subscriberObstacleSPtr
rclcpp::Subscription< visualization_msgs::msg::Marker >::SharedPtr m_subscriberObstacleSPtr
Definition: LaneDetectionGT.hpp:58
LaneDetectionGT::groundtruthLeftLineCallback
void groundtruthLeftLineCallback(visualization_msgs::msg::Marker::SharedPtr p_message)
Definition: LaneDetectionGT.cpp:67
galaxis::map::data::LinePoints::getPointsXY
std::map< T, std::vector< T > > & getPointsXY()
Definition: MapClasses.hpp:57
LaneDetectionGT::m_currentAbsoluteOrientation
double m_currentAbsoluteOrientation
Definition: LaneDetectionGT.hpp:50
LaneDetectionGT::m_subscriberMiddleLineSPtr
rclcpp::Subscription< visualization_msgs::msg::Marker >::SharedPtr m_subscriberMiddleLineSPtr
Definition: LaneDetectionGT.hpp:55
LaneDetectionGT::m_subscriberLeftLineSPtr
rclcpp::Subscription< visualization_msgs::msg::Marker >::SharedPtr m_subscriberLeftLineSPtr
Definition: LaneDetectionGT.hpp:54
file.hpp
LaneDetectionGT::m_publisherObstacleSPtr
rclcpp::Publisher< ObstacleListType >::SharedPtr m_publisherObstacleSPtr
Definition: LaneDetectionGT.hpp:64
LaneDetectionGT::groundtruthObstacleCallback
void groundtruthObstacleCallback(visualization_msgs::msg::Marker::SharedPtr p_message)
Definition: LaneDetectionGT.cpp:136
MapDataLayer::updateMap
void updateMap(const sensor_msgs::msg::Image::ConstSharedPtr &laneDetectionSPtr, Vector2f currentAbsoluteCarPositionCM, double currentAbsoluteOrientation)
Definition: MapDataLayer.cpp:83
LaneDetectionGT::m_groundtruthTileIteratorCenterLine
int m_groundtruthTileIteratorCenterLine
Definition: LaneDetectionGT.hpp:43
galaxis::map::data::LinePoints
Definition: MapClasses.hpp:14
LaneDetectionGT::loop
void loop()
Definition: LaneDetectionGT.cpp:206
Obstacle
Definition: LaneDetectionGT.hpp:26
LaneDetectionGT::m_obstacleMap
std::map< int, Obstacle > m_obstacleMap
Definition: LaneDetectionGT.hpp:46
LaneDetectionGT::m_groundtruthTileIteratorLeftLine
int m_groundtruthTileIteratorLeftLine
Definition: LaneDetectionGT.hpp:42
galaxis::autopilot::imageLLinePixelByteIndex
constexpr int imageLLinePixelByteIndex
Definition: AutopilotSettings.hpp:29
galaxis::utils::read_configuration
shared_ptr< std::map< std::string, std::string > > read_configuration(string const &p_filepath)
Definition: file.cpp:41
LaneDetectionGT::carPoseCallback
void carPoseCallback(geometry_msgs::msg::Pose::SharedPtr p_message)
Definition: LaneDetectionGT.cpp:162
LaneDetectionGT::m_simulatedLDFPSWaitingTimeMicroseconds
int m_simulatedLDFPSWaitingTimeMicroseconds
Definition: LaneDetectionGT.hpp:38
LaneDetectionGT::m_lineImageWindowSize
Vector2i m_lineImageWindowSize
Definition: LaneDetectionGT.hpp:34
galaxis::lina::Vector2f
Eigen::Vector2f Vector2f
Definition: linatypes.hpp:14
LaneDetectionGT.hpp
LaneDetectionGT::m_ready
bool m_ready
Definition: LaneDetectionGT.hpp:39
LaneDetectionGT::m_currentCarPoseTimestamp
rclcpp::Time m_currentCarPoseTimestamp
Definition: LaneDetectionGT.hpp:51
galaxis::map::data
Definition: MapClasses.hpp:11
galaxis::autopilot::imageRLinePixelByteIndex
constexpr int imageRLinePixelByteIndex
Definition: AutopilotSettings.hpp:31
logger.hpp
LaneDetectionGT::~LaneDetectionGT
~LaneDetectionGT()
Definition: LaneDetectionGT.cpp:63
MATH_PI_DOUBLE
constexpr double MATH_PI_DOUBLE
Definition: LaneDetectionGT.cpp:23
LaneDetectionGT::groundtruthCallback
void groundtruthCallback(visualization_msgs::msg::Marker::SharedPtr p_message, LINE_TYPE type)
Definition: LaneDetectionGT.cpp:79
galaxis::utils
Definition: clock.hpp:5
LaneDetectionGT::checkReady
void checkReady()
Definition: LaneDetectionGT.cpp:195
galaxis::lina::Vector2i
Eigen::Vector2i Vector2i
Definition: linatypes.hpp:13
Obstacle::positionCM
Vector2f positionCM
Definition: LaneDetectionGT.hpp:28
galaxis::autopilot::simluationCarPositionOffsetToFrontAxisM
const galaxis::lina::Vector2f simluationCarPositionOffsetToFrontAxisM
Definition: AutopilotSettings.hpp:21
galaxis::utils::log
void log(const Args &... args)
Definition: logger.hpp:33
LaneDetectionGT::m_subscriberCarPoseSPtr
rclcpp::Subscription< geometry_msgs::msg::Pose >::SharedPtr m_subscriberCarPoseSPtr
Definition: LaneDetectionGT.hpp:60
RIGHT_LINE
@ RIGHT_LINE
Definition: LaneDetectionGT.hpp:23
AutopilotSettings.hpp
CENTER_LINE
@ CENTER_LINE
Definition: LaneDetectionGT.hpp:22