Skip to content

Commit 2389578

Browse files
committed
add plane projection and convex approximation to the demo
1 parent 8e68932 commit 2389578

File tree

8 files changed

+172
-19
lines changed

8 files changed

+172
-19
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
## Overview
44

55
This is a ROS package for elevation mapping on GPU. The elevation mapping code is written in python and uses cupy for GPU computation. The
6-
plane segmentation is done independently and runs on CPU.
6+
plane segmentation is done independently and runs on CPU. When the plane segmentation is generated, local convex approximations of the
7+
terrain can be efficiently generated.
78
![screenshot](doc/main_repo.png)
9+
![gif](doc/convex_approximation.gif)
810

911
## Citing
1012

doc/convex_approximation.gif

323 KB
Loading

plane_segmentation/convex_plane_decomposition_ros/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ target_link_libraries(${PROJECT_NAME}_save_elevationmap
8787
${OpenCV_LIBRARIES}
8888
)
8989

90+
add_executable(${PROJECT_NAME}_approximation_demo_node
91+
src/ConvexApproximationDemoNode.cpp
92+
)
93+
target_link_libraries(${PROJECT_NAME}_approximation_demo_node
94+
${catkin_LIBRARIES}
95+
${OpenCV_LIBRARIES}
96+
${PROJECT_NAME}
97+
)
98+
9099
#############
91100
## Install ##
92101
#############

plane_segmentation/convex_plane_decomposition_ros/include/convex_plane_decomposition_ros/RosVisualizations.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
#pragma once
22

3+
#include <geometry_msgs/PolygonStamped.h>
4+
35
#include <jsk_recognition_msgs/PolygonArray.h>
46

57
#include <convex_plane_decomposition/PlanarRegion.h>
68

