Module openrtdynamics2.lang
Expand source code
from .lang import *
__pdoc__ = {}
__pdoc__['lang'] = False
# __all__ = ['show_required_inputs', 'run_batch_simulation', 'SystemInstance', 'CompiledCode']
__all__ = dir()
Sub-modules
openrtdynamics2.lang.block_interface
openrtdynamics2.lang.block_prototypes
openrtdynamics2.lang.block_prototypes_single_subsystem
openrtdynamics2.lang.block_prototypes_subsystems
openrtdynamics2.lang.block_prototypes_switched_subsystems
openrtdynamics2.lang.code_generation_templates
openrtdynamics2.lang.core_blocks
openrtdynamics2.lang.diagram_core
openrtdynamics2.lang.high_level_user_commands
openrtdynamics2.lang.libraries
openrtdynamics2.lang.signal_interface
openrtdynamics2.lang.standard_library
openrtdynamics2.lang.subsystems
openrtdynamics2.lang.system_context
Functions
def PID_controller(r, y, Ts, kp, ki=None, kd=None)
-
Discrete-time PID-controller
Parameters
r
:SignalUserTemplate
- the reference signal
y
:SignalUserTemplate
- the measured plant output
Ts
:float
- the sampleing time
kp
:float
- the parameter kp (proportional)
ki
:float
- the parameter ki (integral)
kd
:float
- the parameter kd (differential)
Returns
SignalUserTemplate
- the control variable u
Expand source code
def PID_controller(r, y, Ts, kp, ki = None, kd = None): """Discrete-time PID-controller Parameters ---------- r : SignalUserTemplate the reference signal y : SignalUserTemplate the measured plant output Ts : float the sampleing time kp : float the parameter kp (proportional) ki : float the parameter ki (integral) kd : float the parameter kd (differential) Returns ------- SignalUserTemplate the control variable u """ Ts = dy.float64(Ts) # control error e = r - y # P u = kp * e # D if kd is not None: u = u + dy.diff(e) * kd / Ts # I if ki is not None: u = u + dy.sum(e) * ki * Ts return u
def abs(u: SignalUserTemplate)
-
Absolute value
Computes the absolute value |u|.
Expand source code
def abs(u : SignalUserTemplate ): """ Absolute value Computes the absolute value |u|. """ return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'abs').outputs[0] )
def acos(u: SignalUserTemplate)
-
Expand source code
def acos(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'acos').outputs[0] )
def add(input_signals: List[SignalUserTemplate], factors: List[float])
-
Linear combination of the list of input signals with the list of factors
the output is given by
input_signals[0] * factors[0] + input_signals[1] * factors[1] + ...
Expand source code
def add(input_signals : List[SignalUserTemplate], factors : List[float]): """ Linear combination of the list of input signals with the list of factors the output is given by input_signals[0] * factors[0] + input_signals[1] * factors[1] + ... """ return wrap_signal( Add(dy.get_system_context(), unwrap_list( input_signals ), factors).outputs[0] )
def append_primay_ouput(output_signal, export_name: str = None)
-
add an output to the current system
Expand source code
def append_primay_ouput(output_signal, export_name : str = None): """ add an output to the current system """ if export_name is not None: output_signal.set_name_raw(export_name) get_system_context().append_primay_ouput(output_signal.unwrap)
def asin(u: SignalUserTemplate)
-
Expand source code
def asin(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'asin').outputs[0] )
def atan(u: SignalUserTemplate)
-
Expand source code
def atan(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'atan').outputs[0] )
def atan2(y: SignalUserTemplate, x: SignalUserTemplate)
-
atan2
This function returns atan2(x,y).
Parameters
x
:SignalUserTemplate
- x
y
:SignalUserTemplate
- y
Returns
SignalUserTemplate
- the output signal
Details
returns atan2(x,y)
Expand source code
def atan2(y : SignalUserTemplate, x : SignalUserTemplate ): """ atan2 This function returns atan2(x,y). Parameters ---------- x : SignalUserTemplate x y : SignalUserTemplate y Returns ------- SignalUserTemplate the output signal Details ------- returns atan2(x,y) """ return wrap_signal( StaticFnByName_2To1(dy.get_system_context(), y.unwrap, x.unwrap, 'atan2').outputs[0] )
def bitwise_and(u1: SignalUserTemplate, u2: SignalUserTemplate)
-
bitwise and
u1 & u2
Expand source code
def bitwise_and(u1 : SignalUserTemplate, u2 : SignalUserTemplate): """ bitwise and u1 & u2 """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list([u1,u2]), operator=' & ').outputs[0] )
def bitwise_not(u: SignalUserTemplate)
-
Bitwise not operator
Parameters
u
:SignalUserTemplate
- the integer input signal
Returns
SignalUserTemplate
- the integer output signal
Details
returns ~u
Expand source code
def bitwise_not(u : SignalUserTemplate ): """ Bitwise not operator Parameters ---------- u : SignalUserTemplate the integer input signal Returns ------- SignalUserTemplate the integer output signal Details ------- returns ~u """ return wrap_signal( Operator0(dy.get_system_context(), u.unwrap, '~').outputs[0] )
def bitwise_or(u1: SignalUserTemplate, u2: SignalUserTemplate)
-
bitwise or
u1 | u2
Expand source code
def bitwise_or(u1 : SignalUserTemplate, u2 : SignalUserTemplate): """ bitwise or u1 | u2 """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list( [u1,u2] ), operator=' | ').outputs[0] )
def bitwise_shift_left(u: SignalUserTemplate, shift: SignalUserTemplate)
-
logical shift left
u << shift
Expand source code
def bitwise_shift_left(u : SignalUserTemplate, shift : SignalUserTemplate): """ logical shift left u << shift """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list( [u,shift] ), operator=' << ').outputs[0] )
def bitwise_shift_right(u: SignalUserTemplate, shift: SignalUserTemplate)
-
logical shift left
u >> shift
Expand source code
def bitwise_shift_right(u : SignalUserTemplate, shift : SignalUserTemplate): """ logical shift left u >> shift """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list( [u,shift] ), operator=' >> ').outputs[0] )
def boolean(value)
-
Cast anything to DataTypeBoolean
Convert the input value to a signal.
Parameters
value
:SignalUserTemplate, int
- the signal or a constant value to convert to a signal
Returns
SignalUserTemplate
- the signal of type boolean
Expand source code
def boolean(value): """Cast anything to DataTypeBoolean Convert the input value to a signal. Parameters ---------- value : SignalUserTemplate, int the signal or a constant value to convert to a signal Returns ------- SignalUserTemplate the signal of type boolean """ if isinstance( value, SignalUserTemplate ): # already a singal return value else: # create a new constant return dy.const(value, dy.DataTypeBoolean(1) )
def clear()
-
clear the context
Expand source code
def clear(): """ clear the context """ init_simulation_context()
def comparison(left: SignalUserTemplate, right: SignalUserTemplate, operator: str)
-
Expand source code
def comparison(left : SignalUserTemplate, right : SignalUserTemplate, operator : str ): return wrap_signal( ComparisionOperator(dy.get_system_context(), left.unwrap, right.unwrap, operator).outputs[0] )
def compile_system(system=None)
-
Expand source code
def compile_system(system = None): if system is None: system = get_system_context() system.propagate_datatypes() # # compile the diagram: turn the blocks and signals into a tree-structure of commands to execute # at runtime. # compiler = dc.CompileDiagram() compile_results = compiler.compile( system ) # return compile_results
def conditional_overwrite(signal: SignalUserTemplate, condition: SignalUserTemplate, new_value)
-
Overwrite the input signal by a given value in case a condition is true
The output is given by
signal for condition==false new_value for condition==true
Parameters
signal
:SignalUserTemplate
- the input signal
condition
:SignalUserTemplate
- the boolean condition for when to overwrite signal
new_value
:SignalUserTemplate, float, int
- the value with is used to replace the input in case the condition is true
Returns
SignalUserTemplate
- the output signal
Expand source code
def conditional_overwrite(signal : SignalUserTemplate, condition : SignalUserTemplate, new_value ): """ Overwrite the input signal by a given value in case a condition is true The output is given by signal for condition==false new_value for condition==true Parameters ---------- signal : SignalUserTemplate the input signal condition : SignalUserTemplate the boolean condition for when to overwrite signal new_value : SignalUserTemplate, float, int the value with is used to replace the input in case the condition is true Returns ------- SignalUserTemplate the output signal """ if isinstance(new_value, SignalUserTemplate): new_value = new_value.unwrap return wrap_signal( ConditionalOverwrite(dy.get_system_context(), signal.unwrap, condition.unwrap, new_value).outputs[0] )
def const(constant, datatype)
-
Expand source code
def const(constant, datatype ): return wrap_signal( Const(dy.get_system_context(), constant, datatype).outputs[0] )
def convert(u: SignalUserTemplate, target_type: DataType)
-
Datatype conversion
The input is converted to the given datatype
Parameters
u
:SignalUserTemplate
- the input signal
target_type
- the datatype to convert the signal to
Returns
SignalUserTemplate
- the output signal with the given type
Expand source code
def convert(u : SignalUserTemplate, target_type : dt.DataType ): """ Datatype conversion The input is converted to the given datatype Parameters ---------- u : SignalUserTemplate the input signal target_type the datatype to convert the signal to Returns ------- SignalUserTemplate the output signal with the given type """ return wrap_signal( ConvertDatatype(dy.get_system_context(), u.unwrap, target_type).outputs[0] )
def cos(u: SignalUserTemplate)
-
Expand source code
def cos(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'cos').outputs[0] )
def counter()
-
Basic counter - the sampling index k
The integer output is increasing with each sampling instant by 1. Counting starts at zero.
Returns
SignalUserTemplate
- the integer output signal describing the sampling index k
Expand source code
def counter(): """Basic counter - the sampling index k The integer output is increasing with each sampling instant by 1. Counting starts at zero. Returns ------- SignalUserTemplate the integer output signal describing the sampling index k """ if not 'counter' in dy.get_system_context().components: # no counter has been defined in this system so far. Hence, create one. increase = dy.const(1, dy.DataTypeInt32(1) ) cnt = dy.signal() tmp = dy.delay(cnt + increase) cnt << tmp tmp.set_name('shared_counter') # store the output signal of the counter as it might be used again. dy.get_system_context().components['counter'] = __Counter(tmp) else: # use the output of an already created counter tmp = dy.get_system_context().components['counter'].output return tmp
def counter_triggered(upper_limit, stepwidth=None, initial_state=0, reset=None, reset_on_limit: bool = False, start_trigger=None, pause_trigger=None, auto_start: bool = True, no_delay: bool = False)
-
A generic counter
Features: - upper limit - triggerable start/pause - resetable - dynamic adjustable step-size
Parameters
upper_limit
:int
- the upper limit of the counter
initial_state
:int
- the state after reset
reset
:SignalUserTemplate
- reset the counter
reset_on_limit
:bool
- reset counter once the upper limit is reached
start_trigger
:SignalUserTemplate
- event to start counting
pause_trigger
:SignalUserTemplate
- event to pause counting
auto_start
:bool
- start counting automatically
no_delay
:bool
- when True the new value of the counter is returned without delay
Returns
SignalUserTemplate
- the boolean output signal
SignalUserTemplate
- event that fires when the upper limit of the counter is reached
Expand source code
def counter_triggered( upper_limit, stepwidth=None, initial_state = 0, reset=None, reset_on_limit:bool=False, start_trigger=None, pause_trigger=None, auto_start:bool=True, no_delay:bool=False ): """A generic counter Features: - upper limit - triggerable start/pause - resetable - dynamic adjustable step-size Parameters ---------- upper_limit : int the upper limit of the counter initial_state : int the state after reset reset : SignalUserTemplate reset the counter reset_on_limit : bool reset counter once the upper limit is reached start_trigger : SignalUserTemplate event to start counting pause_trigger : SignalUserTemplate event to pause counting auto_start : bool start counting automatically no_delay : bool when True the new value of the counter is returned without delay Returns ------- SignalUserTemplate the boolean output signal SignalUserTemplate event that fires when the upper limit of the counter is reached """ if stepwidth is None: stepwidth = dy.int32(1) counter = dy.signal() reached_upper_limit = counter >= dy.int32(upper_limit) if start_trigger is None: start_trigger = dy.boolean(0) # if pause_trigger is not None: activate_trigger = dy.logic_or(reached_upper_limit, pause_trigger) else: if not auto_start: activate_trigger = reached_upper_limit else: # when auto_start is active, continue counting after reset on reached_upper_limit activate_trigger = dy.boolean(0) # state for pause/counting paused = dy.flipflop(activate_trigger=activate_trigger, disable_trigger=start_trigger, initial_state = not auto_start, no_delay=True).set_name('paused') # prevent counter increase stepwidth = dy.conditional_overwrite(stepwidth, paused, 0).set_name('stepwidth') # increase the counter until the end is reached new_counter = counter + dy.conditional_overwrite(stepwidth, reached_upper_limit, 0) if reset is not None: # reset in case this is requested new_counter = dy.conditional_overwrite(new_counter, reset, initial_state) if reset_on_limit: new_counter = dy.conditional_overwrite(new_counter, reached_upper_limit, initial_state) # introduce a state variable for the counter counter << dy.delay( new_counter, initial_state=initial_state ) if not no_delay: return counter, reached_upper_limit else: return new_counter, reached_upper_limit
def cpp_allocate_class(datatype, code_constructor_call)
-
Return a pointer signal pointing to a class instance initialized by code_constructor_call
Parameters
ptr_signal
:DataTypePointer
- the datatype of the pointer to use
code_constructor_call
:str
- the code to initialize the class instance
Expand source code
def cpp_allocate_class(datatype, code_constructor_call): """ Return a pointer signal pointing to a class instance initialized by code_constructor_call Parameters ---------- ptr_signal : DataTypePointer the datatype of the pointer to use code_constructor_call : str the code to initialize the class instance """ return wrap_signal( AllocateClass(dy.get_system_context(), datatype, code_constructor_call).outputs[0] )
def cpp_call_class_member_function(ptr_signal: SignalUserTemplate, input_signals: List[SignalUserTemplate], input_types, output_types, member_function_name_to_calc_outputs: str = None, member_function_name_to_update_states: str = None, member_function_name_to_reset_states: str = None)
-
Call member functions of a c++ class
This function calls member functions of a class instance given by a pointer to an instance. In- and outputs are passed as parameters to the member function given by 'member_function_name_to_calc_outputs'. Herein, the output signals are the first parameters and the input signals then follow.
On an optional state update call, the member function 'member_function_name_to_update_states' is called and the parameters are the input signals.
Parameters
ptr_signal
:SignalUserTemplate
- the pointer to the class instance as generated by cpp_allocate_class()
input_signals
:SignalUserTemplate
- a list of input signals that are passed to the called member functions via the parameters
input_types
:List[ Datatype ]
- the datatypes of the inputs
output_types
:List[ Datatype ]
- the datatypes of the outputs
member_function_name_to_calc_outputs
:str
- the name of the member function to call to compute the output signals
member_function_name_to_update_states
:str
- optional: the name of the member function to call to update the states
Returns
List[SignalUserTemplate|
- the output signals
Expand source code
def cpp_call_class_member_function( ptr_signal : SignalUserTemplate, input_signals : List[SignalUserTemplate], input_types, output_types, member_function_name_to_calc_outputs : str = None, member_function_name_to_update_states : str = None, member_function_name_to_reset_states : str = None ): """ Call member functions of a c++ class This function calls member functions of a class instance given by a pointer to an instance. In- and outputs are passed as parameters to the member function given by 'member_function_name_to_calc_outputs'. Herein, the output signals are the first parameters and the input signals then follow. On an optional state update call, the member function 'member_function_name_to_update_states' is called and the parameters are the input signals. Parameters ---------- ptr_signal : SignalUserTemplate the pointer to the class instance as generated by cpp_allocate_class() input_signals : SignalUserTemplate a list of input signals that are passed to the called member functions via the parameters input_types : List[ Datatype ] the datatypes of the inputs output_types : List[ Datatype ] the datatypes of the outputs member_function_name_to_calc_outputs : str the name of the member function to call to compute the output signals member_function_name_to_update_states : str optional: the name of the member function to call to update the states Returns ------- List[SignalUserTemplate| the output signals """ bp = CallClassMemberFunction( dy.get_system_context(), unwrap_list(input_signals), input_types, output_types, ptr_signal = ptr_signal.unwrap, member_function_name_to_calc_outputs = member_function_name_to_calc_outputs, member_function_name_to_update_states = member_function_name_to_update_states, member_function_name_to_reset_states = member_function_name_to_reset_states ) return wrap_signal_list( bp.outputs )
def delay(u, initial_state=None)
-
Unit delay
Delay the input u by one sampling instant:
y[k+1] = u[k], y[0] = initial_state
Parameters
u
:SignalUserTemplate
- the input signal to delay
initial_state
:SignalUserTemplate
- the initial state (signal or constant value)
Returns
SignalUserTemplate
- the one-step delayed input
Expand source code
def delay(u , initial_state = None): """Unit delay Delay the input u by one sampling instant: y[k+1] = u[k], y[0] = initial_state Parameters ---------- u : SignalUserTemplate the input signal to delay initial_state : SignalUserTemplate the initial state (signal or constant value) Returns ------- SignalUserTemplate the one-step delayed input """ if not isinstance( initial_state, SignalUserTemplate ): return dy.delay__( u, initial_state ) else: event_on_first_sample = initial_event() delayed_input = dy.delay__( u, None ) delayed_input = dy.conditional_overwrite( delayed_input, event_on_first_sample, initial_state ) return delayed_input
def delay__(u: SignalUserTemplate, initial_state=None)
-
Expand source code
def delay__(u : SignalUserTemplate, initial_state = None): return wrap_signal( Delay(dy.get_system_context(), u.unwrap, initial_state ).outputs[0] )
def diff(u: SignalUserTemplate, initial_state=None)
-
Discrete difference
Parameters
u
:SignalUserTemplate
- the input signal
initial_state
:float, SignalUserTemplate
- the initial state
Returns
SignalUserTemplate
- the output signal of the filter
Details:
y = u[k] - u[k-1]
initial state
u[0] = initial_state in case initial_state is not None u[0] = 0 otherwise
Expand source code
def diff(u : SignalUserTemplate, initial_state = None): """Discrete difference Parameters ---------- u : SignalUserTemplate the input signal initial_state : float, SignalUserTemplate the initial state Returns ------- SignalUserTemplate the output signal of the filter Details: -------- y = u[k] - u[k-1] initial state u[0] = initial_state in case initial_state is not None u[0] = 0 otherwise """ i = dy.delay( u, initial_state ) y = dy.add( [ i, u ], [ -1, 1 ] ) return y
def dtf_lowpass_1_order(u: SignalUserTemplate, z_infinity)
-
First-order discrete-time low pass filter
Parameters
u
:SignalUserTemplate
- the input signal
Returns
SignalUserTemplate
- the output signal of the filter
Details:
1 - z_infinity H (z) = -------------- z - z_infinity
Expand source code
def dtf_lowpass_1_order(u : SignalUserTemplate, z_infinity): """First-order discrete-time low pass filter Parameters ---------- u : SignalUserTemplate the input signal Returns ------- SignalUserTemplate the output signal of the filter Details: -------- 1 - z_infinity H (z) = -------------- z - z_infinity """ zinf = dy.float64( z_infinity ) zinf_ = dy.float64( 1 ) - zinf y_delayed = dy.signal() y = zinf * y_delayed + zinf_ * u y_delayed << dy.delay(y) return y
def enter_system(name: str = 'simulation', upper_level_system=None)
-
create a new system and activate it in the context
Expand source code
def enter_system(name : str = 'simulation', upper_level_system = None): """ create a new system and activate it in the context """ # new simulation system = System(upper_level_system, name) # register this subsystem to the parent system if get_system_context() is not None: get_system_context().append_subsystem( system ) push_simulation_context(system) return system
def euler_integrator(u: SignalUserTemplate, Ts, initial_state=0.0)
-
Euler (forward) integrator
Parameters
u
:SignalUserTemplate
- the input signal
Ts
:float
- the sampling time
initial_state
:float, SignalUserTemplate
- the initial state of the integrator
Returns
SignalUserTemplate
- the output signal of the filter
Details:
y[k+1] = y[k] + Ts * u[k]
Expand source code
def euler_integrator( u : SignalUserTemplate, Ts, initial_state = 0.0): """Euler (forward) integrator Parameters ---------- u : SignalUserTemplate the input signal Ts : float the sampling time initial_state : float, SignalUserTemplate the initial state of the integrator Returns ------- SignalUserTemplate the output signal of the filter Details: -------- y[k+1] = y[k] + Ts * u[k] """ yFb = dy.signal() if not isinstance( Ts, SignalUserTemplate ): i = dy.add( [ yFb, u ], [ 1, Ts ] ) else: i = yFb + Ts * u y = dy.delay( i, initial_state ) yFb << y return y
def export_graph(filename, system=None)
-
Expand source code
def export_graph(filename, system = None): if system is None: system = get_system_context() graph = system.exportGraph() with open( os.path.join( filename ), 'w') as outfile: json.dump(graph, outfile)
def flipflop(activate_trigger: SignalUserTemplate, disable_trigger: SignalUserTemplate, initial_state=False, no_delay=False)
-
Flipflop logic element
The block has a state that can be activated or deactivated by the external boolean events 'activate_trigger' and 'disable_trigger', respectively.
Parameters
activate_trigger
:SignalUserTemplate
- the event to activate the state
disable_trigger
:SignalUserTemplate
- the event to deactivate the state
initial_state
:bool
- the initial state
no_delay
:bool
- return the state change without a delay
Returns
SignalUserTemplate
- the state
Expand source code
def flipflop(activate_trigger : SignalUserTemplate, disable_trigger : SignalUserTemplate, initial_state = False, no_delay = False): """Flipflop logic element The block has a state that can be activated or deactivated by the external boolean events 'activate_trigger' and 'disable_trigger', respectively. Parameters ---------- activate_trigger : SignalUserTemplate the event to activate the state disable_trigger : SignalUserTemplate the event to deactivate the state initial_state : bool the initial state no_delay : bool return the state change without a delay Returns ------- SignalUserTemplate the state """ return wrap_signal( Flipflop(dy.get_system_context(), activate_trigger.unwrap, disable_trigger.unwrap, initial_state = initial_state, no_delay=no_delay ).outputs[0] )
def float64(value)
-
Cast anything to DataTypeFloat64
Convert the input value to a signal.
Parameters
value
:SignalUserTemplate, float
- the signal or a constant value to convert to a signal
Returns
SignalUserTemplate
- the signal of type float64
Expand source code
def float64(value): """Cast anything to DataTypeFloat64 Convert the input value to a signal. Parameters ---------- value : SignalUserTemplate, float the signal or a constant value to convert to a signal Returns ------- SignalUserTemplate the signal of type float64 """ if isinstance( value, SignalUserTemplate ): # already a singal return value else: # create a new constant return dy.const(value, dy.DataTypeFloat64(1) )
def fmod(x: SignalUserTemplate, y: SignalUserTemplate)
-
Modulo function for floating point values
This function returns the remainder of dividing x/y.
Parameters
x
:SignalUserTemplate
- x
y
:SignalUserTemplate
- y
Returns
SignalUserTemplate
- the output signal
Details
returns fmod(x,y)
Expand source code
def fmod(x : SignalUserTemplate, y : SignalUserTemplate ): """ Modulo function for floating point values This function returns the remainder of dividing x/y. Parameters ---------- x : SignalUserTemplate x y : SignalUserTemplate y Returns ------- SignalUserTemplate the output signal Details ------- returns fmod(x,y) """ return wrap_signal( StaticFnByName_2To1(dy.get_system_context(), x.unwrap, y.unwrap, 'fmod').outputs[0] )
def gain(u: SignalUserTemplate, gain: float)
-
Expand source code
def gain(u : SignalUserTemplate, gain : float ): return wrap_signal( Gain(dy.get_system_context(), u.unwrap, gain).outputs[0] )
def generate_code(template: TargetGenericCpp, folder=None, build=False, include_code_list: List[str] = [])
-
Expand source code
def generate_code(template : TargetGenericCpp, folder=None, build=False, include_code_list : t.List[str] = [] ): template.add_code_to_include(include_code_list) # Compile system (propagate datatypes) compile_results = compile_system() # Build an executable based on a template template.set_compile_results( compile_results ) code_gen_results = template.code_gen() if folder is not None: # check of path exists - in case no, create it pl.Path(folder).mkdir(parents=True, exist_ok=True) print("Generated code will be written to " + str(folder) + ' .') # write generated code into a folder and build template.write_code(folder) if build: template.build() return code_gen_results
def generic_cpp_static(input_signals: List[SignalUserTemplate], input_names: List[str], input_types, output_names, output_types, cpp_source_code: str)
-
Embed C/C++ source code (stateless code only)
Parameters
input_signals
:List[SignalUserTemplate]
- the list of input signals
input_names
:List[str]
- the list of the names of the input signals to be used as variable names for the c++ code
input_types
:List[Datatype]
- the list of the datatypes of the input signals (must be fixed)
output_types
:List[Datatype]
- the list of the datatypes of the output signals (must be fixed)
output_names
:List[str]
- the list of the names of the output signals to be used as variable names for the c++ code
cpp_source_code
:str
- the code to embed
Returns
List[SignalUserTemplate]
- the output signals
Example
source_code = """ // This is c++ code output1 = value; if (someinput > value) { output2 = value; } else { output2 = someinput; } output3 = 0.0; """ outputs = dy.generic_cpp_static( input_signals=[ someinput, value ], input_names=[ 'someinput', 'value' ], input_types=[ dy.DataTypeFloat64(1), dy.DataTypeFloat64(1) ], output_names=['output1', 'output2', 'output3'], output_types=[ dy.DataTypeFloat64(1), dy.DataTypeFloat64(1), dy.DataTypeFloat64(1) ], cpp_source_code = source_code ) output1 = outputs[0] output2 = outputs[1] output3 = outputs[2]
Expand source code
def generic_cpp_static( input_signals : List[SignalUserTemplate], input_names : List [str], input_types, output_names, output_types, cpp_source_code : str ): """ Embed C/C++ source code (stateless code only) Parameters ---------- input_signals : List[SignalUserTemplate] the list of input signals input_names : List[str] the list of the names of the input signals to be used as variable names for the c++ code input_types : List[Datatype] the list of the datatypes of the input signals (must be fixed) output_types : List[Datatype] the list of the datatypes of the output signals (must be fixed) output_names : List[str] the list of the names of the output signals to be used as variable names for the c++ code cpp_source_code : str the code to embed Returns ------- List[SignalUserTemplate] the output signals Example ------- source_code = \"\"\" // This is c++ code output1 = value; if (someinput > value) { output2 = value; } else { output2 = someinput; } output3 = 0.0; \"\"\" outputs = dy.generic_cpp_static( input_signals=[ someinput, value ], input_names=[ 'someinput', 'value' ], input_types=[ dy.DataTypeFloat64(1), dy.DataTypeFloat64(1) ], output_names=['output1', 'output2', 'output3'], output_types=[ dy.DataTypeFloat64(1), dy.DataTypeFloat64(1), dy.DataTypeFloat64(1) ], cpp_source_code = source_code ) output1 = outputs[0] output2 = outputs[1] output3 = outputs[2] """ return wrap_signal_list( GenericCppStatic(dy.get_system_context(), unwrap_list(input_signals), input_names, input_types, output_names, output_types, cpp_source_code ).outputs )
def generic_subsystem(manifest, inputSignals: List[SignalUserTemplate])
-
Expand source code
def generic_subsystem( manifest, inputSignals : List[SignalUserTemplate] ): return wrap_signal_list( GenericSubsystem(dy.get_system_context(), manifest, unwrap_hash(inputSignals) ).outputSignals )
def get_system_context()
-
Expand source code
def get_system_context(): global current_simulation_context return current_simulation_context
def init(autoreset=False, convert=None, strip=None, wrap=True)
-
Expand source code
def init(autoreset=False, convert=None, strip=None, wrap=True): if not wrap and any([autoreset, convert, strip]): raise ValueError('wrap=False conflicts with any other arg=True') global wrapped_stdout, wrapped_stderr global orig_stdout, orig_stderr orig_stdout = sys.stdout orig_stderr = sys.stderr if sys.stdout is None: wrapped_stdout = None else: sys.stdout = wrapped_stdout = \ wrap_stream(orig_stdout, convert, strip, autoreset, wrap) if sys.stderr is None: wrapped_stderr = None else: sys.stderr = wrapped_stderr = \ wrap_stream(orig_stderr, convert, strip, autoreset, wrap) global atexit_done if not atexit_done: atexit.register(reset_all) atexit_done = True
def init_simulation_context()
-
Expand source code
def init_simulation_context(): global simulation_stack global current_simulation_context global counter_of_created_systems current_simulation_context = None simulation_stack = [] counter_of_created_systems = 1000
def initial_event()
-
Emits an event on the first sampling instant after the reset of the system
Returns
SignalUserTemplate
- the signal of type boolean containing the event
Expand source code
def initial_event(): """Emits an event on the first sampling instant after the reset of the system Returns ------- SignalUserTemplate the signal of type boolean containing the event """ # TODO: introduce caching like done for counter() return dy.counter() == int32(0)
def int32(value)
-
Cast anything to DataTypeInt32
Convert the input value to a signal.
Parameters
value
:SignalUserTemplate, int
- the signal or a constant value to convert to a signal
Returns
SignalUserTemplate
- the signal of type int32
Expand source code
def int32(value): """Cast anything to DataTypeInt32 Convert the input value to a signal. Parameters ---------- value : SignalUserTemplate, int the signal or a constant value to convert to a signal Returns ------- SignalUserTemplate the signal of type int32 """ if isinstance( value, SignalUserTemplate ): # already a singal return value else: # create a new constant return dy.const(value, dy.DataTypeInt32(1) )
def leave_system()
-
Expand source code
def leave_system(): return pop_simulation_context()
def logic_and(u1: SignalUserTemplate, u2: SignalUserTemplate)
-
logical and
u1 && u2
Expand source code
def logic_and(u1 : SignalUserTemplate, u2 : SignalUserTemplate): """ logical and u1 && u2 """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list([u1,u2]), operator=' && ').outputs[0] )
def logic_not(u: SignalUserTemplate)
-
Logic negation
Parameters
u
:SignalUserTemplate
- the boolean input signal
Returns
SignalUserTemplate
- the boolean output signal
Details
returns !u
Expand source code
def logic_not(u : SignalUserTemplate ): """ Logic negation Parameters ---------- u : SignalUserTemplate the boolean input signal Returns ------- SignalUserTemplate the boolean output signal Details ------- returns !u """ return wrap_signal( Operator0(dy.get_system_context(), u.unwrap, '!').outputs[0] )
def logic_or(u1: SignalUserTemplate, u2: SignalUserTemplate)
-
logical or
u1 || u2
Expand source code
def logic_or(u1 : SignalUserTemplate, u2 : SignalUserTemplate): """ logical or u1 || u2 """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list( [u1,u2] ), operator=' || ').outputs[0] )
def logic_xor(u1: SignalUserTemplate, u2: SignalUserTemplate)
-
exclusive logical or (xor)
u1 ^ u2
Expand source code
def logic_xor(u1 : SignalUserTemplate, u2 : SignalUserTemplate): """ exclusive logical or (xor) u1 ^ u2 """ return wrap_signal( Operator1(dy.get_system_context(), inputSignals=unwrap_list( [u1,u2] ), operator=' ^ ').outputs[0] )
def memory(datatype, constant_array, write_index: SignalUserTemplate = None, value: SignalUserTemplate = None)
-
Define an array for storing and reading values
Allocates static memory for an array of elements given a datatype. During each sampling instant, one element can be (over)written.
Parameters
datatype
:Datatype
- the datatype of the array elements
constant_array
:List[float], List[int]
- list of constants that contain the data to initialize the array
write_index
:SignalUserTemplate
- the array index (integer signal) of the element to replace by value (optional)
value
:SignalUserTemplate
- the value to write into the array at write_index (optional)
returns a reference to the memory segment which is accessible by memory_read()
Returns
List[SignalUserTemplate]
- a reference to the memory segment which is accessible by memory_read()
Limitations
currently the memory is not reset on subsystem reset. This will change.
Expand source code
def memory(datatype, constant_array, write_index : SignalUserTemplate = None, value : SignalUserTemplate = None): """ Define an array for storing and reading values Allocates static memory for an array of elements given a datatype. During each sampling instant, one element can be (over)written. Parameters ---------- datatype : Datatype the datatype of the array elements constant_array : List[float], List[int] list of constants that contain the data to initialize the array write_index : SignalUserTemplate the array index (integer signal) of the element to replace by value (optional) value : SignalUserTemplate the value to write into the array at write_index (optional) returns a reference to the memory segment which is accessible by memory_read() Returns ------- List[SignalUserTemplate] a reference to the memory segment which is accessible by memory_read() Limitations ----------- currently the memory is not reset on subsystem reset. This will change. """ if write_index is not None and value is not None: return wrap_signal( Memory(dy.get_system_context(), datatype, constant_array, write_index.unwrap, value.unwrap).outputs[0] ) elif write_index is None and value is None: return wrap_signal( Memory(dy.get_system_context(), datatype, constant_array).outputs[0] ) else: raise BaseException('memory: write_index and value were not properly defined')
def memory_read(memory: SignalUserTemplate, index: SignalUserTemplate)
-
Read an element from an array defined by memory()
Parameters
memory
:SignalUserTemplate
- the memory as returned by memory()
index
:SignalUserTemplate
- the index indicating the element to read
Returns
List[SignalUserTemplate]
- returns the value of the element
Expand source code
def memory_read( memory : SignalUserTemplate, index : SignalUserTemplate ): """ Read an element from an array defined by memory() Parameters ---------- memory : SignalUserTemplate the memory as returned by memory() index : SignalUserTemplate the index indicating the element to read Returns ------- List[SignalUserTemplate] returns the value of the element """ return wrap_signal( MemoryRead(dy.get_system_context(), memory.unwrap, index.unwrap ).outputs[0] )
def operator1(inputSignals: List[SignalUserTemplate], operator: str)
-
Expand source code
def operator1(inputSignals : List[SignalUserTemplate], operator : str ): return wrap_signal( Operator1(dy.get_system_context(), unwrap_list( inputSignals ), operator).outputs[0] )
def play(sequence_array, stepwidth=None, initial_state=0, reset=None, reset_on_end: bool = False, start_trigger=None, pause_trigger=None, auto_start: bool = True, no_delay: bool = False)
-
Play a given sequence of samples
Parameters
sequence_array
:list[float]
- the sequence given as a list of values
reset
:SignalUserTemplate
- reset playback and start from the beginning
reset_on_end
:SignalUserTemplate
- reset playback once the end is reached (repetitive playback)
start_trigger
:SignalUserTemplate
- event to start playback
pause_trigger
:SignalUserTemplate
- event to pause playback
auto_start
:bool
- start playback automatically
Returns
SignalUserTemplate
- the value obtained from sequence_array
SignalUserTemplate
- the current position of playback (index of the currently issued sequence element)
Expand source code
def play( sequence_array, stepwidth=None, initial_state = 0, reset=None, reset_on_end:bool=False, start_trigger=None, pause_trigger=None, auto_start:bool=True, no_delay:bool=False ): """Play a given sequence of samples Parameters ---------- sequence_array : list[float] the sequence given as a list of values reset : SignalUserTemplate reset playback and start from the beginning reset_on_end : SignalUserTemplate reset playback once the end is reached (repetitive playback) start_trigger : SignalUserTemplate event to start playback pause_trigger : SignalUserTemplate event to pause playback auto_start : bool start playback automatically Returns ------- SignalUserTemplate the value obtained from sequence_array SignalUserTemplate the current position of playback (index of the currently issued sequence element) """ sequence_array_storage = dy.memory(datatype=dy.DataTypeFloat64(1), constant_array=sequence_array ) # if prevent_initial_playback: # initial_counter_state = np.size(sequence_array) # else: playback_index, _ = counter_triggered( upper_limit=np.size(sequence_array)-1, stepwidth=stepwidth, initial_state=initial_state, reset=reset, reset_on_limit=reset_on_end, start_trigger=start_trigger, pause_trigger=pause_trigger, auto_start=auto_start, no_delay=no_delay ) # sample the given data sample = dy.memory_read(sequence_array_storage, playback_index) return sample, playback_index
def pow(x: SignalUserTemplate, y: SignalUserTemplate)
-
Power function for floating point values
This function returns the x to the power of y (x^y).
Parameters
x
:SignalUserTemplate
- x
y
:SignalUserTemplate
- y
Returns
SignalUserTemplate
- the output signal
Details
returns pow(x,y)
Expand source code
def pow(x : SignalUserTemplate, y : SignalUserTemplate ): """ Power function for floating point values This function returns the x to the power of y (x^y). Parameters ---------- x : SignalUserTemplate x y : SignalUserTemplate y Returns ------- SignalUserTemplate the output signal Details ------- returns pow(x,y) """ return wrap_signal( StaticFnByName_2To1(dy.get_system_context(), x.unwrap, y.unwrap, 'pow').outputs[0] )
def rate_limit(u, Ts, lower_limit, upper_limit, initial_state=0)
-
Rate limiter
Parameters
Ts
:SignalUserTemplate
- sampling time (constant)
lower_limit
:SignalUserTemplate
- lower rate limit
upper_limit
:SignalUserTemplate
- upper rate limit
Returns
SignalUserTemplate
- the output signal
Expand source code
def rate_limit( u, Ts, lower_limit, upper_limit, initial_state = 0 ): """Rate limiter Parameters ---------- Ts : SignalUserTemplate sampling time (constant) lower_limit : SignalUserTemplate lower rate limit upper_limit : SignalUserTemplate upper rate limit Returns ------- SignalUserTemplate the output signal """ Ts_ = float64(Ts) y = dy.signal() omega = u - y omega_sat = saturate(omega, float64(lower_limit) * Ts_, float64(upper_limit) * Ts_) y << euler_integrator( omega_sat, 1, initial_state=initial_state) return y
def sample_and_hold(u, event, initial_state=None)
-
Sample & hold
Samples the input when event is true and hold this value for the proceeding time instants.
Parameters
u
:SignalUserTemplate
- the input to sample
event
:SignalUserTemplate
- the event on which sampling of the input is performed
initial_state
:SignalUserTemplate
- the initial output
Returns
SignalUserTemplate
- the sampled input
Expand source code
def sample_and_hold(u, event, initial_state = None): """Sample & hold Samples the input when event is true and hold this value for the proceeding time instants. Parameters ---------- u : SignalUserTemplate the input to sample event : SignalUserTemplate the event on which sampling of the input is performed initial_state : SignalUserTemplate the initial output Returns ------- SignalUserTemplate the sampled input """ # NOTE: this could be implemented in a more comp. efficient way directly in C in block_prototypes.py y = dy.signal() delayed_y = delay( y, initial_state ) y << dy.conditional_overwrite( delayed_y, event, u ) return y
def saturate(u, lower_limit=None, upper_limit=None)
-
Saturation
The output is the saturated input
Parameters
lower_limit
:SignalUserTemplate
- lower bound for the output
upper_limit
:SignalUserTemplate
- upper bound for the output
Returns
SignalUserTemplate
- the integer output signal
Details
{ lower_limit for u < lower_limit y = { u otherwise { upper_limit for u > upper_limit
Expand source code
def saturate(u, lower_limit = None, upper_limit = None): """Saturation The output is the saturated input Parameters ---------- lower_limit : SignalUserTemplate lower bound for the output upper_limit : SignalUserTemplate upper bound for the output Returns ------- SignalUserTemplate the integer output signal Details ------- { lower_limit for u < lower_limit y = { u otherwise { upper_limit for u > upper_limit """ y = u if lower_limit is not None: y = dy.conditional_overwrite( y, y < float64(lower_limit), lower_limit ) if upper_limit is not None: y = dy.conditional_overwrite( y, y > float64(upper_limit), upper_limit ) return y
def set_primary_outputs(output_signals, names=None)
-
Expand source code
def set_primary_outputs(output_signals, names = None): if names is not None: for i in range(0,len(names)): output_signals[i].set_name_raw( names[i] ) get_system_context().set_primary_outputs( si.unwrap_list( output_signals ) )
def show_blocks(system=None)
-
List all blocks in the current or given system
Expand source code
def show_blocks(system = None): """ List all blocks in the current or given system """ if system is None: system = get_system_context() print() print(Style.BRIGHT + "-------- list of blocks --------") print() system.ShowBlocks()
def show_execution_lines(compile_results)
-
Expand source code
def show_execution_lines(compile_results): print() print(Style.BRIGHT + "-------- List all execution lines and commands --------") print() compile_results.command_to_execute.print_execution()
def signal()
-
Create a new signal for defining a closed-loop
Expand source code
def signal(): """ Create a new signal for defining a closed-loop """ # return an anonymous signal return si.SignalUser(get_system_context())
def signal_impulse(k_event)
-
Pulse signal generator
Generates a unique pulse at the sampling index k_event.
Parameters
k_event
:SignalUserTemplate
- the sampling index at which the pulse appears
Returns
SignalUserTemplate
- the output signal
Expand source code
def signal_impulse(k_event): """Pulse signal generator Generates a unique pulse at the sampling index k_event. Parameters ---------- k_event : SignalUserTemplate the sampling index at which the pulse appears Returns ------- SignalUserTemplate the output signal """ if k_event < 0: raise BaseException('The sampling index for the event is invalid (k_event < 0)') k = dy.counter() pulse_signal = dy.int32(k_event) == k return pulse_signal
def signal_periodic_impulse(period, phase)
-
Signal generator for periodic pulses
Parameters
period
:SignalUserTemplate
- singal or constant describing the period in samples at which the pulses are generated
phase
:SignalUserTemplate
- singal or constant describing the phase in samples at which the pulses are generated
Returns
SignalUserTemplate
- the output signal
Expand source code
def signal_periodic_impulse(period, phase): """Signal generator for periodic pulses Parameters ---------- period : SignalUserTemplate singal or constant describing the period in samples at which the pulses are generated phase : SignalUserTemplate singal or constant describing the phase in samples at which the pulses are generated Returns ------- SignalUserTemplate the output signal """ k, trigger = counter_triggered( upper_limit=dy.int32(period) - dy.int32(1), reset_on_limit=True ) pulse_signal = dy.int32(phase) == k return pulse_signal
def signal_ramp(k_start)
-
Signal generator for a ramp signal
Parameters
k_start
:SignalUserTemplate
- the sampling index as returned by counter() at which the ramp starts increasing.
Returns
SignalUserTemplate
- the output signal
Details
y[k] = { 0 for k < k_start { k-k_start for k >= k_start
Expand source code
def signal_ramp(k_start): """Signal generator for a ramp signal Parameters ---------- k_start : SignalUserTemplate the sampling index as returned by counter() at which the ramp starts increasing. Returns ------- SignalUserTemplate the output signal Details ------- y[k] = { 0 for k < k_start { k-k_start for k >= k_start """ k = dy.counter() active = dy.int32(k_start) <= k linearRise = dy.convert( (k - dy.int32(k_start) ), dy.DataTypeFloat64(1) ) activation = dy.convert( active, dy.DataTypeFloat64(1) ) return activation * linearRise
def signal_sinus(N_period: int = 100, phi=None)
-
Sine wave generator
Parameters
N_period
:SignalUserTemplate
- period in sampling instants (type: constant integer)
phi
:SignalUserTemplate
- phase shift (signal)
Returns
SignalUserTemplate
- the output signal
Details
The output is computed as follows:
y = sin( k * (1 / N_period * 2 * pi) + phi )
k - is the sampling index
Expand source code
def signal_sinus(N_period : int = 100, phi = None): """Sine wave generator Parameters ---------- N_period : SignalUserTemplate period in sampling instants (type: constant integer) phi : SignalUserTemplate phase shift (signal) Returns ------- SignalUserTemplate the output signal Details ------- The output is computed as follows: y = sin( k * (1 / N_period * 2 * pi) + phi ) k - is the sampling index """ if N_period <= 0: raise BaseException('N_period <= 0') if phi is None: phi = dy.float64(0.0) i, _ = dy.counter_triggered( upper_limit=N_period-1, reset_on_limit=True ) y = dy.sin( i * dy.float64(1/N_period * 2*math.pi) + phi ) return y
def signal_square(period, phase)
-
Square wave signal generator
Parameters
period
:SignalUserTemplate
- singal or constant describing the period in samples at which the edges of the square are placed
phase
:SignalUserTemplate
- singal or constant describing the phase in samples at which the edges of the square are placed
Returns
SignalUserTemplate
- the output signal
Expand source code
def signal_square(period, phase): """Square wave signal generator Parameters ---------- period : SignalUserTemplate singal or constant describing the period in samples at which the edges of the square are placed phase : SignalUserTemplate singal or constant describing the phase in samples at which the edges of the square are placed Returns ------- SignalUserTemplate the output signal """ trigger = signal_periodic_impulse(period, phase) # k, trigger = counter_triggered( upper_limit=dy.int32(period) - dy.int32(1), reset_on_limit=True ) state, activate, deactivate = toggle(trigger, no_delay=True) return state, activate, deactivate
def signal_step(k_step)
-
Signal generator for a step signal
Parameters
k_step
:SignalUserTemplate
- the sampling index as returned by counter() at which the step appears.
Returns
SignalUserTemplate
- the output signal
Expand source code
def signal_step(k_step): """Signal generator for a step signal Parameters ---------- k_step : SignalUserTemplate the sampling index as returned by counter() at which the step appears. Returns ------- SignalUserTemplate the output signal """ k = dy.counter() y = dy.int32(k_step) <= k return y
def signal_step_wise_sequence(time_instance_indices, values, time_scale=None, counter=None, reset=None)
-
Signal generator for a step-wise changeing signal
Parameters
time_instance_indices
:List[int]
- an array of sampling instants at which the signal changes its values
values
:List[float]
- an array of values; must have one more element than time_instance_indices
time_scale
:SignalUserTemplate
- multiplies all elements of time_instance_indices by the given factor (optional)
counter
:SignalUserTemplate
- an alternative sample counter (optional), default: counter=dy.counter()
reset
:SignalUserTemplate
- boolean signal to reset the sequence (optional)
Returns
SignalUserTemplate
- the output signal
Example
time_instance_indices = [ 50, 100, 150, 250, 300, 350, 400, 450, 500 ] values = [ 0, -1.0, 0, 1.0, 0, -1.0, 0, 0.2, -0.2, 0 ] v = step_wise_sequence( time_instance_indices, values )
Expand source code
def signal_step_wise_sequence( time_instance_indices, values, time_scale=None, counter=None, reset=None ): """Signal generator for a step-wise changeing signal Parameters ---------- time_instance_indices : List[int] an array of sampling instants at which the signal changes its values values : List[float] an array of values; must have one more element than time_instance_indices time_scale : SignalUserTemplate multiplies all elements of time_instance_indices by the given factor (optional) counter : SignalUserTemplate an alternative sample counter (optional), default: counter=dy.counter() reset : SignalUserTemplate boolean signal to reset the sequence (optional) Returns ------- SignalUserTemplate the output signal Example ------- time_instance_indices = [ 50, 100, 150, 250, 300, 350, 400, 450, 500 ] values = [ 0, -1.0, 0, 1.0, 0, -1.0, 0, 0.2, -0.2, 0 ] v = step_wise_sequence( time_instance_indices, values ) """ if len(values) - 1 != len(time_instance_indices): raise BaseException( "len(values) - 1 != len(time_instance_indices)" ) if counter is None: counter = dy.counter() indices_mem = dy.memory(datatype=dy.DataTypeInt32(1), constant_array=time_instance_indices ) values_mem = dy.memory(datatype=dy.DataTypeFloat64(1), constant_array=values ) current_index = dy.signal() current_time_index_to_check = dy.memory_read( indices_mem, current_index ) # scale time if time_scale is not None: index_to_check = time_scale * current_time_index_to_check else: index_to_check = current_time_index_to_check # check wether to step to the next sample increase_index = dy.int32(0) increase_index = dy.conditional_overwrite(increase_index, counter >= index_to_check, dy.int32(1) ) cnt_, _ = dy.counter_triggered(upper_limit=len(time_instance_indices), stepwidth=increase_index, reset=reset ) current_index << cnt_ val = dy.memory_read(values_mem, current_index) return val
def sin(u: SignalUserTemplate)
-
Expand source code
def sin(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'sin').outputs[0] )
def sqrt(u: SignalUserTemplate)
-
Square root
Expand source code
def sqrt(u : SignalUserTemplate ): """ Square root """ return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'sqrt').outputs[0] )
def sum(u: SignalUserTemplate, initial_state=0, no_delay=False)
-
Accumulative sum
Parameters
u
:SignalUserTemplate
- the input signal
initial_state
:float, SignalUserTemplate
- the initial state
no_delay
:bool
- when true the output is not delayed
Returns
SignalUserTemplate
- the output signal of the filter
Details:
The difference equation
y[k+1] = y[k] + u[k]
is evaluated. The return value is either
y[k] by default or when no_delay == False
or
y[k+1] in case no_delay == True .
Expand source code
def sum(u : SignalUserTemplate, initial_state=0, no_delay=False): """Accumulative sum Parameters ---------- u : SignalUserTemplate the input signal initial_state : float, SignalUserTemplate the initial state no_delay : bool when true the output is not delayed Returns ------- SignalUserTemplate the output signal of the filter Details: -------- The difference equation y[k+1] = y[k] + u[k] is evaluated. The return value is either y[k] by default or when no_delay == False or y[k+1] in case no_delay == True . """ y_k = dy.signal() y_kp1 = y_k + u y_k << dy.delay(y_kp1, initial_state=initial_state) if no_delay: return y_kp1 else: return y_k
def sum2(u: SignalUserTemplate, initial_state=0)
-
Accumulative sum
Parameters
u
:SignalUserTemplate
- the input signal
initial_state
:float, SignalUserTemplate
- the initial state
Returns
SignalUserTemplate
- the output signal of the filter
Details:
The difference equation
y[k+1] = y[k] + u[k]
is evaluated. The return values are
y[k], y[k+1]
Expand source code
def sum2(u : SignalUserTemplate, initial_state=0): """Accumulative sum Parameters ---------- u : SignalUserTemplate the input signal initial_state : float, SignalUserTemplate the initial state Returns ------- SignalUserTemplate the output signal of the filter Details: -------- The difference equation y[k+1] = y[k] + u[k] is evaluated. The return values are y[k], y[k+1] """ y_k = dy.signal() y_kp1 = y_k + u y_k << dy.delay(y_kp1, initial_state=initial_state) return y_k, y_kp1
def switchNto1(state: SignalUserTemplate, inputs: List[SignalUserTemplate])
-
N to one signal switch
returns
inputs[0] for state == 1 inputs[1] for state == 2 inputs[2] for state == 3 ...
Parameters
state
:SignalUserTemplate
- the state of the switch
inputs
:List[SignalUserTemplate]
- the input signals among which to switch
Returns
SignalUserTemplate
- the output signal of the switch
Expand source code
def switchNto1( state : SignalUserTemplate, inputs : List[SignalUserTemplate] ): """N to one signal switch returns inputs[0] for state == 1 inputs[1] for state == 2 inputs[2] for state == 3 ... Parameters ---------- state : SignalUserTemplate the state of the switch inputs : List[SignalUserTemplate] the input signals among which to switch Returns ------- SignalUserTemplate the output signal of the switch """ return wrap_signal( SwitchNto1(dy.get_system_context(), state.unwrap, unwrap_list(inputs) ).outputs[0] )
def system_input(datatype, name: str = None, default_value=None, value_range=None, title: str = '')
-
Introduce a new system input signal
datatype - the datatype of the signal name - the name of the signal default_value - the default value the will be applied to the system input by default value_range - the available numeric range for the signal the form [min, max]
title - the description of the signalExpand source code
def system_input(datatype, name : str = None, default_value=None, value_range=None, title : str = ""): """ Introduce a new system input signal datatype - the datatype of the signal name - the name of the signal default_value - the default value the will be applied to the system input by default value_range - the available numeric range for the signal the form [min, max] title - the description of the signal """ signal = si.SimulationInputSignalUser(get_system_context(), datatype) if name is not None: signal.set_name(name) properties = {} if default_value is not None: properties['default_value'] = default_value if value_range is not None: properties['range'] = value_range if title is not None: properties['title'] = title signal.set_properties(properties) return signal
def tan(u: SignalUserTemplate)
-
Expand source code
def tan(u : SignalUserTemplate ): return wrap_signal( StaticFnByName_1To1(dy.get_system_context(), u.unwrap, 'tan').outputs[0] )
def toggle(trigger, initial_state=False, no_delay=False)
-
Toggle a state based on an event
Parameters
period
:SignalUserTemplate
- the signal to trigger a state change
initial_state
:int
- the initial state
no_delay
:bool
- when true the toggle immediately reacts to a trigger (default: false)
Returns
SignalUserTemplate
- the boolean state signal
SignalUserTemplate
- the event for activation
SignalUserTemplate
- the event for deactivation
Expand source code
def toggle(trigger, initial_state=False, no_delay=False): """Toggle a state based on an event Parameters ---------- period : SignalUserTemplate the signal to trigger a state change initial_state : int the initial state no_delay : bool when true the toggle immediately reacts to a trigger (default: false) Returns ------- SignalUserTemplate the boolean state signal SignalUserTemplate the event for activation SignalUserTemplate the event for deactivation """ state = dy.signal() activate = dy.logic_and( dy.logic_not( state ), trigger ) deactivate = dy.logic_and( trigger , state) state_ = dy.flipflop( activate, deactivate, initial_state = 0, no_delay=no_delay ) if not no_delay: state << state_ else: state << dy.delay(state_) return state_, activate, deactivate
def transfer_function_discrete(u: SignalUserTemplate, num_coeff: List[float], den_coeff: List[float])
-
Discrete time transfer function
Parameters
u
:SignalUserTemplate
- the input signal
num_coeff
:List[float]
- a list of numerator coefficients of the transfer function
den_coeff
:List[float]
- a list of denominator coefficients of the transfer function
Returns
SignalUserTemplate
- the output signal of the filter
Details:
This filter realizes a discrete-time transfer function by using 'direct form II' c.f. https://en.wikipedia.org/wiki/Digital_filter .
b0 + b1 z^-1 + b2 z^-2 + ... + bN z^-N H(z) = ---------------------------------------- 1 + a1 z^-1 + a2 z^-2 + ... + aM z^-M
The coefficient vectors num_coeff and den_coeff describe the numerator and denominator polynomials, respectively, and are defined as follows:
num_coeff = [b0, b1, .., bN] den_coeff = [a1, a2, ... aM] .
Expand source code
def transfer_function_discrete(u : SignalUserTemplate, num_coeff : t.List[float], den_coeff : t.List[float] ): """Discrete time transfer function Parameters ---------- u : SignalUserTemplate the input signal num_coeff : List[float] a list of numerator coefficients of the transfer function den_coeff : List[float] a list of denominator coefficients of the transfer function Returns ------- SignalUserTemplate the output signal of the filter Details: -------- This filter realizes a discrete-time transfer function by using 'direct form II' c.f. https://en.wikipedia.org/wiki/Digital_filter . b0 + b1 z^-1 + b2 z^-2 + ... + bN z^-N H(z) = ---------------------------------------- 1 + a1 z^-1 + a2 z^-2 + ... + aM z^-M The coefficient vectors num_coeff and den_coeff describe the numerator and denominator polynomials, respectively, and are defined as follows: num_coeff = [b0, b1, .., bN] den_coeff = [a1, a2, ... aM] . """ # get filter order N = len(num_coeff)-1 # feedback start signal z_pre = dy.signal() # array to store state signals z_ = [] # create delay chain z_iterate = z_pre for i in range(0,N): z_iterate = dy.delay( z_iterate ) .extend_name('_z' + str(i) ) z_.append( z_iterate ) # build feedback path # # a1 = den_coeff[0] # a2 = den_coeff[1] # a3 = den_coeff[2] # ... sum_feedback = u for i in range(0,N): a_ip1 = dy.float64( den_coeff[i] ).extend_name('_a' + str(i+1) ) sum_feedback = sum_feedback - a_ip1 * z_[i] sum_feedback.extend_name('_i') # close the feedback loop z_pre << sum_feedback # build output path # # b0 = num_coeff[0] # b1 = num_coeff[1] # b2 = num_coeff[2] # ... for i in range(0,N+1): b_i = dy.float64( num_coeff[i] ).extend_name('_b' + str(i) ) if i==0: y = b_i * sum_feedback else: y = y + b_i * z_[i-1] # y is the filter output return y
def unwrap_angle(angle, normalize_around_zero=False)
-
Unwrap an angle
Unwrap and normalize the input angle to the range
[0, 2*pi[ in case normalize_around_zero == false or [-pi, pi] in case normalize_around_zero == true
Parameters
angle
:SignalUserTemplate
- the input signal (angle in radians)
Returns
SignalUserTemplate
- the output signal
Expand source code
def unwrap_angle(angle, normalize_around_zero = False): """Unwrap an angle Unwrap and normalize the input angle to the range [0, 2*pi[ in case normalize_around_zero == false or [-pi, pi] in case normalize_around_zero == true Parameters ---------- angle : SignalUserTemplate the input signal (angle in radians) Returns ------- SignalUserTemplate the output signal """ def normalize_around_zero(angle): """ Normalize an angle Normalize an angle to a range [-pi, pi] Important: the assumed range for the input is - 2*pi <= angle <= 2*p """ tmp = angle + dy.conditional_overwrite( dy.float64(0), angle <= float64(-math.pi), 2*math.pi ) normalized_angle = tmp + dy.conditional_overwrite( dy.float64(0), angle > float64(math.pi), -2*math.pi ) return normalized_angle # # angle_ = dy.fmod(angle, dy.float64(2*math.pi) ) unwrapped_angle = angle_ + dy.conditional_overwrite( dy.float64(0), angle_ < float64(0), 2*math.pi ) if normalize_around_zero: return normalize_around_zero(unwrapped_angle) else: return unwrapped_angle
Classes
class DataTypeArray (length: int, datatype: DataType)
-
Expand source code
class DataTypeArray(DataType): def __init__(self, length : int, datatype : DataType ): DataType.__init__(self, type_id=None, size=1) self._array_element_datatype = datatype self._length = length @property def cpp_datatype_string(self): return self._array_element_datatype.cpp_datatype_string + ' [' + str(self._length) + ']' @property def datatype_of_elements(self): return self._array_element_datatype def cpp_define_variable(self, variable_name, make_a_reference = False): if make_a_reference: variable_name_ = ' (&' + variable_name + ')' else: variable_name_ = variable_name return self._array_element_datatype.cpp_datatype_string + ' ' + variable_name_ + '[' + str(self._length) + ']'
Ancestors
Instance variables
var cpp_datatype_string
-
Expand source code
@property def cpp_datatype_string(self): return self._array_element_datatype.cpp_datatype_string + ' [' + str(self._length) + ']'
var datatype_of_elements
-
Expand source code
@property def datatype_of_elements(self): return self._array_element_datatype
Methods
def cpp_define_variable(self, variable_name, make_a_reference=False)
-
Expand source code
def cpp_define_variable(self, variable_name, make_a_reference = False): if make_a_reference: variable_name_ = ' (&' + variable_name + ')' else: variable_name_ = variable_name return self._array_element_datatype.cpp_datatype_string + ' ' + variable_name_ + '[' + str(self._length) + ']'
class DataTypeBoolean (size: int)
-
Expand source code
class DataTypeBoolean(DataType): def __init__(self, size : int): DataType.__init__(self, type_id=ORTD_DATATYPE_BOOLEAN, size=size) @property def cpp_datatype_string(self): return 'bool' @property def cpp_printf_pattern(self): return '%d' @property def cpp_zero_element(self): return 'false'
Ancestors
Instance variables
var cpp_datatype_string
-
Expand source code
@property def cpp_datatype_string(self): return 'bool'
var cpp_printf_pattern
-
Expand source code
@property def cpp_printf_pattern(self): return '%d'
var cpp_zero_element
-
Expand source code
@property def cpp_zero_element(self): return 'false'
class DataTypeFloat64 (size: int)
-
Expand source code
class DataTypeFloat64(DataTypeNumeric): def __init__(self, size : int): DataType.__init__(self, type_id=ORTD_DATATYPE_FLOAT, size=size) @property def cpp_datatype_string(self): return 'double' @property def cpp_printf_pattern(self): return '%f' @property def cpp_zero_element(self): return '0.0'
Ancestors
Instance variables
var cpp_datatype_string
-
Expand source code
@property def cpp_datatype_string(self): return 'double'
var cpp_printf_pattern
-
Expand source code
@property def cpp_printf_pattern(self): return '%f'
var cpp_zero_element
-
Expand source code
@property def cpp_zero_element(self): return '0.0'
class DataTypeInt32 (size: int)
-
Expand source code
class DataTypeInt32(DataTypeNumeric): def __init__(self, size : int): DataType.__init__(self, type_id=ORTD_DATATYPE_INT32, size=size) @property def cpp_datatype_string(self): return 'int32_t' @property def cpp_printf_pattern(self): return '%d' @property def cpp_zero_element(self): return '0'
Ancestors
Instance variables
var cpp_datatype_string
-
Expand source code
@property def cpp_datatype_string(self): return 'int32_t'
var cpp_printf_pattern
-
Expand source code
@property def cpp_printf_pattern(self): return '%d'
var cpp_zero_element
-
Expand source code
@property def cpp_zero_element(self): return '0'
class DataTypeNumeric (size: int)
-
Expand source code
class DataTypeNumeric(DataType): def __init__(self, size : int): DataType.__init__(self, type_id=ORTD_DATATYPE_FLOAT, size=size)
Ancestors
Subclasses
class DataTypePointer (cpp_type_name_class: str)
-
Create a pointer pointing to an instance of a given class
Example:
cpp_type_name_class = 'SomeClass'
In the source code of the class, the following definition is required
typedef SomeClass *SomeClassPtr
Expand source code
class DataTypePointer(DataType): """ Create a pointer pointing to an instance of a given class Example: -------- cpp_type_name_class = 'SomeClass' In the source code of the class, the following definition is required typedef SomeClass *SomeClassPtr """ def __init__(self, cpp_type_name_class : str ): DataType.__init__(self, type_id=None, size=1) self._cpp_ptr_type_name = cpp_type_name_class + 'Ptr' # cpp_ptr_type_name self._cpp_type_name_class = cpp_type_name_class @property def cpp_datatype_string(self): """ return the c++ datatype string of the pointer to the class instance """ return self._cpp_ptr_type_name @property def cpp_datatype_string_class(self): """ return the c++ datatype string of the class """ return self._cpp_type_name_class def is_equal_to(self, other_type): result = DataType.is_equal_to(self, other_type) if result == 1: if self._cpp_ptr_type_name == other_type._cpp_ptr_type_name: return 1 else: return result
Ancestors
Instance variables
var cpp_datatype_string
-
return the c++ datatype string of the pointer to the class instance
Expand source code
@property def cpp_datatype_string(self): """ return the c++ datatype string of the pointer to the class instance """ return self._cpp_ptr_type_name
var cpp_datatype_string_class
-
return the c++ datatype string of the class
Expand source code
@property def cpp_datatype_string_class(self): """ return the c++ datatype string of the class """ return self._cpp_type_name_class
Methods
def is_equal_to(self, other_type)
-
Expand source code
def is_equal_to(self, other_type): result = DataType.is_equal_to(self, other_type) if result == 1: if self._cpp_ptr_type_name == other_type._cpp_ptr_type_name: return 1 else: return result
class SignalUserTemplate (system, wrapped_signal: Signal)
-
Expand source code
class SignalUserTemplate(object): def __init__(self, system, wrapped_signal : Signal): self._system = system self._wrapped_signal = wrapped_signal def __hash__(self): return id(self) @property def unwrap(self): """ Get the library-internal representation of a signal (internal use only) """ return self._wrapped_signal @property def name(self): """ the identifier of the signal """ return self._wrapped_signal.name @property def properties(self): """ A hash array of properties """ return self._wrapped_signal.properties def set_properties(self, p): """ Set the properties of the signal """ self._wrapped_signal.set_properties(p) return self def set_datatype(self, datatype): # call setDatatype_nonotitication to prevent the (untested) automatic update of the datatypes self._wrapped_signal.setDatatype_nonotitication(datatype) return self def set_name(self, name): """ Set the signals identifier. Must be a string without spaces and alphanumerical characters only. """ self._wrapped_signal.set_name(name) return self def set_name_raw(self, name): self._wrapped_signal.set_name_raw(name) return self def extend_name(self, name): """ Extand the current signal identifier by appending characters at the end of the string """ self._wrapped_signal.set_name( self._wrapped_signal.name + name ) return self def set_blockname(self, name): """ Set the name of the block that has the signal as one of its outputs """ self._wrapped_signal.set_blockname(name) return self # ... # # operator overloads # def __add__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='+').outputs[0] ) def __radd__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='+').outputs[0] ) def __sub__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='-').outputs[0] ) def __rsub__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ other.unwrap, self.unwrap ], operator='-').outputs[0] ) def __mul__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='*').outputs[0] ) def __rmul__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='*').outputs[0] ) def __truediv__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ self.unwrap, other.unwrap ], operator='/').outputs[0] ) def __rtruediv__(self, other): other = convert_python_constant_val_to_const_signal(other) return wrap_signal( block_prototypes.Operator1( dy.get_system_context(), inputSignals=[ other.unwrap, self.unwrap ], operator='/').outputs[0] ) # _comparison operators def __le__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '<=' ) ) def __rle__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = other, right = self, operator = '<=' ) ) def __ge__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '>=' ) ) def __rge__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = other, right = self, operator = '>=' ) ) def __lt__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '<' ) ) def __rlt__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = other, right = self, operator = '<' ) ) def __gt__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '>' ) ) def __rgt__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = other, right = self, operator = '>' ) ) def __eq__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '==' ) ) def __req__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '==' ) ) def __ne__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '!=' ) ) def __rne__(self, other): other = convert_python_constant_val_to_const_signal(other) return ( _comparison(left = self, right = other, operator = '!=' ) )
Subclasses
Instance variables
var name
-
the identifier of the signal
Expand source code
@property def name(self): """ the identifier of the signal """ return self._wrapped_signal.name
var properties
-
A hash array of properties
Expand source code
@property def properties(self): """ A hash array of properties """ return self._wrapped_signal.properties
var unwrap
-
Get the library-internal representation of a signal (internal use only)
Expand source code
@property def unwrap(self): """ Get the library-internal representation of a signal (internal use only) """ return self._wrapped_signal
Methods
def extend_name(self, name)
-
Extand the current signal identifier by appending characters at the end of the string
Expand source code
def extend_name(self, name): """ Extand the current signal identifier by appending characters at the end of the string """ self._wrapped_signal.set_name( self._wrapped_signal.name + name ) return self
def set_blockname(self, name)
-
Set the name of the block that has the signal as one of its outputs
Expand source code
def set_blockname(self, name): """ Set the name of the block that has the signal as one of its outputs """ self._wrapped_signal.set_blockname(name) return self
def set_datatype(self, datatype)
-
Expand source code
def set_datatype(self, datatype): # call setDatatype_nonotitication to prevent the (untested) automatic update of the datatypes self._wrapped_signal.setDatatype_nonotitication(datatype) return self
def set_name(self, name)
-
Set the signals identifier. Must be a string without spaces and alphanumerical characters only.
Expand source code
def set_name(self, name): """ Set the signals identifier. Must be a string without spaces and alphanumerical characters only. """ self._wrapped_signal.set_name(name) return self
def set_name_raw(self, name)
-
Expand source code
def set_name_raw(self, name): self._wrapped_signal.set_name_raw(name) return self
def set_properties(self, p)
-
Set the properties of the signal
Expand source code
def set_properties(self, p): """ Set the properties of the signal """ self._wrapped_signal.set_properties(p) return self
class TargetBasicExecutable (i_max: int, input_signals_mapping={})
-
generates code for the runtime environment
Expand source code
class TargetBasicExecutable(TargetGenericCpp): """ generates code for the runtime environment """ def __init__(self, i_max : int, input_signals_mapping = {} ): self._i_max = i_max TargetGenericCpp.__init__(self) self.input_signals_mapping = input_signals_mapping self.initCodeTemplate() def code_gen(self): # call helper to fill in some generic elements into the template code_gen_results = TargetGenericCpp.code_gen(self) # # make strings # # constant inputs inputConstAssignments = [] for signal, value in self.input_signals_mapping.items(): inputConstAssignments.append( signal.name + ' = ' + str(value) ) inputConstAssignment = '; '.join( inputConstAssignments ) + ';' self.sourceCode = Template(self.template).safe_substitute( iMax=self._i_max, inputConstAssignment=inputConstAssignment ) code_gen_results['sourcecode'] = self.sourceCode return code_gen_results def write_code(self, folder): TargetGenericCpp.writeFiles(self, folder) self.codeFolder = folder f = open(os.path.join( folder + "main.cpp"), "w") f.write( self.sourceCode ) f.close() def build(self): os.system("c++ " + self.codeFolder + "main.cpp -o " + self.codeFolder + "main") def run(self): # run the generated executable p = subprocess.Popen(self.codeFolder + 'main', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) retval = p.wait() # parse csv data data = [ ] outputs = range(0, len(self.main_command.command_to_put_main_system.outputCommand.outputSignals) ) for o in outputs: data.append( [] ) for line in p.stdout.readlines(): sample = line.decode("utf-8").split(' ') for o in outputs: data[ o ].append( float( sample[o] ) ) # put data into a key-array dataStruct = { } o = 0 for s in self.main_command.command_to_put_main_system.outputCommand.outputSignals: dataStruct[ s.name ] = data[o] o = o + 1 return dataStruct def initCodeTemplate(self): # # template for main function in c++ # self.template = """ #include <math.h> #include <stdio.h> // // implementation of $mainSimulationName // $algorithmCode // // main // int main () { // create an instance of the simulation $mainSimulationName simulation; // input signals $inputAll_NamesVarDef // output signals $outputNamesVarDef // const assignments of the input signals $inputConstAssignment // reset the simulation simulation.resetStates(); // simulate int i; for (i=0; i< $iMax; ++i) { simulation.calcResults_1( $calcOutputsArgs ); simulation.updateStates( $input2_NamesCSVList ); printf("$outputPrinfPattern\\n", $outputNamesCSVList); } } """
Ancestors
Methods
def build(self)
-
Expand source code
def build(self): os.system("c++ " + self.codeFolder + "main.cpp -o " + self.codeFolder + "main")
def code_gen(self)
-
Expand source code
def code_gen(self): # call helper to fill in some generic elements into the template code_gen_results = TargetGenericCpp.code_gen(self) # # make strings # # constant inputs inputConstAssignments = [] for signal, value in self.input_signals_mapping.items(): inputConstAssignments.append( signal.name + ' = ' + str(value) ) inputConstAssignment = '; '.join( inputConstAssignments ) + ';' self.sourceCode = Template(self.template).safe_substitute( iMax=self._i_max, inputConstAssignment=inputConstAssignment ) code_gen_results['sourcecode'] = self.sourceCode return code_gen_results
def initCodeTemplate(self)
-
Expand source code
def initCodeTemplate(self): # # template for main function in c++ # self.template = """ #include <math.h> #include <stdio.h> // // implementation of $mainSimulationName // $algorithmCode // // main // int main () { // create an instance of the simulation $mainSimulationName simulation; // input signals $inputAll_NamesVarDef // output signals $outputNamesVarDef // const assignments of the input signals $inputConstAssignment // reset the simulation simulation.resetStates(); // simulate int i; for (i=0; i< $iMax; ++i) { simulation.calcResults_1( $calcOutputsArgs ); simulation.updateStates( $input2_NamesCSVList ); printf("$outputPrinfPattern\\n", $outputNamesCSVList); } } """
def run(self)
-
Expand source code
def run(self): # run the generated executable p = subprocess.Popen(self.codeFolder + 'main', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) retval = p.wait() # parse csv data data = [ ] outputs = range(0, len(self.main_command.command_to_put_main_system.outputCommand.outputSignals) ) for o in outputs: data.append( [] ) for line in p.stdout.readlines(): sample = line.decode("utf-8").split(' ') for o in outputs: data[ o ].append( float( sample[o] ) ) # put data into a key-array dataStruct = { } o = 0 for s in self.main_command.command_to_put_main_system.outputCommand.outputSignals: dataStruct[ s.name ] = data[o] o = o + 1 return dataStruct
def write_code(self, folder)
-
Expand source code
def write_code(self, folder): TargetGenericCpp.writeFiles(self, folder) self.codeFolder = folder f = open(os.path.join( folder + "main.cpp"), "w") f.write( self.sourceCode ) f.close()
Inherited members
class TargetGenericCpp (enable_tracing=False)
-
generates code for the runtime environment
Expand source code
class TargetGenericCpp: """ generates code for the runtime environment """ def __init__(self, enable_tracing=False ): ExecutionCommand.__init__(self) # TODO: what is this? # if compile_results is not None: # self.compileResults = compile_results # self.main_command = compile_results.command_to_execute # else: # those are set via set_compile_results after a system is compiled self.compileResults = None self.main_command = None self._include_code_list = None # self._algorithm_code = None # list of systems to include self._includedSystems = [] self._enable_tracing = enable_tracing def set_compile_results(self, compile_results : CompileResults ): self.compileResults = compile_results self.main_command = compile_results.command_to_execute def include_systems(self, system : SystemLibraryEntry): self._includedSystems = system def add_code_to_include(self, include_code_list : List[str] = []): self._include_code_list = include_code_list def get_algorithm_code(self): """ Return only the code that implement the system and all sub systems """ return self._algorithm_code def code_gen(self): # generate code for the algorithm self.manifest, self._algorithm_code = _generate_algorithm_code( self.compileResults, self._enable_tracing, self._includedSystems, self._include_code_list ) # TODO: iterate over all functions present in the API of the system # NOTE: Currently only the main functions are used: output, update, and reset # API_functions = self.main_command.command_to_put_main_system.API_functions # # make strings # def makeStrings(signals): names_CSV_list = cgh.signal_list_to_names_string(signals) names_var_def = cgh.define_variable_list_string(signals) printf_pattern = cgh.signalListHelper_printfPattern_string(signals) return names_CSV_list, names_var_def, printf_pattern # for the output signals # input1_NamesCSVList; list of output signals. e.g. 'y1, y2, y3' outputNamesCSVList, outputNamesVarDef, outputPrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.outputSignals ) # the inputs to the output command # input1_NamesCSVList: list of output signals. e.g. 'y1, y2, y3' input1_NamesCSVList, input1_NamesVarDef, input1PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.inputSignals ) # the inputs to the update command # input2_NamesCSVList list of output signals. e.g. 'u1, u2, u3' input2_NamesCSVList, input2_NamesVarDef, input2_PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.updateCommand.inputSignals ) # all inputs # merge the list of inputs for the calcoutput and stateupdate function allInputs = list(set(self.main_command.command_to_put_main_system.outputCommand.inputSignals + self.main_command.command_to_put_main_system.updateCommand.inputSignals)) inputAll_NamesCSVList, inputAll_NamesVarDef, inputAll_PrinfPattern = makeStrings( allInputs ) # the names of input and output signals of the outputCommand combined calcOutputsArgs = cgh.signal_list_to_name_list( self.main_command.command_to_put_main_system.outputCommand.outputSignals + self.main_command.command_to_put_main_system.outputCommand.inputSignals ) # fill in template self.template = Template(self.template).safe_substitute( mainSimulationName = self.main_command.command_to_put_main_system.API_name, algorithmCode=self._algorithm_code, input1_NamesVarDef=input1_NamesVarDef, input1_NamesCSVList=input1_NamesCSVList, input2_NamesVarDef=input2_NamesVarDef, input2_NamesCSVList=input2_NamesCSVList, inputAll_NamesVarDef=inputAll_NamesVarDef, inputAll_NamesCSVList=inputAll_NamesCSVList, outputNamesCSVList=outputNamesCSVList, outputNamesVarDef=outputNamesVarDef, outputPrinfPattern=outputPrinfPattern, calcOutputsArgs=calcOutputsArgs ) return {'sourcecode' : self.template, 'manifest' : self.manifest, 'algorithm_sourcecode' : self._algorithm_code } def writeFiles(self, folder): with open( os.path.join( folder + '//simulation_manifest.json' ), 'w') as outfile: json.dump(self.manifest, outfile) def build(self): pass def run(self): pass
Subclasses
Methods
def add_code_to_include(self, include_code_list: List[str] = [])
-
Expand source code
def add_code_to_include(self, include_code_list : List[str] = []): self._include_code_list = include_code_list
def build(self)
-
Expand source code
def build(self): pass
def code_gen(self)
-
Expand source code
def code_gen(self): # generate code for the algorithm self.manifest, self._algorithm_code = _generate_algorithm_code( self.compileResults, self._enable_tracing, self._includedSystems, self._include_code_list ) # TODO: iterate over all functions present in the API of the system # NOTE: Currently only the main functions are used: output, update, and reset # API_functions = self.main_command.command_to_put_main_system.API_functions # # make strings # def makeStrings(signals): names_CSV_list = cgh.signal_list_to_names_string(signals) names_var_def = cgh.define_variable_list_string(signals) printf_pattern = cgh.signalListHelper_printfPattern_string(signals) return names_CSV_list, names_var_def, printf_pattern # for the output signals # input1_NamesCSVList; list of output signals. e.g. 'y1, y2, y3' outputNamesCSVList, outputNamesVarDef, outputPrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.outputSignals ) # the inputs to the output command # input1_NamesCSVList: list of output signals. e.g. 'y1, y2, y3' input1_NamesCSVList, input1_NamesVarDef, input1PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.inputSignals ) # the inputs to the update command # input2_NamesCSVList list of output signals. e.g. 'u1, u2, u3' input2_NamesCSVList, input2_NamesVarDef, input2_PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.updateCommand.inputSignals ) # all inputs # merge the list of inputs for the calcoutput and stateupdate function allInputs = list(set(self.main_command.command_to_put_main_system.outputCommand.inputSignals + self.main_command.command_to_put_main_system.updateCommand.inputSignals)) inputAll_NamesCSVList, inputAll_NamesVarDef, inputAll_PrinfPattern = makeStrings( allInputs ) # the names of input and output signals of the outputCommand combined calcOutputsArgs = cgh.signal_list_to_name_list( self.main_command.command_to_put_main_system.outputCommand.outputSignals + self.main_command.command_to_put_main_system.outputCommand.inputSignals ) # fill in template self.template = Template(self.template).safe_substitute( mainSimulationName = self.main_command.command_to_put_main_system.API_name, algorithmCode=self._algorithm_code, input1_NamesVarDef=input1_NamesVarDef, input1_NamesCSVList=input1_NamesCSVList, input2_NamesVarDef=input2_NamesVarDef, input2_NamesCSVList=input2_NamesCSVList, inputAll_NamesVarDef=inputAll_NamesVarDef, inputAll_NamesCSVList=inputAll_NamesCSVList, outputNamesCSVList=outputNamesCSVList, outputNamesVarDef=outputNamesVarDef, outputPrinfPattern=outputPrinfPattern, calcOutputsArgs=calcOutputsArgs ) return {'sourcecode' : self.template, 'manifest' : self.manifest, 'algorithm_sourcecode' : self._algorithm_code }
def get_algorithm_code(self)
-
Return only the code that implement the system and all sub systems
Expand source code
def get_algorithm_code(self): """ Return only the code that implement the system and all sub systems """ return self._algorithm_code
def include_systems(self, system: SystemLibraryEntry)
-
Expand source code
def include_systems(self, system : SystemLibraryEntry): self._includedSystems = system
def run(self)
-
Expand source code
def run(self): pass
def set_compile_results(self, compile_results: CompileResults)
-
Expand source code
def set_compile_results(self, compile_results : CompileResults ): self.compileResults = compile_results self.main_command = compile_results.command_to_execute
def writeFiles(self, folder)
-
Expand source code
def writeFiles(self, folder): with open( os.path.join( folder + '//simulation_manifest.json' ), 'w') as outfile: json.dump(self.manifest, outfile)
class TargetWasm (enable_tracing=False)
-
generates code for the Webassemble runtime environment
https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html
Expand source code
class TargetWasm(TargetGenericCpp): """ generates code for the Webassemble runtime environment https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html """ def __init__(self, enable_tracing = False ): TargetGenericCpp.__init__(self, enable_tracing=enable_tracing) self.initCodeTemplate() def code_gen(self): # build I/O structs ioExport = self.generate_code_writeIO(self.main_command.command_to_put_main_system.outputCommand) ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.updateCommand) ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.resetCommand) self.template = Template(self.template).safe_substitute( ioExport=ioExport, inputConstAssignment='' ) # call helper to fill in some generic elements into the template code_gen_results = TargetGenericCpp.code_gen(self) self.sourceCode = self.template code_gen_results['sourcecode'] = self.sourceCode return code_gen_results def generate_code_writeIO__(self, command_API, inputOutput : int): if inputOutput == 1: structPrefix = 'Inputs_' signals = command_API.inputSignals elif inputOutput == 2: structPrefix = 'Outputs_' signals = command_API.outputSignals mainSimulationName = self.main_command.command_to_put_main_system.API_name lines = '' # Inputs structname = structPrefix + command_API.API_name lines += 'value_object<' + mainSimulationName + '::' + structname + '>("' + mainSimulationName + '__' + structname + '")\n' for s in signals: fieldName = s.name lines += '.field("' + fieldName + '", &' + mainSimulationName + '::' + structname + '::' + fieldName + ')\n' lines += ';\n\n' return lines def generate_code_writeIO(self, command_API): return self.generate_code_writeIO__(command_API, 1) + self.generate_code_writeIO__(command_API, 2) def write_code(self, folder): TargetGenericCpp.writeFiles(self, folder) self.codeFolder = folder f = open( Path( folder ) / "main.cpp", "w") f.write( self.sourceCode ) f.close() def build(self): buildCommand = 'emcc --bind -s MODULARIZE=1 -s EXPORT_NAME="ORTD_simulator" ' + os.path.join(self.codeFolder , "main.cpp") + " -g4 -s -o " + os.path.join( self.codeFolder , "main.js" ) print("Running compiler: " + buildCommand) returnCode = os.system(buildCommand) print( "Compilation result: ", returnCode ) def initCodeTemplate(self): # # template for main function in c++ # self.template = """ #include <math.h> #include <stdio.h> #include <emscripten/bind.h> using namespace emscripten; // // implementation of $mainSimulationName // $algorithmCode // Binding code EMSCRIPTEN_BINDINGS(my_class_example) { class_<$mainSimulationName>("$mainSimulationName") .constructor<>() .function("resetStates", &$mainSimulationName::resetStates__) .function("calcResults_1", &$mainSimulationName::calcResults_1__) .function("updateStates", &$mainSimulationName::updateStates__) ; // -------------------------------- $ioExport } """
Ancestors
Methods
def build(self)
-
Expand source code
def build(self): buildCommand = 'emcc --bind -s MODULARIZE=1 -s EXPORT_NAME="ORTD_simulator" ' + os.path.join(self.codeFolder , "main.cpp") + " -g4 -s -o " + os.path.join( self.codeFolder , "main.js" ) print("Running compiler: " + buildCommand) returnCode = os.system(buildCommand) print( "Compilation result: ", returnCode )
def code_gen(self)
-
Expand source code
def code_gen(self): # build I/O structs ioExport = self.generate_code_writeIO(self.main_command.command_to_put_main_system.outputCommand) ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.updateCommand) ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.resetCommand) self.template = Template(self.template).safe_substitute( ioExport=ioExport, inputConstAssignment='' ) # call helper to fill in some generic elements into the template code_gen_results = TargetGenericCpp.code_gen(self) self.sourceCode = self.template code_gen_results['sourcecode'] = self.sourceCode return code_gen_results
def generate_code_writeIO(self, command_API)
-
Expand source code
def generate_code_writeIO(self, command_API): return self.generate_code_writeIO__(command_API, 1) + self.generate_code_writeIO__(command_API, 2)
def generate_code_writeIO__(self, command_API, inputOutput: int)
-
Expand source code
def generate_code_writeIO__(self, command_API, inputOutput : int): if inputOutput == 1: structPrefix = 'Inputs_' signals = command_API.inputSignals elif inputOutput == 2: structPrefix = 'Outputs_' signals = command_API.outputSignals mainSimulationName = self.main_command.command_to_put_main_system.API_name lines = '' # Inputs structname = structPrefix + command_API.API_name lines += 'value_object<' + mainSimulationName + '::' + structname + '>("' + mainSimulationName + '__' + structname + '")\n' for s in signals: fieldName = s.name lines += '.field("' + fieldName + '", &' + mainSimulationName + '::' + structname + '::' + fieldName + ')\n' lines += ';\n\n' return lines
def initCodeTemplate(self)
-
Expand source code
def initCodeTemplate(self): # # template for main function in c++ # self.template = """ #include <math.h> #include <stdio.h> #include <emscripten/bind.h> using namespace emscripten; // // implementation of $mainSimulationName // $algorithmCode // Binding code EMSCRIPTEN_BINDINGS(my_class_example) { class_<$mainSimulationName>("$mainSimulationName") .constructor<>() .function("resetStates", &$mainSimulationName::resetStates__) .function("calcResults_1", &$mainSimulationName::calcResults_1__) .function("updateStates", &$mainSimulationName::updateStates__) ; // -------------------------------- $ioExport } """
def write_code(self, folder)
-
Expand source code
def write_code(self, folder): TargetGenericCpp.writeFiles(self, folder) self.codeFolder = folder f = open( Path( folder ) / "main.cpp", "w") f.write( self.sourceCode ) f.close()
Inherited members
class state_sub (subsystem_name=None)
-
A single subsystem as part of a state machine (implemented by sub_statemachine)
- methods to called by the user -
set_switched_outputs(signals, state_signal) - connect a list of signals to the output of the state machine
Expand source code
class state_sub(SwitchedSubsystemPrototype): """ A single subsystem as part of a state machine (implemented by sub_statemachine) - methods to called by the user - set_switched_outputs(signals, state_signal) - connect a list of signals to the output of the state machine """ def __init__(self, subsystem_name = None ): SwitchedSubsystemPrototype.__init__(self, subsystem_name) self._output_signals = None self._state_signal = None def set_switched_outputs(self, signals, state_signal): """ set the output signals of a subsystem embedded into the state machine - signals - normal system output that are forwarded using a switch - state_signal - control signal indicating the next state the state machine enters """ self._output_signals = signals self._state_signal = state_signal self.set_switched_outputs_prototype( signals + [state_signal] ) @property def state_control_output(self): return self._state_signal @property def subsystem_outputs(self): return self._output_signals
Ancestors
Instance variables
var state_control_output
-
Expand source code
@property def state_control_output(self): return self._state_signal
var subsystem_outputs
-
Expand source code
@property def subsystem_outputs(self): return self._output_signals
Methods
def set_switched_outputs(self, signals, state_signal)
-
set the output signals of a subsystem embedded into the state machine
- signals - normal system output that are forwarded using a switch
- state_signal - control signal indicating the next state the state machine enters
Expand source code
def set_switched_outputs(self, signals, state_signal): """ set the output signals of a subsystem embedded into the state machine - signals - normal system output that are forwarded using a switch - state_signal - control signal indicating the next state the state machine enters """ self._output_signals = signals self._state_signal = state_signal self.set_switched_outputs_prototype( signals + [state_signal] )
Inherited members
class sub_if (condition_signal: SignalUserTemplate, subsystem_name=None, prevent_output_computation=False)
-
NOTE: in case the if condition is false, the outputs are hold. Eventally uninitialized.
Expand source code
class sub_if: """ NOTE: in case the if condition is false, the outputs are hold. Eventally uninitialized. """ def __init__(self, condition_signal : dy.SignalUserTemplate, subsystem_name = None, prevent_output_computation = False ): if subsystem_name is not None: self._subsystem_name = subsystem_name else: self._subsystem_name = generate_subsystem_name() self._condition_signal = condition_signal self._prevent_output_computation = prevent_output_computation # self._outputs_of_embeded_subsystem = [] # outputs (links to the subsystem outputs) to be used by the user self._output_links = None def set_outputs(self, signals): self._outputs_of_embeded_subsystem = signals.copy() def __enter__(self): self._system = enter_subsystem(self._subsystem_name ) return self def __exit__(self, type, value, traceback): embedded_subsystem = dy.get_system_context() # set the outputs of the system embedded_subsystem.set_primary_outputs( si.unwrap_list( self._outputs_of_embeded_subsystem ) ) # create generic subsystem block prototype self._subsystem_block_prototype = bp.GenericSubsystem( sim=embedded_subsystem.upper_level_system, manifest=None, inputSignals=None, embedded_subsystem=embedded_subsystem, N_outputs=len(self._outputs_of_embeded_subsystem) ) # leave the context of the subsystem dy.leave_system() # # now in the system in which the embeder block (including the logic) shall be placed. # # create the embedder prototype embeddedingBlockPrototype = bp.TruggeredSubsystem( sim=dy.get_system_context(), control_input=si.unwrap( self._condition_signal ), subsystem_prototype=self._subsystem_block_prototype, prevent_output_computation = self._prevent_output_computation) # connect the normal outputs via links self._output_links = si.wrap_signal_list( embeddedingBlockPrototype.outputs ) # connect the additional (control) outputs # self._state_output = si.wrap_signal( embeddedingBlockPrototype.state_output ) @property def outputs(self): if self._output_links is None: BaseException("Please close the subsystem before querying its outputs") return self._output_links
Instance variables
var outputs
-
Expand source code
@property def outputs(self): if self._output_links is None: BaseException("Please close the subsystem before querying its outputs") return self._output_links
Methods
def set_outputs(self, signals)
-
Expand source code
def set_outputs(self, signals): self._outputs_of_embeded_subsystem = signals.copy()
class sub_loop (max_iterations: int, subsystem_name=None)
-
Expand source code
class sub_loop: """ """ def __init__(self, max_iterations : int, subsystem_name = None ): if subsystem_name is not None: self._subsystem_name = subsystem_name else: self._subsystem_name = generate_subsystem_name() self._max_iterations = max_iterations # control outputs of the embedded subsystem self._until_signal = None self._yield_signal = None # self._outputs_of_embeded_subsystem = [] # outputs (links to the subsystem outputs) to be used by the user self._output_links = None def set_outputs(self, signals): self._outputs_of_embeded_subsystem = si.unwrap_list( signals.copy() ) def loop_until(self, condition_signal): self._until_signal = condition_signal.unwrap def loop_yield(self, condition_signal): self._yield_signal = condition_signal.unwrap def __enter__(self): self._system = enter_subsystem(self._subsystem_name ) return self def __exit__(self, type, value, traceback): embedded_subsystem = dy.get_system_context() # collect all outputs all_output_signals = [] all_output_signals.extend(self._outputs_of_embeded_subsystem) if self._until_signal is not None: all_output_signals.append(self._until_signal) if self._yield_signal is not None: all_output_signals.append(self._yield_signal) # set the outputs of the system embedded_subsystem.set_primary_outputs( all_output_signals ) # create generic subsystem block prototype self._subsystem_block_prototype = bp.GenericSubsystem( sim=embedded_subsystem.upper_level_system, manifest=None, inputSignals=None, embedded_subsystem=embedded_subsystem, N_outputs=len(all_output_signals) ) # leave the context of the subsystem dy.leave_system() # # now in the system in which the embeder block (including the logic) shall be placed. # # create the embeeder prototype embeddedingBlockPrototype = bp.LoopUntilSubsystem( sim=dy.get_system_context(), max_iterations=self._max_iterations, subsystem_prototype=self._subsystem_block_prototype, until_signal=self._until_signal, yield_signal=self._yield_signal) # subsystem_prototypes=subsystem_prototypes, # reference_outputs= si.unwrap_list( self._reference_outputs ) ) # connect the normal outputs via links self._output_links = si.wrap_signal_list( embeddedingBlockPrototype.outputs ) # connect the additional (control) outputs # self._state_output = si.wrap_signal( embeddedingBlockPrototype.state_output ) @property def outputs(self): if self._output_links is None: BaseException("Please close the subsystem before querying its outputs") return self._output_links
Instance variables
var outputs
-
Expand source code
@property def outputs(self): if self._output_links is None: BaseException("Please close the subsystem before querying its outputs") return self._output_links
Methods
def loop_until(self, condition_signal)
-
Expand source code
def loop_until(self, condition_signal): self._until_signal = condition_signal.unwrap
def loop_yield(self, condition_signal)
-
Expand source code
def loop_yield(self, condition_signal): self._yield_signal = condition_signal.unwrap
def set_outputs(self, signals)
-
Expand source code
def set_outputs(self, signals): self._outputs_of_embeded_subsystem = si.unwrap_list( signals.copy() )
class sub_statemachine (switch_subsystem_name)
-
A state machine subsystem
- properties -
self.state - status signal of the state machine (available after 'with sub_statemachine' has findished)
Expand source code
class sub_statemachine(SwitchPrototype): """ A state machine subsystem - properties - self.state - status signal of the state machine (available after 'with sub_statemachine' has findished) """ def __init__(self, switch_subsystem_name): number_of_control_outputs = 1 # add one control output to inform about the current state SwitchPrototype.__init__(self, switch_subsystem_name, number_of_control_outputs ) # state output signal undefined until defined by on_exit() self._state_output = None @property def state(self): """ get the signal describing the current state """ return self._state_output def new_subsystem(self, subsystem_name = None): system = state_sub(subsystem_name=subsystem_name) self._subsystem_list.append(system) return system def on_exit(self, subsystem_prototypes): # create the embeeder prototype embeddedingBlockPrototype = bp.StatemachineSwitchSubsystems( sim=dy.get_system_context(), subsystem_prototypes=subsystem_prototypes, reference_outputs= si.unwrap_list( self._reference_outputs ) ) # connect the normal outputs via links self._switch_output_links = si.wrap_signal_list( embeddedingBlockPrototype.switched_normal_outputs ) # connect the additional (control) outputs self._state_output = si.wrap_signal( embeddedingBlockPrototype.state_output )
Ancestors
Instance variables
var state
-
get the signal describing the current state
Expand source code
@property def state(self): """ get the signal describing the current state """ return self._state_output
Methods
def new_subsystem(self, subsystem_name=None)
-
Expand source code
def new_subsystem(self, subsystem_name = None): system = state_sub(subsystem_name=subsystem_name) self._subsystem_list.append(system) return system
Inherited members
class sub_switch (switch_subsystem_name, select_signal: SignalUserTemplate)
-
a switch for subsystems that are implemented by SwitchedSubsystemPrototype (class to be derived)
switch_subsystem_name - the name of the switch number_of_control_outputs - the number of system outputs in addition to the embedded systems outputs i.e. control outputs of a switch/statemaching/…
- member variables -
self._switch_output_links - overwrite by derived class when calling on_exit() self.outputs - a list of output signals as defined by self._switch_output_links
- methods to be defined -
on_exit(subsystem_prototypes) - callback once all subsystems were defined during this callback self._switch_output_links must be defined
Expand source code
class sub_switch(SwitchPrototype): def __init__(self, switch_subsystem_name, select_signal : dy.SignalUserTemplate ): self._select_signal = select_signal SwitchPrototype.__init__(self, switch_subsystem_name, number_of_control_outputs=0) def new_subsystem(self, subsystem_name = None): system = SwitchedSubsystem(subsystem_name=subsystem_name) self._subsystem_list.append(system) return system def on_exit(self, subsystem_prototypes): # create the embeeder prototype embeddedingBlockPrototype = bp.SwitchSubsystems( sim=dy.get_system_context(), control_input=self._select_signal.unwrap, subsystem_prototypes=subsystem_prototypes, reference_outputs= si.unwrap_list( self._reference_outputs ) ) # connect the normal outputs via links self._switch_output_links = si.wrap_signal_list( embeddedingBlockPrototype.switched_normal_outputs )
Ancestors
Methods
def new_subsystem(self, subsystem_name=None)
-
Expand source code
def new_subsystem(self, subsystem_name = None): system = SwitchedSubsystem(subsystem_name=subsystem_name) self._subsystem_list.append(system) return system
Inherited members