Beispiel #1
0
def find_second_closest(path, x, y, index_star):

    one = dy.int32(1)

    ip1 = index_star + one
    x_test_ip1 = dy.memory_read(memory=path['X'], index=ip1)
    y_test_ip1 = dy.memory_read(memory=path['Y'], index=ip1)
    distance_ip1 = distance_between(x, y, x_test_ip1, y_test_ip1)

    im1 = index_star - one
    x_test_im1 = dy.memory_read(memory=path['X'], index=im1)
    y_test_im1 = dy.memory_read(memory=path['Y'], index=im1)
    distance_im1 = distance_between(x, y, x_test_im1, y_test_im1)

    which = distance_ip1 > distance_im1

    second_clostest_distance = distance_ip1
    second_clostest_distance = dy.conditional_overwrite(
        second_clostest_distance, condition=which, new_value=distance_im1)

    index_second_star = ip1
    index_second_star = dy.conditional_overwrite(index_second_star,
                                                 condition=which,
                                                 new_value=im1)

    return second_clostest_distance, index_second_star
Beispiel #2
0
def sample_path_finite_difference(path, index):

    y1 = dy.memory_read(memory=path['Y'], index=index)
    y2 = dy.memory_read(memory=path['Y'], index=index + dy.int32(1))

    x1 = dy.memory_read(memory=path['X'], index=index)
    x2 = dy.memory_read(memory=path['X'], index=index + dy.int32(1))

    Delta_x = x2 - x1
    Delta_y = y2 - y1

    psi_r = dy.atan2(Delta_y, Delta_x)
    x_r = x1
    y_r = y1

    return x_r, y_r, psi_r
Beispiel #3
0
def _get_line_segment(path, x, y, index_star):
    """
        Given the index of the clostest point, compute the index of the 2nd clostest point.
    """

    one = dy.int32(1)

    x_star, y_star = sample_path_xy(path, index=index_star)

    x_test_ip1, y_test_ip1 = sample_path_xy(path, index=index_star + one)
    distance_ip1 = distance_between(x, y, x_test_ip1, y_test_ip1)

    x_test_im1, y_test_im1 = sample_path_xy(path, index=index_star - one)
    distance_im1 = distance_between(x, y, x_test_im1, y_test_im1)

    # find out which point is the 2nd closest
    # which = True  means that the point referred by the index index_star - 1 is the 2nd closest
    # which = False means that the point referred by the index index_star + 1 is the 2nd closest
    which = distance_ip1 > distance_im1

    second_clostest_distance = dy.conditional_overwrite(distance_ip1,
                                                        condition=which,
                                                        new_value=distance_im1)

    index_second_star = dy.conditional_overwrite(index_star + one,
                                                 condition=which,
                                                 new_value=index_star - one)

    #
    i_s = dy.conditional_overwrite(index_star,
                                   condition=which,
                                   new_value=index_star - one)
    i_e = dy.conditional_overwrite(index_star + one,
                                   condition=which,
                                   new_value=index_star)

    #
    # get start/end xy-points of the line segment which is closest
    # the line is described by (x_s, y_s) --> (x_e, y_e)
    #

    # find start point (x_s, y_s)
    x_s = dy.conditional_overwrite(x_star,
                                   condition=which,
                                   new_value=x_test_im1)
    y_s = dy.conditional_overwrite(y_star,
                                   condition=which,
                                   new_value=y_test_im1)

    # find stop point (x_e, y_e)
    x_e = dy.conditional_overwrite(x_test_ip1,
                                   condition=which,
                                   new_value=x_star)
    y_e = dy.conditional_overwrite(y_test_ip1,
                                   condition=which,
                                   new_value=y_star)

    return i_s, i_e, x_s, y_s, x_e, y_e, index_second_star, second_clostest_distance
