Skip to content

Commit 5d3e0ef

Browse files
Extend pcl_manual_registration with visual aides and alignment inspection popup
1 parent 670f359 commit 5d3e0ef

7 files changed

Lines changed: 227 additions & 60 deletions

File tree

apps/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ if(VTK_FOUND)
8585
${SUBSYS_NAME}
8686
SOURCES
8787
include/pcl/apps/manual_registration.h
88+
include/pcl/apps/pcl_viewer_dialog.h
8889
src/manual_registration/manual_registration.cpp
90+
src/manual_registration/pcl_viewer_dialog.cpp
8991
src/manual_registration/manual_registration.ui
92+
src/manual_registration/pcl_viewer_dialog.ui
9093
BUNDLE)
9194

9295
target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface pcl_filters ${QTX}::Widgets)

apps/include/pcl/apps/manual_registration.h

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,6 @@
4848

4949
using PointT = pcl::PointXYZ;
5050

51-
// Useful macros
52-
// clang-format off
53-
#define FPS_CALC(_WHAT_) \
54-
do { \
55-
static unsigned count = 0; \
56-
static double last = pcl::getTime(); \
57-
double now = pcl::getTime(); \
58-
++count; \
59-
if (now - last >= 1.0) { \
60-
std::cout << "Average framerate(" << _WHAT_ << "): " \
61-
<< double(count) / double(now - last) << " Hz" << std::endl; \
62-
count = 0; \
63-
last = now; \
64-
} \
65-
} while (false)
66-
// clang-format on
67-
6851
namespace Ui {
6952
class MainWindow;
7053
}
@@ -76,6 +59,8 @@ class ManualRegistration : public QMainWindow {
7659
using CloudPtr = Cloud::Ptr;
7760
using CloudConstPtr = Cloud::ConstPtr;
7861

62+
PCL_MAKE_ALIGNED_OPERATOR_NEW;
63+
7964
ManualRegistration();
8065

8166
~ManualRegistration() override = default;
@@ -94,7 +79,7 @@ class ManualRegistration : public QMainWindow {
9479
}
9580

9681
void
97-
SourcePointPickCallback(const pcl::visualization::PointPickingEvent& event, void*);
82+
SrcPointPickCallback(const pcl::visualization::PointPickingEvent& event, void*);
9883
void
9984
DstPointPickCallback(const pcl::visualization::PointPickingEvent& event, void*);
10085

@@ -131,6 +116,9 @@ class ManualRegistration : public QMainWindow {
131116

132117
Eigen::Matrix4f transform_ = Eigen::Affine3f::Identity().matrix();
133118

119+
std::set<std::string> annotations_src_;
120+
std::set<std::string> annotations_dst_;
121+
134122
public Q_SLOTS:
135123
void
136124
confirmSrcPointPressed();
@@ -146,10 +134,8 @@ public Q_SLOTS:
146134
applyTransformPressed();
147135
void
148136
refinePressed();
149-
void
150-
undoPressed();
151-
void
152-
safePressed();
137+
/* void */
138+
/* undoPressed(); */
153139

154140
private Q_SLOTS:
155141
void
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
#include <pcl/visualization/pcl_visualizer.h>
3+
#include <pcl/point_cloud.h>
4+
#include <pcl/point_types.h>
5+
6+
#include <Eigen/Geometry>
7+
8+
#include <QDialog>
9+
#include <QTimer>
10+
11+
using CloudT = pcl::PointCloud<pcl::PointXYZ>;
12+
13+
namespace Ui {
14+
class PCLViewerDialogUi;
15+
}
16+
17+
class PCLViewerDialog : public QDialog {
18+
Q_OBJECT
19+
Ui::PCLViewerDialogUi* ui_;
20+
QTimer* render_timer_;
21+
pcl::visualization::PCLVisualizer::Ptr vis_;
22+
23+
public:
24+
PCLViewerDialog(QWidget* parent = 0);
25+
26+
void
27+
setPointClouds(CloudT::ConstPtr src_cloud,
28+
CloudT::ConstPtr tgt_cloud,
29+
const Eigen::Affine3f& t);
30+
31+
public Q_SLOTS:
32+
33+
void
34+
refreshView();
35+
};

apps/src/manual_registration/manual_registration.cpp

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
*/
4040

4141
#include <pcl/apps/manual_registration.h>
42+
#include <pcl/apps/pcl_viewer_dialog.h>
4243
#include <pcl/filters/voxel_grid.h>
4344
#include <pcl/io/pcd_io.h> // for loadPCDFile
4445
#include <pcl/registration/icp.h>
@@ -61,6 +62,9 @@
6162
#include <vtkRendererCollection.h>
6263

6364
using namespace pcl;
65+
using namespace pcl::visualization;
66+
using std::string;
67+
using std::to_string;
6468

6569
//////////////////////////////////////////////////////////////////////////////////////////////////////////
6670
ManualRegistration::ManualRegistration()
@@ -93,7 +97,7 @@ ManualRegistration::ManualRegistration()
9397
vis_src_->getInteractorStyle()->setKeyboardModifier(
9498
pcl::visualization::INTERACTOR_KB_MOD_SHIFT);
9599

96-
vis_src_->registerPointPickingCallback(&ManualRegistration::SourcePointPickCallback,
100+
vis_src_->registerPointPickingCallback(&ManualRegistration::SrcPointPickCallback,
97101
*this);
98102

99103
// Set up the destination window
@@ -135,15 +139,14 @@ ManualRegistration::ManualRegistration()
135139
this,
136140
SLOT(applyTransformPressed()));
137141
connect(ui_->refineButton, SIGNAL(clicked()), this, SLOT(refinePressed()));
138-
connect(ui_->undoButton, SIGNAL(clicked()), this, SLOT(undoPressed()));
139-
connect(ui_->safeButton, SIGNAL(clicked()), this, SLOT(safePressed()));
142+
/* connect(ui_->undoButton, SIGNAL(clicked()), this, SLOT(undoPressed())); */
140143

141144
cloud_src_modified_ = true; // first iteration is always a new pointcloud
142145
cloud_dst_modified_ = true;
143146
}
144147

145148
void
146-
ManualRegistration::SourcePointPickCallback(
149+
ManualRegistration::SrcPointPickCallback(
147150
const pcl::visualization::PointPickingEvent& event, void*)
148151
{
149152
// Check to see if we got a valid point. Early exit.
@@ -188,6 +191,13 @@ ManualRegistration::confirmSrcPointPressed()
188191
PCL_INFO("Selected %zu source points\n", static_cast<std::size_t>(src_pc_.size()));
189192
src_point_selected_ = false;
190193
src_pc_.width = src_pc_.size();
194+
const string annotation = "marker-" + to_string(annotations_src_.size());
195+
vis_src_->addSphere(src_point_, 0.02, annotation);
196+
vis_src_->setShapeRenderingProperties(PCL_VISUALIZER_OPACITY, 0.2, annotation);
197+
vis_src_->setShapeRenderingProperties(
198+
PCL_VISUALIZER_COLOR, 0.5, 0.25, 0.25, annotation);
199+
vis_src_->getShapeActorMap()->at(annotation)->SetPickable(false);
200+
annotations_src_.emplace(annotation);
191201
}
192202
else {
193203
PCL_INFO("Please select a point in the source window first\n");
@@ -203,6 +213,14 @@ ManualRegistration::confirmDstPointPressed()
203213
static_cast<std::size_t>(dst_pc_.size()));
204214
dst_point_selected_ = false;
205215
dst_pc_.width = dst_pc_.size();
216+
217+
const string annotation = "marker-" + std::to_string(annotations_dst_.size());
218+
vis_dst_->addSphere(dst_point_, 0.02, annotation);
219+
vis_dst_->setShapeRenderingProperties(PCL_VISUALIZER_OPACITY, 0.2, annotation);
220+
vis_dst_->setShapeRenderingProperties(
221+
PCL_VISUALIZER_COLOR, 0.5, 0.25, 0.25, annotation);
222+
vis_dst_->getShapeActorMap()->at(annotation)->SetPickable(false);
223+
annotations_dst_.emplace(annotation);
206224
}
207225
else {
208226
PCL_INFO("Please select a point in the destination window first\n");
@@ -218,12 +236,30 @@ ManualRegistration::calculatePressed()
218236
}
219237
pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> tfe;
220238
tfe.estimateRigidTransformation(src_pc_, dst_pc_, transform_);
221-
std::cout << "Transform : " << std::endl << transform_ << std::endl;
239+
PCL_INFO("Calculated tranform:\n%1.5f %1.5f %1.5f %1.5f\n%1.5f %1.5f %1.5f "
240+
"%1.5f\n%1.5f %1.5f %1.5f %1.5f\n%1.5f %1.5f %1.5f %1.5f\n",
241+
transform_(0, 0),
242+
transform_(0, 1),
243+
transform_(0, 2),
244+
transform_(0, 3),
245+
transform_(1, 0),
246+
transform_(1, 1),
247+
transform_(1, 2),
248+
transform_(1, 3),
249+
transform_(2, 0),
250+
transform_(2, 1),
251+
transform_(2, 2),
252+
transform_(2, 3),
253+
transform_(3, 0),
254+
transform_(3, 1),
255+
transform_(3, 2),
256+
transform_(3, 3));
222257
}
223258

224259
void
225260
ManualRegistration::clearPressed()
226261
{
262+
PCL_INFO("Clearing points.");
227263
dst_point_selected_ = false;
228264
src_point_selected_ = false;
229265
src_pc_.clear();
@@ -232,6 +268,16 @@ ManualRegistration::clearPressed()
232268
src_pc_.width = 0;
233269
dst_pc_.height = 1;
234270
dst_pc_.width = 0;
271+
272+
for (const string& annotation : annotations_src_) {
273+
vis_src_->removeShape(annotation);
274+
}
275+
annotations_src_.clear();
276+
277+
for (const string& annotation : annotations_dst_) {
278+
vis_dst_->removeShape(annotation);
279+
}
280+
annotations_dst_.clear();
235281
}
236282

237283
void
@@ -272,16 +318,17 @@ ManualRegistration::orthoChanged(int state)
272318
void
273319
ManualRegistration::applyTransformPressed()
274320
{
275-
visualization::PCLVisualizer vis_both;
276-
vis_both.addPointCloud(cloud_dst_, "cloud_dst_");
277-
vis_both.addPointCloud(cloud_src_, "cloud_src_");
278-
vis_both.updatePointCloudPose("cloud_src_", Eigen::Affine3f(transform_));
279-
vis_both.spin();
321+
PCLViewerDialog* diag = new PCLViewerDialog(this);
322+
diag->setModal(true);
323+
diag->setGeometry(this->x(), this->y(), this->width(), this->height());
324+
diag->setPointClouds(cloud_src_, cloud_dst_, Eigen::Affine3f(transform_));
325+
diag->show();
280326
}
281327

