Dynamic Models
This example demonstrates dynamic models and state transition matrices used in Kalman filtering and target tracking.
Overview
Dynamic models describe how a target’s state evolves over time. They are fundamental to:
Kalman filtering: Prediction step requires state transition
Target tracking: Motion models for different target types
Navigation: INS mechanization and error propagation
Simulation: Generating realistic target trajectories
Key Concepts
- State Transition Matrix (Phi)
The discrete-time matrix that propagates state from time k to k+1:
x[k+1] = Phi * x[k] + process_noise- Process Noise Covariance (Q)
Captures uncertainty in the motion model due to unknown accelerations or model mismatch.
- Continuous vs Discrete Time
Continuous: differential equations (dx/dt = F*x)
Discrete: difference equations (x[k+1] = Phi*x[k])
Conversion: Phi = exp(F*dt)
State Estimation: The state transition matrix propagates the state estimate and covariance through time, shown as uncertainty ellipses.
Models Demonstrated
- Constant Velocity (CV)
State: [x, vx, y, vy, z, vz]
Assumes constant velocity between updates
Process noise models unknown accelerations
- Drift Functions
Continuous-time rate of change
Position changes at velocity rate
Velocity remains constant (for CV model)
3D Tracking: Dynamic models enable prediction of 3D target trajectories using the state transition matrix.
Code Highlights
The example demonstrates:
State transition matrix computation with
f_constant_velocity()Process noise covariance with
diffusion_constant_velocity()Drift function evaluation with
drift_constant_velocity()Continuous to discrete time conversion
Source Code
1"""
2Demonstration of dynamic models and state transition matrices.
3
4This example shows:
5- Continuous and discrete-time system models
6- State transition matrices (Phi matrices)
7- Process noise covariance (Q matrices)
8- Kalman filter compatibility
9"""
10
11import os
12from pathlib import Path
13
14import numpy as np
15import plotly.graph_objects as go
16
17from pytcl.dynamic_models.continuous_time import (
18 diffusion_constant_velocity,
19)
20from pytcl.dynamic_models.discrete_time import f_constant_velocity
21
22SHOW_PLOTS = os.environ.get("PYTCL_SHOW_PLOTS", "1") != "0"
23
24
25def demo_state_transition_matrix() -> None:
26 """Demonstrate state transition matrix properties."""
27 print("\n" + "=" * 60)
28 print("State Transition Matrices")
29 print("=" * 60)
30
31 dt = 0.1 # Time step
32
33 # Get state transition matrix for constant velocity model
34 # Returns 6x6 matrix for 3D position/velocity
35 phi = f_constant_velocity(dt)
36
37 print(f"\nTime step: {dt}s")
38 print(f"State transition matrix (Phi) shape: {phi.shape}")
39 print("Matrix (first 3x3 block):")
40 print(phi[:3, :3])
41
42 # The matrix has a block structure
43 # [I dt*I]
44 # [0 I ]
45 # where I is 3x3 for position and velocity in 3D
46
47
48def demo_process_noise() -> None:
49 """Demonstrate process noise matrices."""
50 print("\n" + "=" * 60)
51 print("Process Noise Covariance Matrices")
52 print("=" * 60)
53
54 dt = 0.1
55 sigma_v = 1.0 # Process noise standard deviation
56
57 # Get process noise covariance matrix
58 q_matrix = diffusion_constant_velocity(dt, sigma_v)
59
60 print(f"\nTime step: {dt}s")
61 print(f"Process noise std: {sigma_v} m/s")
62 print(f"Process noise matrix (Q) shape: {q_matrix.shape}")
63
64 # Properties
65 print(f"\nProcess noise norm: {np.linalg.norm(q_matrix):.6f}")
66
67
68def demo_drift_matrix() -> None:
69 """Demonstrate drift (mean) functions."""
70 print("\n" + "=" * 60)
71 print("Drift Functions")
72 print("=" * 60)
73
74 # Drift function takes a state vector and returns rate of change
75 # For constant velocity, position changes at velocity rate
76 state = np.array([0.0, 1.0, 0.0, 2.0, 0.0, 3.0]) # 3D pos/vel
77
78 from pytcl.dynamic_models.continuous_time.dynamics import (
79 drift_constant_velocity as drift_cv,
80 )
81
82 drift_result = drift_cv(state)
83
84 print(f"\nExample state (3D position + velocity):")
85 print(f" Position: {state[0::2]}")
86 print(f" Velocity: {state[1::2]}")
87 print(f"\nDrift (rate of change) result:")
88 print(f" {drift_result}")
89
90 # Expected: [vel_1, 0, vel_2, 0, vel_3, 0]
91 # showing that position changes at velocity rate and velocity doesn't change
92
93
94def demo_continuous_to_discrete_conversion() -> None:
95 """Demonstrate continuous to discrete time conversion principle."""
96 print("\n" + "=" * 60)
97 print("Continuous to Discrete Conversion")
98 print("=" * 60)
99
100 # For a constant velocity model in 1D:
101 # Continuous: dx/dt = v, dv/dt = 0
102 # Or in matrix form: [dx/dt; dv/dt] = [0 1; 0 0] * [x; v]
103
104 # Discrete approximation: state[k+1] = Phi * state[k]
105 # where Phi = exp(F * dt) ≈ I + F*dt for small dt
106
107 F = np.array([[0.0, 1.0], [0.0, 0.0]]) # Continuous F matrix
108 dts = [0.05, 0.1, 0.2, 0.5]
109
110 print("\nContinuous F matrix (1D constant velocity):")
111 print(F)
112
113 print("\nDiscrete Phi matrices (Phi ~= I + F*dt):")
114 print("Time Step | Phi[0,1] Value")
115 print("-" * 30)
116
117 phi_values = []
118 for dt_val in dts:
119 # For constant velocity: Phi = [[1, dt], [0, 1]]
120 phi_approx = np.eye(2) + F * dt_val
121 phi_values.append(phi_approx[0, 1])
122 print(f"{dt_val:>8} | {phi_approx[0, 1]:>14.6f}")
123
124 # Plot
125 if SHOW_PLOTS:
126 fig = go.Figure()
127
128 fig.add_trace(
129 go.Scatter(
130 x=dts,
131 y=phi_values,
132 mode="lines+markers",
133 name="Phi[0,1]",
134 line=dict(color="purple", width=2),
135 marker=dict(size=8),
136 )
137 )
138
139 fig.update_layout(
140 title="Discrete State Transition Element vs Time Step",
141 xaxis_title="Time Step (s)",
142 yaxis_title="Phi[0,1] Value",
143 height=400,
144 )
145
146 if SHOW_PLOTS:
147 fig.show()
148 else:
149 fig.write_html(
150 str(OUTPUT_DIR / "dynamic_models_demo.html"),
151 include_plotlyjs="cdn",
152 div_id="dynamic_models_demo",
153 )
154
155
156def main() -> None:
157 """Run all demonstrations."""
158 print("\n" + "=" * 60)
159 print("Dynamic Models Demonstration")
160 print("=" * 60)
161
162 demo_state_transition_matrix()
163 demo_process_noise()
164 demo_drift_matrix()
165 demo_continuous_to_discrete_conversion()
166
167 print("\n" + "=" * 60)
168 print("Demonstration Complete")
169 print("=" * 60)
170
171
172OUTPUT_DIR = Path("docs/_static/images/examples")
173OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
174
175if __name__ == "__main__":
176 main()
Running the Example
python examples/dynamic_models_demo.py
See Also
Kalman Filter Comparison - Kalman filter implementations
Multi-Target Tracking - Multi-target tracking
3D Target Tracking - 3D tracking example