Beispiel #4
0
def tracker(path, x, y):
    """
        Continuously project the point (x, y) onto the given path (closest distance)

        This is an internal function. C.f. track_projection_on_path for details and assumptions.

        returns in structure tracking_results:
            tracked_index    - the index in the path array for the closest distance to (x, y)
            Delta_index      - the change of the index to the previous lookup
            distance         - the absolute value of the closest distance of (x, y) to the path

            reached_the_end_of_currently_available_path_data
                             - reached the end of the path
    """

    #
    # define the optimization problem
    #

    # pack parameters
    par = (x, y)

    def J(path, index, par):

        # unpack parameters
        x, y = par

        # cost function J: index -> distance
        x_test, y_test = sample_path_xy(path, index)
        distance = distance_between(x_test, y_test, x, y)

        # cost
        return distance

    #
    # continuous optimization
    #

    results = continuous_optimization_along_path(path, dy.int32(0), J, par)

    #
    distance = results['J_star']
    minimal_distance_reached = results['reached_minimum']

    #
    tracking_results = dy.structure()
    tracking_results['tracked_index'] = results['optimal_index']
    tracking_results['Delta_index'] = results['Delta_index']
    tracking_results['distance'] = distance
    tracking_results['minimal_distance_reached'] = minimal_distance_reached
    tracking_results[
        'reached_the_end_of_currently_available_path_data'] = results[
            'reached_the_end_of_currently_available_path_data']

    return tracking_results
def generate_signal_PWM(period, modulator):

    number_of_samples_to_stay_in_A = period * modulator
    number_of_samples_to_stay_in_B = period * (dy.float64(1) - modulator)

    number_of_samples_to_stay_in_A.set_name('number_of_samples_to_stay_in_A')
    number_of_samples_to_stay_in_B.set_name('number_of_samples_to_stay_in_B')

    with dy.sub_statemachine("statemachine1") as switch:

        with switch.new_subsystem('state_on') as system:

            on = dy.float64(1.0).set_name('on')

            counter = dy.counter().set_name('counter')
            timeout = (counter >=
                       number_of_samples_to_stay_in_A).set_name('timeout')
            next_state = dy.conditional_overwrite(
                signal=dy.int32(-1), condition=timeout,
                new_value=1).set_name('next_state')

            system.set_switched_outputs([on], next_state)

        with switch.new_subsystem('state_off') as system:

            off = dy.float64(0.0).set_name('off')

            counter = dy.counter().set_name('counter')
            timeout = (counter >=
                       number_of_samples_to_stay_in_B).set_name('timeout')
            next_state = dy.conditional_overwrite(
                signal=dy.int32(-1), condition=timeout,
                new_value=0).set_name('next_state')

            system.set_switched_outputs([off], next_state)

    # define the outputs
    pwm = switch.outputs[0].set_name("pwm")
    state_control = switch.state.set_name('state_control')

    return pwm, state_control
def path_horizon_head_index(path):
    """
        Get the current head-index position in the horizon and the distance at the head
    """

    if path['buffer_type']  == 'dy.memory':
        head_index                     = dy.int32( path['samples'] - 1 )
        distance_at_the_end_of_horizon = dy.memory_read( memory=path['D'],   index=head_index ) 

    elif path['buffer_type']  == 'circular_buffer':
        head_index                     = cb.get_current_absolute_write_index(path['D']) - 1
        distance_at_the_end_of_horizon = cb.read_from_absolute_index(path['D'], head_index)

    return head_index, distance_at_the_end_of_horizon
Beispiel #7
0
def path_horizon_tail_index(path):
    """
        Get the current tail-index position in the horizon and the distance at the tail
    """

    if path['buffer_type'] == 'dy.memory':
        tail_index = dy.int32(0)
        distance_at_the_begin_of_horizon = dy.memory_read(memory=path['D'],
                                                          index=tail_index)

    elif path['buffer_type'] == 'circular_buffer':
        tail_index = cb.get_absolute_minimal_index(path['D'])
        distance_at_the_begin_of_horizon = cb.read_from_absolute_index(
            path['D'], tail_index)

    return tail_index, distance_at_the_begin_of_horizon