79
namespace convex_plane_decomposition {
810

11+
geometry_msgs::PolygonStamped to3dRosPolygon(const CgalPolygon2d& polygon, const Eigen::Isometry3d& transformPlaneToWorld,
12+
const std_msgs::Header& header);
13+
14+
std::vector<geometry_msgs::PolygonStamped> to3dRosPolygon(const CgalPolygonWithHoles2d& polygonWithHoles,
15+
const Eigen::Isometry3d& transformPlaneToWorld, const std_msgs::Header& header);
16+
917
jsk_recognition_msgs::PolygonArray convertBoundariesToRosPolygons(const std::vector<PlanarRegion>& planarRegions,
1018
const std::string& frameId, grid_map::Time time);
1119

plane_segmentation/convex_plane_decomposition_ros/launch/demo.launch

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
<arg name="node_parameter_file" value="$(find convex_plane_decomposition_ros)/config/demo_node.yaml"/>
3939
</include>
4040

41+
<!-- Launch the approximation demo. -->
42+
<node pkg="convex_plane_decomposition_ros" type="convex_plane_decomposition_ros_approximation_demo_node" name="convex_plane_decomposition_ros_approximation_demo_node"
43+
output="screen" launch-prefix=""/>
44+
4145
<!-- Launch rviz. -->
4246
<node type="rviz" name="rviz" respawn="true" pkg="rviz" args="-d $(find convex_plane_decomposition_ros)/rviz/config_demo.rviz" />
4347

plane_segmentation/convex_plane_decomposition_ros/rviz/config_demo.rviz

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Panels:
55
Property Tree Widget:
66
Expanded:
77
- /Global Options1
8-
Splitter Ratio: 0.6307384967803955
8+
Splitter Ratio: 0.45271122455596924
99
Tree Height: 1658
1010
- Class: rviz/Selection
1111
Name: Selection
@@ -107,6 +107,37 @@ Visualization Manager:
107107
Unreliable: false
108108
Use Rainbow: false
109109
Value: false
110+
- Alpha: 1
111+
Class: rviz/PointStamped
112+
Color: 204; 41; 204
113+
Enabled: true
114+
History Length: 1
115+
Name: Query
116+
Queue Size: 10
117+
Radius: 0.10000000149011612
118+
Topic: /convex_plane_decomposition_ros_approximation_demo_node/queryPosition
119+
Unreliable: false
120+
Value: true
121+
- Alpha: 1
122+
Class: rviz/PointStamped
123+
Color: 245; 121; 0
124+
Enabled: true
125+
History Length: 1
126+
Name: Projection
127+
Queue Size: 10
128+
Radius: 0.10000000149011612
129+
Topic: /convex_plane_decomposition_ros_approximation_demo_node/projectedQueryPosition
130+
Unreliable: false
131+
Value: true
132+
- Alpha: 1
133+
Class: rviz/Polygon
134+
Color: 245; 121; 0
135+
Enabled: true
136+
Name: ConvexApproximation
137+
Queue Size: 10
138+
Topic: /convex_plane_decomposition_ros_approximation_demo_node/convex_terrain
139+
Unreliable: false
140+
Value: true
110141
Enabled: true
111142
Global Options:
112143
Background Color: 255; 255; 255
@@ -135,33 +166,33 @@ Visualization Manager:
135166
Views:
136167
Current:
137168
Class: rviz/XYOrbit
138-
Distance: 12.910699844360352
169+
Distance: 7.742486953735352
139170
Enable Stereo Rendering:
140171
Stereo Eye Separation: 0.05999999865889549
141172
Stereo Focal Distance: 1
142173
Swap Stereo Eyes: false
143174
Value: false
144175
Field of View: 0.7853981852531433
145176
Focal Point:
146-
X: 0.23195862770080566
147-
Y: 6.398481369018555
148-
Z: 3.2901763916015625e-05
177+
X: -3.113455057144165
178+
Y: 1.4824542999267578
179+
Z: 3.337860107421875e-05
149180
Focal Shape Fixed Size: true
150181
Focal Shape Size: 0.05000000074505806
151182
Invert Z Axis: false
152183
Name: Current View
153184
Near Clip Distance: 0.009999999776482582
154-
Pitch: 0.5807958841323853
185+
Pitch: 0.3057960569858551
155186
Target Frame: <Fixed Frame>
156-
Yaw: 1.4850016832351685
187+
Yaw: 2.410000801086426
157188
Saved: ~
158189
Window Geometry:
159190
Displays:
160191
collapsed: false
161192
Height: 2032
162193
Hide Left Dock: false
163194
Hide Right Dock: false
164-
QMainWindow State: 000000ff00000000fd0000000400000000000001f7000006e8fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b000000b000fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed0000033300000185000000b0fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000006e000006e80000018200fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000375fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000003750000013200fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e1000001970000000300000e7000000060fc0100000002fb0000000800540069006d0065010000000000000e700000057100fffffffb0000000800540069006d0065010000000000000450000000000000000000000c6d000006e800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
195+
QMainWindow State: 000000ff00000000fd0000000400000000000002b8000006e8fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b000000b000fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed0000033300000185000000b0fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000006e000006e80000018200fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000375fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d000003750000013200fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e1000001970000000300000e7000000060fc0100000002fb0000000800540069006d0065010000000000000e700000057100fffffffb0000000800540069006d0065010000000000000450000000000000000000000bac000006e800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
165196
Selection:
166197
collapsed: false
167198
Time:
@@ -171,5 +202,5 @@ Window Geometry:
171202
Views:
172203
collapsed: false
173204
Width: 3696
174-
X: 3984
205+
X: 144
175206
Y: 54
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//
2+
// Created by rgrandia on 24.06.20.
3+
//
4+
5+
#include <mutex>
6+
7+
#include <ros/ros.h>
8+
9+
#include <geometry_msgs/PointStamped.h>
10+
11+
#include <convex_plane_decomposition/ConvexRegionGrowing.h>
12+
#include <convex_plane_decomposition/GeometryUtils.h>
13+
#include <convex_plane_decomposition/SegmentedPlaneProjection.h>
14+
15+
#include <convex_plane_decomposition_msgs/PlanarTerrain.h>
16+
17+
#include <convex_plane_decomposition_ros/MessageConversion.h>
18+
#include <convex_plane_decomposition_ros/RosVisualizations.h>
19+
20+
const std::string frameId = "odom";
21+
std::mutex terrainMutex;
22+
std::unique_ptr<convex_plane_decomposition::PlanarTerrain> planarTerrainPtr;
23+
24+
void callback(const convex_plane_decomposition_msgs::PlanarTerrain::ConstPtr& msg) {
25+
std::unique_ptr<convex_plane_decomposition::PlanarTerrain> newTerrain(
26+
new convex_plane_decomposition::PlanarTerrain(convex_plane_decomposition::fromMessage(*msg)));
27+
28+
std::lock_guard<std::mutex> lock(terrainMutex);
29+
planarTerrainPtr.swap(newTerrain);
30+
}
31+
32+
geometry_msgs::PointStamped toMarker(const Eigen::Vector3d& position, const std_msgs::Header& header) {
33+
geometry_msgs::PointStamped sphere;
34+
sphere.header = header;
35+
sphere.point.x = position.x();
36+
sphere.point.y = position.y();
37+
sphere.point.z = position.z();
38+
return sphere;
39+
}
40+
41+
float randomFloat(float a, float b) {
42+
float random = ((float)rand()) / (float)RAND_MAX;
43+
float diff = b - a;
44+
float r = random * diff;
45+
return a + r;
46+
}
47+
48+
int main(int argc, char** argv) {
49+
ros::init(argc, argv, "convex_approximation_demo_node");
50+
ros::NodeHandle nodeHandle("~");
51+
52+
// Publishers for visualization
53+
auto positionPublisher = nodeHandle.advertise<geometry_msgs::PointStamped>("queryPosition", 1);
54+
auto projectionPublisher = nodeHandle.advertise<geometry_msgs::PointStamped>("projectedQueryPosition", 1);
55+
auto convexTerrainPublisher = nodeHandle.advertise<geometry_msgs::PolygonStamped>("convex_terrain", 1);
56+
auto terrainSubscriber = nodeHandle.subscribe("/convex_plane_decomposition_ros/planar_terrain", 1, &callback);
57+
58+
// Node loop
59+
ros::Rate rate(ros::Duration(1.0));
60+
while (ros::ok()) {
61+
{
62+
std::lock_guard<std::mutex> lock(terrainMutex);
63+
if (planarTerrainPtr) {
64+
const auto& map = planarTerrainPtr->gridMap;
65+
66+
// Find edges.
67+
double maxX = map.getPosition().x() + map.getLength().x() * 0.5;
68+
double minX = map.getPosition().x() - map.getLength().x() * 0.5;
69+
double maxY = map.getPosition().y() + map.getLength().y() * 0.5;
70+
double minY = map.getPosition().y() - map.getLength().y() * 0.5;
71+
72+
Eigen::Vector3d query{randomFloat(minX, maxX), randomFloat(minY, maxY), randomFloat(0.0, 1.0)};
73+
auto penaltyFunction = [](const Eigen::Vector3d& projectedPoint) { return 0.0; };
74+
75+
const auto projection = getBestPlanarRegionAtPositionInWorld(query, planarTerrainPtr->planarRegions, penaltyFunction);
76+
77+
int numberOfVertices = 16;
78+
double growthFactor = 1.05;
79+
const auto convexRegion = convex_plane_decomposition::growConvexPolygonInsideShape(
80+
projection.regionPtr->boundaryWithInset.boundary, projection.positionInTerrainFrame, numberOfVertices, growthFactor);
81+
82+
std_msgs::Header header;
83+
header.stamp.fromNSec(planarTerrainPtr->gridMap.getTimestamp());
84+
header.frame_id = frameId;
85+
86+
auto convexRegionMsg =
87+
convex_plane_decomposition::to3dRosPolygon(convexRegion, projection.regionPtr->transformPlaneToWorld, header);
88+
89+
convexTerrainPublisher.publish(convexRegionMsg);
90+
positionPublisher.publish(toMarker(query, header));
91+
projectionPublisher.publish(toMarker(projection.positionInWorld, header));
92+
}
93+
}
94+
95+
ros::spinOnce();
96+
rate.sleep();
97+
}
98+
99+
return 0;
100+
}

plane_segmentation/convex_plane_decomposition_ros/src/RosVisualizations.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
#include "convex_plane_decomposition_ros/RosVisualizations.h"
22

33
#include <geometry_msgs/Point32.h>
4-
#include <geometry_msgs/PolygonStamped.h>
54

65
namespace convex_plane_decomposition {
76

8-
inline geometry_msgs::PolygonStamped to3d(const CgalPolygon2d& polygon, const Eigen::Isometry3d& transformPlaneToWorld,
9-
const std_msgs::Header& header) {
7+
geometry_msgs::PolygonStamped to3dRosPolygon(const CgalPolygon2d& polygon, const Eigen::Isometry3d& transformPlaneToWorld,
8+
const std_msgs::Header& header) {
109
geometry_msgs::PolygonStamped polygon3d;
1110
polygon3d.header = header;
1211
polygon3d.polygon.points.reserve(polygon.size());
@@ -21,15 +20,15 @@ inline geometry_msgs::PolygonStamped to3d(const CgalPolygon2d& polygon, const Ei
2120
return polygon3d;
2221
}
2322

24-
inline std::vector<geometry_msgs::PolygonStamped> to3d(const CgalPolygonWithHoles2d& polygonWithHoles, const Eigen::Isometry3d& transformPlaneToWorld,
25-
const std_msgs::Header& header) {
23+
std::vector<geometry_msgs::PolygonStamped> to3dRosPolygon(const CgalPolygonWithHoles2d& polygonWithHoles,
24+
const Eigen::Isometry3d& transformPlaneToWorld, const std_msgs::Header& header) {
2625
std::vector<geometry_msgs::PolygonStamped> polygons;
2726

2827
polygons.reserve(polygonWithHoles.number_of_holes() + 1);
29-
polygons.emplace_back(to3d(polygonWithHoles.outer_boundary(), transformPlaneToWorld, header));
28+
polygons.emplace_back(to3dRosPolygon(polygonWithHoles.outer_boundary(), transformPlaneToWorld, header));
3029

3130
for (const auto& hole : polygonWithHoles.holes()) {
32-
polygons.emplace_back(to3d(hole, transformPlaneToWorld, header));
31+
polygons.emplace_back(to3dRosPolygon(hole, transformPlaneToWorld, header));
3332
}
3433
return polygons;
3534
}
@@ -46,7 +45,7 @@ jsk_recognition_msgs::PolygonArray convertBoundariesToRosPolygons(const std::vec
4645
polygon_buffer.labels.reserve(planarRegions.size());
4746
uint32_t label = 0;
4847
for (const auto& planarRegion : planarRegions) {
49-
auto boundaries = to3d(planarRegion.boundaryWithInset.boundary, planarRegion.transformPlaneToWorld, header);
48+
auto boundaries = to3dRosPolygon(planarRegion.boundaryWithInset.boundary, planarRegion.transformPlaneToWorld, header);
5049
std::move(boundaries.begin(), boundaries.end(), std::back_inserter(polygon_buffer.polygons));
5150
for (size_t i = 0; i < boundaries.size(); ++i) {
5251
polygon_buffer.labels.push_back(label);
@@ -70,7 +69,7 @@ jsk_recognition_msgs::PolygonArray convertInsetsToRosPolygons(const std::vector<
7069
uint32_t label = 0;
7170
for (const auto& planarRegion : planarRegions) {
7271
for (const auto& inset : planarRegion.boundaryWithInset.insets) {
73-
auto insets = to3d(inset, planarRegion.transformPlaneToWorld, header);
72+
auto insets = to3dRosPolygon(inset, planarRegion.transformPlaneToWorld, header);
7473
std::move(insets.begin(), insets.end(), std::back_inserter(polygon_buffer.polygons));
7574
for (size_t i = 0; i < insets.size(); ++i) {
7675
polygon_buffer.labels.push_back(label);

0 commit comments

Comments
 (0)