Exemple #1
0
def test_basic_code_gen():
    # create a new system
    system = dy.enter_system()

    # define system inputs
    input1 = dy.system_input(dy.DataTypeFloat64(1),
                             name='input1',
                             default_value=5.0,
                             value_range=[0, 25],
                             title="input #1")

    # the diagram
    tmp = input1 * dy.float64(2.0)
    tmp.set_name("some_name")
    output = dy.delay(tmp)

    # define output(s)
    dy.append_output(output, 'outputs')

    # generate code
    code_gen_results = dy.generate_code(template=dy.TargetWasm(),
                                        folder="generated/",
                                        build=False)
    sourcecode, manifest = code_gen_results['sourcecode'], code_gen_results[
        'manifest']

    # clear workspace
    dy.clear()
# load track data
with open("track_data/simple_track.json", "r") as read_file:
    track_data = json.load(read_file)

#
# Demo: a vehicle controlled to follow a given path
#
#       Implemented using the code generator openrtdynamics 2 - https://pypi.org/project/openrtdynamics2/ .
#       This generates c++ code for Web Assembly to be run within the browser.
#

system = dy.enter_system()

velocity = dy.system_input(dy.DataTypeFloat64(1),
                           name='velocity',
                           default_value=23.75,
                           value_range=[0, 25],
                           title="vehicle velocity")
k_p = dy.system_input(dy.DataTypeFloat64(1),
                      name='k_p',
                      default_value=2.0,
                      value_range=[0, 10.0],
                      title="controller gain")
disturbance_amplitude = dy.system_input(
    dy.DataTypeFloat64(1),
    name='disturbance_amplitude',
    default_value=20.0,
    value_range=[-45, 45],
    title="disturbance amplitude") * dy.float64(math.pi / 180.0)