Beispiel #8
0
def tracker(path, x, y):
    index_track = dy.signal()

    with dy.sub_loop(max_iterations=1000) as system:

        search_index_increment = dy.int32(
            1)  # positive increment assuming positive velocity

        Delta_index = dy.sum(search_index_increment, initial_state=-1)
        Delta_index_previous_step = Delta_index - search_index_increment

        x_test = dy.memory_read(memory=path['X'],
                                index=index_track + Delta_index)
        y_test = dy.memory_read(memory=path['Y'],
                                index=index_track + Delta_index)

        distance = distance_between(x_test, y_test, x, y)

        distance_previous_step = dy.delay(distance, initial_state=100000)
        minimal_distance_reached = distance_previous_step < distance

        # introduce signal names
        distance.set_name('tracker_distance')
        minimal_distance_reached.set_name('minimal_distance_reached')

        # break condition
        system.loop_until(minimal_distance_reached)

        # return
        system.set_outputs([Delta_index_previous_step, distance_previous_step])

    Delta_index = system.outputs[0].set_name('tracker_Delta_index')
    distance = system.outputs[1].set_name('distance')

    index_track_next = index_track + Delta_index

    index_track << dy.delay(index_track_next, initial_state=1)

    return index_track_next, Delta_index, distance
    output_signals = [ y ]


if testname == 'test_ramp':
    y1 = dy.float64(3) * dy.signal_ramp(10) - dy.float64(2) * dy.signal_ramp(70) 
    y2 = dy.float64(-5) * dy.signal_ramp(40)

    y1.set_name('y1')

    output_signals = [ y1, y2 ]



if testname == 'test_datatype_convertion':
    y = dy.int32(333)

    y = dy.convert(y, dy.DataTypeFloat64(1) )
    
    output_signals = [ y ]


if testname == 'dtf_lowpass_1_order':

    u = dy.float64(1.0)

    y = dy.dtf_lowpass_1_order(u, z_infinity=0.95 )
    
    output_signals = [ y ]

Beispiel #10
0
# estimate the travelled distance by integration of the vehicle velocity
d_hat = dy.euler_integrator(
    velocity, Ts, initial_state=0) + path_distance_start_open_loop_control

# estimated travelled distance (d_hat) to path-index
open_loop_index, _, _ = tracker_distance_ahead(
    path,
    current_index=path_index_start_open_loop_control,
    distance_ahead=d_hat)

dy.append_output(open_loop_index, 'open_loop_index')

# get the reference orientation and curvature
_, _, _, psi_rr, K_r = sample_path(path, index=open_loop_index +
                                   dy.int32(1))  # new sampling

#
# compute an enhanced (less noise) signal for the path orientation psi_r by integrating the
# curvature profile and fusing the result with psi_rr to mitigate the integration drift.
#

psi_r, psi_r_dot = compute_path_orientation_from_curvature(Ts,
                                                           velocity,
                                                           psi_rr,
                                                           K_r,
                                                           L=1.0)

