cyberbotics / webots

Webots Robot Simulator
https://cyberbotics.com
Apache License 2.0
3.2k stars 1.68k forks source link

This texture doesn't play nice with infrared sensors #2365

Closed Justin-Fisher closed 3 years ago

Justin-Fisher commented 3 years ago

When I use the following texture as the basemap for a texturedbox (set to compact mapping), infrared sensors cannot detect the difference between high-red colors (red/yellow) versus low-red colors (blue/black) even though it has no problem doing so on many other quite similar textures. In fact, when I simply switch with textured box has which texture as its basemap, that switches which textured box the infrared sensor messes up on, which tells me that it must be something about this texture. But I have no idea what!

(I'm not sure if it matters, but I've been trying this on textured boxes with some faces removed.)

upper_block

Expected behavior Pointing an infrared sensor with default settings at this should produce 1000 when aimed at blue or black, as it does for lots of other textures. Instead it produces basically the same reading as it produces when aimed at red or yellow (for me that's usually 300-something, depending upon just how close the sensor is to the surface).

System

DavidMansolino commented 3 years ago

I have made some tests with this texture and the texturedbox, to me it looks all correct.

Note the reflection factor used for infra-red distance-sensors:

f = 0.2 + 0.8 red_level (1 - 0.5 roughness) (1 - 0.5 * occlusion)

In our case with the texturedbox the roughness is always 1 and the occlusion is always 0, so we can simplify like this:

f = 0.2 + 0.4 * red_level

Now I have tried with a distance-sensor with the default lookup table and at a distance of 0.1 meter of the box.

On red:

red_level = 1 f = 0.2 + 0.4 * red_level = 0.6
used distance = 0.1 / 0.6 = 0.1666..

The distance-sensor returns me 166.666... in the simulation, this looks correct.

On blue:

red_level = 0 f = 0.2 + 0.4 * red_level = 0.2 used distance = 0.1 / 0.2 = 0.5

The distance-sensor returns me 500 in the simulation, this looks correct too.

If you have different values can you please share at which distance and pointing where exactly on the texture?

Justin-Fisher commented 3 years ago

My settings were similar to yours though my boxes had roughness of 0.2 rather than your 1. Changing my roughness to 1 nearly doubles the sensor readings, as we would expect, but still leaves blue, red, and yellow giving the same reading when the blue one should instead be much higher. My numbers were also generally higher than yours, but that's probably just a consequence of my mounting my IR sensors further from the surface. With roughness 0, pure red and pure yellow give me readings of 361, which fits with the visual showing that the surface is about 1/3 of the whisker away. The problem is blue reads 361 on this texture too, but not on other textures that look much like it.

I guess my next step will be to recreate some similar textures and see if I can figure out what's causing this. This was actually the first texture I made for this simulation, and the others were made by reloading and altering this one in Gimp, so it's odd that whatever problem this one had didn't carry over to the others. That makes me suspect that the problem might have something to do with the bucket-of-popcorn image, because that's the only thing that's really unique to this texture. One hypothesis I toyed with was the thought that I might have gotten some transparent pixels in that image somehow, but I think transparency is stripped when I export as .jpg, so I don't think that would explain it. (And the fact that it isn't causing the same problem for you is mysterious too, because for me switching this texture in and out is enough to cause/cure the problem, but I guess there must be some other factor that's contributing too.)

DavidMansolino commented 3 years ago

Would it be possible for you to share a simple world file, containing the texture and two distance-sensors (one pointing at blue and one at red) where the problem occurs so that I can reproduce exactly the problem you have?

Justin-Fisher commented 3 years ago

So it turns out that the problem was easy to "fix": simply reloading the image in Gimp and hitting export again created a look-alike texture where the blue shows up fine on infrared; and switching back to the earlier image makes it not show up again, even though the two images are visually indistinguishable to my eye (though their jpeg compression probably is a tiny bit different). That probably also partially explains why the later textures I based off this one worked fine.

This still leaves the question of what was wrong with my original image. It loads up fine in both Webots and Gimp, and looks fine, so it seems like the file can't have been all that corrupted, and it's odd that the only way it was at all unusual was just how the IR sensor reacted to it.

Justin-Fisher commented 3 years ago

Ok, weirder still. Another "fix" that works is to simply copy the file with a new filename (without even bothering to recompress it as jpg). Switching the baseColorMap back and forth between upper_block.jpg and upper_block - Copy.jpg switches whether or not IR sensors pick up blue, even though these files are perfect duplicates, aside from filename and some metadata...

I guess if merely copying the file is enough to solve the problem, there probably won't be any way for me to send you a copy of the file to have you reproduce it! My current hypotheses are either (a) that Webots somehow caches previously loaded files, and keeps reloading a glitched cached version, perhaps because the last-edit time on the original file hasn't changed, though this seems unlikely because the problem persists across Webots restarts, or (b) that there is some sort of metadata in the original file that keeps webots from viewing it as IR-able, where merely copying the file is enough to fix this metadata. Weird...

Anyway, since this problem was pretty easily fixed, it probably isn't a high priority to figure out what caused it. Thanks for checking!

DavidMansolino commented 3 years ago

Ok, in that case, that explains why I can't reproduce the problem, thank you for the feedback. Unfortunately, that also means that it is going to be very difficult to fix since we can't reproduce it.

About your hypotheses. a. Yes, Webots does cache textures, but this cache is deleted when restarting Webots. b. Yes, this is possible that your file is somehow corrupted, I already saw once an image file that was kind of 'corrupted' and just copy-pasting it solved the issue, but in that case, before copying it, Webots was complaining that it was not able to load the file.

Justin-Fisher commented 3 years ago

Ok, I think I figured out what was happening. It looks like Webots won't let me load the same texture onto two Textured Boxes and have IR work with both of them. A while back, when I was setting up the geometry for the world, I had given another box a copy of the texture that ended up causing me problems, just as a placeholder until I got around to making its actual texture. Now that I replaced it with its final texture, I can now load the problematic texture again and it works fine. I discovered this by noting that in another place where I used the same texture twice, only one copy was working with IR.

So... here's a revision to the bug report:

Loading the same texture onto two textured boxes makes IR work on only one of those boxes. Simply copying the texture file and loading the other copy onto one of the boxes makes both work.

Expected behavior: you should be able to use the same texture file on multiple objects, and just as it already appears correctly on screen when you do so, it should also appear correctly through IR sensors.

Justin-Fisher commented 3 years ago

Hrmmm... darn it. It's more complicated than this somehow, because this copy the file trick didn't fix one of the textures that my IR sensor isn't working on... I'll let you know if I figure out more

DavidMansolino commented 3 years ago

I can indeed reproduce exactly what you mentioned now when using two exactly identical textured boxes. This is visible with this world file (and the texture file):

#VRML_SIM R2020b utf8
WorldInfo {
  coordinateSystem "NUE"
}
Viewpoint {
  orientation -0.1845777226689386 -0.9699076698065577 -0.15877712790185441 1.6995217892070873
  position -0.2711644126455983 0.14524558649997066 0.044176449485784565
}
TexturedBackground {
}
TexturedBackgroundLight {
}
Transform {
  translation 0 0 0.11
  children [
    TexturedBoxShape {
      textureUrl [
        "96641318-29ed5900-12ea-11eb-8b63-a016b01bb85f.jpg"
      ]
      textureMapping "compact"
    }
  ]
}
Transform {
  children [
    TexturedBoxShape {
      textureUrl [
        "96641318-29ed5900-12ea-11eb-8b63-a016b01bb85f.jpg"
      ]
      textureMapping "compact"
    }
  ]
}
Robot {
  children [
    DistanceSensor {
      translation 0 0.06 0.003
      rotation 0 0 1 -1.5707953071795862
      name "distance sensor left"
      translationStep 0.001
      type "infra-red"
    }
    DistanceSensor {
      translation 0 0.06 0.112
      rotation 0 0 1 -1.5707953071795862
      name "distance sensor right"
      translationStep 0.001
      type "infra-red"
    }
  ]
}

image

Justin-Fisher commented 3 years ago

So I got my other duplicate texture "fixed". Doing so required reloading the world, which is odd because I didn't need to reload world to "fix" the first one. I'm not sure whether using the same normal map on these objects might have been contributing. Anyway, it's working now, so I'm resolving not to touch it!

DavidMansolino commented 3 years ago

The problem seems around here: https://github.com/cyberbotics/webots/blob/master/src/webots/nodes/WbShape.cpp#L369 The u,v texture coordinate computation is correct but the returned color associated to this coordinate is wrong (returns (1.0, 1.0, 1.0) in any cases.

DavidMansolino commented 3 years ago

Ok, the problem is here: https://github.com/cyberbotics/webots/blob/master/src/webots/nodes/WbImageTexture.cpp#L340 Since the texture comes from the cache for the second shape, the mImage were never populated, and therefore it falseback on the default value.

DavidMansolino commented 3 years ago

@Justin-Fisher, this is now fixed and will be available in the nightly builds from tomorrow.