sample_disturbance = dy.system_input(dy.DataTypeInt32(1),
                                     name='sample_disturbance',
# load track data
with open("track_data/simple_track.json", "r") as read_file:
    track_data = json.load(read_file)


#
# Demo: a vehicle controlled to follow a given path
#
#       Implemented using the code generator openrtdynamics 2 - https://pypi.org/project/openrtdynamics2/ .
#       This generates c++ code for Web Assembly to be run within the browser.
#

system = dy.enter_system()

velocity               = dy.system_input( dy.DataTypeFloat64(1), name='velocity',              default_value=25.0,   value_range=[0, 25],     title="vehicle velocity [m/s]")
steering_rate          = dy.system_input( dy.DataTypeFloat64(1), name='steering_rate',         default_value=1.0,    value_range=[-10, 10],   title="steering_rate [degrees/s]")              * dy.float64(math.pi / 180.0)
initial_steering       = dy.system_input( dy.DataTypeFloat64(1), name='initial_steering',      default_value=-10.0,  value_range=[-40, 40],   title="initial steering angle [degrees]")       * dy.float64(math.pi / 180.0)
initial_orientation    = dy.system_input( dy.DataTypeFloat64(1), name='initial_orientation',   default_value=0.0,    value_range=[-360, 360], title="initial orientation angle [degrees]")    * dy.float64(math.pi / 180.0)

# parameters
wheelbase = 3.0

# sampling time
Ts = 0.01

# create storage for the reference path:
path = import_path_data(track_data)

# linearly increasing steering angle
delta = dy.euler_integrator( steering_rate, Ts, initial_state=initial_steering )


# testname = 'signal_periodic_impulse' # 
testname = 'inline_ifsubsystem_oscillator' # 'signal_periodic_impulse' #'loop_until' #'inline_ifsubsystem_oscillator' # 
testname = 'cpp_class'

test_modification_1 = True  # option should not have an influence on the result
test_modification_2 = False # shall raise an error once this is true


if testname == 'test1':

    baseDatatype = dy.DataTypeFloat64(1) 

    U = dy.system_input( baseDatatype ).set_name('extU')

    y1 = firstOrderAndGain( U, 0.2, gain=0.8, name="1")
    y2 = firstOrderAndGain( y1, 0.2, gain=0.8, name="2")
    y3 = firstOrderAndGain( y2, 0.2, gain=0.8, name="3")

    E1 = dy.system_input( baseDatatype ).set_name('extE1')
    E2 = dy.system_input( baseDatatype ).set_name('extE2')

    y = dy.add( [ y3, E1, E2 ], [ 0.1, 0.2, 0.3] ).set_blockname('y (add)').set_name('y')

    # define the outputs of the simulation
    output_signals = [ y, y2 ]

    # specify what the input signals shall be in the runtime
    input_signals_mapping = {}
Exemple #5
0
# load track data
with open("track_data/simple_track.json", "r") as read_file:
    track_data = json.load(read_file)

#
# Demo: a vehicle controlled in an open-loop manner to follow a given path as long as possible
#
#       Implemented using the code generator openrtdynamics 2 - https://pypi.org/project/openrtdynamics2/ .
#       This generates c++ code for Web Assembly to be run within the browser.
#

system = dy.enter_system()

initial_velocity = dy.system_input(dy.DataTypeFloat64(1),
                                   name='initial_velocity',
                                   default_value=11.0,
                                   value_range=[0, 25],
                                   title="initial condition: vehicle velocity")
acceleration = dy.system_input(dy.DataTypeFloat64(1),
                               name='acceleration',
                               default_value=-2.5,
                               value_range=[-8, 0],
                               title="initial condition: vehicle acceleration")
disturbance_ofs = dy.system_input(
    dy.DataTypeFloat64(1),
    name='disturbance_ofs',
    default_value=-0.7,
    value_range=[-4, 4],
    title="disturbance: steering offset") * dy.float64(math.pi / 180.0)
delta_factor = dy.system_input(dy.DataTypeFloat64(1),
                               name='delta_factor',
# cfg
advanced_control = False

#
# A vehicle controlled to follow a given path 
#

system = dy.enter_system()
baseDatatype = dy.DataTypeFloat64(1) 

# define simulation inputs
if not advanced_control:


    velocity               = dy.system_input( dy.DataTypeFloat64(1), name='velocity',              default_value=7.2,   value_range=[0, 25],   title="vehicle velocity")
    k_p                    = dy.system_input( dy.DataTypeFloat64(1), name='k_p',                   default_value=0.612, value_range=[0, 4.0],  title="controller gain")
    disturbance_amplitude  = dy.system_input( dy.DataTypeFloat64(1), name='disturbance_amplitude', default_value=-11.0, value_range=[-45, 45], title="disturbance amplitude") * dy.float64(math.pi / 180.0)
    sample_disturbance     = dy.system_input( dy.DataTypeInt32(1),   name='sample_disturbance',    default_value=50,    value_range=[0, 300],  title="disturbance position")
    z_inf_compensator      = dy.system_input( dy.DataTypeFloat64(1), name='z_inf',                 default_value=0.9,   value_range=[0, 1.0],  title="z_inf_compensator")





if advanced_control:
    velocity       = dy.system_input( baseDatatype ).set_name('velocity').set_properties({ "range" : [0, 25], "unit" : "m/s", "default_value" : 23.75, "title" : "vehicle velocity" })
    k_p            = dy.system_input( baseDatatype ).set_name('k_p').set_properties({ "range" : [0, 4.0], "default_value" : 0.24, "title" : "controller gain" })

    disturbance_amplitude  = dy.system_input( baseDatatype ).set_name('disturbance_amplitude').set_properties({ "range" : [-45, 45], "unit" : "degrees", "default_value" : 0, "title" : "disturbance amplitude" })     * dy.float64(math.pi / 180.0)
    sample_disturbance     = dy.convert(dy.system_input( baseDatatype ).set_name('sample_disturbance').set_properties({ "range" : [0, 300], "unit" : "samples", "default_value" : 0, "title" : "disturbance position" }), target_type=dy.DataTypeInt32(1) )
Exemple #7
0
def compile_lateral_path_transformer(wheelbase=3.0, Ts=0.01):
    """
    Build OpenRTDynamics code for the lateral path transformation
    """

    dy.clear()
    system = dy.enter_system()

    velocity = dy.system_input(dy.DataTypeFloat64(1),
                               name='velocity_',
                               default_value=1,
                               value_range=[0, 25],
                               title="vehicle velocity")
    Delta_l_r = dy.system_input(dy.DataTypeFloat64(1),
                                name='Delta_l_r',
                                default_value=0.0,
                                value_range=[-10, 10],
                                title="lateral deviation to the path")
    Delta_l_r_dot = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_l_r_dot',
        default_value=0.0,
        value_range=[-10, 10],
        title="1st-order time derivative of lateral deviation to the path")
    Delta_l_r_dotdot = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_l_r_dotdot',
        default_value=0.0,
        value_range=[-10, 10],
        title="2nd-order time derivative of lateral deviation to the path")

    async_input_data_valid = dy.system_input(dy.DataTypeBoolean(1),
                                             name='async_input_data_valid')
    input_sample_valid = dy.system_input(dy.DataTypeBoolean(1),
                                         name='input_sample_valid')

    path_sample = {}
    path_sample['d'] = dy.system_input(dy.DataTypeFloat64(1), name='d_sample')
    path_sample['x'] = dy.system_input(dy.DataTypeFloat64(1), name='x_sample')
    path_sample['y'] = dy.system_input(dy.DataTypeFloat64(1), name='y_sample')
    path_sample['psi'] = dy.system_input(dy.DataTypeFloat64(1),
                                         name='psi_sample')
    path_sample['K'] = dy.system_input(dy.DataTypeFloat64(1), name='K_sample')

    input_signals = Ts, wheelbase, velocity, Delta_l_r, Delta_l_r_dot, Delta_l_r_dotdot

    output_signals = async_path_data_handler(input_sample_valid,
                                             async_input_data_valid,
                                             path_sample, input_signals)

    #
    # outputs: these are available for visualization in the html set-up
    #

    dy.append_output(output_signals['output_valid'], 'output_valid')
    dy.append_output(output_signals['need_more_path_input_data'],
                     'need_more_path_input_data')
    dy.append_output(output_signals['distance_at_the_end_of_horizon'],
                     'distance_at_the_end_of_horizon')
    dy.append_output(output_signals['distance_ahead'], 'distance_ahead')
    dy.append_output(output_signals['head_index'], 'head_index')
    dy.append_output(output_signals['read_position'], 'read_position')
    dy.append_output(output_signals['elements_free_to_write'],
                     'elements_free_to_write')

    dy.append_output(output_signals['tracked_index'], 'tracked_index')
    dy.append_output(output_signals['d_star'], 'path_d_star')

    dy.append_output(output_signals['d'], 'path_d')
    dy.append_output(output_signals['x'], 'path_x')
    dy.append_output(output_signals['y'], 'path_y')
    dy.append_output(output_signals['psi_r'], 'path_psi')
    dy.append_output(output_signals['K'], 'path_K')

    dy.append_output(output_signals['delta'], 'vehicle_delta')
    dy.append_output(output_signals['delta_dot'], 'vehicle_delta_dot')

    dy.append_output(output_signals['psi'], 'vehicle_psi')
    dy.append_output(output_signals['psi_dot'], 'vehicle_psi_dot')

    dy.append_output(velocity * dy.float64(1.0), 'velocity')

    # generate code for Web Assembly (wasm), requires emcc (emscripten) to build
    code_gen_results = dy.generate_code(
        template=dy.TargetWasm(enable_tracing=False),
        folder="generated/tmp1",
        build=False)

    compiled_system = dyexe.CompiledCode(code_gen_results)

    return code_gen_results, compiled_system
def compile_path_tracker(par={},
                         target_template=None,
                         folder=None,
                         samples_in_buffer=10000):
    """
    Build OpenRTDynamics code for the path tracker

    par               - optional parameters for the model (unused so far)
    target_template   - the openrtdynamics code generation terget template to use
    folder            - the folder to which the generated files are written 
    samples_in_buffer - the size of the buffer storing the samples for the input path    
    """

    dy.clear()
    system = dy.enter_system()

    # time-series for velocity, position, orientation, ...
    input_signals = {}
    input_signals['Ts'] = dy.system_input(dy.DataTypeFloat64(1),
                                          name='Ts',
                                          default_value=0.01,
                                          title="sampling time [s]")
    input_signals['velocity'] = dy.system_input(dy.DataTypeFloat64(1),
                                                name='velocity_',
                                                default_value=1,
                                                title="vehicle velocity [m/s]")
    input_signals['velocity_dot'] = dy.system_input(
        dy.DataTypeFloat64(1),
        name='velocity_dot',
        default_value=1,
        title="vehicle acceleration [m/s^2] (optional)")
    input_signals['x'] = dy.system_input(dy.DataTypeFloat64(1),
                                         name='x',
                                         default_value=0,
                                         title="state x [m]")
    input_signals['y'] = dy.system_input(dy.DataTypeFloat64(1),
                                         name='y',
                                         default_value=0,
                                         title="state y [m]")
    input_signals['x_dot'] = dy.system_input(
        dy.DataTypeFloat64(1),
        name='x_dot',
        default_value=0,
        title="state d/dt x [m/s] (optional)")
    input_signals['y_dot'] = dy.system_input(
        dy.DataTypeFloat64(1),
        name='y_dot',
        default_value=0,
        title="state d/dt y [m/s] (optional)")
    input_signals['Delta_u'] = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_u',
        default_value=0,
        title="Delta_u [rad] (optional)")
    input_signals['Delta_u_dot'] = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_u_dot',
        default_value=0,
        title="Delta_u_dot[rad/s] (optional)")

    # control inputs
    async_input_data_valid = dy.system_input(dy.DataTypeBoolean(1),
                                             name='async_input_data_valid')
    input_sample_valid = dy.system_input(dy.DataTypeBoolean(1),
                                         name='input_sample_valid')

    # inputs for asynchronously arriving path samples
    path_sample = {}
    path_sample['d'] = dy.system_input(dy.DataTypeFloat64(1), name='d_sample')
    path_sample['x'] = dy.system_input(dy.DataTypeFloat64(1), name='x_sample')
    path_sample['y'] = dy.system_input(dy.DataTypeFloat64(1), name='y_sample')
    path_sample['psi'] = dy.system_input(dy.DataTypeFloat64(1),
                                         name='psi_sample')
    path_sample['K'] = dy.system_input(dy.DataTypeFloat64(1), name='K_sample')

    #
    # combine all input signals in a structure that serve as parameters to the
    # callback function (the embedded system) vl.path_lateral_modification2
    #

    output_signals = async_path_data_handler(input_sample_valid,
                                             async_input_data_valid,
                                             path_sample, path_tracking,
                                             input_signals, par,
                                             samples_in_buffer)

    #
    # outputs
    #

    dy.append_output(output_signals['output_valid'], 'output_valid')
    dy.append_output(output_signals['need_more_path_input_data'],
                     'need_more_path_input_data')
    dy.append_output(output_signals['distance_at_the_end_of_horizon'],
                     'distance_at_the_end_of_horizon')
    dy.append_output(output_signals['distance_ahead'], 'distance_ahead')
    dy.append_output(output_signals['head_index'], 'head_index')
    dy.append_output(output_signals['read_position'], 'read_position')
    dy.append_output(output_signals['elements_free_to_write'],
                     'elements_free_to_write')

    # data sampled at the closest point on path
    dy.append_output(output_signals['tracked_index'], 'tracked_index')
    dy.append_output(output_signals['d_star'], 'd_star')
    dy.append_output(output_signals['v_star'], 'v_star')

    dy.append_output(output_signals['x_r'], 'x_r')
    dy.append_output(output_signals['y_r'], 'y_r')
    dy.append_output(output_signals['psi_r'], 'psi_r')
    dy.append_output(output_signals['K_r'], 'K_r')

    dy.append_output(output_signals['psi_r_dot'], 'psi_r_dot')

    dy.append_output(output_signals['Delta_l'], 'Delta_l')
    dy.append_output(output_signals['Delta_l_dot'], 'Delta_l_dot')

    # generate code
    if target_template is None:
        target_template = tg.TargetCppMinimal()

    code_gen_results = dy.generate_code(template=target_template,
                                        folder=folder)

    compiled_system = dyexe.CompiledCode(code_gen_results)

    return code_gen_results, compiled_system