dy.append_output(psi_rr, 'psi_rr')
dy.append_output(psi_r_dot, 'psi_r_dot')
Beispiel #11
0
def continuous_optimization_along_path(path, current_index, J, par):
    """
        Minimize the given cost function by varying the index of the path array  


                  <----- Delta_index_track ----->
        array: X  X  X  X  X  X  X  X  X  X  X  X  X  X  X 
                  ^               
            current_index
    """

    if 'Delta_d' in path:
        # constant sampling interval in distance
        # computation can be simplified
        pass

    # get the highest available array index in the horizon
    index_head, _ = path_horizon_head_index(path)

    #
    #
    #

    Delta_index_track = dy.signal()

    # initialize J_star
    J_star_0 = J(path, current_index + Delta_index_track, par)

    #
    # compute the direction (gradient) in which J has its decent
    # if true: with increasing index J increases  --> decrease search index
    # if false: with increasing index J decreases --> increase search index
    #
    J_prev_index = J(path, current_index + Delta_index_track - 1, par)
    J_Delta_to_next_index = J_star_0 - J_prev_index

    search_index_increment = dy.conditional_overwrite(
        dy.int32(1), J_Delta_to_next_index > 0, dy.int32(-1))

    # loop to find the minimum of J
    with dy.sub_loop(max_iterations=1000,
                     subsystem_name='optim_loop') as system:

        # J_star(k) - the smallest J found so far
        J_star = dy.signal()

        # inc- / decrease the search index
        Delta_index_previous_step, Delta_index = dy.sum2(
            search_index_increment, initial_state=0)
        index_to_investigate = current_index + Delta_index_track + Delta_index

        # sample the cost function and check if it got smaller in this step
        J_to_verify = J(path, index_to_investigate, par)
        step_caused_improvement = J_to_verify < J_star

        # in case the step yielded a lower cost, replace the prev. minimal cost
        J_star_next = dy.conditional_overwrite(J_star, step_caused_improvement,
                                               J_to_verify)

        # state for J_star
        J_star << dy.delay(J_star_next, initial_state=J_star_0)

        #
        # loop break conditions
        #

        # when reaching the end of the available data, stop the loop and indicate the need for extending the horizon
        reached_the_end_of_currently_available_path_data = index_to_investigate >= index_head  # reached the end of the input data?

        # similarly check for the begin ...
        reached_the_begin_of_currently_available_path_data = index_to_investigate - 1 <= path_horizon_tail_index(
            path)[0]

        # in case the iteration did not reduce the cost, assume that the minimum was reached in the prev. iteration
        reached_minimum = dy.logic_not(step_caused_improvement)

        system.loop_until(
            dy.logic_or(
                dy.logic_or(reached_minimum,
                            reached_the_end_of_currently_available_path_data),
                reached_the_begin_of_currently_available_path_data).set_name(
                    'loop_until'))

        # assign signals names to appear in the generated source code
        J_star_0.set_name('J_star_0')
        search_index_increment.set_name('search_index_increment')
        J_star.set_name('J_star')
        Delta_index.set_name('Delta_index')
        index_head.set_name('index_head')
        index_to_investigate.set_name('index_to_investigate')
        J_to_verify.set_name('J_to_verify')
        step_caused_improvement.set_name('step_caused_improvement')

        # return
        outputs = dy.structure()
        outputs['Delta_index'] = Delta_index_previous_step
        outputs['J_star'] = J_star_next
        outputs['reached_minimum'] = reached_minimum
        outputs[
            'reached_the_end_of_currently_available_path_data'] = reached_the_end_of_currently_available_path_data
        outputs['index_head'] = index_head * 1
        outputs['index_to_investigate'] = index_to_investigate
        outputs['J_to_verify'] = J_to_verify

        system.set_outputs(outputs.to_list())
    outputs.replace_signals(system.outputs)

    Delta_index = outputs['Delta_index']
    J_star = outputs['J_star']
    reached_minimum = outputs['reached_minimum']
    reached_the_end_of_currently_available_path_data = outputs[
        'reached_the_end_of_currently_available_path_data']

    # Introduce dy.sink(signal) in ORTD to ensure the given signals is not optimized out and becomes visible in the debugging traces
    dummy = 0 * outputs['index_head'] + 0 * outputs[
        'index_to_investigate'] + 0 * outputs['J_to_verify']

    Delta_index_track_next = Delta_index_track + Delta_index
    Delta_index_track << dy.delay(
        Delta_index_track_next, initial_state=1
    )  # start at 1 so that the backwards gradient can be computed at index=1
    Delta_index_track.set_name('Delta_index_track')

    # optimal index
    optimal_index = current_index + Delta_index_track_next

    results = dy.structure()
    results['optimal_index'] = optimal_index
    results['J_star'] = J_star + 0 * dummy
    results['Delta_index'] = Delta_index
    results['Delta_index_track_next'] = Delta_index_track_next
    results['reached_minimum'] = reached_minimum
    results[
        'reached_the_end_of_currently_available_path_data'] = reached_the_end_of_currently_available_path_data

    return results
if advanced_control:
    Delta_index_ahead, distance_residual, Delta_index_ahead_i1 = tracker_distance_ahead(path, current_index=tracked_index, distance_ahead=distance_ahead)

    dy.append_output(distance_residual, 'distance_residual')
    dy.append_output(Delta_index_ahead_i1, 'Delta_index_ahead_i1')
    dy.append_output(Delta_index_ahead, 'Delta_index_ahead')

# verify
if False:
    index_closest_compare, distance_compare, index_start_compare = lookup_closest_point( N=path['samples'], path_distance_storage=path['D'], path_x_storage=path['X'], path_y_storage=path['Y'], x=x, y=y )
    dy.append_output(index_closest_compare, 'index_closest_compare')


# get the reference
x_r, y_r, psi_rr, K_r = sample_path(path, index=tracked_index + dy.int32(1) )  # new sampling
# x_r, y_r, psi_rr = sample_path_finite_difference(path, index=tracked_index ) # old sampling





