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

Fix pcd_viewer color handling when invalid fields are present in pcd #2105

Merged

Conversation

hrnr
Copy link
Contributor

@hrnr hrnr commented Nov 28, 2017

Hi all,

I'm still very new to the pcl library (few hours), but I think that I have already fixed a bug. Please correct me if I'm wrong, I'm really a newbie here.

I have a .pcd file with dimensions like this:

Available dimensions: x y z _ rgb _

I have noticed that pcd_viewer does not show this .pcd in rgb colors. After some investigation it seems that it is caused by preceding invalid field before rgb field.

I'm still wondering what are these invalid fields doing in my pointcloud. Is this supposed to be a normal result of serialization to binary .pcd?

Cheers,
Jiri

@taketwo
Copy link
Member

taketwo commented Nov 29, 2017

In order to allow SSE optimizations, point cloud fields are aligned. For example, the xyz field occupies 128 bits instead of 96, which means that in fact it is a xyz_ field with garbage in the end.

Please post your point cloud so that we can give it a try. Also, are you using PCL master?

@SergioRAgostinho SergioRAgostinho added the needs: author reply Specify why not closed/merged yet label Nov 29, 2017
@hrnr
Copy link
Contributor Author

hrnr commented Nov 29, 2017

Yes, I'm using master at 47629c1.

My pointcloud is here: https://drive.google.com/file/d/1svASo3UfT-ozJG6QrJLMA0kr_Io5ApA_/view?usp=sharing

When you load with master pcd_viewer you will get an warning and ColorHandler for random color. This this patch it should load without warning and with ColorHandler using rgb.

Let me know if you want any new test for this. However the bug is in the main() of pcd_viewer.cpp, so I guess it might be quite hard to test.

