Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make lidar measurement model class #195

Merged
merged 31 commits into from
Sep 25, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e619675
Make lidar measurement model class
at-wat Sep 9, 2018
81cf634
Fix model
at-wat Sep 9, 2018
0a7a366
Fix includes
at-wat Sep 9, 2018
7e6e2ad
Merge branch 'master' into lidar-measurement-model-class
at-wat Sep 11, 2018
2b8bff5
Don't return null shared_ptr from random sampler
at-wat Sep 18, 2018
26e606b
Add test for PointCloudRandomSampler class
at-wat Sep 18, 2018
4ba9695
Fix constness
at-wat Sep 18, 2018
2982960
Fix signed/unsigned compare
at-wat Sep 18, 2018
59645ad
Define beam model as a class
at-wat Sep 18, 2018
c7de317
Remove unused variables
at-wat Sep 18, 2018
75d130c
Merge branch 'master' into lidar-measurement-model-class
at-wat Sep 18, 2018
4c5350c
Add comment
at-wat Sep 19, 2018
7caf1e0
Transfar old parameter values to new ones
at-wat Sep 19, 2018
3c87670
Remove unused parameters
at-wat Sep 19, 2018
2d5d062
Change log output level
at-wat Sep 19, 2018
d024a99
Fix parameter name migration rule
at-wat Sep 19, 2018
a28be14
Fix function name
at-wat Sep 19, 2018
6c4befc
Update parameter name in test launches
at-wat Sep 19, 2018
5cd5ff2
Add test for mcl_3dl_compat::paramRename
at-wat Sep 19, 2018
9a8a451
Address review comments
at-wat Sep 20, 2018
0d8990a
Address review comments
at-wat Sep 20, 2018
f9444b8
Fix test
at-wat Sep 20, 2018
b37c72e
Remove STATE_TYPE from LidarMeasurementModel template parameter
at-wat Sep 21, 2018
de81133
Remove POINT_TYPE from LidarMeasurementModel template parameter
at-wat Sep 21, 2018
b2e8e71
Move impl from .h to .cpp
at-wat Sep 21, 2018
a038fad
Add LidarMeasurementResult struct to return measurement result
at-wat Sep 21, 2018
257a144
Fix constness
at-wat Sep 25, 2018
49572be
Fix State6Dof's size value
at-wat Sep 25, 2018
239b387
Add range assert to the State6Dof::[] operator
at-wat Sep 25, 2018
2efa4a7
Address review comments
at-wat Sep 25, 2018
cca96e3
Add dummy return to State6Dof::operator[] for out-of-range index
at-wat Sep 25, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions include/mcl_3dl/lidar_measurement_model_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018, the mcl_3dl authors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef MCL_3DL_LIDAR_MEASUREMENT_MODEL_BASE_H
#define MCL_3DL_LIDAR_MEASUREMENT_MODEL_BASE_H
DaikiMaekawa marked this conversation as resolved.
Show resolved Hide resolved

#include <ros/ros.h>

#include <pcl/point_types.h>
#include <pcl_ros/point_cloud.h>

#include <mcl_3dl/pf.h>

namespace mcl_3dl
{
template <class STATE_TYPE, class POINT_TYPE>
class LidarMeasurementModelBase
{
static_assert(
std::is_base_of<pf::ParticleBase<float>, STATE_TYPE>::value,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is odd. how come you force to use only float? as it's template, a programmer might give other types, too.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's very complicated to static_assert templated class.
allowing pf::ParticleBase<float> and also pf::ParticleBase<double> would be enough for now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this interface class doesn't need to take STATE_TYPE as class templates.
STATE_TYPE is used only for an argument of measure function. So, for me up-casting to pf::ParticleBase by the function argument is sufficient.

Copy link
Owner Author

@at-wat at-wat Sep 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, this makes sense for me.
However in this case, since pf::ParticleBase is templated, it is not allowed to be used as an argument of virtual function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you bind interfaces by pure virtual function, yes. Taking a derived class via class template parameter, and static cast from this pointer to a derived class for each member functions allows you to make common function interfaces that has own template parameters.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, these lidar measurement models are available only for State6DOF, not for general pf::ParticleBase.
So, just support State6DOF would be enough for this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds reasonable.

"STATE_TYPE is not based on pf::ParticleBase<float>");

public:
DaikiMaekawa marked this conversation as resolved.
Show resolved Hide resolved
using Ptr = std::shared_ptr<LidarMeasurementModelBase<STATE_TYPE, POINT_TYPE>>;

virtual void loadConfig(
const ros::NodeHandle &nh,
const std::string &name) = 0;
DaikiMaekawa marked this conversation as resolved.
Show resolved Hide resolved
virtual void setGlobalLocalizationStatus(
size_t, size_t) = 0;

virtual typename pcl::PointCloud<POINT_TYPE>::Ptr filter(
const typename pcl::PointCloud<POINT_TYPE>::Ptr &) const = 0;

virtual std::pair<float, float> measure(
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

define measurement result type

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on this PR?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I've forgotten this. thanks.

typename mcl_3dl::ChunkedKdtree<POINT_TYPE>::Ptr &,
const typename pcl::PointCloud<POINT_TYPE>::Ptr &,
const STATE_TYPE &) const = 0;
};
} // namespace mcl_3dl

#endif // MCL_3DL_LIDAR_MEASUREMENT_MODEL_BASE_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (c) 2018, the mcl_3dl authors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDEDNode BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef MCL_3DL_LIDAR_MEASUREMENT_MODEL_LIDAR_MEASUREMENT_MODEL_LIKELIHOOD_H
#define MCL_3DL_LIDAR_MEASUREMENT_MODEL_LIDAR_MEASUREMENT_MODEL_LIKELIHOOD_H

#include <ros/ros.h>

#include <pcl/point_types.h>
#include <pcl_ros/point_cloud.h>

#include <mcl_3dl/pf.h>
#include <mcl_3dl/point_cloud_random_sampler.h>

namespace mcl_3dl
{
template <class STATE_TYPE, class POINT_TYPE>
class LidarMeasurementModelLikelihood : public LidarMeasurementModelBase<STATE_TYPE, POINT_TYPE>
{
private:
size_t num_points_;
size_t num_points_default_;
size_t num_points_global_;
float clip_far_sq_;
float clip_near_sq_;
float clip_z_min_;
float clip_z_max_;
float match_weight_;
float match_dist_min_;
float match_dist_flat_;

PointCloudRandomSampler<POINT_TYPE> sampler_;

public:
void loadConfig(
const ros::NodeHandle &nh,
const std::string &name)
{
ros::NodeHandle pnh(nh, name);

int num_points, num_points_global;
pnh.param("num_points", num_points, 96);
pnh.param("num_points_global", num_points_global, 8);
num_points_default_ = num_points_ = num_points;
num_points_global_ = num_points_global;

double clip_near, clip_far;
pnh.param("clip_near", clip_near, 0.5);
pnh.param("clip_far", clip_far, 10.0);
clip_near_sq_ = clip_near * clip_near;
clip_far_sq_ = clip_far * clip_far;

double clip_z_min, clip_z_max;
pnh.param("clip_z_min", clip_z_min, -2.0);
pnh.param("clip_z_max", clip_z_max, 2.0);
clip_z_min_ = clip_z_min;
clip_z_max_ = clip_z_max;

double match_weight;
pnh.param("match_weight", match_weight, 5.0);
match_weight_ = match_weight;

double match_dist_min, match_dist_flat;
pnh.param("match_dist_min", match_dist_min, 0.2);
pnh.param("match_dist_flat", match_dist_flat, 0.05);
match_dist_min_ = match_dist_min;
match_dist_flat_ = match_dist_flat;
}
void setGlobalLocalizationStatus(
size_t num_particles,
size_t current_num_particles)
{
if (current_num_particles <= num_particles)
{
num_points_ = num_points_default_;
return;
}
size_t num = num_points_;
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

num_points_default_

if (current_num_particles > num_particles)
num = num * num_particles / current_num_particles;
if (num < num_points_global_)
num = num_points_global_;

num_points_ = num;
}

typename pcl::PointCloud<POINT_TYPE>::Ptr filter(
const typename pcl::PointCloud<POINT_TYPE>::Ptr &pc) const
{
const auto local_points_filter = [this](const POINT_TYPE &p)
{
if (p.x * p.x + p.y * p.y > clip_far_sq_)
return true;
if (p.x * p.x + p.y * p.y < clip_near_sq_)
return true;
if (p.z < clip_z_min_ || clip_z_max_ < p.z)
return true;
return false;
};
pc->erase(
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy before erase

std::remove_if(pc->begin(), pc->end(), local_points_filter), pc->end());
pc->width = 1;
pc->height = pc->points.size();

return sampler_.sample(pc, num_points_);
}

std::pair<float, float> measure(
typename mcl_3dl::ChunkedKdtree<POINT_TYPE>::Ptr &kdtree,
const typename pcl::PointCloud<POINT_TYPE>::Ptr &pc,
const STATE_TYPE &s) const
{
pcl::PointCloud<pcl::PointXYZI>::Ptr pc_particle(new pcl::PointCloud<pcl::PointXYZI>);
std::vector<int> id(1);
std::vector<float> sqdist(1);

float score_like = 0;
*pc_particle = *pc;
s.transform(*pc_particle);
size_t num = 0;
for (auto &p : pc_particle->points)
{
if (kdtree->radiusSearch(p, match_dist_min_, id, sqdist, 1))
{
const float dist = match_dist_min_ - std::max(sqrtf(sqdist[0]), match_dist_flat_);
if (dist < 0.0)
continue;

score_like += dist * match_weight_;
num++;
}
}
const float match_ratio = static_cast<float>(num) / pc_particle->points.size();

return std::pair<float, float>(score_like, match_ratio);
}
};
} // namespace mcl_3dl

#endif // MCL_3DL_LIDAR_MEASUREMENT_MODEL_LIDAR_MEASUREMENT_MODEL_LIKELIHOOD_H
77 changes: 77 additions & 0 deletions include/mcl_3dl/point_cloud_random_sampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2018, the mcl_3dl authors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef MCL_3DL_POINT_CLOUD_RANDOM_SAMPLER_H
#define MCL_3DL_POINT_CLOUD_RANDOM_SAMPLER_H

#include <random>

#include <pcl/point_types.h>
#include <pcl_ros/point_cloud.h>

namespace mcl_3dl
{
template <class POINT_TYPE>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this template to sample().

class PointCloudRandomSampler
at-wat marked this conversation as resolved.
Show resolved Hide resolved
{
private:
std::random_device seed_gen_;
std::shared_ptr<std::default_random_engine> engine_;

public:
PointCloudRandomSampler()
: engine_(new std::default_random_engine(seed_gen_()))
{
}
typename pcl::PointCloud<POINT_TYPE>::Ptr sample(
const typename pcl::PointCloud<POINT_TYPE>::Ptr &pc,
const size_t num) const
{
if (pc->points.size() == 0)
return typename pcl::PointCloud<POINT_TYPE>::Ptr();

typename pcl::PointCloud<POINT_TYPE>::Ptr output(new pcl::PointCloud<POINT_TYPE>);
output->points.resize(num);

std::uniform_int_distribution<size_t> ud(0, pc->points.size() - 1);

for (size_t i = 0; i < num; i++)
{
output->points.push_back(pc->points[ud(*engine_)]);
}
output->width = 1;
output->height = output->points.size();
output->header = pc->header;

return output;
}
};
} // namespace mcl_3dl

#endif // MCL_3DL_POINT_CLOUD_RANDOM_SAMPLER_H
Loading