9 #include <sensor_msgs/image_encodings.hpp>
11 using std::placeholders::_1;
20 log(
"AutoPilotNode: Initializing...");
24 std::string configPath =
"settings/onstartup_autopilot.json";
26 json& settingsJson = (*settingsJsonSPtr)[
"settings"];
36 if(settingsJson[
"wait_for_qr_code_detection"] ==
false) {
40 catch (
const std::runtime_error& error) {
42 log_warning(
"##########################################################");
43 log_warning(
"############## READING CONFIGURATION FAILED ##############");
44 log_warning(
"############# Falling BACK TO DEFAULT CONFIG #############");
45 log_warning(
"##########################################################");
64 rclcpp::QoS qos_params_situation = get_qos_profile(QOS_RELIABLE);
65 m_autopilotStatePubSPtr = this->create_publisher<std_msgs::msg::UInt8>(
"/galaxis/ap/situation_state", qos_params_situation);
71 rclcpp::QoS qos_params = get_qos_profile(QOS_BEST_EFFORT);
73 galaxis::ros::TOPIC_VCI_LANE_IMAGE_SIMULATION,
78 qos_params = get_qos_profile(QOS_BEST_EFFORT);
93 log_warning(
"SimulationLineDetection and Autopilot must run in same docker container!");
96 galaxis::ros::create_subscription(
this,
103 rclcpp::QoS qos_params = get_qos_profile(QOS_BEST_EFFORT);
105 galaxis::ros::TOPIC_VCI_LANE_IMAGE_SIMULATION,
128 rclcpp::Time timeNow = this->get_clock()->now();
138 log(
"AutopilotNode: Waiting for messages...");
159 std::unique_ptr<CarPoseEstimatedType> carposeUPtr = std::make_unique<CarPoseEstimatedType>();
160 carposeUPtr->pose.pos_x = localizationPointSPtr->position[0] / 1000;
161 carposeUPtr->pose.pos_y = localizationPointSPtr->position[1] / 1000;
162 carposeUPtr->pose.orientation = localizationPointSPtr->orientation;
163 carposeUPtr->header.stamp = localizationPointSPtr->timestamp;
173 long long time = stopwatch.
get_time();
175 if(time > 0) usleep(time);
188 auto msgUPtr = std::make_unique<std_msgs::msg::UInt8>();
192 long long time = stopwatch.
get_time();
193 log(
"\033[33mAutoPilotNode [debug_publish_loop]: Sending Debug Messages [microsec]: ", time,
"\033[0m");
207 log(
"\033[44[AutoPilotNode] [lane_detection_shared_memory_loop] New lane message!\033[49");
209 sensor_msgs::msg::Image::SharedPtr imageMsg = std::make_shared<sensor_msgs::msg::Image>();
210 imageMsg->height = 256;
211 imageMsg->width = 256;
212 imageMsg->step = imageMsg->width * 3;
213 imageMsg->data.resize(imageMsg->step * imageMsg->height);
214 imageMsg->encoding = sensor_msgs::image_encodings::RGB8;
216 data.
data = imageMsg->data.data();
217 data.
dataSize = imageMsg->data.size();
220 if(dataSizeRead == 0) {
221 log_warning(
"[AutoPilotNode] Sth failed while reading shared memory!");
225 log_warning(
"[AutoPilotNode] Shared Memory: Failed to read whole image!");
228 imageMsg->header.stamp = rclcpp::Time(data.
tv_sec, data.
tv_nsec);
235 std::this_thread::sleep_for(3ms);
241 rclcpp::Time currentTime = this->get_clock()->now();
245 double siny_cosp = 2 * (p_message->orientation.w * p_message->orientation.z + p_message->orientation.x * p_message->orientation.y);
246 double cosy_cosp = 1 - 2 * (p_message->orientation.y * p_message->orientation.y + p_message->orientation.z * p_message->orientation.z);
247 double yaw = std::atan2(siny_cosp, cosy_cosp);
252 absoluteYOrientation = std::fmod(absoluteYOrientation, 2*
MATH_PI_DOUBLE);
258 Eigen::Rotation2Df rotationMat(-absoluteYOrientation);
259 carPosOffToFrontAx = rotationMat * carPosOffToFrontAx;
260 position += carPosOffToFrontAx;
271 log(
"AutoPilotNode: Received Measurements Message");
272 rclcpp::Time msgTimestamp = msg->header.stamp;
275 double orientation = msg->orientation;
283 log(
"AutoPilotNode: Received Lane Detection Message! Image Age [millisec]: ", (this->get_clock()->now() - msg->header.stamp).nanoseconds() / 1000000.f,
"; Last Update was before [millisec]: ", (this->get_clock()->now() -
m_lastLaneDetectionUpdate).nanoseconds() / 1000000.f);
287 log_warning(
"AutoPilotNode: Localizer never received Car Position. Skip.");
291 if(msg->encoding != sensor_msgs::image_encodings::RGB8) {
292 log_warning(
"AutoPilotNode: Lane Detection Image Encoding wrong! Must be RGB8 (skipping frame)");
299 rclcpp::Time msgTimestamp = msg->header.stamp;
308 auto localizationLookupDiffTime = msgTimestamp - localizationPointSPtr->timestamp;
309 log_debug(
"AutoPilotNode: Lane Detection-Pose Lookup Diff Time [nanosec]: ", localizationLookupDiffTime.nanoseconds());
310 log_debug(
"AutoPilotNode: Lookup Orientation [Rad]: ", localizationPointSPtr->orientation);
315 catch (
const std::runtime_error& error) {
316 log_error(
"Runtime ERROR: ", error.what());
319 log(
"AutoPilotNode [on_vci_lane_detection_callback]: Map Data Layer update duration [microsec]: ", stopwatch.
get_time());
331 log(
"\033[36mAutoPilotNode [send_controller_references]: Polynom Extraction [microsec]: ", stopwatch.
get_time(),
"\033[0m");
333 std::unique_ptr<PathpolynomType> polyMsg = std::make_unique<PathpolynomType>();
335 polyMsg->header.stamp = this->get_clock()->now();
346 log_error(
"[AutopilotNode] Polynom Wrong.");
356 polyMsg->right_enabled =
true;
366 polyMsg->center_enabled =
true;
376 polyMsg->left_enabled =
true;
379 std::unique_ptr<ControllerReferenceType> controllerRefMsgUPtr = std::make_unique<ControllerReferenceType>();
381 controllerRefMsgUPtr->header.stamp = this->get_clock()->now();
387 std::unique_ptr<ParkingOperationType> parkingOperationUPtr = std::make_unique<ParkingOperationType>();
388 parkingOperationUPtr->header = polyMsg->header;
390 parkingOperationUPtr->operation = 2;
393 parkingOperationUPtr->operation = 1;
404 log_warning(
"AutoPilotNode [on_obstacle_callback]: Obstacle CB - Localizer never received Car Position. Skip.");
408 if(msg->obstacles.size() <= 0) {
return; }
410 log(
"AutoPilotNode: Obstacle Message received. Size: ", msg->obstacles.size());
412 rclcpp::Time msgTimestamp = msg->header.stamp;
416 for(
auto obstacleTypeObj : msg->obstacles) {
422 log_debug(
"AutoPilotNode: QRCode Message received. Value: ", msg->detected);
424 if(msg->detected ==
true) {
434 log_debug(
"AutoPilotNode: StopLine Message received. Value: ", msg->stopline_distance);
437 if(msg->stopline_flag ==
true) {
445 if(currentOrientation < min || currentOrientation > max) {
450 if(msg->startline_flag ==
true) {
452 float minOrientationForParking = 2.f;
453 float maxOrientationForParking = 4.f;
457 if(currentOrientation >= minOrientationForParking && currentOrientation <= maxOrientationForParking) {
458 positionOffset = currentPosition;
465 log_debug(
"AutoPilotNode: ParkingState Message received. Value: ",
int(msg->state));
467 switch (msg->state) {
492 log(
"AutoPilotNode [send_map_debug_image]: Skip sending message. Reason: NO Subscriber");
496 log_warning(
"AutoPilotNode [send_map_debug_image]: Cannot send map data (not existing). Skipped.");
502 std::shared_ptr<sensor_msgs::msg::Image> lineMessageUPtr = std::make_unique<sensor_msgs::msg::Image>();
504 lineMessageUPtr->header.stamp = positionTimepointNow->timestamp;
508 lineMessageUPtr->encoding = sensor_msgs::image_encodings::RGB8;
509 lineMessageUPtr->is_bigendian = 0;
510 lineMessageUPtr->step = lineMessageUPtr->width * 3;
512 lineMessageUPtr->data.clear();
513 lineMessageUPtr->data.resize(lineMessageUPtr->step * lineMessageUPtr->height);
515 int linePointsAmountOnImage = 0;
523 for (
int i = 0; i < 3; ++i) {
524 for(
auto& [pointXRaw, pointsYVec] : lineMapObjPtr->
getPointsXY()) {
525 for (
auto& pointYRaw : pointsYVec) {
530 vec += shiftVecForLookBehind;
533 int pointX = std::round(vec[0]) + lineMessageUPtr->width / 2;
534 int pointY = lineMessageUPtr->height - std::round(vec[1]);
537 if (pointX < 0 || pointY < 0 || pointX >=
static_cast<int>(lineMessageUPtr->width) || pointY >=
static_cast<int>(lineMessageUPtr->height)) {
542 int index = lineMessageUPtr->step * pointY + pointX * 3 + pixelByteIndex;
543 if(index < 0 || index >=
static_cast<int>(lineMessageUPtr->data.size()))
continue;
545 lineMessageUPtr->data[index] = 255;
547 linePointsAmountOnImage++;
549 catch (
const std::exception& ex) {
550 log_warning(
"AutopilotNode: [send_map_debug_image] Exception thrown: ", ex.what());
570 bool rightLane =
true;
571 for (
int i = 0; i < 2; ++i) {
572 for(
auto& point : *vectorPtr) {
573 int imgPointX = std::round(point[0] + shiftVecForLookBehind[0]) + lineMessageUPtr->width / 2;
574 int imgPointY = lineMessageUPtr->height - std::round(point[1] + shiftVecForLookBehind[1]);
577 if (imgPointX < 0 || imgPointY < 0 || imgPointX >=
static_cast<int>(lineMessageUPtr->width) || imgPointY >=
static_cast<int>(lineMessageUPtr->height)) {
582 int index = lineMessageUPtr->step * imgPointY + imgPointX * 3;
583 if(index < 0 || index + 2 >=
static_cast<int>(lineMessageUPtr->data.size()))
continue;
586 lineMessageUPtr->data[index] = 255;
589 lineMessageUPtr->data[index + 1] = 255;
592 lineMessageUPtr->data[index + 2] = 255;
594 linePointsAmountOnImage++;
596 catch (
const std::exception& ex) {
597 log_warning(
"AutopilotNode: [send_map_debug_image] Exception thrown: ", ex.what());
608 for(
unsigned int i = 0; i < lineMessageUPtr->height; ++i) {
609 int index = i * lineMessageUPtr->step + origin[0] * 3;
610 if(index < 0 || index + 2 >=
static_cast<int>(lineMessageUPtr->data.size()))
log_warning(
"AutoPilotNode [send_map_debug_image]: While sending debug map message. (origin draw grid (X))");
611 lineMessageUPtr->data[index] = 255;
612 lineMessageUPtr->data[index + 1] = 255;
613 lineMessageUPtr->data[index + 2] = 255;
616 for(
unsigned int i = 0; i < lineMessageUPtr->width; ++i) {
618 if(index < 0 || index + 2 >=
static_cast<int>(lineMessageUPtr->data.size()))
log_warning(
"AutoPilotNode [send_map_debug_image]: While sending debug map message. (origin draw grid (Y))");
619 lineMessageUPtr->data[index] = 255;
620 lineMessageUPtr->data[index + 1] = 255;
621 lineMessageUPtr->data[index + 2] = 255;
626 Eigen::Rotation2Df rotationMat(positionTimepointNow->orientation);
628 Vector2f relObsPos = obstacle.get_position_now() - positionTimepointNow->position / 10;
629 relObsPos = rotationMat * relObsPos;
630 relObsPos += shiftVecForLookBehind;
632 int radiusCM = obstacle.get_width() / 2;
633 for(
int y = -radiusCM; y <= radiusCM; y++) {
634 for(
int x = -radiusCM; x <= radiusCM; x++) {
635 if(x*x+y*y <= radiusCM*radiusCM) {
636 int imageX = relObsPos[0] + x + lineMessageUPtr->width / 2;
637 int imageY = lineMessageUPtr->height - relObsPos[1] + y;
638 int index = imageY * lineMessageUPtr->step + imageX * 3;
641 if (imageX < 0 || imageY < 0 || imageX >=
static_cast<int>(lineMessageUPtr->width) || imageY >=
static_cast<int>(lineMessageUPtr->height)) {
645 if(index >= 0 && index + 2 <=
static_cast<int>(lineMessageUPtr->data.size())) {
646 lineMessageUPtr->data[index] = 255;
647 lineMessageUPtr->data[index + 1] = 255;
648 lineMessageUPtr->data[index + 2] = 255;
662 for(
int i = 0; i < 2; i++) {
669 for(
auto const& point : points) {
670 int imgPointX = std::round(point[0] + shiftVecForLookBehind[0]) + lineMessageUPtr->width / 2;
671 int imgPointY = lineMessageUPtr->height - std::round(point[1] + shiftVecForLookBehind[1]);
674 if (imgPointX < 0 || imgPointY < 0 || imgPointX >=
static_cast<int>(lineMessageUPtr->width) || imgPointY >=
static_cast<int>(lineMessageUPtr->height)) {
679 int index = lineMessageUPtr->step * imgPointY + imgPointX * 3;
680 if(index < 0 || index + 2 >=
static_cast<int>(lineMessageUPtr->data.size()))
continue;
683 lineMessageUPtr->data[index] = r;
686 lineMessageUPtr->data[index + 1] = g;
689 lineMessageUPtr->data[index + 2] = b;
691 linePointsAmountOnImage++;
693 catch (
const std::exception& ex) {
694 log_warning(
"AutopilotNode: [send_map_debug_image] Exception thrown: ", ex.what());
701 for(
int x = -shiftVecForLookBehind[1]; x < lineMessageUPtr->height - shiftVecForLookBehind[1]; ++x) {
706 int imgPointX = std::round(-y + shiftVecForLookBehind[0]) + lineMessageUPtr->width / 2;
707 int imgPointY = lineMessageUPtr->height - std::round(x + shiftVecForLookBehind[1]);
710 if (imgPointX < 0 || imgPointY < 0 || imgPointX >=
static_cast<int>(lineMessageUPtr->width) || imgPointY >=
static_cast<int>(lineMessageUPtr->height)) {
715 int index = lineMessageUPtr->step * imgPointY + imgPointX * 3;
716 if(index < 0 || index + 2 >=
static_cast<int>(lineMessageUPtr->data.size()))
continue;
718 lineMessageUPtr->data[index] = 204;
719 lineMessageUPtr->data[index+1] = 204;
720 lineMessageUPtr->data[index+2] = 204;
722 linePointsAmountOnImage++;
724 catch (
const std::exception& ex) {
725 log_warning(
"AutopilotNode: [send_map_debug_image] Exception thrown: ", ex.what());
733 log(
"AutoPilotNode [send_map_debug_image]: Data Layer Image Message sent. LinePointsAmountOnImage: ", linePointsAmountOnImage);
738 log(
"AutoPilotNode [send_full_map_debug_image]: Skip sending message. Reason: NO Subscriber");
746 auto lineMessageUPtr = std::make_unique<sensor_msgs::msg::Image>();
748 lineMessageUPtr->header.stamp = this->get_clock()->now();
749 lineMessageUPtr->width = extractionWindow[0];
750 lineMessageUPtr->height = extractionWindow[1];
751 lineMessageUPtr->encoding = sensor_msgs::image_encodings::RGB8;
752 lineMessageUPtr->is_bigendian = 0;
753 lineMessageUPtr->step = lineMessageUPtr->width * 3;
755 lineMessageUPtr->data.clear();
756 lineMessageUPtr->data.resize(lineMessageUPtr->step * lineMessageUPtr->height);
765 for (
int i = 0; i < 3; ++i) {
766 for(
auto& [pointXRaw, pointsYVec] : lineObjPtr->
getPointsXY()) {
767 for (
auto& pointYRaw : pointsYVec) {
773 int pointX = std::round(vec[0]) + lineMessageUPtr->width / 2;
774 int pointY = lineMessageUPtr->height - std::round(vec[1]);
777 if (pointX < 0 || pointY < 0 || pointX >=
static_cast<int>(lineMessageUPtr->width) || pointY >=
static_cast<int>(lineMessageUPtr->height)) {
782 int index = lineMessageUPtr->step * pointY + pointX * 3 + pixelByteIndex;
783 if(index >=
static_cast<int>(lineMessageUPtr->data.size()))
continue;
785 lineMessageUPtr->data[index] = 255;
787 catch (
const std::exception& ex) {
788 log_warning(
"AutoPilotNode: [send_full_map_debug_image] Exception thrown: ", ex.what());
794 lineObjPtr = &linesObjRaw->centerLine;
798 lineObjPtr = &linesObjRaw->rightLine;
807 log(
"AutoPilotNode [send_full_map_debug_image]: Data Layer FULL MAP Image Message sent. Time consumed [ms]: ", stopwatch.
get_milliseconds());
813 log(
"[AutopilotNode] NEW PARAMETERS");
815 rcl_interfaces::msg::SetParametersResult result;
816 result.successful =
true;
819 for (
const auto ¶m: parameters) {
820 if (param.get_name() ==
"obstacle.position_diff_for_rerecognition_cm") {
821 if(check_parameter<int>(param, result, 0)) {
825 else if (param.get_name() ==
"obstacle.obstacle_lookup_distance_cm") {
826 if(check_parameter<int>(param, result, 0)) {
830 else if (param.get_name() ==
"obstacle.obstacle_lookup_distance_step_cm") {
831 if(check_parameter<int>(param, result, 0)) {
835 else if (param.get_name() ==
"obstacle.obstacle_to_lane_center_minimum_distance_for_dodge_cm") {
836 if(check_parameter<int>(param, result, 0)) {
840 else if (param.get_name() ==
"obstacle.obstacle_track_time_ms") {
841 if(check_parameter<int>(param, result, 0)) {
842 div_t divres = div(
int(param.as_int()), 1000);
846 else if (param.get_name() ==
"map_data_layer.lookup_window_size_width_cm") {
847 if(check_parameter<int>(param, result, 0, 300.0)) {
851 else if (param.get_name() ==
"map_data_layer.lookup_window_size_height_cm") {
852 if(check_parameter<int>(param, result, 0, 300.0)) {
861 else if (param.get_name() ==
"map_data_layer.grid_cell_threshold_import") {
862 if(check_parameter<int>(param, result, 0, 255)) {
866 else if (param.get_name() ==
"map_data_layer.grid_cell_threshold_extract") {
867 if(check_parameter<int>(param, result, 0, 255)) {
871 else if (param.get_name() ==
"map_data_layer.grid_cell_threshold_decrease_per_step") {
872 if(check_parameter<int>(param, result, 0, 255)) {
876 else if (param.get_name() ==
"map_data_layer.grid_cell_threshold_increase_per_view") {
877 if(check_parameter<int>(param, result, 0, 255)) {
881 else if (param.get_name() ==
"map_data_extraction_postprocessing.cluster_line_eps_cm") {
882 if(check_parameter<int>(param, result, 1, 50)) {
886 else if (param.get_name() ==
"map_data_extraction_postprocessing.cluster_line_min_pts") {
887 if(check_parameter<int>(param, result, 1, 50)) {
891 else if (param.get_name() ==
"trajectory_polynom.degree") {
892 if(check_parameter<int>(param, result, 1, 10)) {
896 else if (param.get_name() ==
"trajectory_polynom.minimum_points_amount") {
897 if(check_parameter<int>(param, result)) {
901 else if (param.get_name() ==
"trajectory_polynom.append_points_behind_amount") {
902 if(check_parameter<int>(param, result, 0)) {
906 else if (param.get_name() ==
"trajectory_polynom.append_points_behind_distance_cm") {
907 if(check_parameter<int>(param, result, 1, 200)) {
911 else if (param.get_name() ==
"decision.velocity_reference_m_s") {
912 if(check_parameter<double>(param, result, 0.0, 3.0)) {
916 else if (param.get_name() ==
"decision.distance_after_switch_back_to_drive_lane_m") {
917 if(check_parameter<double>(param, result, 0.0, 10.0)) {
921 else if (param.get_name() ==
"decision.critical_obstacle_distance_for_lane_changing_cm") {
922 if(check_parameter<int>(param, result, 0, 500)) {
926 else if (param.get_name() ==
"decision.velocity_reference_parking_zone_m_s") {
927 if(check_parameter<double>(param, result, 0, 2)) {
931 else if (param.get_name() ==
"controller_reference.send_sleep_time_micros") {
932 if(check_parameter<int>(param, result, 1, 100000)) {
936 else if (param.get_name() ==
"lane_center_improvement.polynom_evaluation_step_cm") {
937 if(check_parameter<int>(param, result, 1)) {
941 else if (param.get_name() ==
"lane_center_improvement.polynom_evaluation_step_size_cm") {
942 if(check_parameter<int>(param, result, 1, 100)) {
946 else if (param.get_name() ==
"lane_center_improvement.minimum_number_of_clustered_line_points_to_activate") {
947 if(check_parameter<int>(param, result, 0)) {
951 else if (param.get_name() ==
"control_lines.ignore_stopline_in_start_area_radius_mm") {
952 if(check_parameter<double>(param, result, 0, 100000)) {
957 result.successful =
false;
958 result.reason +=
"[" + param.get_name() +
"] UNKNOWN param or NOT IMPLEMENTED; ";
962 if(result.successful ==
false) {
963 log_warning(
"[AutopilotNode] Failed to set some parameters. Reasons: ", result.reason);