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

Add PCLVisualizer::containsCloud. #1181

Merged
merged 2 commits into from
May 16, 2015

Conversation

sotte
Copy link
Contributor

@sotte sotte commented Mar 19, 2015

Hey,

I "needed" the following function and it's just two lines of code. It basically allows you to check the PCLVisualizer contains the cloud with the given id independent of the type of the cloud.

Let me know what you think.


containsCloud allows to check if the viewer already contains a cloud with the
given id.

updatePointCloud also checks this AND updates the point cloud, however,
in many scenarios only the check is important.
containsCloud is much clearer and only requires the id of the cloud.

Why containsCloud:
In many tutorials the user keeps track of the added pointclouds by hand, i.e.,
flags like graph_added are used.
This is necessary because the updatePointCloud cannot be used.
containsCloud solves this issue.

@@ -579,6 +579,17 @@ namespace pcl
double r = 1.0, double g = 1.0, double b = 1.0,
const std::string &id = "", int viewport = 0);

/** \brief Check if the clound with the given id was already added to this vizualizer.
Copy link
Contributor

Choose a reason for hiding this comment

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

cloud not clound 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And this is why reviews are a good idea, thanks! :)

@taketwo
Copy link
Member

taketwo commented Mar 20, 2015

👍

There is one subtlety that's worth documenting. For some reason when you add a polygon mesh (with addPolygonMesh()), the created actor ends up in cloud_actor_map_. Therefore your check will be give false positive if a polygon mesh with the given id already exists.

I would add a note/warning to the docstring to avoid confusion.

@sotte
Copy link
Contributor Author

sotte commented Mar 20, 2015

I searched a bit more and pretty much everything you add to the viewer ends up in the cloud_actor_map_, i.e., all functions that start with add extend the cloud_actor_map_.
Here is an imcomplete list:

  • addPointCloud
  • addPolyModelFromPolyData
  • addTextureMesh

I guess the underlying problem is that the concept of the cloud_actor_map_ is not really explained anywhere and the name implies that it only deals with clouds, which is not the case.

Anyway, should we mention previously named functions as well? Or should we rename the function? containsId, containsInput, containsXXX?

@taketwo
Copy link
Member

taketwo commented Mar 20, 2015

Maybe this function should also check shape_actor_map_?

@sotte
Copy link
Contributor Author

sotte commented Mar 20, 2015

Oh man, I didn't even know that shape_actor_map_ exists. There is also coordinate_actor_map_.

I don't know what is the best way to proceed. How about this:

  • containsCloud(const std::string& id) only checks the cloud_actor_map_
  • containsShape(const std::string& id) only checks the shape_actor_map_
  • containsCoordinate(const std::string& id) only checks the coordinate_actor_map_ (Is this function really necessary? I never worked with coordinates.)
  • contains(const std::string& id) checks all of the above, basically checking if something with the given id was added.

@taketwo
Copy link
Member

taketwo commented Mar 22, 2015

Or we can enforce uniqueness of the name independently of the particular actor map where it ends up. Then only a single contains function will be needed. What do you think?

@sotte
Copy link
Contributor Author

sotte commented Mar 22, 2015

This would mean that every time we want to add "stuff" we have to check if the id aleady exists in one of the three actor maps, right?

This would require quite a bit of refactoring (nothing hard but quite a few lines of code). My two-liner is turning into something bigger but I guess I could implement it.

Would this somehow influence the backward compatibility?

@taketwo
Copy link
Member

taketwo commented Mar 22, 2015

The refactoring will amount to changing lines like:

ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
   // ...

with which every add function starts already to just a call to your new contains function.

Would this somehow influence the backward compatibility?

Well may give problems to those who used objects of different types with the same name. (But I have hard times imagining why someone would add a point cloud called "cloud" and then a sphere also called "cloud"). Anyway, a warning message will be printed, so it will be relatively easy to solve the problem for those who are affected.

@sotte
Copy link
Contributor Author

sotte commented Mar 22, 2015

OK, I'll implement it...

@sotte
Copy link
Contributor Author

sotte commented Mar 22, 2015

I just found https://github.com/PointCloudLibrary/pcl/blob/master/visualization/src/pcl_visualizer.cpp#L780.
There seems to be a certain semantic for ids with the same name in ShapeActorMap and CloudActorMap. Now I'm wondering if we don't break anything by requiering uniqueness.

@taketwo
Copy link
Member

taketwo commented Mar 22, 2015

I don't think so. Check this commit message. It seems that there was/is quite a jumble with what goes where (to which actor map). For example, polygon meshes end up in cloud map, whereas polygons go to the shape map...

@sotte
Copy link
Contributor Author

sotte commented May 10, 2015

Some addPointCloud function do multiple things. Here is an example:

pcl::visualization::PCLVisualizer::addPointCloud (
   const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
   const GeometryHandlerConstPtr &geometry_handler,
   const std::string &id, int viewport)
{
  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
  if (am_it != cloud_actor_map_->end ())
  {
    am_it->second.geometry_handlers.push_back (geometry_handler);
    return (true);
  }
  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
}

If id was not added yet, the data is added.
If id was found, the handler is updated.

Should the later case not be handled in the update function?

@taketwo
Copy link
Member

taketwo commented May 15, 2015

Hm... maybe. But that's a different issue, isn't it?

Could you please squash the first two commits? Also please correct a few whitespace/line break issues in the last commit (lines 85, 124, 614).

👍 for the elaborate commit message!

`contains` allows to check if the viewer (or more precisely the *_actor_map)
already contains input data with the given id.

Why `contains()`:

Currently `updatePointCloud` checks if the viewer contains something with the
given id AND updates the point cloud.  However, in many scenarios only the
check is important. The new `contains` is much clearer and only requires the id
of the data.

`contains` also removes the need for manual bookkeeping (ala `graph_added`
flags),  because now it is easy to query any *_actor_map, not just the
cloud_actor_map.
@sotte sotte force-pushed the visualizer_containsCloud branch from e0aec91 to 10f088e Compare May 15, 2015 18:56
@sotte
Copy link
Contributor Author

sotte commented May 15, 2015

I just wanted to mention the issue though.

I squashed the two commits. But I'm not sure about the whitespaces. Looks ok to me. What exactly do you mean?

CloudActorMap::iterator am_it = cloud_actor_map_->find (id);

if (am_it != cloud_actor_map_->end ())
if ( contains(id))
Copy link
Member

Choose a reason for hiding this comment

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

Extra space before and missing space after contains

@taketwo
Copy link
Member

taketwo commented May 15, 2015

Thanks! I left inline comments.

In most add* functions it's straight forward to replace the old pattern for
checking the ids with the new contains function. This commit contains all the
easy cases.

The warning were also adjusted to look like this:

  PCL_WARN ("[functionName] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());

Note that previously some warning were wrong, e.g., they complained about
PointClouds, even though Gradients were added. This was fixed by using the
generic warning from above.

In some spots pcl::console::print_warn was used instead of PCL_WARN.
Now PCL_WARN is used in all add* functions.
@sotte sotte force-pushed the visualizer_containsCloud branch from 10f088e to 4a4eb21 Compare May 16, 2015 07:40
@sotte
Copy link
Contributor Author

sotte commented May 16, 2015

Thanks! Updated.

taketwo added a commit that referenced this pull request May 16, 2015
@taketwo taketwo merged commit 0ffe5df into PointCloudLibrary:master May 16, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants