Kaynağa Gözat

Fixed RKF45 and LaTeX wrt student solutions

Randy Paredis 4 yıl önce
ebeveyn
işleme
825ff1c425

+ 21 - 10
doc/examples/ContinuousTime.rst

@@ -56,6 +56,11 @@ changes throughout the simulation time. The clock-as-a-block structure allows th
 variation of the :code:`dt`, as is required for adaptive step size. This can be done
 manually by computing some simulation outputs, or via RK-preprocessing.
 
+.. attention::
+    Runge-Kutta preprocessing is only available if there are one or more instances of
+    :class:`CBD.lib.std.IntegratorBlock` in the original model. Also make sure not to
+    use a flattened model to prevent errors.
+
 The :class:`CBD.preprocessing.rungekutta.RKPreprocessor` transforms the original CBD
 model into a new block diagram that applies the Runge-Kutta algorithm with error
 estimation. The full family of Runge-Kutta algorithms can be used as long as they are
@@ -71,15 +76,21 @@ adaptive step size of a CBD model called :code:`sinGen`, the following code can
    from CBD.preprocessing.butcher import ButcherTableau as BT
    from CBD.preprocessing.rungekutta import RKPreprocessor
 
+   # Add a clock to the model, or RK will not work, 1e-4 is the starting delta
+   sinGen.addFixedRateClock("clock", 1e-4)
+
    tableau = BT.RKF45()
    RKP = RKPreprocessor(tableau, atol=2e-5, hmin=0.1, safety=.84)
-   newModel = RKP.preprocess(sinGen)
-
-Notice how the :code:`preprocess` method returns a new model that must be used in the simulation.
-Make sure to refer to this model when reading output traces or changing constants (see
-:doc:`Dashboard`). Note that this will only work if one or more :code:`CBD.lib.std.IntegratorBlock`
-are used (otherwise, the original model will be returned). To obtain a block from the original
-model, the path :code:`RK.RK-K_0.block_name` should be used. However, it is perfectly possible there
-are multiple variations in the transformed model. Hence, it is highly encouraged to only read data
-from the output ports and not from blocks in the model itself. This is an unfortunate side-effect
-of "transforming" the model to comply to adaptive step size simulation.
+   newModel = RKP.preprocess(oldModel)
+
+.. attention::
+    Notice how the :code:`preprocess` method returns a new model that must be used in the simulation.
+    Make sure to refer to this model when reading output traces or changing constants (see also
+    :doc:`Dashboard`).
+
+.. warning::
+    To obtain a block from the original model, the path :code:`RK.RK-K_0.block_name` could be used. However,
+    because of the way RK works, it is perfectly possible there are multiple copies in the transformed model.
+    It is discouraged to use the internal blocks for signal information. Therefore, please only read data
+    from the output ports and not from blocks in the model itself. This is an unfortunate side-effect
+    of "transforming" the model to comply to adaptive step size simulation.

+ 19 - 3
examples/SinGen/RKF45.py

@@ -5,11 +5,27 @@ from CBD.preprocessing.butcher import ButcherTableau as BT
 from CBD.preprocessing.rungekutta import RKPreprocessor
 
 sinGen = SinGen("SinGen")
-
+sinGen.addFixedRateClock("clock", 1e-4)
 tableau = BT.RKF45()
-RKP = RKPreprocessor(tableau, atol=2e-5, hmin=0.1, safety=.84)
+RKP = RKPreprocessor(tableau, atol=2e-5, hmin=1e-4, hmax=0.01, safety=.84)
 newModel = RKP.preprocess(sinGen)
 
-sim_time = 100.0
+sim_time = 21.0
 sim = Simulator(newModel)
 sim.run(sim_time)
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+data = newModel.getSignal('OUT1')
+t, v = [t for t, _ in data], [v for _, v in data]
+
+fig = plt.figure()
+ax = fig.subplots()
+ax.set_xticks(np.arange(0, 22.5, 2.5))
+ax.set_yticks(np.arange(-1, 1.1, 0.25))
+ax.plot(t, v, '-')
+ax.plot(t, v, 'o', color='red', mfc='none')
+plt.grid()
+plt.show()
+# plt.savefig("sin-rkf.png")

BIN
examples/SinGen/sin-rkf.png


+ 1 - 1
examples/notebook/HybridTrain.ipynb

@@ -1778,7 +1778,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.9"
+   "version": "3.8.10"
   }
  },
  "nbformat": 4,

+ 5 - 5
src/CBD/Core.py

@@ -25,14 +25,14 @@ class BaseBlock:
         if name != "":
             self.setBlockName(name)
 
-        # The output signals produced by this block is encoded as a dictionary.
+        # The output signals produced by this block are encoded in a dictionary.
         # The key of this dictionary is the name of the output port.
         # Each element of the dictionary contains an ordered list of values.
         self.__signals = dict()
         for output_port in output_ports:
             self.__signals[output_port] = []
 
-        # The input links produced by this block is encoded as a dictionary.
+        # The input links produced by this block are encoded in a dictionary.
         # The key of this dictionary is the name of the input port.
         # Each element of the dictionary contains
         # a tuple of the block and the output name of the other block.
@@ -405,7 +405,7 @@ class CBD(BaseBlock):
 
     def flatten(self, parent=None, ignore=None, psep="."):
         """
-        Flatten the CBD parent and call flatten recursively for CBD's in this CBD
+        Flatten the CBD inline and call recursively for all sub-CBDs.
 
         Args:
             parent (CBD):   Reference to the parent. Used for the recursive call.
@@ -652,7 +652,7 @@ class CBD(BaseBlock):
 
     def getSignals(self):
         res = {}
-        for port in super(self).getSignals().keys():
+        for port in super().getSignals().keys():
             res[port] = self.getSignal(port)
         return res
 
@@ -699,4 +699,4 @@ class CBD(BaseBlock):
         return name
 
 
-from .lib.std import Clock, ConstantBlock, DummyClock
+from CBD.lib.std import Clock, ConstantBlock, DummyClock

+ 2 - 0
src/CBD/converters/CBDDraw.py

@@ -7,6 +7,8 @@ from CBD.lib.std import *
 from CBD.util import hash64
 import sys
 
+# TODO: add draw for plantuml
+
 def draw(cbd, filename, colors=None):
 	"""
 	Output :class:`CBD` as a graphviz script to filename.

+ 15 - 11
src/CBD/converters/latexify/CBD2Latex.py

@@ -122,24 +122,32 @@ class CBD2Latex:
 				eq = self.get_block_equation(block)
 				for e in eq:
 					self.equations.append(e)
-			elif block.getBlockType() == "WireBlock":
+			elif block.getBlockType() in "WireBlock":
 				path = block.getPath(self.config['path_sep'])
 				lhs = self._rename(path + self.config['path_sep'] + "OUT1")
 				rhs = VarFnc(self._rename(path + self.config['path_sep'] + "IN1"))
 				self.equations.append(Eq(lhs, rhs))
+			elif block.getBlockType() in "InputPortBlock":
+				path = block.getPath(self.config['path_sep'])
+				lhs = self._rename(path)
+				rhs = VarFnc(self._rename(path))
+				self.equations.append(Eq(lhs, rhs))
 
 		# Add all connections
 		for block in self.model.getBlocks():
 			tp = block.getBlockType()
 			path = block.getPath(self.config['path_sep'])
 			for k, v in block.getLinksIn().items():
+				v_path = self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port)
+				if v.block.getBlockType() == "InputPortBlock":
+					v_path = self._rename(v.block.getPath(self.config['path_sep']))
 				if tp in ["OutputPortBlock"]:
 					lhs = self._rename(path)
-					rhs = VarFnc(self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port))
+					rhs = VarFnc(v_path)
 					self.equations.append(Eq(lhs, rhs))
 				else:
 					lhs = self._rename(path + self.config['path_sep'] + k)
-					rhs = VarFnc(self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port))
+					rhs = VarFnc(v_path)
 					self.equations.append(Eq(lhs, rhs))
 
 	def render(self, rl=None):
@@ -234,7 +242,7 @@ class CBD2Latex:
 			:func:`simplify`
 		"""
 		_MEMORY = ["D"]
-		outputs = self.outputs
+		outputs = self.outputs[:]
 		for e in self.equations:
 			if e.rhs.name in _MEMORY:
 				outputs.append(e.lhs)
@@ -253,14 +261,10 @@ class CBD2Latex:
 				for eq in self.equations:
 					if eq.lhs == d.name:
 						deqs.append(eq)
-			dlin = []
 			for deq in deqs:
-				oeq.apply(deq)
-				to_delete.add(deq.lhs)
-				dlin.append(Eq(deq.lhs, VarFnc(output)))
-			for eq in self.equations:
-				for deq in dlin:
-					eq.apply(deq)
+				if deq.lhs not in outputs:
+					oeq.apply(deq)
+					to_delete.add(deq.lhs)
 
 		# simplify functions
 		neq = []

+ 27 - 19
src/CBD/converters/latexify/error.py

@@ -1,4 +1,6 @@
+from CBD.Core import *
 from CBD.lib.std import *
+from CBD.converters.latexify import CBD2Latex
 
 class IntegratorBlock2(CBD):
 	"""
@@ -9,37 +11,37 @@ class IntegratorBlock2(CBD):
 		CBD.__init__(self, block_name, ["IN1", "delta_t", "IC"], ["OUT1"])
 
 		# Create the Blocks
-		self.addBlock(AdderBlock("kAiImoiaHzM8GD00MDgT-13"))
-		self.addBlock(ProductBlock("kAiImoiaHzM8GD00MDgT-18"))
-		self.addBlock(DelayBlock("kAiImoiaHzM8GD00MDgT-26"))
-		self.addBlock(NegatorBlock("kAiImoiaHzM8GD00MDgT-32"))
-		self.addBlock(AdderBlock("kAiImoiaHzM8GD00MDgT-36"))
-		self.addBlock(DelayBlock("mzvCIIcZAN48EzE2zRyw-1"))
+		self.addBlock(AdderBlock("adder2"))
+		self.addBlock(ProductBlock("mult"))
+		self.addBlock(DelayBlock("delay2"))
+		self.addBlock(NegatorBlock("neg"))
+		self.addBlock(AdderBlock("adder1"))
+		self.addBlock(DelayBlock("delay1"))
 
 		# Create the Connections
