Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
laser
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Model registry
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mobile_robotics
wolf_projects
wolf_lib
plugins
laser
Compare revisions
devel to 27-new-branch-laser-3d-2
Compare revisions
Changes are shown as if the
source
revision was being merged into the
target
revision.
Learn more about comparing revisions.
Source
mobile_robotics/wolf_projects/wolf_lib/plugins/laser
Select target project
No results found
27-new-branch-laser-3d-2
Select Git revision
Swap
Target
mobile_robotics/wolf_projects/wolf_lib/plugins/laser
Select target project
mobile_robotics/wolf_projects/wolf_lib/plugins/laser
1 result
devel
Select Git revision
Show changes
Only incoming changes from source
Include changes to target since source was created
Compare
View open merge request
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
test/gtest_laser3d_tools.cpp
+161
-0
161 additions, 0 deletions
test/gtest_laser3d_tools.cpp
test/gtest_processor_odom_icp_3d.cpp
+172
-0
172 additions, 0 deletions
test/gtest_processor_odom_icp_3d.cpp
test/yaml/problem_odom_icp_3d.yaml
+52
-0
52 additions, 0 deletions
test/yaml/problem_odom_icp_3d.yaml
with
385 additions
and
0 deletions
test/gtest_laser3d_tools.cpp
0 → 100644
Edit
View file @
11d440cd
//--------LICENSE_START--------
//
// Copyright (C) 2020,2021,2022 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
// Authors: Joan Solà Ortega (jsola@iri.upc.edu)
// All rights reserved.
//
// This file is part of WOLF
// WOLF is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//--------LICENSE_END--------
// wolf laser
#include
"laser/utils/laser3d_tools.h"
#include
"laser/internal/config.h"
// //Wolf
#include
"core/common/wolf.h"
#include
"core/utils/utils_gtest.h"
#include
<core/math/rotations.h>
// pcl
#include
<pcl/registration/gicp.h>
#include
<pcl/registration/gicp6d.h>
// Eigen
#include
<Eigen/Geometry>
// std
#include
<iostream>
#include
<string>
#include
<filesystem>
#include
<unistd.h>
//#define write_results
////// vsainz: i have to write a test
using
namespace
wolf
;
using
namespace
Eigen
;
std
::
string
laser_root_dir
=
_WOLF_LASER_ROOT_DIR
;
TEST
(
pairAlign
,
identity
)
{
// Load data
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_ref
=
pcl
::
make_shared
<
pcl
::
PointCloud
<
pcl
::
PointXYZ
>>
();
loadData
(
laser_root_dir
+
"/test/data/1.pcd"
,
*
pcl_ref
);
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_other
=
pcl_ref
;
// same PCld --> ground truth transform is identity
WOLF_INFO
(
"Ground truth transform :
\n
"
,
Matrix4d
::
Identity
());
// Guess
Isometry3d
transformation_guess
=
Translation3d
(
1
,
1
,
1
)
*
AngleAxisd
(
0.2
,
Vector3d
(
1
,
2
,
3
).
normalized
());
WOLF_INFO
(
"Initial guess transform:
\n
"
,
transformation_guess
.
matrix
());
// final transform
Isometry3d
transformation_final
;
// Solver configuration
RegistrationPtr
registration_solver
=
pcl
::
make_shared
<
pcl
::
IterativeClosestPointNonLinear
<
pcl
::
PointXYZ
,
pcl
::
PointXYZ
>>
();
registration_solver
->
setTransformationEpsilon
(
1e-6
);
// Set the maximum distance between two correspondences (src<->tgt) to 10cm
// Note: adjust this based on the size of your datasets
registration_solver
->
setMaxCorrespondenceDistance
(
0.5
);
// visaub: changed to 100 cm
// Set the point representation
// reg.setPointRepresentation(pcl::make_shared<const MyPointRepresentation>(point_representation));
registration_solver
->
setMaximumIterations
(
200
);
pclDownsample
(
pcl_ref
,
pcl_ref
);
pclDownsample
(
pcl_other
,
pcl_other
);
// Alignment
wolf
::
pairAlign
(
pcl_ref
,
pcl_other
,
transformation_guess
,
transformation_final
,
registration_solver
);
WOLF_INFO
(
"Final transform:
\n
"
,
transformation_final
.
matrix
());
ASSERT_MATRIX_APPROX
(
transformation_final
.
matrix
(),
Matrix4d
::
Identity
(),
1e-2
);
}
TEST
(
pairAlign
,
known_transformation
)
{
// Load data
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_ref
=
pcl
::
make_shared
<
pcl
::
PointCloud
<
pcl
::
PointXYZ
>>
();
loadData
(
laser_root_dir
+
"/test/data/1.pcd"
,
*
pcl_ref
);
// known transform
Affine3d
transformation_known
=
Affine3d
::
Identity
();
transformation_known
.
translation
()
<<
1.0
,
0.5
,
0.2
;
transformation_known
.
rotate
(
AngleAxisd
(
0.3
,
Vector3d
::
UnitZ
()));
// Move point cloud
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_other
=
pcl
::
make_shared
<
pcl
::
PointCloud
<
pcl
::
PointXYZ
>>
();
pcl
::
transformPointCloud
(
*
pcl_ref
,
*
pcl_other
,
transformation_known
);
// Guess
Isometry3d
transformation_guess
=
Isometry3d
::
Identity
();
// final transform
Isometry3d
transformation_final
;
WOLF_INFO
(
"Applied transformation:
\n
"
,
transformation_known
.
matrix
());
// Solver configuration
RegistrationPtr
registration_solver
=
pcl
::
make_shared
<
pcl
::
IterativeClosestPointNonLinear
<
pcl
::
PointXYZ
,
pcl
::
PointXYZ
>>
();
// pcl::GeneralizedIterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> registration_solver;
double
max_trans_epsilon_meters
=
0.001
;
double
max_rot_epsilon_degrees
=
0.1
;
double
trf_rotation_epsilon
=
cos
(
toRad
(
max_rot_epsilon_degrees
));
registration_solver
->
setTransformationEpsilon
(
max_trans_epsilon_meters
*
max_trans_epsilon_meters
);
registration_solver
->
setTransformationRotationEpsilon
(
trf_rotation_epsilon
);
// Set the maximum distance between two correspondences (src<->tgt) to 10cm
// Note: adjust this based on the size of your datasets
registration_solver
->
setMaxCorrespondenceDistance
(
0.5
);
// visaub: changed to 100 cm
registration_solver
->
setMaximumIterations
(
100
);
// Downsample
pclDownsample
(
pcl_ref
,
pcl_ref
,
0.1
);
pclDownsample
(
pcl_other
,
pcl_other
,
0.1
);
// Alignment
wolf
::
pairAlign
(
pcl_ref
,
pcl_other
,
transformation_guess
,
transformation_final
,
registration_solver
);
WOLF_INFO
(
"Final transform:
\n
"
,
transformation_final
.
matrix
());
// auto convcrit = registration_solver->getConvergeCriteria();
// WOLF_INFO("convergence criteria: ", registration_solver->getConvergeCriteria()->getConvergenceState());
ASSERT_MATRIX_APPROX
(
transformation_final
.
matrix
(),
transformation_known
.
matrix
(),
1e-2
);
}
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
// ::testing::GTEST_FLAG(filter) = "pairAlign.known_transformation";
return
RUN_ALL_TESTS
();
}
This diff is collapsed.
Click to expand it.
test/gtest_processor_odom_icp_3d.cpp
0 → 100644
Edit
View file @
11d440cd
//--------LICENSE_START--------
//
// Copyright (C) 2020,2021,2022 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
// Authors: Joan Solà Ortega (jsola@iri.upc.edu)
// All rights reserved.
//
// This file is part of WOLF
// WOLF is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//--------LICENSE_END--------
// wolf laser
#include
"laser/sensor/sensor_laser_3d.h"
#include
"laser/processor/processor_odom_icp_3d.h"
#include
"laser/internal/config.h"
// wolf core
#include
"core/common/wolf.h"
#include
<core/sensor/factory_sensor.h>
#include
"core/processor/factory_processor.h"
// wolf yaml
#include
<core/utils/params_server.h>
#include
<core/yaml/parser_yaml.h>
#include
"core/yaml/yaml_conversion.h"
// testing
#include
<core/utils/utils_gtest.h>
#include
<core/utils/logging.h>
// pcl includes
#include
<pcl/point_cloud.h>
#include
<pcl/io/pcd_io.h>
#include
<pcl/filters/voxel_grid.h>
// other includes
#include
<string>
using
namespace
wolf
;
std
::
string
laser_root_dir
=
_WOLF_LASER_ROOT_DIR
;
class
Test_ProcessorOdomIcp3D_yaml
:
public
testing
::
Test
{
public:
ProblemPtr
P
;
SensorLaser3dPtr
S
;
ProcessorOdomIcp3dPtr
p
;
FrameBasePtr
F0
,
F1
,
F
;
CaptureLaser3dPtr
C0
,
C1
,
C2
,
C3
;
VectorXd
data
;
MatrixXd
data_cov
;
protected:
void
SetUp
()
override
{
WOLF_INFO
(
laser_root_dir
);
ParserYaml
parser
=
ParserYaml
(
"problem_odom_icp_3d.yaml"
,
laser_root_dir
+
"/test/yaml/"
);
ParamsServer
server
=
ParamsServer
(
parser
.
getParams
());
P
=
Problem
::
autoSetup
(
server
);
S
=
std
::
static_pointer_cast
<
SensorLaser3d
>
(
P
->
getHardware
()
->
getSensorList
().
front
());
p
=
std
::
static_pointer_cast
<
ProcessorOdomIcp3d
>
(
S
->
getProcessorList
().
front
());
P
->
print
(
4
,
1
,
1
,
1
);
}
};
TEST
(
Init
,
register_in_factories
)
{
FactorySensor
::
registerCreator
(
"SensorLaser3d"
,
SensorLaser3d
::
create
);
AutoConfFactorySensor
::
registerCreator
(
"SensorLaser3d"
,
SensorLaser3d
::
create
);
FactoryProcessor
::
registerCreator
(
"ProcessorOdomIcp3d"
,
ProcessorOdomIcp3d
::
create
);
AutoConfFactoryProcessor
::
registerCreator
(
"ProcessorOdomIcp3d"
,
ProcessorOdomIcp3d
::
create
);
}
TEST_F
(
Test_ProcessorOdomIcp3D_yaml
,
process_make_keyframes_always_same_pcl
)
{
std
::
vector
<
VectorComposite
>
X
(
10
);
auto
last_kf_id
=
P
->
getLastFrame
()
?
P
->
getLastFrame
()
->
id
()
:
0
;
unsigned
int
i
=
0
;
for
(
TimeStamp
t
=
0
;
t
<
10
;
t
+=
1
)
{
// Load pointcloud from file
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_ref0
=
pcl
::
make_shared
<
pcl
::
PointCloud
<
pcl
::
PointXYZ
>>
();
loadData
(
laser_root_dir
+
"/test/data/1.pcd"
,
*
pcl_ref0
);
// make Capture and process
C0
=
std
::
make_shared
<
CaptureLaser3d
>
(
t
,
S
,
pcl_ref0
);
C0
->
process
();
// store state where the KFs are
if
(
p
->
getOrigin
()
->
getFrame
()
->
id
()
!=
last_kf_id
)
{
last_kf_id
=
P
->
getLastFrame
()
->
id
();
X
[
i
]
=
p
->
getLast
()
->
getFrame
()
->
getState
(
"PO"
);
i
++
;
}
}
P
->
print
(
4
,
1
,
1
,
1
);
ASSERT_MATRIX_APPROX
(
X
.
at
(
0
).
vector
(
"PO"
),
X
.
at
(
1
).
vector
(
"PO"
),
1e-8
);
// pointclouds are the same
ASSERT_MATRIX_APPROX
(
X
.
at
(
0
).
vector
(
"PO"
),
X
.
at
(
2
).
vector
(
"PO"
),
1e-8
);
// pointclouds are the same
ASSERT_MATRIX_APPROX
(
X
.
at
(
0
).
vector
(
"PO"
),
X
.
at
(
3
).
vector
(
"PO"
),
1e-8
);
// pointclouds are the same
ASSERT_MATRIX_APPROX
(
X
.
at
(
0
).
vector
(
"PO"
),
X
.
at
(
4
).
vector
(
"PO"
),
1e-8
);
// pointclouds are the same
ASSERT_MATRIX_APPROX
(
X
.
at
(
0
).
vector
(
"PO"
),
X
.
at
(
5
).
vector
(
"PO"
),
1e-8
);
// pointclouds are the same
}
TEST_F
(
Test_ProcessorOdomIcp3D_yaml
,
process_kitti
)
{
// Loads different kitti frames
// source: 2011_09_26_drive_0005_sync/velodyne_points
std
::
vector
<
VectorComposite
>
X
(
15
);
unsigned
int
i
=
0
;
std
::
string
fname
;
//ex: 0000000050.bin
TimeStamp
t
=
0.0
;
// should be read from velodyne_points/timestamps.txt
for
(
int
j
=
100
;
j
<=
105
;
j
++
)
// from scan 100 to 105
{
// Load pointcloud from file
pcl
::
PointCloud
<
pcl
::
PointXYZ
>::
Ptr
pcl_ref_j
=
pcl
::
make_shared
<
pcl
::
PointCloud
<
pcl
::
PointXYZ
>>
();
fname
=
"0000000000"
+
std
::
to_string
(
j
)
+
".bin"
;
fname
=
fname
.
substr
(
fname
.
length
()
-
14
,
fname
.
length
());
loadData
(
laser_root_dir
+
"/test/data/kitti/"
+
fname
,
*
pcl_ref_j
);
WOLF_INFO
(
"Loaded PointCloud "
+
fname
);
// make Capture and process
C0
=
std
::
make_shared
<
CaptureLaser3d
>
(
t
,
S
,
pcl_ref_j
);
C0
->
process
();
// store state at integer timestamps (where the KFs are)
if
(
std
::
fabs
(
t
.
get
()
-
(
double
)
i
)
<
0.1
)
{
X
[
i
]
=
p
->
getLast
()
->
getFrame
()
->
getState
(
"PO"
);
i
++
;
}
t
+=
0.1
;
}
P
->
print
(
4
,
1
,
1
,
1
);
}
/*
TEST(Test_ProcessorOdomIcp3D_yaml, load_single_binary){
pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_ref_i = pcl::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
loadData(laser_root_dir + "/test/data/kitti/0000000101.bin", *pcl_ref_i);
}*/
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
// ::testing::GTEST_FLAG(filter) = "Test_ProcessorOdomIcp3D_yaml.process_kitti";
return
RUN_ALL_TESTS
();
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
test/yaml/problem_odom_icp_3d.yaml
0 → 100644
Edit
View file @
11d440cd
config
:
problem
:
frame_structure
:
"
PO"
dimension
:
3
prior
:
mode
:
"
factor"
$state
:
P
:
[
0
,
0
,
0
]
O
:
[
0
,
0
,
0
,
1
]
$sigma
:
P
:
[
.1
,
.1
,
.1
]
O
:
[
.1
,
.1
,
.1
]
time_tolerance
:
0.05
tree_manager
:
type
:
"
None"
map
:
type
:
"
MapBase"
plugin
:
"
core"
sensors
:
-
name
:
"
Lidar"
type
:
"
SensorLaser3d"
# No
plugin
:
"
laser"
extrinsic
:
pose
:
[
0.5
,
0
,
0
,
0
,
0
,
0
,
1
]
processors
:
-
name
:
"
Odometry
ICP
3d"
type
:
"
ProcessorOdomIcp3d"
sensor_name
:
"
Lidar"
plugin
:
"
laser"
time_tolerance
:
0.05
max_new_features
:
0
apply_loss_function
:
false
keyframe_vote
:
voting_active
:
true
min_features_for_keyframe
:
0
max_time_span
:
0.000099
# KF every frame
max_fitness_score
:
0.0001
# maximum Euclidean fitness score (e.g., mean of squared distances from the source to the target)
angle_turned
:
1.0
state_getter
:
true
state_priority
:
1
pcl_downsample
:
true
pcl_downsample_voxel_size
:
0.20
icp_algorithm
:
"
icp_nl"
# "icp", "icp_nl", "gicp"
icp_max_iterations
:
20
icp_transformation_rotation_epsilon
:
0.9999
# this is cos(alpha)
icp_transformation_translation_epsilon
:
1e-9
# this is translation squared
icp_max_correspondence_distance
:
0.05
This diff is collapsed.
Click to expand it.
Prev
1
2
Next