laser_geometry/test/projection_test.py
Chris Lalancette bfe1c494fd
Fix building on running on Windows Debug. (#82)
* Fix building on running on Windows Debug.

In particular, we need to set the python executable properly
when running on Windows Debug.  While we are in here, we also
fix up some dependencies in the package.xml and CMakeLists.txt.
We also have to remove WERROR ON, due to some Python
warnings that are outside of our control.  Finally, we heavily
reduce the number of tests being run here so that the tests
complete in a reasonable amount of time, even on (slow) Windows
debug.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2021-09-09 14:59:07 -04:00

130 lines
4.3 KiB
Python
Executable File

#!/usr/bin/env python3
import rclpy
import rclpy.duration
import rclpy.time
import sensor_msgs_py.point_cloud2 as pc2
from sensor_msgs.msg import LaserScan
from laser_geometry import LaserProjection
import numpy as np
from itertools import product
import pytest
PROJECTION_TEST_RANGE_MIN = 0.23
PROJECTION_TEST_RANGE_MAX = 40.00
class BuildScanException(Exception):
pass
def build_constant_scan(
range_val, intensity_val,
angle_min, angle_max, angle_increment, scan_time):
count = np.uint(np.ceil((angle_max - angle_min) / angle_increment))
if count < 0:
raise BuildScanException
scan = LaserScan()
scan.header.stamp = rclpy.time.Time(seconds=10.10).to_msg()
scan.header.frame_id = "laser_frame"
scan.angle_min = angle_min
scan.angle_max = angle_max
scan.angle_increment = angle_increment
scan.scan_time = scan_time.nanoseconds / 1e9
scan.range_min = PROJECTION_TEST_RANGE_MIN
scan.range_max = PROJECTION_TEST_RANGE_MAX
scan.ranges = [range_val for _ in range(count)]
scan.intensities = [intensity_val for _ in range(count)]
scan.time_increment = scan_time.nanoseconds / 1e9 / count
return scan
def test_project_laser():
tolerance = 6 # decimal places
projector = LaserProjection()
ranges = [-1.0, 1.0, 5.0, 100.0]
intensities = np.arange(1.0, 4.0).tolist()
min_angles = -np.pi / np.array([1.0, 1.5, 8.0])
max_angles = -min_angles
angle_increments = np.pi / np.array([180., 360., 720.])
scan_times = [rclpy.duration.Duration(seconds=1./i) for i in [40, 20]]
for range_val, intensity_val, \
angle_min, angle_max, angle_increment, scan_time in \
product(ranges, intensities,
min_angles, max_angles, angle_increments, scan_times):
try:
scan = build_constant_scan(
range_val, intensity_val,
angle_min, angle_max, angle_increment, scan_time)
except BuildScanException:
assert (angle_max - angle_min)/angle_increment <= 0
cloud_out = projector.projectLaser(scan, -1.0,
LaserProjection.ChannelOption.INTENSITY |
LaserProjection.ChannelOption.INDEX |
LaserProjection.ChannelOption.DISTANCE |
LaserProjection.ChannelOption.TIMESTAMP)
assert len(cloud_out.fields) == 7, \
"PointCloud2 with channel INDEX: fields size != 7"
valid_points = 0
for i in range(len(scan.ranges)):
ri = scan.ranges[i]
if (PROJECTION_TEST_RANGE_MIN <= ri and
ri <= PROJECTION_TEST_RANGE_MAX):
valid_points += 1
assert valid_points == cloud_out.width, \
"Valid points != PointCloud2 width"
idx_x = idx_y = idx_z = 0
idx_intensity = idx_index = 0
idx_distance = idx_stamps = 0
i = 0
for f in cloud_out.fields:
if f.name == "x":
idx_x = i
elif f.name == "y":
idx_y = i
elif f.name == "z":
idx_z = i
elif f.name == "intensity":
idx_intensity = i
elif f.name == "index":
idx_index = i
elif f.name == "distances":
idx_distance = i
elif f.name == "stamps":
idx_stamps = i
i += 1
i = 0
for point in pc2.read_points(cloud_out):
ri = scan.ranges[i]
ai = scan.angle_min + i * scan.angle_increment
assert point[idx_x] == pytest.approx(ri * np.cos(ai),
abs=tolerance), "x not equal"
assert point[idx_y] == pytest.approx(ri * np.sin(ai),
tolerance), "y not equal"
assert point[idx_z] == pytest.approx(0, tolerance), "z not equal"
assert point[idx_intensity] == pytest.approx(scan.intensities[i],
tolerance), "Intensity not equal"
assert point[idx_index] == pytest.approx(i, tolerance), \
"Index not equal"
assert point[idx_distance] == pytest.approx(ri, tolerance), \
"Distance not equal"
assert point[idx_stamps] == pytest.approx(
i * scan.time_increment, tolerance), "Timestamp not equal"
i += 1
if __name__ == '__main__':
pytest.main()