-		self.addConnection("IN1", "mzvCIIcZAN48EzE2zRyw-1", input_port_name='IN1')
-		self.addConnection("delta_t", "kAiImoiaHzM8GD00MDgT-18", input_port_name='IN2')
-		self.addConnection("IC", "kAiImoiaHzM8GD00MDgT-36", input_port_name='IN1')
-		self.addConnection("IC", "mzvCIIcZAN48EzE2zRyw-1", input_port_name='IC')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-18", "kAiImoiaHzM8GD00MDgT-13", output_port_name='OUT1',
+		self.addConnection("IN1", "delay1", input_port_name='IN1')
+		self.addConnection("delta_t", "mult", input_port_name='IN2')
+		self.addConnection("IC", "adder1", input_port_name='IN1')
+		self.addConnection("IC", "delay1", input_port_name='IC')
+		self.addConnection("mult", "adder2", output_port_name='OUT1',
 						   input_port_name='IN2')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-18", "kAiImoiaHzM8GD00MDgT-32", output_port_name='OUT1',
+		self.addConnection("mult", "neg", output_port_name='OUT1',
 						   input_port_name='IN1')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-13", "OUT1", output_port_name='OUT1')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-13", "kAiImoiaHzM8GD00MDgT-26", output_port_name='OUT1',
+		self.addConnection("adder2", "OUT1", output_port_name='OUT1')
+		self.addConnection("adder2", "delay2", output_port_name='OUT1',
 						   input_port_name='IN1')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-26", "kAiImoiaHzM8GD00MDgT-13", output_port_name='OUT1',
+		self.addConnection("delay2", "adder2", output_port_name='OUT1',
 						   input_port_name='IN1')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-32", "kAiImoiaHzM8GD00MDgT-36", output_port_name='OUT1',
+		self.addConnection("neg", "adder1", output_port_name='OUT1',
 						   input_port_name='IN2')