I have checked the faulty CI: Travis timeouted, because it took too long (but I'm pretty sure this change is not increasing build time considerably). Appveyor faulted even before building for its internal reasons (is it even configured?). I think that none of these is related to this PR.

@taketwo
Copy link
Member

taketwo commented Nov 29, 2017

Thanks, I'll have a look.

CI errors are unrelated. On Travis we've been struggling with timeouts in app building task for a while now. Appveyor is currently in the process of being set up (#2083).

@taketwo taketwo self-assigned this Nov 29, 2017
Copy link
Member

@taketwo taketwo left a comment

Choose a reason for hiding this comment

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

Indeed a bug. Proposed fix looks good, thanks!

@@ -2983,7 +2983,7 @@ pcl::visualization::PCLVisualizer::updateColorHandlerIndex (const std::string &i
int color_handler_size = int (am_it->second.color_handlers.size ());
if (index >= color_handler_size)
{
pcl::console::print_warn (stderr, "[updateColorHandlerIndex] Invalid index <%d> given! Maximum range is: 0-%lu.\n", index, static_cast<unsigned long> (am_it->second.color_handlers.size ()));
pcl::console::print_warn (stderr, "[updateColorHandlerIndex] Invalid index <%d> given! Maximum range is: [0-%d).\n", index, color_handler_size);
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it be color_handler_size - 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it was wrong there. I have tried to fix that with right-open interval convention [0-5), which makes it now correct, but it is not maybe that natural. I will rework that.

for (size_t f = 0; f < cloud->fields.size (); ++f)
{
if (!isValidFieldName (cloud->fields[f].name)) {
Copy link
Member

Choose a reason for hiding this comment

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

Please put the curly bracket on a separate line

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorry about that. I'm not used to this convention. Do you use some clang-format/linter?

btw do you know there are many trailing whitespace issues?

@hrnr
Copy link
Contributor Author

hrnr commented Nov 29, 2017

I have fixed both issues and rebased.

Error comment now should be more clear. I have also fix the check to check also for underflows, not it is guaranteed we can use that as an index.

@SergioRAgostinho
Copy link
Member

My two cents

diff --git a/visualization/tools/pcd_viewer.cpp b/visualization/tools/pcd_viewer.cpp
index b9d2d5e..7bfdbfb 100644
--- a/visualization/tools/pcd_viewer.cpp
+++ b/visualization/tools/pcd_viewer.cpp
@@ -617,16 +617,16 @@ main (int argc, char** argv)
     {
       int rgb_idx = 0;
       int label_idx = 0;
-      for (size_t f = 0; f < cloud->fields.size (); ++f)
+      for (size_t f = 0, i = 0; f < cloud->fields.size (); ++f)
       {
         if (cloud->fields[f].name == "rgb" || cloud->fields[f].name == "rgba")
         {
-          rgb_idx = f + 1;
+          rgb_idx = ++i;
           color_handler.reset (new pcl::visualization::PointCloudColorHandlerRGBField<pcl::PCLPointCloud2> (cloud));
         }
         else if (cloud->fields[f].name == "label")
         {
-          label_idx = f + 1;
+          label_idx = ++i;
           color_handler.reset (new pcl::visualization::PointCloudColorHandlerLabelField<pcl::PCLPointCloud2> (cloud, !use_optimal_l_colors));
         }
         else

@taketwo
Copy link
Member

taketwo commented Nov 30, 2017

Do you use some clang-format/linter?

Unfortunately we don't have a clang-format config matching PCL style guide.

btw do you know there are many trailing whitespace issues?

Yep. There is also lots of misformatted code in the repo, but the policy is to not touch it (otherwise git blame is confused).

@hrnr
Copy link
Contributor Author

hrnr commented Nov 30, 2017

@SergioRAgostinho That patch does not work. Try for yourself with any pcd. As you see it is hard to get it right (after all we have the bug there, so it must be hard, right?). You would need to increment i for all fields, but be careful enough to skip invalid fields.

My solution might not seem very elegant to you (matter of opinion), but it has some important properties.

  1. It is clearly documenting that we need to skip invalid fields. It is important that we somehow document this bug (especially when we don't have test for it), so somebody does not reintroduce it on the next change of this code. Using a variable is better than a comment, because it is much easier to miss a comment (and some people tend to ignore comments).
  2. It keeps the explicit +1 for skipping the random color handler. This is very non-obvious with your approach.
  3. It skips invalid fields as early as possible, so there is a better chance, that they will not cause another bugs for people modifying this code in the future.

I've added a comment about that +1, to make it clear why it is there.

{
pcl::console::print_warn (stderr, "[updateColorHandlerIndex] Invalid index <%d> given! Maximum range is: 0-%lu.\n", index, static_cast<unsigned long> (am_it->second.color_handlers.size ()));
pcl::console::print_warn (stderr, "[updateColorHandlerIndex] Invalid index <%d> given! Index must be less than %d.\n", index, int(color_handler_size));
Copy link
Member

Choose a reason for hiding this comment

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

Actually, why casting here? Just use %zu format.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

%zu is officially available only from C++11 forwards. is it okay to use?

Copy link
Member

Choose a reason for hiding this comment

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

AFAIK it's ANSI C99 feature. But your question reminded me of the issues we had with MSVC (#588). So better use %lu.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, exactly it is ANSI C99 feature. But ISO C++03 has not been rebased on C99, so also %zu is missing. This has been done in C++11 (rebase on C99) and there is %zu along with other. Only C++14 is finally based on C11.

However in real world %zu is pretty much fine on all linuxes, and some recent VS. macs should be fine too. If you turn on -pedantic it should be reported as standard violation.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, good to know!

int color_handler_size = int (am_it->second.color_handlers.size ());
if (index >= color_handler_size)
size_t color_handler_size = am_it->second.color_handlers.size ();
if (!(size_t(index) < color_handler_size))
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, missing space again :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

which space needs to be there? size_t (index)? something about brackets?

Copy link
Member

Choose a reason for hiding this comment

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

size_t (index)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@SergioRAgostinho
Copy link
Member

Second try for completeness

diff --git a/visualization/tools/pcd_viewer.cpp b/visualization/tools/pcd_viewer.cpp
index b9d2d5e..63d4120 100644
--- a/visualization/tools/pcd_viewer.cpp
+++ b/visualization/tools/pcd_viewer.cpp
@@ -617,22 +617,25 @@ main (int argc, char** argv)
     {
       int rgb_idx = 0;
       int label_idx = 0;
-      for (size_t f = 0; f < cloud->fields.size (); ++f)
+      for (size_t f = 0, i = 1; f < cloud->fields.size (); ++f, ++i)
       {
         if (cloud->fields[f].name == "rgb" || cloud->fields[f].name == "rgba")
         {
-          rgb_idx = f + 1;
+          rgb_idx = i;
           color_handler.reset (new pcl::visualization::PointCloudColorHandlerRGBField<pcl::PCLPointCloud2> (cloud));
         }
         else if (cloud->fields[f].name == "label")
         {
-          label_idx = f + 1;
+          label_idx = i;
           color_handler.reset (new pcl::visualization::PointCloudColorHandlerLabelField<pcl::PCLPointCloud2> (cloud, !use_optimal_l_colors));
         }
         else
         {
           if (!isValidFieldName (cloud->fields[f].name))
+          {
+            --i;
             continue;
+          }
           color_handler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (cloud, cloud->fields[f].name));
         }
         // Add the cloud to the renderer

Do you use some clang-format/linter?

I started making something yesterday. It's still not quite there yet.

@taketwo
Copy link
Member

taketwo commented Nov 30, 2017

I started making something yesterday. It's still not quite there yet.

Make sure you use clang-5, it has a number of new settings.

@SergioRAgostinho
Copy link
Member

Yeah. I noticed it already :/ But should we aim already for 5 even though xenial is shipping 3.8?

@taketwo
Copy link
Member

taketwo commented Nov 30, 2017

Let's move format discussion to #2106.

* clearly state index must be less than size we are printing
* catch also underflow when negative index is given
* invalid fields needs to be skipped otherwise ColorHandler indexes will overflow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants