Live plotting directly from SimObjects can be achieved by integrating with Python and matplotlib. This tutorial explains the typical workflow and how to adapt it to your own SimObject library.
Prerequisites
Optional: build the example project
git clone ssh://git@git.code.sintef.no/fhsim/fhsim_pyplot.git
cd fhsim_pyplot
conan install . -s build_type=Release --build=missing
conan build .
If your organization provides prebuilt binaries, you can use those instead.
Add live plotting to your own SimObject library
- Add
fhsim_pyplot as a dependency in your conanfile.py.
- Update CMake:
find_package(fhsim_pyplot MODULE REQUIRED)
set(Python3_FIND_REGISTRY LAST)
find_package(Python3 REQUIRED COMPONENTS Development.Embed NumPy)
# ... add your simobject library target, e.g. fhsim_awesome
target_compile_features(fhsim_awesome PUBLIC cxx_std_17)
target_link_libraries(fhsim_awesome PRIVATE
fhsim_pyplot::pyplot
Python3::Python
Python3::NumPy)
- Include
pyplot/pyplot.h in your SimObject implementation.
- Call plotting functions from your runtime update path.
- Ensure required runtime Python libraries are available in your execution environment.
Creating tailored plot functions
Each function in pyplot/pyplot.cpp maps closely to matplotlib-style calls. The example below plots two signals in separate subplots:
void Plotx1x2(const std::vector<double> &time,
const std::vector<double> &x1,
const std::vector<double> &x2)
{
matplotlibcpp::clf();
matplotlibcpp::title("Plot title");
matplotlibcpp::subplot(2, 1, 1);
matplotlibcpp::grid(true);
matplotlibcpp::named_plot("Data from x1", time, x1);
matplotlibcpp::legend();
matplotlibcpp::ylabel("[unit from x1]");
matplotlibcpp::subplot(2, 1, 2);
matplotlibcpp::grid(true);
matplotlibcpp::named_plot("Data from x2", time, x2);
matplotlibcpp::legend();
matplotlibcpp::ylabel("[unit from x2]");
matplotlibcpp::xlabel("Time [s]");
matplotlibcpp::pause(0.01);
}
- Note
- Keep plotting rates moderate. Plotting every solver sub-step can degrade simulation performance significantly.