def compile_lateral_path_transformer(par={},
                                     target_template=None,
                                     folder=None,
                                     samples_in_buffer=10000):
    """
    Build OpenRTDynamics code for the lateral path transformation

    par               - optional parameters for the model (unused so far)
    target_template   - the openrtdynamics code generation terget template to use
    folder            - the folder to which the generated files are written 
    samples_in_buffer - the size of the buffer storing the samples for the input path    
    """

    dy.clear()
    system = dy.enter_system()

    # parameters
    Ts = dy.system_input(dy.DataTypeFloat64(1),
                         name='Ts',
                         default_value=0.01,
                         title="sampling time [s]")
    wheelbase = dy.system_input(dy.DataTypeFloat64(1),
                                name='wheelbase',
                                default_value=3.0,
                                title="wheelbase (l_r) [m]")

    # time-series for velocity, lateral distance, ...
    velocity = dy.system_input(dy.DataTypeFloat64(1),
                               name='velocity_',
                               default_value=1,
                               value_range=[0, 25],
                               title="vehicle velocity [m/s]")
    Delta_l_r = dy.system_input(dy.DataTypeFloat64(1),
                                name='Delta_l_r',
                                default_value=0.0,
                                value_range=[-10, 10],
                                title="lateral deviation to the path [m]")
    Delta_l_r_dot = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_l_r_dot',
        default_value=0.0,
        value_range=[-10, 10],
        title="1st-order time derivative of lateral deviation to the path [m/s]"
    )
    Delta_l_r_dotdot = dy.system_input(
        dy.DataTypeFloat64(1),
        name='Delta_l_r_dotdot',
        default_value=0.0,
        value_range=[-10, 10],
        title=
        "2nd-order time derivative of lateral deviation to the path [m/s^2]")

    # initial states of the vehicle
    d0 = dy.system_input(dy.DataTypeFloat64(1),
                         name='d0',
                         default_value=0,
                         title="initial state d0 [m]")
    x0 = dy.system_input(dy.DataTypeFloat64(1),
                         name='x0',
                         default_value=0,
                         title="initial state x0 [m]")
    y0 = dy.system_input(dy.DataTypeFloat64(1),
                         name='y0',
                         default_value=0,
                         title="initial state y0 [m]")
    psi0 = dy.system_input(dy.DataTypeFloat64(1),
                           name='psi0',
                           default_value=0,
                           title="initial state psi0 [rad]")
    delta0 = dy.system_input(dy.DataTypeFloat64(1),
                             name='delta0',
                             default_value=0,
                             title="initial state delta0 [rad]")
    delta_dot0 = dy.system_input(dy.DataTypeFloat64(1),
                                 name='delta_dot0',
                                 default_value=0,
                                 title="initial state delta_dot0 [rad/s]")

    # control inputs
    async_input_data_valid = dy.system_input(dy.DataTypeBoolean(1),
                                             name='async_input_data_valid')
    input_sample_valid = dy.system_input(dy.DataTypeBoolean(1),
                                         name='input_sample_valid')

    # inputs for asynchronously arriving path samples
    path_sample = {}
    path_sample['d'] = dy.system_input(dy.DataTypeFloat64(1), name='d_sample')
    path_sample['x'] = dy.system_input(dy.DataTypeFloat64(1), name='x_sample')
    path_sample['y'] = dy.system_input(dy.DataTypeFloat64(1), name='y_sample')
    path_sample['psi'] = dy.system_input(dy.DataTypeFloat64(1),
                                         name='psi_sample')
    path_sample['K'] = dy.system_input(dy.DataTypeFloat64(1), name='K_sample')

    #
    # combine all input signals in a structure that serve as parameters to the
    # callback function (the embedded system) vl.path_lateral_modification2
    #
    input_signals = {
        'Ts': Ts,
        'wheelbase': wheelbase,
        'velocity': velocity,
        'Delta_l_r': Delta_l_r,
        'Delta_l_r_dot': Delta_l_r_dot,
        'Delta_l_r_dotdot': Delta_l_r_dotdot,
        'd0': d0,
        'x0': x0,
        'y0': y0,
        'psi0': psi0,
        'delta0': delta0,
        'delta_dot0': delta_dot0
    }

    output_signals = async_path_data_handler(
        input_sample_valid, async_input_data_valid, path_sample,
        vl.path_lateral_modification2, input_signals, par, samples_in_buffer)

    #
    # outputs
    #

    dy.append_output(output_signals['output_valid'], 'output_valid')
    dy.append_output(output_signals['need_more_path_input_data'],
                     'need_more_path_input_data')
    dy.append_output(output_signals['distance_at_the_end_of_horizon'],
                     'distance_at_the_end_of_horizon')
    dy.append_output(output_signals['distance_ahead'], 'distance_ahead')
    dy.append_output(output_signals['head_index'], 'head_index')
    dy.append_output(output_signals['read_position'], 'read_position')
    dy.append_output(output_signals['elements_free_to_write'],
                     'elements_free_to_write')

    dy.append_output(output_signals['tracked_index'], 'tracked_index')

    dy.append_output(output_signals['d_star'], 'path_d_star')
    dy.append_output(output_signals['d'], 'path_d')
    dy.append_output(output_signals['x'], 'path_x')
    dy.append_output(output_signals['y'], 'path_y')
    dy.append_output(output_signals['psi_r'], 'path_psi')
    dy.append_output(output_signals['K'], 'path_K')

    dy.append_output(output_signals['delta'], 'vehicle_delta')
    dy.append_output(output_signals['delta_dot'], 'vehicle_delta_dot')

    dy.append_output(output_signals['psi'], 'vehicle_psi')
    dy.append_output(output_signals['psi_dot'], 'vehicle_psi_dot')

    dy.append_output(velocity * dy.float64(1.0), 'velocity')

    # generate code
    if target_template is None:
        target_template = tg.TargetCppMinimal()

    code_gen_results = dy.generate_code(template=target_template,
                                        folder=folder)

    compiled_system = dyexe.CompiledCode(code_gen_results)

    return code_gen_results, compiled_system
