Skip to content

Commit

Permalink
Make roads which are snapped at both ends connect smoothly
Browse files Browse the repository at this point in the history
Implementation uses a cubic Hermite spline
  • Loading branch information
johschmitz committed Nov 15, 2022
1 parent 76e2b7e commit ce3bebd
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 10 deletions.
41 changes: 33 additions & 8 deletions addon/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,45 @@ def update_elevation(self, params_input):
line - parabola
curve combination inside one geometry.
Symbols and equations used:
Slope of incoming road: m_0
Parabola (Curve 0): h_p1 = a_p1 + b_p1 * s + c_p1 * s^2
Line (Curve 1): h_l = a_l + b_l * s
Parabola (Curve 2): h_p2 = a_p2 + b_p2 * s + c_p2 * s^2
Slope of outgoing road: m_3
'''
if (params_input['point_start'].z == params_input['point_end'].z
and params_input['slope_start'] == 0
and params_input['slope_end'] == 0):
# No elevation
self.params['elevation'] = [{'s': 0, 'a': 0, 'b': 0, 'c': 0, 'd': 0}]
elif params_input['connected_start'] == False and params_input['connected_end'] == False:
# No incoming and outgoing roads connected
# Symbols and equations used:
# Slope of road: m_0
m_0 = (params_input['point_end'].z - params_input['point_start'].z) / self.params['length']
self.params['elevation'] = [{'s': 0, 'a': 0, 'b': m_0, 'c': 0, 'd': 0}]
elif params_input['connected_start'] == True and params_input['connected_end'] == True:
# Symbols and equations used:
# Height of incoming road: h_0
# Height of outgoing road: h_1
# Slope of incoming road: m_0
# Slope of outgoing road: m_1
# Length of road: s_1
# https://en.m.wikipedia.org/wiki/Cubic_Hermite_spline
h_0 = 0
h_1 = params_input['point_end'].z - params_input['point_start'].z
m_0 = params_input['slope_start']
m_1 = -1.0 * params_input['slope_end']
s_1 = self.params['length']
a = h_0
# b = s_1 * m_0
b = m_0
c = (-3 * h_0 - 2 * s_1 * m_0 + 3 * h_1 - s_1 * m_1) / s_1**2
d = (2 * h_0 + s_1 * m_0 - 2 * h_1 + s_1 * m_1) / s_1**3
self.params['elevation'] = [{'s': 0, 'a': a, 'b': b, 'c': c, 'd': d}]
else:
# TODO: get slope of predecessor and succesor
# Symbols and equations used:
# Slope of incoming road: m_0
# Parabola (Curve 0): h_p1 = a_p1 + b_p1 * s + c_p1 * s^2
# Line (Curve 1): h_l = a_l + b_l * s
# Parabola (Curve 2): h_p2 = a_p2 + b_p2 * s + c_p2 * s^2
# Slope of outgoing road: m_3
m_0 = params_input['slope_start']
m_3 = params_input['slope_end']

Expand Down Expand Up @@ -123,7 +148,7 @@ def get_slope_start(self):
'''
Return slope at beginning of geometry.
'''
return self.params['elevation'][0]['b']
return -1.0 * self.params['elevation'][0]['b']

def get_slope_end(self):
'''
Expand Down
4 changes: 2 additions & 2 deletions addon/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def point_to_junction_joint(obj, point):
distances.append((Vector(joint['contact_point_vec']) - point).length)
arg_min_dist = distances.index(min(distances))
return joints[arg_min_dist]['id_incoming'], joints[arg_min_dist]['contact_point'], \
cp_vectors[arg_min_dist], joints[arg_min_dist]['heading']
cp_vectors[arg_min_dist], joints[arg_min_dist]['heading'], joints[arg_min_dist]['slope']

def point_to_junction_connector(obj, point):
'''
Expand Down Expand Up @@ -460,7 +460,7 @@ def mouse_to_object_params(context, event, filter):
if filter == 'OpenDRIVE_junction':
if obj.name.startswith('junction_area'):
hit = True
id_incoming, point_type, snapped_point, heading = point_to_junction_joint(obj, raycast_point)
id_incoming, point_type, snapped_point, heading, slope = point_to_junction_joint(obj, raycast_point)
id_obj = id_incoming
id_junction = obj['id_odr']
elif filter == 'OpenSCENARIO':
Expand Down

0 comments on commit ce3bebd

Please sign in to comment.