3dgeo-heidelberg / helios

http://uni-heidelberg.de/helios
Other
191 stars 44 forks source link

Confusion about the setting of scan angle #141

Closed EnochYing closed 2 years ago

EnochYing commented 2 years ago

There are several places to define scan angles, which make me confused.

  1. The survey file specifies a scanner that includes a series of parameters including scanAngleMax_deg and scanAngleEffectiveMax_deg. I am not clear about their meaning. Do they relate to horizontal or vertical scan angle? And what are the differences between these two parameters?

  2. Some scan angle related parameters including scanAngle_deg, verticalAngleMin_deg, verticalAngleMax_deg, headRotateStart_deg, and headRotateStop_deg can also be directly defined via a scannerSettings template in the survey XML file. The wiki document explains their meanings clearly but I am not sure their relationship with the parameters scanAngleMax_deg and scanAngleEffectiveMax_deg. In other words, when all the parameters are defined, how can I understand and vertical and horizontal FOVs of a scan.

Thanks very much.

lwiniwar commented 2 years ago

Hi @ChanningYing, thank you for your questions. Let me answer them one-by-one. Note: I have omitted the unit _deg from all parameters in the following for more clarity.

  1. Rotating polygon scanners have a "dead-zone" where the laser beam is only partially hitting a single mirror surface. For these cases, no data is recorded, as not enough energy is reflected into the targeted direction. You can usually find this in the data sheets of the scanners by comparing the "pulse repetition rate (PRR)" with the "max. effective measurement rate". From the difference of those, you can calculate the "real" scanAngleMax, while the data sheet gives you the scanAngleEffectiveMax. Example: PRR 400 kHz, effective measurement rate 266000 points per second. The maximum scan angle is given to be 30 degrees (off-nadir). Consider the following sketch: grafik Where the measurement rates have been halved to correspond to off-nadir angles. The scanner's theoretical FOV is the gray area, while the actual FOV is the white one (given by 30°). You can now calculate X by taking simple ratio: 30°/133 = x°/200, therefore x~45.01°. We know that it is a polygonal mirror, so integer multiples need to add up to 360°, so we will use 45° as the scanAngleMax and 30° as the scanAngleEffectiveMax

Why is this important? The platform (imagine an airplane) moves forward while the pulses in the grey area are sent out, but no points are recorded. This means that you will have an overall lower point density (more realistic). If you just set scanAngleMax and scanAngleEffectiveMax both to 30°, you will simulate a higher point density, with unrealistic point distributions at the strip boundaries.

  1. That depends on the platform you are using your scanner on. While in the terrestrial (static) case, the laser scanner is working on two axes (vertical and horizontal), in the airborne or mobile cases, the scanner only works on one axis, and the second axis is created by the moving platform. The terrestial "first" axis is defined to be vertical. Therefore, scanAngle refers to the vertical axis in TLS and to the only axis (typically across-track) in ALS/MLS. Note that this is a setting of the scanner (i.e., set in the scanner XML). For every leg of a TLS survey (platform type = static), you can define scanner settings in the survey file. Here, verticalScanAngle (min/max) allow you to override the scanAngleEffectiveMax setting, because you might not want to have a survey window symmetric to the horizon. The headRotateStart and headRotateStop merely correspond to the second, horizontal movement of the scanner.

Combining these two answers: If you set a smaller verticalScanAngle (via min/max) or a smaller scanAngleEffective, you filter the points that are output. grafik

In this plot, you see (on the left), a survey with only scanAngleEffectiveMax and scanAngleMax, where orange points are recorded and grey points are discarded (but considered as simulation steps, e.g. for moving the platform). On the right is an example with verticalScanAngle set, which just overrides the scanAngleEffectiveMax setting.

I hope this makes things more clear. Best, Lukas

EnochYing commented 2 years ago

Hi Lukas,

Thanks very much for your prompt and very detailed and clear reply. I now understand how to set these parameters.

I just tried to scan a indoor building scene using a static scanner. The key parameters include: scanAngleMax=scanAngleEffectiveMax=90, verticalScanAngle (min/max)= (-60/90), headRotateStart=0, headRotateStop =360, rangeMin_m = 0.5. Platform stands on the ground and scanner mounted at the height of 1.5m. In theory, some area right under the scanner should not be scanned (because of the vertical FOV). But there is no hole in the resulting point clouds. What is the problem? Are there any points I missed to correctly implement the scanning?

By the way, is it possible to output point normal in addition to xyz coordinates? Thanks very much.

Best, Enoch

