Skip to main content
Version: 0.2.3

synapsys.viz

Visualization module: canonical color palette and plug-and-play 3D simulation windows.

from synapsys.viz import (
Dark, mpl_theme,
CartPoleView, PendulumView, MassSpringDamperView,
)

SimViewBase

Base class for all views. Inherits from QMainWindow. Do not instantiate directly — use the concrete subclasses.

Class attributes (configurable in subclasses)

AttributeTypeDefaultDescription
_titlestr"Synapsys Simulator"Qt window title
_mpl_titlestr"Telemetry"matplotlib panel title
_dtfloat0.02simulation time step in seconds
_hist_lenint500history deque length
_mpl_skipint3render matplotlib every N ticks
_pert_max_defaultfloat20.0default perturbation magnitude
_slider_rangetuple(1, 50)magnitude slider range
_slider_unitstr"N"unit shown on the slider label
_splitter_wtuple(770, 630)initial panel widths (3D, mpl)
_u_clipfloat50.0controller output saturation
_u_clip_totalfloat80.0total saturation after adding perturbation

Public method

run() -> None

Creates QApplication (if not already present), initializes QMainWindow, builds the full UI and enters the Qt event loop. Does not return (calls sys.exit).

CartPoleView().run()
CartPoleView(controller=fn).run()

Hooks (optional override in subclasses)

MethodSignatureDescription
_lqr_u(x)(ndarray) → ndarrayLQR control law. Default: −K@x. Override for setpoint tracking.
_pert_vector()() → ndarrayConverts scalar _pert to input vector.
_build_extra_controls(hb)(QHBoxLayout) → NoneInjects extra widgets into the control bar.
_on_reset()() → NoneCalled after sim.reset() — useful for resetting extra state.
_post_tick(x, u)(ndarray, ndarray) → NoneCalled at the end of each tick. Used for auto-reset logic (e.g. track limit in CartPole).

CartPoleView

CartPoleView(
controller: Callable | None = None,
m_c: float = 1.0, # cart mass [kg]
m_p: float = 0.1, # bob mass [kg]
l: float = 0.5, # pole length [m]
g: float = 9.81, # gravity [m/s²]
x0: np.ndarray | None = None, # initial state (4,) — default [0, 0, 0.18, 0]
)

System: cart on a track with an articulated inverted pendulum.

State: x = [cart position (m), velocity (m/s), angle θ (rad), angular velocity (rad/s)]

Input: horizontal force on the cart (N).

Default LQR: Q = diag([1, 0.1, 100, 10]), R = 0.01·I

Perturbation: ◀/▶ buttons and A/D keys — horizontal force (1–80 N, default 30 N).

Auto-reset: the cart resets automatically when it reaches 92% of the track length (_LIMIT_FRAC = 0.92). Between 72% and 92% the cart changes color to amber as a warning.


PendulumView

PendulumView(
controller: Callable | None = None,
m: float = 1.0, # bob mass [kg]
l: float = 1.0, # pole length [m]
g: float = 9.81, # gravity [m/s²]
b: float = 0.1, # viscous damping
x0: np.ndarray | None = None, # initial state (2,) — default [0.18, 0]
)

System: single-link inverted pendulum on a fixed base.

State: x = [angle θ (rad), angular velocity θ̇ (rad/s)]

Input: joint torque (N·m).

Unstable pole: λ = +√(g/l)+3.13 rad/s at default parameters.

Default LQR: Q = diag([80, 5]), R = I

Perturbation: ↺/↻ buttons and A/D keys — torque (1–40 N·m, default 20 N·m). Red arrows appear at the pole tip indicating direction and magnitude.


MassSpringDamperView

MassSpringDamperView(
controller: Callable | None = None,
m: float = 1.0, # mass [kg]
c: float = 0.5, # damping [N·s/m]
k: float = 2.0, # spring constant [N/m]
x0: np.ndarray | None = None, # initial state (2,) — default [0, 0]
setpoints: list | None = None, # list of (label, value_m) — default 3 points
)

System: 1D mass-spring-damper with setpoint tracking.

State: x = [position q (m), velocity q̇ (m/s)]

Input: external force (N).

LQR with feed-forward: u = −K·(x − x_ref) + k·sp

Default setpoints: [("0 m", 0.0), ("+1.5 m", 1.5), ("−1.5 m", -1.5)] (buttons or keys 1/2/3). Custom setpoints:

MassSpringDamperView(setpoints=[("0", 0.0), ("+2m", 2.0), ("-2m", -2.0)]).run()

Perturbation: ◀/▶ buttons and A/D keys — force (1–30 N, default 15 N).


Dark

Synapsys design system color tokens (mirrors the website dark mode).

from synapsys.viz.palette import Dark

Backgrounds

TokenHexUse
Dark.BG#111111Window background / matplotlib figure
Dark.SURFACE#1a1a1aCards, panels, matplotlib axes
Dark.PANEL#1e1e1eQt GroupBox
Dark.BORDER#2e2e2eDefault borders
Dark.BORDER_LT#222222Subtle border

Text

TokenHexUse
Dark.FG#e2e8f0Primary text
Dark.MUTED#999999Axis labels, secondary text
Dark.SUBTLE#666666Tertiary text / hints
Dark.GRID#2e2e2ematplotlib grid lines

Brand

TokenHexUse
Dark.GOLD#c8a870Primary brand color / highlight
Dark.GOLD_DIM#987040Dark variant
Dark.GOLD_LT#d8b880Light variant
Dark.TEAL#0d9488Secondary brand color

Status / alerts

TokenHexUse
Dark.DANGER#ef4444Error, limit reached, active perturbation
Dark.WARN#f59e0bWarning (e.g. cart approaching track limit)
Dark.OK#22c55eStabilized / ok

Signals

TokenHexPhysical quantity
Dark.SIG_POS#3b82f6Position / displacement
Dark.SIG_POS_LT#60a5faPosition (light variant / second channel)
Dark.SIG_VEL#f97316Velocity / rate
Dark.SIG_VEL_LT#fb923cVelocity (light variant)
Dark.SIG_ANG#f97316Angle
Dark.SIG_REF#22c55eSetpoint / reference
Dark.SIG_REF_DK#16a34aReference (dark variant — dashed line)
Dark.SIG_REF_LT#4ade80Reference (light variant — checked/active)
Dark.SIG_CTRL#ef4444Control force / torque
Dark.SIG_PHASE#a78bfaPhase portrait
Dark.SIG_TRAIL#7c3aed3D trail
Dark.SIG_ALT#facc15Altitude z
Dark.SIG_CYAN#38bdf8Current point (dot marker)

3D objects

TokenHexObject
Dark.MESH_BODY#2563ebMain body (mass, cart)
Dark.MESH_POLE#c8a870Pole / arm
Dark.MESH_BOB#f97316Bob / pole tip
Dark.MESH_SPRING#c8a870Spring
Dark.MESH_DAMP#64748bDamper
Dark.MESH_STRUCT#334155Structure / base
Dark.MESH_WALL#334155Anchor wall
Dark.MESH_FLOOR#1a1a1aFloor / ground plane
Dark.MESH_RAIL#475569Track rail
Dark.MESH_STOP#ef4444Track end stop
Dark.MESH_REF#4ade80Reference sphere (setpoint)

mpl_theme()

from synapsys.viz.palette import mpl_theme
mpl_theme()

Applies Synapsys theme global rcParams to matplotlib. Must be called before creating any Figure.

Automatically configures: figure.facecolor, axes.facecolor, grid, ticks, legend, and font (JetBrains Mono).