def euler_integrator(u: dy.Signal, sampling_rate: float, initial_state=0.0):

    yFb = dy.signal()

    i = dy.add([yFb, u], [1, sampling_rate])
    y = dy.delay(i, initial_state)

    yFb << y

    return y


ofs = dy.float64(0.1).set_name('ofs')

# define system inputs
friction = dy.system_input(baseDatatype).set_name('friction') * dy.float64(
    0.05) + ofs
mass = dy.system_input(baseDatatype).set_name('mass') * dy.float64(0.05) + ofs
length = dy.system_input(baseDatatype).set_name('length') * dy.float64(
    0.05) + ofs

# length = dy.float64(0.3)
g = dy.float64(9.81).set_name('g')

# create placeholder for the plant output signal
angle = dy.signal()
angular_velocity = dy.signal()

angular_acceleration = dy.float64(
    0) - g / length * dy.sin(angle) - (friction /
                                       (mass * length)) * angular_velocity
# load track data
with open("track_data/simple_track.json", "r") as read_file:
    track_data = json.load(read_file)


#
# Demo: a vehicle controlled to follow a given path
#
#       Implemented using the code generator openrtdynamics 2 - https://pypi.org/project/openrtdynamics2/ .
#       This generates c++ code for Web Assembly to be run within the browser.
#

