Skip to content

Commit

Permalink
Fix geometry loading and sign placement with lane offset
Browse files Browse the repository at this point in the history
  • Loading branch information
johschmitz committed Oct 19, 2024
1 parent e14a57c commit 113ccb0
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 33 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ recommendable. It allows hot reloading and rapid iterations.

# How to run the test

There is a handfull of tests for the geometries in the `tests/` directory. They
There is a handful of tests for the geometries in the `tests/` directory. They
can be run by executing pytest from the Blender python distribution in the
project root directory

Expand Down
7 changes: 5 additions & 2 deletions addon/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ def calculate_elevation(self, s):
elevation['d'] * s_section**3
return z, curvature_elevation

def sample_cross_section(self, s, t_vec):
def sample_cross_section(self, s, t_vec, with_lane_offset):
'''
Sample a cross section (multiple t values) in the local coordinate
system. Also return corresponding curvature and heading of the
Expand All @@ -458,7 +458,10 @@ def sample_cross_section(self, s, t_vec):
vector_hdg_t.rotate(Matrix.Rotation(hdg + pi/2, 2))
xyz = []
for t in t_vec:
lane_offset = helpers.calculate_lane_offset(s, self.lane_offset_coefficients, self.total_length)
if with_lane_offset:
lane_offset = helpers.calculate_lane_offset(s, self.lane_offset_coefficients, self.total_length)
else:
lane_offset = 0
xy_vec = Vector((x_s, y_s)) + t * vector_hdg_t + lane_offset * vector_hdg_t
xyz += [(xy_vec.x, xy_vec.y, z)]
return xyz, hdg, curvature_abs
Expand Down
4 changes: 2 additions & 2 deletions addon/modal_road_object_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def modal(self, context, event):
# Recalculate the selected point by transforming back from the calculated Frenet coordinates
selected_point_new = self.selected_geometry.matrix_world @ \
Vector(self.selected_geometry.sample_cross_section(
self.params_input['point_s'], [self.params_input['point_t']])[0][0])
self.params_input['point_s'], [self.params_input['point_t']], False)[0][0])
if event.alt:
# Calculate angular change to update start heading
heading_difference = self.calculate_heading_start_difference(
Expand Down Expand Up @@ -359,7 +359,7 @@ def modal(self, context, event):
return {'RUNNING_MODAL'}
if self.state == 'SELECT_ROAD':
if self.params_snap['id_obj'] != None:
self.selected_geometry = load_geometry(self.selected_road['dsc_type'], self.selected_road['geometry'])
self.selected_geometry = load_geometry(self.selected_road['dsc_type'], self.selected_road['geometry'], self.selected_road['lane_offset_coefficients'])
self.id_road = self.params_snap['id_obj']
self.id_lane = self.params_snap['id_lane']
# Set elevation so that end point selection starts on the same level
Expand Down
8 changes: 4 additions & 4 deletions addon/road.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def get_split_cps(self):
cp_base = self.geometry.sections[-1]['point_end']
# Split
cp_split = self.geometry.matrix_world @ Vector(self.geometry.sample_cross_section(
t, [t_cp_split])[0][0])
t, [t_cp_split])[0][0], True)
# Check which part of the split contains the center lane, that part
# gets the contact point on the center lane
if t_cp_split < 0:
Expand Down Expand Up @@ -481,7 +481,7 @@ def get_road_sample_points(self, lanes, strips_s_boundaries):
s = 0
strips_t_values = self.get_strips_t_values(lanes, s)
# Obtain first curvature value
xyz_samples, hdg, curvature_abs = self.geometry.sample_cross_section(0, strips_t_values)
xyz_samples, hdg, curvature_abs = self.geometry.sample_cross_section(0, strips_t_values, True)
# We need 2 vectors for each strip to later construct the faces with one
# list per face on each side of each strip
sample_points = [[[]] for _ in range(2 * (len(strips_t_values) - 1))]
Expand All @@ -506,7 +506,7 @@ def get_road_sample_points(self, lanes, strips_s_boundaries):

# Sample next points along road geometry (all t values for current s value)
strips_t_values = self.get_strips_t_values(lanes, s)
xyz_samples, hdg, curvature_abs = self.geometry.sample_cross_section(s, strips_t_values)
xyz_samples, hdg, curvature_abs = self.geometry.sample_cross_section(s, strips_t_values, True)
point_index = -2
while point_index < len(sample_points) - 2:
point_index = point_index + 2
Expand All @@ -532,7 +532,7 @@ def get_road_sample_points(self, lanes, strips_s_boundaries):
# Sample the geometry
t_values = [strips_t_values[idx_strip], strips_t_values[idx_strip + 1]]
xyz_boundary, hdg, curvature_abs = self.geometry.sample_cross_section(
s_boundaries_next[idx_smaller], t_values)
s_boundaries_next[idx_smaller], t_values, True)
if idx_smaller == 0:
# Append left extra point
sample_points[2 * idx_strip][idx_boundaries[1]].append(xyz_boundary[0])
Expand Down
18 changes: 9 additions & 9 deletions tests/test_geometry_arc.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_geometry_arc_straight_case():

# Sample the first section
length_0 = geometry.total_length
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([6.0, 3.0, 0.0], 1e-5)

Expand All @@ -43,13 +43,13 @@ def test_geometry_arc_straight_case():

# Sample the first section again
length_0 = geometry.sections[0]['length']
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([6.0, 3.0, 0.0], 1e-5)

# Sample the second section
length_1 = geometry.total_length
xyz_local_1, h_0, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0])
xyz_local_1, h_0, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0], with_lane_offset=False)
xyz_global_1 = geometry.matrix_world @ Vector(xyz_local_1[0])
assert [xyz_global_1.x, xyz_global_1.y, xyz_global_1.z] == approx([8.0, 4.0, 0.0], 1e-5)

Expand All @@ -64,7 +64,7 @@ def test_geometry_arc_180():
geometry.update(params_input, 0.0, 0.0 solver)

length_0 = geometry.total_length
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([1.0, 1.0, 0.0], 1e-5)

Expand All @@ -78,7 +78,7 @@ def test_geometry_arc_negative_start_heading():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0 solver)

xyz_local, h, c = geometry.sample_cross_section(s=geometry.total_length, t_vec=[sqrt(2.0)])
xyz_local, h, c = geometry.sample_cross_section(s=geometry.total_length, t_vec=[sqrt(2.0)], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([-2.0, 0.0, 0.0], abs=1e-5)

Expand All @@ -94,7 +94,7 @@ def test_geometry_arc_y_axis_straight():
geometry.update(params_input, 0.0, 0.0 solver)

length_0 = geometry.total_length
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([0.0, 1.0, 0.0], abs=1e-5)

Expand All @@ -110,7 +110,7 @@ def test_geometry_arc_270_three_pieces():
geometry.update(params_input, 0.0, 0.0 solver)

length_0 = geometry.total_length
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[5.0])
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[5.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([15.0, 20.0, 0.0], 1e-5)

Expand All @@ -121,7 +121,7 @@ def test_geometry_arc_270_three_pieces():
geometry.update(params_input, 0.0, 0.0 solver)

length = geometry.total_length
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[2.0])
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[2.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([10.0, 28.0, 0.0], 1e-5)

Expand All @@ -133,6 +133,6 @@ def test_geometry_arc_270_three_pieces():
geometry.update(params_input, 0.0, 0.0 solver)

length = geometry.total_length
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[-5.0])
xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[-5.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([-5.0, 20.0, 0.0], 1e-5)
6 changes: 3 additions & 3 deletions tests/test_geometry_clothoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_geometry_clothoid():
geometry.update(params_input, 0.0, 0.0 solver)

length_0 = geometry.total_length
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0, with_lane_offset=False])
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([6.0, 3.0, 0.0], 1e-5)

Expand All @@ -39,11 +39,11 @@ def test_geometry_clothoid():
geometry.update(params_input, 0.0, 0.0 solver)

length_0 = geometry.sections[0]['length']
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([6.0, 3.0, 0.0], 1e-5)

length_1 = geometry.total_length
xyz_local_1, h_1, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0])
xyz_local_1, h_1, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0], with_lane_offset=False)
xyz_global_1 = geometry.matrix_world @ Vector(xyz_local_1[0])
assert [xyz_global_1.x, xyz_global_1.y, xyz_global_1.z] == approx([8.0, 4.0, 0.0], 1e-5)
18 changes: 9 additions & 9 deletions tests/test_geometry_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_geometry_line_1d():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([15.0, 10.0, 0.0], 1e-5)

Expand All @@ -37,7 +37,7 @@ def test_geometry_line_1d():
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
length_section = geometry.sections[1]['length']
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([25.0, 10.0, 0.0], 1e-5)

Expand All @@ -51,7 +51,7 @@ def test_geometry_line_2d():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([40.0, 20.0, 0.0], 1e-5)

Expand All @@ -60,7 +60,7 @@ def test_geometry_line_2d():
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
length_section = geometry.sections[1]['length']
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([80.0, 40.0, 0.0], 1e-5)

Expand All @@ -69,7 +69,7 @@ def test_geometry_line_2d():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([320.0, 160.0, 0.0], 1e-5)

Expand All @@ -83,7 +83,7 @@ def test_geometry_line_2d_projection():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([40.0, 20.0, 0.0], 1e-5)

Expand All @@ -92,7 +92,7 @@ def test_geometry_line_2d_projection():
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
length_section = geometry.sections[1]['length']
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
# FIXME there seems to be a small error in the projection
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([80.0, 40.0, 0.0], 1e-5)
Expand All @@ -107,14 +107,14 @@ def test_geometry_line_3d():
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([4.0, 2.0, 1.5], 1e-5)

params_input['points'] = [Vector((2.0, 1.0, 1.0)), Vector((6.0, 3.0, 2.0)), Vector((10.0, 5.0, 4.0))]
geometry.add_section()
geometry.update(params_input, 0.0, 0.0, None)
length = geometry.total_length
xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0])
xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0], with_lane_offset=False)
xyz_global = geometry.matrix_world @ Vector(xyz_local[0])
assert [xyz_global.x, xyz_global.y, xyz_global.z] == approx([10.0, 5.0, 4.0], 1e-5)
6 changes: 3 additions & 3 deletions tests/test_geometry_parampoly3.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_geometry_parampoly3():
geometry.update(params_input, 0.0, 0.0, solver)

length_0 = geometry.total_length
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([30.0, 0.0, 0.0], 1e-5)

Expand All @@ -39,11 +39,11 @@ def test_geometry_parampoly3():
geometry.update(params_input, 0.0, 0.0, solver)

length_0 = geometry.sections[0]['length']
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])
xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0], with_lane_offset=False)
xyz_global_0 = geometry.matrix_world @ Vector(xyz_local_0[0])
assert [xyz_global_0.x, xyz_global_0.y, xyz_global_0.z] == approx([30.0, 0.0, 0.0], 1e-5)

length_1 = geometry.total_length
xyz_local_1, h_1, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0])
xyz_local_1, h_1, c_1 = geometry.sample_cross_section(s=length_1, t_vec=[0.0], with_lane_offset=False)
xyz_global_1 = geometry.matrix_world @ Vector(xyz_local_1[0])
assert [xyz_global_1.x, xyz_global_1.y, xyz_global_1.z] == approx([40.0, 0.0, 0.0], 1e-5)

0 comments on commit 113ccb0

Please sign in to comment.