lwiniwar commented 2 years ago

Hi Enoch,

could you please provide your survey, scanner and scene xmls? Zipping and uploading here should work fine.

Export of normals is currently not possible. Feel free to create a feature request issue, if you think this would be useful for a larger community.

Thanks, Lukas

EnochYing commented 2 years ago

test.zip

Hi Lukas,

The zipped file is attached. The subfolders are named according to the Helios++ file structure.

Point cloud normal may be useful for plane extraction for 3D reconstruction.

Thanks very much. Enoch

lwiniwar commented 2 years ago

Thank you, I can reproduce the issue. I'll get back to you with a solution.

Ad Normal Vectors: We believe that Virtual Laser Scanning (as provided by HELIOS++) should aim to recreate the data provided by real sensors, which do not provide such normal information. There are certain exceptions, e.g., we supply the hitObjectId, i.e., the ID of the object that produced a return, to allow for the automatic generation of training data. I could imagine a use-case where normal vector estimation methods are to be compared to one another, and the real value in the model is needed. In all other use-cases, I would prefer the user to use external normal vector computation methods (e.g. in CloudCompare), as one would need to do with real data.

lwiniwar commented 2 years ago

Hi Enoch, we have investigated the issue and there seems to be a bug where the settings defined in the scanner file are overwritten by default values even if no new values were given in the survey <leg> definitions. We are working on a fix for the next release. In the meantime, I suggest the following workaround: using the new exe file (helios.zip), it was compiled from the dev-scanangle-fixes-branch, set the scanner settings for each leg in the survey file (even if they are the same for each leg). You should then get the results you want. If you run into any more issues, just let me know. Best, Lukas

EnochYing commented 2 years ago

Hi Lukas,

Thanks for your reply. I tried the new exe file you sent. Unfortunately, the results are the same, still without expected holes.

Best, Enoch

lwiniwar commented 2 years ago

Hi Enoch, thank you for your patience. In the meantime, we identified the problem in the code and I hope it is fixed now. If possible, please test the new executable and let me know if it works as expected: cmake-build-release-py38.zip

(Background: There were some problems with parameter overloading, when they were defined at multiple points in the code. See #150 for details).

Best, Lukas

EnochYing commented 2 years ago

Hi Lukas,

Thanks for your reply. I would be happy to do the test. But I found the new executable you sent is based on python 3.8, while my workflow is built on python 3.9. Could you please send me the version in python 3.9? Thanks very much.

Best, Enoch

lwiniwar commented 2 years ago

Hi Enoch,

apologies, please find the version for Python 3.9 here: cmake-build-release-py39.zip

Best, Lukas

EnochYing commented 2 years ago

Hi Lukas,

Sorry for the delay. But just test the new version and there is a running error that says __import pyhelios ImportError: dynamic module does not define module export function (PyInit_pyhelios)__

The compiling files seems incorrect.

By the way, I am going to set up a virtual scanner corresponding to Trimble. When I was trying to make the scanner parameter file based on the template of riegl_vz400, I found there are a lot of parameters not available, including:

In this situation, what should I do to make the virtual laser scanner close to the real one as much as possible?

Thanks Enoch

lwiniwar commented 2 years ago

Hi Enoch,

hmm, I see. I think you still have the version from the last release, not from the current dev branch, right? We did some changes on how pyhelios is imported. For now, I see two options:

About your other question: It's difficult to say without knowing the model of the scanner (Trimble is just a manufacturer). Generally, I can say the following:

Finally, concerning your last question: We have had success by comparing the output of HELIOS++ with data from a real scanner, and tuning parameters to make the output as close to the real data as possible. For example, see Weiser et al. (2021): https://www.sciencedirect.com/science/article/pii/S0034425721003618

I hope this helps! Lukas

EnochYing commented 2 years ago

Hi Lukas,

Thanks so much for your prompt and detailed reply.

I tried your first option, and it works. I did a scan and I can find a hole in the resulting point clouds!!!

I forgot adding the scanner model. It is Trimble x7. I understand what you said except the point related to subray approach. Actually, when I built the simulation using the function pyhelios.Simulation(), I did not see any input parameter related to the selection of subray approach or other approaches.

Enoch

lwiniwar commented 2 years ago

Hi Enoch,

great to hear that this now works. I will close this issue for now, feel free to open another one if you have any more questions! About the subray approach and pyhelios, you are right, this is not possible yet. You can only define it in the scanner XML and then load it from there.

I will open a new issue about exposing this to pyhelios.

Best, Lukas