# compute the noise-reduced path orientation Psi_r from curvature
#
# NOTE: velocity: should be the projection of the vehicle velocity on the path?
#
psi_r, psi_r_dot = compute_path_orientation_from_curvature( Ts, velocity, psi_rr, K_r, L=1.0 ) 

dy.append_output(psi_rr,     'psi_rr')
dy.append_output(psi_r_dot, 'psi_r_dot')
Beispiel #13
0
def tracker_distance_ahead(path, current_index, distance_ahead):
    """

                  <----- Delta_index_track ----->
        array: X  X  X  X  X  X  X  X  X  X  X  X  X  X  X 
                  ^               
            current_index
    """

    if 'Delta_d' in path:
        # constant sampling interval in distance
        # computation can be simplified
        pass

    target_distance = dy.float64(distance_ahead) + dy.memory_read(
        memory=path['D'], index=current_index)

    def J(index):

        d_test = dy.memory_read(memory=path['D'], index=index)
        distance = dy.abs(d_test - target_distance)

        return distance

    Delta_index_track = dy.signal()

    # initialize J_star
    J_star_0 = J(current_index + Delta_index_track)
    J_star_0.set_name('J_star_0')

    #
    # compute the direction in which J has its decent
    # if true: with increasing index J increases  --> decrease search index
    # if false: with increasing index J decreases --> increase search index
    #
    J_next_index = J(current_index + Delta_index_track + dy.int32(1))
    J_Delta_to_next_index = J_next_index - J_star_0

    direction_flag = J_Delta_to_next_index > dy.float64(0)

    search_index_increment = dy.int32(1)
    search_index_increment = dy.conditional_overwrite(search_index_increment,
                                                      direction_flag,
                                                      dy.int32(-1))
    search_index_increment.set_name('search_index_increment')

    # loop to find the minimum of J
    with dy.sub_loop(max_iterations=1000) as system:

        # J_star(k) - the smallest J found so far
        J_star = dy.signal()

        # inc- / decrease the search index
        Delta_index_prev_it, Delta_index = dy.sum2(search_index_increment,
                                                   initial_state=0)

        Delta_index.set_name('Delta_index')

        # sample the cost function and check if it got smaller in this step
        J_to_verify = J(current_index + Delta_index_track + Delta_index)
        J_to_verify.set_name('J_to_verify')

        step_caused_improvment = J_to_verify < J_star

        # replace the
        J_star_next = dy.conditional_overwrite(J_star, step_caused_improvment,
                                               J_to_verify)

        # state for J_star
        J_star << dy.delay(J_star_next,
                           initial_state=J_star_0).set_name('J_star')

        # loop break condition
        system.loop_until(dy.logic_not(step_caused_improvment))

        # return the results computed in the loop
        system.set_outputs([Delta_index_prev_it, J_to_verify, J_star])

    Delta_index = system.outputs[0]

    Delta_index_track_next = Delta_index_track + Delta_index
    Delta_index_track << dy.delay(Delta_index_track_next, initial_state=0)
    Delta_index_track.set_name('Delta_index_track')

    # compute the residual distance
    optimal_distance = dy.memory_read(memory=path['D'],
                                      index=current_index +
                                      Delta_index_track_next)
    distance_residual = target_distance - optimal_distance

    return Delta_index_track_next, distance_residual, Delta_index


#
# lateral open-loop control to realize an 'obstacle-avoiding maneuver'
#
# the dynamic model for the lateral distance Delta_l is 
#
#   d/dt Delta_l = u, 
#
# meaning u is the lateral velocity to which is used to control the lateral
# distance to the path.
#

# generate a velocity profile
u_move_left  = dy.signal_step( dy.int32(50) )  - dy.signal_step( dy.int32(200) )
u_move_right = dy.signal_step( dy.int32(500) ) - dy.signal_step( dy.int32(350) )

# apply a rate limiter to limit the acceleration
u = dy.rate_limit( max_lateral_velocity * (u_move_left + u_move_right), Ts, dy.float64(-1) * max_lateral_accleration, max_lateral_accleration) 

dy.append_output(u, 'u')

# internal lateral model (to verify the lateral dynamics of the simulated vehicle)
Delta_l_mdl = dy.euler_integrator(u, Ts)
dy.append_output(Delta_l_mdl, 'Delta_l_mdl')