282328
void
283329
ManualRegistration::refinePressed()
284330
{
331+
PCL_INFO("Refining transform ...\n");
285332
VoxelGrid<PointT> grid_filter;
286333
grid_filter.setLeafSize(0.05, 0.05, 0.05);
287334
PointCloud<PointT>::Ptr src_copy{new PointCloud<PointT>(*cloud_src_)};
@@ -291,28 +338,43 @@ ManualRegistration::refinePressed()
291338
grid_filter.setInputCloud(dst_copy);
292339
grid_filter.filter(*dst_copy);
293340

294-
IterativeClosestPoint<PointT, PointT>::Ptr icp{
295-
new IterativeClosestPoint<PointT, PointT>};
341+
using ICP = IterativeClosestPoint<PointT, PointT>;
342+
ICP::Ptr icp = pcl::make_shared<ICP>();
296343
icp->setInputSource(src_copy);
297344
icp->setInputTarget(dst_copy);
345+
298346
icp->setMaximumIterations(100);
299347
icp->setMaxCorrespondenceDistance(0.1);
300-
icp->setEuclideanFitnessEpsilon(0.000000001);
301-
icp->setTransformationEpsilon(0.000000001);
302-
icp->setTransformationRotationEpsilon(0.000000001);
348+
icp->setEuclideanFitnessEpsilon(0.01);
349+
icp->setTransformationEpsilon(0.01);
350+
icp->setTransformationRotationEpsilon(0.01);
303351
PointCloud<PointT>::Ptr aligned{new PointCloud<PointT>};
304352
icp->align(*aligned, transform_);
305353
transform_ = icp->getFinalTransformation();
306-
std::cout << "refined transform:\n" << transform_ << std::endl;
307-
}
308354