system = dy.enter_system()

velocity                = dy.system_input( dy.DataTypeFloat64(1), name='velocity',                  default_value=6.0,  value_range=[0, 25],    title="vehicle velocity")
max_lateral_velocity    = dy.system_input( dy.DataTypeFloat64(1), name='max_lateral_velocity',      default_value=1.0,  value_range=[0, 4.0],   title="maximal lateral velocity")
max_lateral_accleration = dy.system_input( dy.DataTypeFloat64(1), name='max_lateral_accleration',   default_value=2.0,  value_range=[1.0, 4.0], title="maximal lateral acceleration")

# parameters
wheelbase = 3.0

# sampling time
Ts = 0.01

# create storage for the reference path:
path = import_path_data(track_data)

# create placeholders for the plant output signals
x   = dy.signal()
y   = dy.signal()
    i = dy.add( [ yFb, u ], [ 1, Ts ] ).set_name(name + '_i')
    y = dy.delay( i, initial_state ).set_name(name + '_y')

    yFb << y

    return y





baseDatatype = dy.DataTypeFloat64(1) 

# define system inputs
number_of_samples_to_stay_in_A = dy.system_input( baseDatatype ).set_name('number_of_samples_to_stay_in_A')
threshold_for_x_to_leave_B     = dy.system_input( baseDatatype ).set_name('threshold_for_x_to_leave_B')
U2                             = dy.system_input( baseDatatype ).set_name('osc_excitement')

# 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')
def euler_integrator(u: dy.Signal, sampling_rate: float, initial_state=0.0):

    yFb = dy.signal()

    i = dy.add([yFb, u], [1, sampling_rate])
    y = dy.delay(i, initial_state)

    yFb << y

    return y


# define system inputs
velocity = dy.system_input(baseDatatype).set_name('velocity').set_properties({
    "range": [0, 20.0],
    "default_value":
    20.0
})
k_p = dy.system_input(baseDatatype).set_name('k_p').set_properties({
    "range": [0, 1.0],
    "default_value":
    0.33
})

wheelbase = 3.0

# generate a step-wise reference signal
pwm_signal, state_control = generate_signal_PWM(period=dy.float64(200),
                                                modulator=dy.float64(0.5))
reference = (pwm_signal - dy.float64(0.5)) * dy.float64(1.0)
reference.set_name('reference')