pcl icon indicating copy to clipboard operation
pcl copied to clipboard

Add an actual way to randomly generate a point cloud of arbitary type

Open kunaltyagi opened this issue 3 years ago • 4 comments

We'll find some way to use Boost to allow simple generators for the point types.

Eg: Use PointT itself to create the parameters and share the distribution across all (eg: no mixing of Uniform and Normal for the point)

That should make our tests and tutorials a bit easier to use

kunaltyagi avatar Dec 23 '21 20:12 kunaltyagi

Once done, we could deprecate the current x,y,z specific functions of CloudGenerator and then do using CloudGenerator = PointCloudGenerator;. Thoughts?

kunaltyagi avatar Dec 23 '21 20:12 kunaltyagi

Is the intention to limit/simplify the cloudgenerator so you cannot have different distributions on each component (X/Y/Z) - what do we gain from this?

larshg avatar Feb 11 '22 19:02 larshg

Is the intention to limit/simplify the cloudgenerator so you cannot have different distributions on each component (X/Y/Z)

Definitely not. The PointGenerator can create different distributions as needed

what do we gain from this?

Currently, only PointXYZ can be generated. If I wish to generate PointNormal or PointXYZRGBA, I'm out of luck

kunaltyagi avatar Feb 23 '22 03:02 kunaltyagi

Sorry for the late reply. I agree, a proper way to generate random clouds of any type would be nice (related: issue #5097). I think we should add a few point generators along with PointCloudGenerator. Otherwise, it probably won't be used much because users first have to define their own point generators. Also, we see whether PointCloudGenerator is nice to use in practice. Currently in PCL (tutorials, tests), random points are mostly created so that all fields have a uniform distribution. Ideally, we would have one point generator that works for all point types. That way, we don't need generators for each point types (PointXYZ, PointXYZRGB, PointNormal, PointXYZI, ..., lots of boilerplate code). I started something, but it isn't very elegant yet:

template<typename PointT>
class UniformPointGenerator1 {
  inline PointT
  run() {
    PointT point;
    auto fields=pcl::getFields<PointT>();
    for(const auto& field : fields) {
      switch (field.datatype) {
        case pcl::PCLPointField::UINT8:
        {
          std::uint8_t value = uint8_dist(rng, {reinterpret_cast<const char*> (&min) + field.offset,
                                                reinterpret_cast<const char*> (&max) + field.offset});
          memcpy (reinterpret_cast<const char*> (&point) + field.offset, &value, sizeof (std::uint8_t));
          break;
        }
        // TODO other cases
    }
    return point;
  }
  private:
    std::mt19937 rng;
    PointT min, max;
    std::uniform_real_distribution<float> float_dist;
    std::uniform_real_distribution<double> double_dist;
    std::uniform_int_distribution<std::uint8_t> uint8_dist;
    // TODO other distributions. Maybe possible to add only necessary distributions?
}

We could also consider following the std random (or std boost) interface more closely, which would e.g. mean to pass the random number generator (e.g. std::mt19937) when calling the fill or get functions.

There are also some drawbacks with std random we should consider, for example that it seems to be slower than boost random in msvc stl, that the implementations of rngs and/or distributions differ between stl implementations (gcc/clang/msvc), meaning that the results are not reproducible even with same seeds, and some other things.

mvieth avatar Apr 05 '22 09:04 mvieth