# some modification of one input
U = U2 * dy.float64(1.234)
U.set_name("stachmachine_input_U")

with dy.sub_statemachine( "statemachine1" ) as switch:

    with switch.new_subsystem('state_A') as system:

        # implement a dummy system the produces zero values for x and v
        x = dy.float64(0.0).set_name('x_def')
        v = dy.float64(0.0).set_name('v_def')

        counter = dy.counter().set_name('counter')
        timeout = ( counter > number_of_samples_to_stay_in_A ).set_name('timeout')
        next_state = dy.conditional_overwrite(signal=dy.int32(-1), condition=timeout, new_value=1 ).set_name('next_state')

        system.set_switched_outputs([ x, v, counter ], next_state)


    with switch.new_subsystem('state_B') as system:

        # implement a simple spring-mass oscillator: 
        # x is the position, v is the velocity, acc is the acceleration

        # create placeholder symbols for x and v (as they are used before being defined)
        x = dy.signal()
        v = dy.signal()

        acc = dy.add( [ U, v, x ], [ 1, -0.1, -0.1 ] ).set_blockname('acc').set_name('acc')
def tracker(path, x, y):
    """
        Continuously project the point (x, y) onto the given path (closest distance)

        This is an internal function. C.f. track_projection_on_path for details and assumptions.

        returns in structure tracking_results:
            tracked_index    - the index in the path array for the closest distance to (x, y)
            Delta_index      - the change of the index to the previous lookup
            distance         - the absolute value of the closest distance of (x, y) to the path

            reached_the_end_of_currently_available_path_data
                             - reached the end of the path
    """
    index_head, _ = path_horizon_head_index(path)
    index_head.set_name('index_head')

    # the index that currently describes the index on the path with the closest distance to (x,y)
    index_track = dy.signal().set_name('index_track')

    with dy.sub_loop( max_iterations=200, subsystem_name='tracker_loop' ) as system:

        search_index_increment = dy.int32(1) # positive increment assuming positive velocity

        Delta_index = dy.sum(search_index_increment, initial_state=-1 )
        Delta_index_previous_step = Delta_index - search_index_increment

        # the index at which to compute the distance to and see if it is the minimum 
        index_to_investigate  = index_track + Delta_index
        x_test, y_test        = sample_path_xy(path, index_to_investigate)
        distance              = distance_between( x_test, y_test, x, y )

        distance_previous_step = dy.delay(distance, initial_state=100000)
        minimal_distance_reached = distance_previous_step < distance

        # introduce signal names
        distance.set_name('distance')
        minimal_distance_reached.set_name('minimal_distance_reached')

        # break condition
        reached_the_end_of_currently_available_path_data = index_to_investigate >= index_head # reached the end of the input data?
        system.loop_until( dy.logic_or( minimal_distance_reached, reached_the_end_of_currently_available_path_data ) )

        # return        
        system.set_outputs([ 
            Delta_index_previous_step.set_name('Delta_index_previous_step'),
            distance_previous_step.set_name('distance_previous_step'),
            minimal_distance_reached.set_name('minimal_distance_reached'), 
            reached_the_end_of_currently_available_path_data.set_name('reached_the_end_of_currently_available_path_data')
        ])


    Delta_index                                      = system.outputs[0].set_name('tracker_Delta_index')
    distance                                         = system.outputs[1].set_name('distance')
    minimal_distance_reached                         = system.outputs[2].set_name('minimal_distance_reached')
    reached_the_end_of_currently_available_path_data = system.outputs[3].set_name('reached_the_end_of_currently_available_path_data')

    # update current state of index_track 
    index_track_next = index_track + Delta_index 
    index_track << dy.delay(index_track_next, initial_state=1)

    #
    tracking_results = dy.structure()
    tracking_results['tracked_index']                                    = index_track_next
    tracking_results['Delta_index']                                      = Delta_index
    tracking_results['distance']                                         = distance
    tracking_results['minimal_distance_reached']                         = minimal_distance_reached
    tracking_results['reached_the_end_of_currently_available_path_data'] = reached_the_end_of_currently_available_path_data

    # return index_track_next, Delta_index, distance, minimal_distance_reached, reached_the_end_of_currently_available_path_data

    return tracking_results