309-
void
310-
ManualRegistration::undoPressed()
311-
{}
355+
PCL_INFO("Calculated tranform:\n%1.5f %1.5f %1.5f %1.5f\n%1.5f %1.5f %1.5f "
356+
"%1.5f\n%1.5f %1.5f %1.5f %1.5f\n%1.5f %1.5f %1.5f %1.5f\n",
357+
transform_(0, 0),
358+
transform_(0, 1),
359+
transform_(0, 2),
360+
transform_(0, 3),
361+
transform_(1, 0),
362+
transform_(1, 1),
363+
transform_(1, 2),
364+
transform_(1, 3),
365+
transform_(2, 0),
366+
transform_(2, 1),
367+
transform_(2, 2),
368+
transform_(2, 3),
369+
transform_(3, 0),
370+
transform_(3, 1),
371+
transform_(3, 2),
372+
transform_(3, 3));
373+
}
312374

313-
void
314-
ManualRegistration::safePressed()
315-
{}
375+
/* void */
376+
/* ManualRegistration::undoPressed() */
377+
/* {} */
316378

317379
void
318380
ManualRegistration::timeoutSlot()
@@ -343,8 +405,10 @@ ManualRegistration::refreshView()
343405
{
344406
#if VTK_MAJOR_VERSION > 8
345407
ui_->qvtk_widget_dst->renderWindow()->Render();
408+
ui_->qvtk_widget_src->renderWindow()->Render();
346409
#else
347410
ui_->qvtk_widget_dst->update();
411+
ui_->qvtk_widget_src->update();
348412
#endif // VTK_MAJOR_VERSION > 8
349413
}
350414

apps/src/manual_registration/manual_registration.ui

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,17 @@
9696
</property>
9797
</widget>
9898
</item>
99-
<item>
100-
<widget class="QPushButton" name="safeButton">
101-
<property name="text">
102-
<string>Safe Transform</string>
103-
</property>
104-
</widget>
105-
</item>
106-
<item>
107-
<widget class="QPushButton" name="undoButton">
108-
<property name="text">
109-
<string>Undo</string>
110-
</property>
111-
</widget>
112-
</item>
99+
<!-- <item> -->
100+
<!-- <widget class="QPushButton" name="undoButton"> -->
101+
<!-- <property name="text"> -->
102+
<!-- <string>Undo</string> -->
103+
<!-- </property> -->
104+
<!-- </widget> -->
105+
<!-- </item> -->
113106
<item>
114107
<widget class="QCheckBox" name="orthoButton">
115108
<property name="text">
116-
<string>OrthoGraphic</string>
109+
<string>Orthographic</string>
117110
</property>
118111
</widget>
119112
</item>

0 commit comments

Comments
 (0)