Skip to content

Coding patterns

Peter Corke edited this page Mar 13, 2023 · 1 revision

There are a few different ways that you can write your system using bdsim.

Classical

import bdsim

sim = bdsim.BDSim(animation=True)  # create simulator
bd = sim.blockdiagram()  # create an empty block diagram

# define the blocks
demand = bd.STEP(T=1, name="demand")
sum = bd.SUM("+-")
gain = bd.GAIN(10)
plant = bd.LTI_SISO(0.5, [2, 1], name="plant")
scope = bd.SCOPE(styles=["k", "r--"])

# connect the blocks
bd.connect(demand, sum[0], scope[1])
bd.connect(plant, sum[1])
bd.connect(sum, gain)
bd.connect(gain, plant)
bd.connect(plant, scope[0])

Pythonic

import bdsim

sim = bdsim.BDSim(animation=True)  # create simulator
bd = sim.blockdiagram()  # create an empty block diagram

# define the blocks
demand = bd.STEP(T=1, name="demand")
plant = bd.LTI_SISO(0.5, [2, 1], name="plant")
scope = bd.SCOPE(styles=["k", "r--"])

# connect the blocks using Python syntax
scope[0] = plant
scope[1] = demand
plant[0] = 10 * (demand - plant)

Non factory

In the patterns above the blocks are created by factory methods of the bd object like STEP or SCOPE. These are dynamically loaded at run time and in fact correspond to the constructors of classes called Step and Scope defined in files in the blocks folder. We can can construct instances of those classes directly, but at the expense of slightly increased verbosity.

import bdsim
from bdsim.blocks import Step, Sum, Gain, LTI_SISO, Scope

sim = bdsim.BDSim(animation=True)  # create simulator
bd = sim.blockdiagram()  # create an empty block diagram

# define the blocks
demand = Step(T=1, name="demand", bd=bd)
sum = Sum("+-", bd=bd)
gain = Gain(1, bd=bd0)
plant = LTI_SISO(0.5, [2, 1], name="plant", bd=bd)
scope = Scope(styles=["k", "r--"], bd=bd)

# connect the blocks using Python syntax
scope[0] = plant
scope[1] = demand
plant[0] = 10 * (demand - plant)

We need to tell each block which block diagram it belongs to by passing in the bd argument. There are two advantages of this approach that overcome the extra verbiage:

  • Your IDE will be able to help you with documentation and type hints as you edit. The factory method indirection defeats PyLance for example.
  • The fairly complex process of searching for blocks and importing them is done by the default "runtime" which is called run_sim.py which has dependencies on many Python packages. Without that, your code might be able to run in a simple environment like Micro/Circuit Python (but there's still a way to go with that).