| 55 | } |
| 56 | |
| 57 | GridMap GridMapCvProcessing::getTransformedMap(GridMap&& gridMapSource, const Eigen::Isometry3d& transform, |
| 58 | const std::string& heightLayerName, const std::string& newFrameId) { |
| 59 | // Check if height layer is valid. |
| 60 | if (!gridMapSource.exists(heightLayerName)) { |
| 61 | throw std::out_of_range("GridMap::getTransformedMap(...) : No map layer '" + heightLayerName + "' available."); |
| 62 | } |
| 63 | |
| 64 | // Check if transformation is z aligned. |
| 65 | if (std::abs(transform(2, 2) - 1) >= 0.05) { |
| 66 | throw std::invalid_argument("The given transform is not Z aligned!"); |
| 67 | } |
| 68 | |
| 69 | auto yawPitchRoll = transform.rotation().eulerAngles(2, 1, 0); // Double check convention! |
| 70 | double rotationAngle = yawPitchRoll.x() * 180 / CV_PI; |
| 71 | if (std::abs(yawPitchRoll.y()) >= 3 && std::abs(yawPitchRoll.z()) >= 3) { // Resolve yaw ambiguity in euler angles. |
| 72 | rotationAngle += 180; |
| 73 | } |
| 74 | |
| 75 | gridMapSource.convertToDefaultStartIndex(); |
| 76 | |
| 77 | // Create the rotated gridMap. |
| 78 | GridMap transformedMap(gridMapSource.getLayers()); |
| 79 | transformedMap.setBasicLayers(gridMapSource.getBasicLayers()); |
| 80 | transformedMap.setTimestamp(gridMapSource.getTimestamp()); |
| 81 | transformedMap.setFrameId(newFrameId); |
| 82 | |
| 83 | // openCV rotation parameters, initalized on first layer. |
| 84 | cv::Mat imageRotationMatrix; |
| 85 | cv::Rect2f boundingBox; |
| 86 | |
| 87 | bool firstLayer = true; |
| 88 | for (const auto& layer : gridMapSource.getLayers()) { |
| 89 | cv::Mat imageSource, imageResult; |
| 90 | |
| 91 | // From gridMap to openCV image. Assumes defaultStartIndex. |
| 92 | cv::eigen2cv(gridMapSource[layer], imageSource); |
| 93 | |
| 94 | // Calculate transformation matrix and update geometry of the resulting grid map. |
| 95 | if (firstLayer) { |
| 96 | // Get rotation matrix for rotating the image around its center in pixel coordinates. See |
| 97 | // https://answers.opencv.org/question/82708/rotation-center-confusion/ |
| 98 | cv::Point2f imageCenter = |
| 99 | cv::Point2f((imageSource.cols - 1) / 2.0, (imageSource.rows - 1) / 2.0); |
| 100 | |
| 101 | imageRotationMatrix = cv::getRotationMatrix2D(imageCenter, rotationAngle, 1.0); |
| 102 | boundingBox = cv::RotatedRect(cv::Point2f(0, 0), imageSource.size(), rotationAngle).boundingRect2f(); |
| 103 | |
| 104 | // Adjust transformation matrix. See |
| 105 | // https://docs.opencv.org/3.4/da/d54/group__imgproc__transform.html#gafbbc470ce83812914a70abfb604f4326 and https://stackoverflow.com/questions/22041699/rotate-an-image-without-cropping-in-opencv-in-c |
| 106 | imageRotationMatrix.at<double>(0, 2) += boundingBox.width / 2.0 - imageSource.cols / 2.0; |
| 107 | imageRotationMatrix.at<double>(1, 2) += boundingBox.height / 2.0 - imageSource.rows / 2.0; |
| 108 | |
| 109 | // Calculate the new center of the gridMap. |
| 110 | Position3 newCenter = transform * Position3{(gridMapSource.getPosition().x()), (gridMapSource.getPosition().y()), 0.0}; |
| 111 | |
| 112 | // Set the size of the rotated gridMap. |
| 113 | transformedMap.setGeometry({boundingBox.height * gridMapSource.getResolution(), boundingBox.width * gridMapSource.getResolution()}, |
| 114 | gridMapSource.getResolution(), Position(newCenter.x(), newCenter.y())); |
nothing calls this directly
no test coverage detected