-		self.addConnection("kAiImoiaHzM8GD00MDgT-36", "kAiImoiaHzM8GD00MDgT-26", output_port_name='OUT1',
+		self.addConnection("adder1", "delay2", output_port_name='OUT1',
 						   input_port_name='IC')
-		self.addConnection("mzvCIIcZAN48EzE2zRyw-1", "kAiImoiaHzM8GD00MDgT-18", output_port_name='OUT1',
+		self.addConnection("delay1", "mult", output_port_name='OUT1',
 						   input_port_name='IN1')
 
 class DerivatorBlock2(CBD):
 	def __init__(self, block_name):
-		super().__init__(block_name, input_ports=["IN1", "delta_t", "IC"], output_ports=['OUT1'])
+		CBD.__init__(self, block_name, input_ports=["IN1", "delta_t", "IC"], output_ports=['OUT1'])
 
 		# Create the Blocks
 		self.addBlock(DelayBlock("delay"))
@@ -66,3 +68,9 @@ class DerivatorBlock2(CBD):
 		self.addConnection("ICsum", "delay", output_port_name='OUT1', input_port_name='IC')
 		self.addConnection("delay", "min", output_port_name='OUT1', input_port_name='IN1')
 		self.addConnection("min", "sum", output_port_name='OUT1', input_port_name='IN1')
+
+
+if __name__ == '__main__':
+	cbd = IntegratorBlock2("cbd")
+	ltx = CBD2Latex(cbd, show_steps=True)
+	ltx.simplify()

+ 2 - 1
src/CBD/converters/latexify/functions.py

@@ -207,7 +207,8 @@ class Fnc:
 
 	def apply(self, eq):
 		for i, a in enumerate(self.args):
-			self.args[i] = a.apply(eq)
+			res = a.apply(eq)
+			self.args[i] = res
 		return self
 
 	@staticmethod

+ 120 - 0
src/CBD/preprocessing/IVP.dot

@@ -0,0 +1,120 @@
+// CBD model of the IVP block
+// Created with CBD.converters.CBDDraw
+digraph model {
+ splines=ortho;
+ label=<<B>IVP (CBD)</B>>;
+ labelloc="t";
+ fontsize=20;
+ node_139813853987792 [label="time", shape=none];
+ inter_139813853987792_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853987792 -> inter_139813853987792_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139814229629200 [label="rel_time", shape=none];
+ inter_139814229629200_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139814229629200 -> inter_139814229629200_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854644352 [label="IN1", shape=none];
+ inter_139813854644352_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854644352 -> inter_139813854644352_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854411360 [label="OUT1", shape=none];
+ inter_139813855326160_OUT1 -> node_139813854411360 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813855052368 [label="IN2", shape=none];
+ inter_139813855052368_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855052368 -> inter_139813855052368_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854558240 [label="OUT2", shape=none];
+ inter_139813854068800_OUT1 -> node_139813854558240 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813854559056 [label="IN3", shape=none];
+ inter_139813854559056_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854559056 -> inter_139813854559056_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855323232 [label="OUT3", shape=none];
+ inter_139813855052368_OUT1 -> node_139813855323232 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813855326160 [label="AdderBlock\n(pid.yi2I8LGNgJVZGdKpCqtK-18)", shape=box];
+ inter_139813855325632_OUT1 -> node_139813855326160 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855324768_OUT1 -> node_139813855326160 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855326160_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855326160 -> inter_139813855326160_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855325632 [label="WireBlock\n(pid.v_ideal)", shape=box];
+ inter_139813854401248_OUT1 -> node_139813855325632 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855325632_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855325632 -> inter_139813855325632_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855324768 [label="ProductBlock\n(pid.yi2I8LGNgJVZGdKpCqtK-11)", shape=box];
+ inter_139813855324480_OUT1 -> node_139813855324768 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855018432_OUT1 -> node_139813855324768 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855324768_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855324768 -> inter_139813855324768_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854401248 [label="LookUp\n(v_ideal)", shape=box];
+ inter_139813854401248_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854401248 -> inter_139813854401248_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855324480 [label="WireBlock\n(pid.v)", shape=box];
+ inter_139813855016320_OUT1 -> node_139813855324480 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855324480_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855324480 -> inter_139813855324480_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855018432 [label=" ConstantBlock\n(pid.minus_one)\n-1", shape=ellipse];
+ inter_139813855018432_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855018432 -> inter_139813855018432_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855016320 [label="WireBlock\n(trolley.v_trolley)", shape=box];
+ inter_139813855052368_OUT1 -> node_139813855016320 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855016320_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855016320 -> inter_139813855016320_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854068800 [label="ProductBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-36)", shape=box];
+ inter_139813854069472_OUT1 -> node_139813854068800 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070384_OUT1 -> node_139813854068800 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854068800_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854068800 -> inter_139813854068800_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854069472 [label="AdderBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-24)", shape=box];
+ inter_139813854798704_OUT1 -> node_139813854069472 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853907408_OUT1 -> node_139813854069472 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854069472_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854069472 -> inter_139813854069472_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854070384 [label="InverterBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-32)", shape=box];
+ inter_139813854591632_OUT1 -> node_139813854070384 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070384_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854070384 -> inter_139813854070384_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854798704 [label="WireBlock\n(trolley.F)", shape=box];
+ inter_139813853908080_OUT1 -> node_139813854798704 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854798704_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854798704 -> inter_139813854798704_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853907408 [label="ProductBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-11)", shape=box];
+ inter_139813855114576_OUT1 -> node_139813853907408 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854574576_OUT1 -> node_139813853907408 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853907408_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853907408 -> inter_139813853907408_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853908080 [label="WireBlock\n(pid.F)", shape=box];
+ inter_139813854070912_OUT1 -> node_139813853908080 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853908080_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853908080 -> inter_139813853908080_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854070912 [label="AdderBlock\n(pid.yi2I8LGNgJVZGdKpCqtK-63)", shape=box];
+ inter_139813854072016_OUT1 -> node_139813854070912 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855113280_OUT1 -> node_139813854070912 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070912_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854070912 -> inter_139813854070912_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854072016 [label="ProductBlock\n(pid.yi2I8LGNgJVZGdKpCqtK-23)", shape=box];
+ inter_139813855326160_OUT1 -> node_139813854072016 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853905008_OUT1 -> node_139813854072016 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854072016_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854072016 -> inter_139813854072016_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855113280 [label="ProductBlock\n(pid.yi2I8LGNgJVZGdKpCqtK-37)", shape=box];
+ inter_139813854573424_OUT1 -> node_139813855113280 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854644352_OUT1 -> node_139813855113280 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855113280_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855113280 -> inter_139813855113280_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853905008 [label=" ConstantBlock\n(pid.K_p)\n325", shape=ellipse];
+ inter_139813853905008_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853905008 -> inter_139813853905008_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854573424 [label=" ConstantBlock\n(pid.K_i)\n1.45", shape=ellipse];
+ inter_139813854573424_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854573424 -> inter_139813854573424_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813855114576 [label=" ConstantBlock\n(trolley.parameters)\n-3.2832", shape=ellipse];
+ inter_139813855114576_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813855114576 -> inter_139813855114576_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854574576 [label="PowerBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-16)", shape=box];
+ inter_139813854352576_OUT1 -> node_139813854574576 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813855052368_OUT1 -> node_139813854574576 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854574576_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854574576 -> inter_139813854574576_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854352576 [label=" ConstantBlock\n(trolley.ocKHeEGP0XS8eeZlxnOF-20)\n2", shape=ellipse];
+ inter_139813854352576_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854352576 -> inter_139813854352576_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854591632 [label=" ConstantBlock\n(trolley.mass)\n2453", shape=ellipse];
+ inter_139813854591632_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854591632 -> inter_139813854591632_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+
+}

+ 17 - 1
src/CBD/preprocessing/PRT_rungekutta.py

@@ -4,7 +4,23 @@
 
 from CBD.Core import *
 from CBD.lib.std import *
-from CBD.lib.std import LookUp
+
+class LookUp(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+
+    def compute(self, curIteration):
+        time = self.getClock().getTime(curIteration)
+        if time < 10:
+            self.appendToSignal(0)
+        elif time < 170:
+            self.appendToSignal(10)
+        elif time < 200:
+            self.appendToSignal(8)
+        elif time < 260:
+            self.appendToSignal(18)
+        else:
+            self.appendToSignal(12)
 
 DELTA_T = 0.1
 

+ 12 - 6
src/CBD/preprocessing/PRT_rungekutta_experiment.py

@@ -7,27 +7,33 @@ from CBD.simulator import Simulator
 import matplotlib.pyplot as plt
 from CBD.preprocessing.rungekutta import *
 from CBD.preprocessing.butcher import ButcherTableau as BT
+from CBD.converters.CBDDraw import draw
 
 DELTA_T = 1
 
 cbd = simulation_pid("simulation_pid")
-prep = RKPreprocessor(BT.RKF45(), atol=2e-5, hmin=1e-8, safety=.84)
+cbd.addFixedRateClock("clock", DELTA_T)
+prep = RKPreprocessor(BT.HeunEuler(), atol=2e-5, hmin=1e-2, safety=.84)
 model = prep.preprocess(cbd)
+draw(model, "RKF45.dot")
+# draw(model.findBlock("RK")[0], "RKF45.dot")
+
 
 # Run the Simulation
 sim = Simulator(model)
 sim.setDeltaT(DELTA_T)
-sim.run(300)
+sim.setProgressBar(True)
+sim.run(100)
 
 
-data = cbd.getSignal('v_trolley')
+data = model.getSignal('v_trolley')
 t, v = [t for t, _ in data], [v for _, v in data]
 
-print(v)
+# print(v)
 fig = plt.figure()
 ax = fig.subplots()
 ax.set_title("V_trolley")
 ax.set_xlabel("t")
 ax.set_ylabel("m/s")
-ax.plot(t, v)
-plt.show()
+ax.plot(t, v, ',')
+plt.show()

+ 221 - 0
src/CBD/preprocessing/RK.dot

@@ -0,0 +1,221 @@
+// CBD model of the RK block
+// Created with CBD.converters.CBDDraw
+digraph model {
+ splines=ortho;
+ label=<<B>RK (CBD)</B>>;
+ labelloc="t";
+ fontsize=20;
+ node_139813854070000 [label="h", shape=none];
+ inter_139813854070000_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854070000 -> inter_139813854070000_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854354112 [label="time", shape=none];
+ inter_139813854354112_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854354112 -> inter_139813854354112_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854562576 [label="rel_time", shape=none];
+ inter_139813854562576_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854562576 -> inter_139813854562576_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854122240 [label="IC1", shape=none];
+ inter_139813854122240_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854122240 -> inter_139813854122240_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854125120 [label="OUT1", shape=none];
+ inter_139813854124688_OUT1 -> node_139813854125120 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813854124688 [label="DelayBlock\n(delay_1)", shape=box];
+ inter_139813854122240_OUT1 -> node_139813854124688 [headlabel="IC", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609696_OUT1 -> node_139813854124688 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854124688_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854124688 -> inter_139813854124688_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854125168 [label="IC2", shape=none];
+ inter_139813854125168_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854125168 -> inter_139813854125168_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609072 [label="OUT2", shape=none];
+ inter_139813853609264_OUT1 -> node_139813853609072 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813853609264 [label="DelayBlock\n(delay_2)", shape=box];
+ inter_139813854125168_OUT1 -> node_139813853609264 [headlabel="IC", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609792_OUT1 -> node_139813853609264 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609264_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609264 -> inter_139813853609264_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853608352 [label="IC3", shape=none];
+ inter_139813853608352_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853608352 -> inter_139813853608352_OUT1 [taillabel="", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609408 [label="OUT3", shape=none];
+ inter_139813853606912_OUT1 -> node_139813853609408 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813853606912 [label="DelayBlock\n(delay_3)", shape=box];
+ inter_139813853608352_OUT1 -> node_139813853606912 [headlabel="IC", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606096_OUT1 -> node_139813853606912 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606912_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853606912 -> inter_139813853606912_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609024 [label="AdderBlock\n(RKSum_1_1)", shape=box];
+ inter_139813854123344_OUT1 -> node_139813853609024 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854793792_OUT1 -> node_139813853609024 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609024_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609024 -> inter_139813853609024_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609696 [label="AdderBlock\n(YSum_1_1)", shape=box];
+ inter_139813853609024_OUT1 -> node_139813853609696 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854124688_OUT1 -> node_139813853609696 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609696_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609696 -> inter_139813853609696_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609312 [label="AdderBlock\n(RKSum_1_2)", shape=box];
+ inter_139813854562288_OUT1 -> node_139813853609312 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854794800_OUT1 -> node_139813853609312 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609312_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609312 -> inter_139813853609312_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609792 [label="AdderBlock\n(YSum_1_2)", shape=box];
+ inter_139813853609312_OUT1 -> node_139813853609792 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609264_OUT1 -> node_139813853609792 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609792_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609792 -> inter_139813853609792_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853609504 [label="AdderBlock\n(RKSum_1_3)", shape=box];
+ inter_139813854562000_OUT1 -> node_139813853609504 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854795616_OUT1 -> node_139813853609504 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609504_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853609504 -> inter_139813853609504_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853606096 [label="AdderBlock\n(YSum_1_3)", shape=box];
+ inter_139813853609504_OUT1 -> node_139813853606096 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606912_OUT1 -> node_139813853606096 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606096_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853606096 -> inter_139813853606096_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651200 [label="AdderBlock\n(RKSum_2_1)", shape=box];
+ inter_139813854563824_OUT1 -> node_139813853651200 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854758032_OUT1 -> node_139813853651200 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651200_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651200 -> inter_139813853651200_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651248 [label="AdderBlock\n(YSum_2_1)", shape=box];
+ inter_139813853651200_OUT1 -> node_139813853651248 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854124688_OUT1 -> node_139813853651248 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651248_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651248 -> inter_139813853651248_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651008 [label="AdderBlock\n(RKSum_2_2)", shape=box];
+ inter_139813854560560_OUT1 -> node_139813853651008 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854758848_OUT1 -> node_139813853651008 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651008_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651008 -> inter_139813853651008_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651152 [label="AdderBlock\n(YSum_2_2)", shape=box];
+ inter_139813853651008_OUT1 -> node_139813853651152 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609264_OUT1 -> node_139813853651152 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651152_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651152 -> inter_139813853651152_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651056 [label="AdderBlock\n(RKSum_2_3)", shape=box];
+ inter_139813854561136_OUT1 -> node_139813853651056 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854759088_OUT1 -> node_139813853651056 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651056_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651056 -> inter_139813853651056_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813853651344 [label="AdderBlock\n(YSum_2_3)", shape=box];
+ inter_139813853651056_OUT1 -> node_139813853651344 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606912_OUT1 -> node_139813853651344 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651344_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813853651344 -> inter_139813853651344_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854353296 [label="CBD\n(RK-K_1)", shape=Msquare];
+ inter_139813854124688_OUT1 -> node_139813854353296 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609264_OUT1 -> node_139813854353296 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606912_OUT1 -> node_139813854353296 [headlabel="IN3", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070000_OUT1 -> node_139813854353296 [headlabel="h", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854354112_OUT1 -> node_139813854353296 [headlabel="time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854562576_OUT1 -> node_139813854353296 [headlabel="rel_time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854353296 -> inter_139813854353296_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_139813854353296_OUT2 [shape=point, width=0.01, height=0.01];
+ node_139813854353296 -> inter_139813854353296_OUT2 [taillabel="OUT2", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_139813854353296_OUT3 [shape=point, width=0.01, height=0.01];
+ node_139813854353296 -> inter_139813854353296_OUT3 [taillabel="OUT3", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854122864 [label=" ConstantBlock\n(B1_1)\n1", shape=ellipse];
+ inter_139813854122864_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854122864 -> inter_139813854122864_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854123344 [label="ProductBlock\n(Mult1_1_1)", shape=box];
+ inter_139813854122864_OUT1 -> node_139813854123344 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT1 -> node_139813854123344 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854123344_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854123344 -> inter_139813854123344_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854562288 [label="ProductBlock\n(Mult1_2_1)", shape=box];
+ inter_139813854122864_OUT1 -> node_139813854562288 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT2 -> node_139813854562288 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854562288_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854562288 -> inter_139813854562288_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854562000 [label="ProductBlock\n(Mult1_3_1)", shape=box];
+ inter_139813854122864_OUT1 -> node_139813854562000 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT3 -> node_139813854562000 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854562000_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854562000 -> inter_139813854562000_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854122816 [label=" ConstantBlock\n(B2_1)\n0.5", shape=ellipse];
+ inter_139813854122816_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854122816 -> inter_139813854122816_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854563824 [label="ProductBlock\n(Mult2_1_1)", shape=box];
+ inter_139813854122816_OUT1 -> node_139813854563824 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT1 -> node_139813854563824 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854563824_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854563824 -> inter_139813854563824_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854560560 [label="ProductBlock\n(Mult2_2_1)", shape=box];
+ inter_139813854122816_OUT1 -> node_139813854560560 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT2 -> node_139813854560560 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854560560_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854560560 -> inter_139813854560560_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854561136 [label="ProductBlock\n(Mult2_3_1)", shape=box];
+ inter_139813854122816_OUT1 -> node_139813854561136 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT3 -> node_139813854561136 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854561136_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854561136 -> inter_139813854561136_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854821536 [label="CBD\n(RK-K_2)", shape=Msquare];
+ inter_139813854124688_OUT1 -> node_139813854821536 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609264_OUT1 -> node_139813854821536 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606912_OUT1 -> node_139813854821536 [headlabel="IN3", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070000_OUT1 -> node_139813854821536 [headlabel="h", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854354112_OUT1 -> node_139813854821536 [headlabel="time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854562576_OUT1 -> node_139813854821536 [headlabel="rel_time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854353296_OUT1 -> node_139813854821536 [headlabel="k_1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854821536 -> inter_139813854821536_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_139813854821536_OUT2 [shape=point, width=0.01, height=0.01];
+ node_139813854821536 -> inter_139813854821536_OUT2 [taillabel="OUT2", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_139813854821536_OUT3 [shape=point, width=0.01, height=0.01];
+ node_139813854821536 -> inter_139813854821536_OUT3 [taillabel="OUT3", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854388816 [label=" ConstantBlock\n(B1_2)\n0", shape=ellipse];
+ inter_139813854388816_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854388816 -> inter_139813854388816_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854793792 [label="ProductBlock\n(Mult1_1_2)", shape=box];
+ inter_139813854388816_OUT1 -> node_139813854793792 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT1 -> node_139813854793792 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854793792_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854793792 -> inter_139813854793792_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854794800 [label="ProductBlock\n(Mult1_2_2)", shape=box];
+ inter_139813854388816_OUT1 -> node_139813854794800 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT2 -> node_139813854794800 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854794800_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854794800 -> inter_139813854794800_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854795616 [label="ProductBlock\n(Mult1_3_2)", shape=box];
+ inter_139813854388816_OUT1 -> node_139813854795616 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT3 -> node_139813854795616 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854795616_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854795616 -> inter_139813854795616_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854795952 [label=" ConstantBlock\n(B2_2)\n0.5", shape=ellipse];
+ inter_139813854795952_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854795952 -> inter_139813854795952_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854758032 [label="ProductBlock\n(Mult2_1_2)", shape=box];
+ inter_139813854795952_OUT1 -> node_139813854758032 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT1 -> node_139813854758032 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854758032_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854758032 -> inter_139813854758032_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854758848 [label="ProductBlock\n(Mult2_2_2)", shape=box];
+ inter_139813854795952_OUT1 -> node_139813854758848 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT2 -> node_139813854758848 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854758848_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854758848 -> inter_139813854758848_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854759088 [label="ProductBlock\n(Mult2_3_2)", shape=box];
+ inter_139813854795952_OUT1 -> node_139813854759088 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854821536_OUT3 -> node_139813854759088 [headlabel="IN2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854759088_OUT1 [shape=point, width=0.01, height=0.01];
+ node_139813854759088 -> inter_139813854759088_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_139813854796480 [label="h_new", shape=none];
+ inter_139813854759760_h_new -> node_139813854796480 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_139813854759760 [label="CBD\n(error)", shape=Msquare];
+ inter_139813853609696_OUT1 -> node_139813854759760 [headlabel="y_1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651248_OUT1 -> node_139813854759760 [headlabel="z_1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853609792_OUT1 -> node_139813854759760 [headlabel="y_2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651152_OUT1 -> node_139813854759760 [headlabel="z_2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853606096_OUT1 -> node_139813854759760 [headlabel="y_3", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813853651344_OUT1 -> node_139813854759760 [headlabel="z_3", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854070000_OUT1 -> node_139813854759760 [headlabel="h", arrowhead="normal", arrowtail="none", dir=both];
+ inter_139813854759760_h_new [shape=point, width=0.01, height=0.01];
+ node_139813854759760 -> inter_139813854759760_h_new [taillabel="h_new", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_139813854759760_error [shape=point, width=0.01, height=0.01];
+ node_139813854759760 -> inter_139813854759760_error [taillabel="error", arrowtail="invempty", arrowhead="none", dir=both];
+
+}

+ 53 - 0
src/CBD/preprocessing/RKF45.dot

@@ -0,0 +1,53 @@
+// CBD model of the simulation_pid block
+// Created with CBD.converters.CBDDraw
+digraph model {
+ splines=ortho;
+ label=<<B>simulation_pid (CBD)</B>>;
+ labelloc="t";
+ fontsize=20;
+ node_140635660111680 [label="v_trolley", shape=none];
+ inter_140635659848240_OUT2 -> node_140635660111680 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_140635660111152 [label="x_trolley", shape=none];
+ inter_140635659848240_OUT3 -> node_140635660111152 [headlabel="", arrowhead="normal", arrowtail="none", dir=both];
+ node_140635659848240 [label="CBD\n(RK)", shape=Msquare];
+ inter_140635659586192_time -> node_140635659848240 [headlabel="time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659586192_rel_time -> node_140635659848240 [headlabel="rel_time", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659586192_delta -> node_140635659848240 [headlabel="h", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659583792_OUT1 -> node_140635659848240 [headlabel="IC1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659584608_OUT1 -> node_140635659848240 [headlabel="IC2", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659583984_OUT1 -> node_140635659848240 [headlabel="IC3", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659848240_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659848240 -> inter_140635659848240_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_140635659848240_OUT2 [shape=point, width=0.01, height=0.01];
+ node_140635659848240 -> inter_140635659848240_OUT2 [taillabel="OUT2", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_140635659848240_OUT3 [shape=point, width=0.01, height=0.01];
+ node_140635659848240 -> inter_140635659848240_OUT3 [taillabel="OUT3", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_140635659848240_h_new [shape=point, width=0.01, height=0.01];
+ node_140635659848240 -> inter_140635659848240_h_new [taillabel="h_new", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659586192 [label="Clock\n(clock)", shape=Msquare];
+ inter_140635659586720_OUT1 -> node_140635659586192 [headlabel="h", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659586192_time [shape=point, width=0.01, height=0.01];
+ node_140635659586192 -> inter_140635659586192_time [taillabel="time", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_140635659586192_rel_time [shape=point, width=0.01, height=0.01];
+ node_140635659586192 -> inter_140635659586192_rel_time [taillabel="rel_time", arrowtail="invempty", arrowhead="none", dir=both];
+ inter_140635659586192_delta [shape=point, width=0.01, height=0.01];
+ node_140635659586192 -> inter_140635659586192_delta [taillabel="delta", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659584416 [label=" ConstantBlock\n(HIC)\n0.1", shape=ellipse];
+ inter_140635659584416_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659584416 -> inter_140635659584416_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659586720 [label="DelayBlock\n(HDelay)", shape=box];
+ inter_140635659848240_h_new -> node_140635659586720 [headlabel="IN1", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659584416_OUT1 -> node_140635659586720 [headlabel="IC", arrowhead="normal", arrowtail="none", dir=both];
+ inter_140635659586720_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659586720 -> inter_140635659586720_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659583792 [label=" ConstantBlock\n(IC)\n0", shape=ellipse];
+ inter_140635659583792_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659583792 -> inter_140635659583792_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659584608 [label=" ConstantBlock\n(null1)\n0", shape=ellipse];
+ inter_140635659584608_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659584608 -> inter_140635659584608_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+ node_140635659583984 [label=" ConstantBlock\n(null)\n0", shape=ellipse];
+ inter_140635659583984_OUT1 [shape=point, width=0.01, height=0.01];
+ node_140635659583984 -> inter_140635659583984_OUT1 [taillabel="OUT1", arrowtail="invempty", arrowhead="none", dir=both];
+
+}

+ 26 - 27
src/CBD/preprocessing/rungekutta.py

@@ -66,11 +66,11 @@ class RKPreprocessor:
 		IVP, plinks = self.create_IVP(original)
 
 		if len(plinks) == 0:
+			print("Warning: No IntegratorBlocks found, returning original.")
 			return original
 
 		# 2. Create an RK-model, based on the given tableau
 		RK = self.create_RK(IVP)
-		# draw(RK, "test.dot")
 
 		# 3. Substitute the RK-model collection in the original CBD
 		outputs = original.getSignals().keys()
@@ -97,11 +97,9 @@ class RKPreprocessor:
 			new_model.addBlock(ConstantBlock("clock-delta", self._h_range[0]))
 			new_model.addConnection("clock-delta", "clock", "h")
 			new_model.addConnection("clock-delta", RK, "h")
-		for y in outputs:
-			itg, mop = original.getBlockByName(y).getBlockConnectedToInput("IN1")
-			if itg.getBlockName() in plinks:
-				p = plinks[itg.getBlockName()]
-				new_model.addConnection(RK, y, output_port_name='OUT%d' % p)
+		for itg_name, p in plinks.items():
+			itg = original.findBlock(itg_name)[0]
+			if "IC" in itg.getLinksIn():
 				ic, icop = itg.getBlockConnectedToInput("IC")
 				collection = self.collect(ic, finish=[IntegratorBlock, Clock, TimeBlock])
 				if not new_model.hasBlock(ic.getBlockName()):
@@ -124,30 +122,24 @@ class RKPreprocessor:
 						new_model.addConnection(cb.getBlockName(), block.getBlockName(), c, op)
 				new_model.addConnection(ic.getBlockName(), RK, "IC%d" % p, icop)
 			else:
-				# parallel process
-				collection = self.collect(original.getBlockByName(y), finish=[IntegratorBlock, Clock, TimeBlock])
-				for block in collection:
-					if not new_model.hasBlock(block.getBlockName()):
-						new_model.addBlock(block.clone())
-				for block in collection:
-					cs = block.getInputPortNames()
-					for c in cs:
-						cb, op = block.getBlockConnectedToInput(c)
-						if cb.getBlockName() in plinks:
-							new_model.addConnection(RK, block.getBlockName(), c, "OUT%d" % plinks[cb.getBlockName()])
-						elif cb.getBlockType() == "TimeBlock":
-							new_model.addConnection("clock", block.getBlockName(), c, "time")
-						elif cb.getBlockType() == "Clock":
-							new_model.addConnection("clock", block.getBlockName(), c, op)
-						else:
-							new_model.addConnection(cb.getBlockName(), block.getBlockName(), c, op)
-				new_model.addConnection(itg.getBlockName(), y, output_port_name=mop)
+				new_model.addBlock(ConstantBlock("RK-IC%d" % p))
+				new_model.addConnection("RK-IC%d" % p, RK, "IC%d" % p)
+
+		for y in outputs:
+			itg, mop = original.getBlockByName(y).getBlockConnectedToInput("IN1")
+			prefix = ""
+			while isinstance(itg, CBD) and itg.getBlockType() != "IntegratorBlock":
+				prefix = prefix + itg.getBlockName() + "."
+				itg, mop = itg.getBlockByName(mop).getBlockConnectedToInput("IN1")
+			assert itg.getBlockType() == "IntegratorBlock"
+			p = plinks[prefix + itg.getBlockName()]
+			new_model.addConnection(RK, y, output_port_name="OUT%d" % p)
 
 		return new_model
 
-	def collect(self, start, sport=None, finish=None):
+	def collect(self, start, sport=None, finish=None, visited=None):
 		"""
-		Breadth-first search collection of all blocks, starting from the start block and
+		Depth-first search collection of all blocks, starting from the start block and
 		ending when it can't anymore or when it must finish.
 
 		Args:
@@ -160,16 +152,22 @@ class RKPreprocessor:
 			finish (iter):              A set of block types (not strings, the actual types!) to
 										exclude from the collection, halting a branch whenever
 										one of these has been reached.
+			visited (iter):             The list of blocks that already have been visited. This
+										is only to be used by the recursive call. Use :code:`None`
+										at a top-level.
 		"""
 		# FIXME: loops are not recognized
 		if finish is None:
 			finish = []
+		if visited is None:
+			visited = []
 		collection = [x[1].block for x in start.getLinksIn().items() if \
 		              ((sport is not None and x[0] in sport) or (sport is None)) \
+			            and not x[1].block in visited \
 		                and not isinstance(x[1].block, tuple(finish))]
 		n_collection = [x.getBlockName() for x in collection]
 		for block in collection:
-			ccoll = self.collect(block, None, finish)
+			ccoll = self.collect(block, None, finish, list(visited) + [block])
 			for child in ccoll:
 				cname = child.getBlockName()
 				if cname not in n_collection:
@@ -219,6 +217,7 @@ class RKPreprocessor:
 
 			# First add the blocks
 			for child in collection:
+				if child.getBlockName() in [x.getBlockName() for x in IVP.getBlocks()]: continue
 				if child.getBlockType() == "InputPortBlock":
 					IVP.addInputPort(child.getBlockName())
 				elif child.getBlockType() == "OutputPortBlock":