CppPlot - Thư viện C++ plotting chuyên nghiệp, header-only, không phụ thuộc, tối ưu cho hệ thống embedded, real-time, và scientific computing.
cppplot/
├── include/cppplot/
│ ├── cppplot.hpp # Main header (includes all)
│ ├── pyplot.hpp # Matplotlib-style API
│ ├── figure.hpp # Figure management
│ ├── axes.hpp # Axes and plotting
│ │
│ ├── core/ # Core utilities
│ │ ├── types.hpp
│ │ ├── color.hpp
│ │ ├── style.hpp
│ │ ├── utils.hpp
│ │ └── latex.hpp
│ │
│ ├── backends/ # Output backends
│ │ ├── svg_backend.hpp # ✅ Done
│ │ ├── pdf_backend.hpp # 🔜 v2.5
│ │ └── png_backend.hpp # 🔜 v3.0
│ │
│ ├── control/ # 🔜 v1.5 - Control Systems
│ │ ├── control.hpp # Main control header
│ │ ├── transfer_function.hpp
│ │ ├── state_space.hpp
│ │ ├── bode.hpp
│ │ ├── nyquist.hpp
│ │ ├── root_locus.hpp
│ │ └── time_response.hpp
│ │
│ ├── signal/ # 🔜 v2.0 - Signal Processing
│ │ ├── signal.hpp
│ │ ├── fft.hpp
│ │ ├── spectrogram.hpp
│ │ ├── filter.hpp
│ │ └── window.hpp
│ │
│ ├── stats/ # 🔜 v2.0 - Statistics
│ │ ├── stats.hpp
│ │ ├── histogram.hpp
│ │ ├── boxplot.hpp
│ │ ├── violin.hpp
│ │ └── heatmap.hpp
│ │
│ └── plot3d/ # 🔜 v3.0 - 3D Plotting
│ ├── plot3d.hpp
│ ├── surface.hpp
│ ├── contour.hpp
│ └── wireframe.hpp
│
├── examples/
│ ├── basic_demo.cpp
│ ├── subplot_demo.cpp
│ ├── control_system_demo.cpp # ✅ Done
│ ├── signal_processing_demo.cpp
│ └── statistics_demo.cpp
│
└── tests/
- Line plots, scatter, bar, histogram
- SVG backend
- Format strings (matplotlib-style)
- Subplots and layouts
- GridSpec
- Error bars, fill_between
- Log scale
- Annotations (text, axhline, axvline)
- Basic LaTeX rendering
Status: All planned features implemented
-
TransferFunctionclass (polynomials num/den) -
StateSpaceclass (A, B, C, D matrices) - Conversion: TF ↔ SS ↔ ZPK
- Series, parallel, feedback connections
- Stability analysis (poles, zeros)
-
bode()- Automatic Bode plot function -
nyquist()- Automatic Nyquist plot -
nichols()- Nichols chart - Gain margin, phase margin calculation
- Bandwidth calculation
-
step()- Step response -
impulse()- Impulse response -
initial()- Initial condition response -
lsim()- Arbitrary input simulation - Rise time, settling time, overshoot (
stepinfo())
-
rlocus()- Automatic root locus -
pzmap()- Pole-zero map -
sisotool()-style interactive (basic) - Lead/Lag compensator design helpers
- Discrete-time systems (
DiscreteTransferFunction,c2d_tustin,c2d_zoh) - LQR/DLQR controller design
- Kalman filter and LQG
- MPC (Model Predictive Control)
- H∞ synthesis (robust control)
- Sliding mode control (nonlinear)
- μ-analysis (uncertainty modeling)
- Standalone Matrix class (no Eigen dependency)
- LU, QR, Hessenberg, Schur decompositions
- Eigenvalue computation (any size)
- Matrix exponential (Padé with scaling)
- Condition number, spectral radius
- Cholesky decomposition, positive definiteness check
- Lyapunov/Sylvester equation solvers
- FFT (using kiss_fft or custom)
- Spectrogram, PSD
- Filter design (Butterworth, Chebyshev)
- Window functions
- Advanced histograms
- Boxplot, violin plot
- Heatmap, correlation matrix
- Scatter matrix
- PDF backend (using libharu or custom)
- Better font handling
- Full LaTeX support (equations)
- Color maps (viridis, plasma, etc.)
- Custom themes
- 3D surface plots
- Contour plots
- Wireframe
- 3D scatter
- PNG backend (stb_image_write)
// Target API
#include <cppplot/control/control.hpp>
using namespace cppplot::control;
// Create transfer function: G(s) = (s+1) / (s^2 + 2s + 1)
TransferFunction G({1, 1}, {1, 2, 1});
// Or from zeros, poles, gain
auto G2 = zpk({-1}, {-1, -1}, 1.0);
// State-space
StateSpace sys(A, B, C, D);
// Conversions
auto ss = tf2ss(G);
auto tf = ss2tf(sys);
// Connections
auto G_series = G1 * G2; // Series
auto G_parallel = G1 + G2; // Parallel
auto G_feedback = feedback(G, H); // Closed-loop// One-liner plots (Python Control style)
bode(G); // Auto Bode plot
bode({G1, G2, G3}); // Multiple systems
bode(G, omega); // Custom frequency range
nyquist(G); // Auto Nyquist
nyquist(G, opts({{"arrows", "true"}}));
step(G); // Step response
step(G, t); // Custom time vector
step({G1, G2}); // Compare systems
rlocus(G); // Root locus
rlocus(G, kvect); // Custom K range
pzmap(G); // Pole-zero map
pzmap({G1, G2}); // Compare// Margins
auto [gm, pm, wgc, wpc] = margin(G);
// Time-domain specs
auto info = stepinfo(G);
// info.rise_time, info.settling_time, info.overshoot, info.peak
// Stability
bool stable = isstable(G);
auto p = poles(G);
auto z = zeros(G);
// Bandwidth
double wb = bandwidth(G);- ✅
TransferFunctionclass - ✅
bode()function - ✅
nyquist()function - ✅
step()function - ✅
pzmap()function - ✅
rlocus()function - ✅
margin()function - ✅
stepinfo()function
- ✅
StateSpaceclass - ✅
impulse()function - ✅
nichols()chart - ✅
bandwidth()function
- ✅
lsim()arbitrary input - ✅ Discrete-time systems
-
sisotool()interactive (not planned)
include/cppplot/control/
├── control.hpp # Main header - includes all
├── transfer_function.hpp # TF class
├── state_space.hpp # SS class (optional for v1.5)
├── analysis.hpp # margin, stepinfo, poles, zeros
├── plots/
│ ├── bode.hpp # bode() function
│ ├── nyquist.hpp # nyquist() function
│ ├── root_locus.hpp # rlocus() function
│ ├── pzmap.hpp # pzmap() function
│ └── time_response.hpp # step(), impulse(), lsim()
└── utils/
├── polynomial.hpp # Polynomial arithmetic
└── frequency.hpp # logspace, unwrap, etc.
-
API Simplicity: One-liner for common plots
bode(TransferFunction({1}, {1, 2, 1}));
-
Compatibility: Follow Python Control naming conventions
-
Performance: Fast enough for real-time visualization
-
Documentation: Every function documented with examples
-
Testing: Unit tests for all transfer function operations
Last updated: January 2026