19#include <janus/core/Function.hpp>
20#include <janus/math/AutoDiff.hpp>
52 using Scalar = janus::SymbolicScalar;
73 const int n_controls =
static_cast<int>(config.control_signals.size());
76 auto [x_vec, x_mx] = janus::sym_vec_pair(
"x",
static_cast<int>(n_states));
77 Scalar t_sym = janus::sym(
"t");
80 std::vector<Scalar> u_elements;
83 auto [u_v, u_m] = janus::sym_vec_pair(
"u", n_controls);
84 for (
int i = 0; i < n_controls; ++i) {
85 u_elements.push_back(u_v(i));
95 for (
int i = 0; i < n_controls; ++i) {
96 sym_sim_.
SetSignal(config.control_signals[i], u_elements[i]);
100 JanusVector<Scalar> xdot_vec = sym_sim_.ComputeDerivatives();
103 std::vector<Scalar> xdot_elements;
104 xdot_elements.reserve(n_states);
105 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(n_states); ++i) {
106 xdot_elements.push_back(xdot_vec(i));
108 Scalar xdot_mx = Scalar::vertcat(xdot_elements);
111 std::vector<janus::SymbolicArg> inputs;
112 if (config.include_time) {
113 inputs.push_back(t_sym);
115 inputs.push_back(x_mx);
116 if (n_controls > 0) {
117 inputs.push_back(u_mx);
121 if (config.generate_dynamics) {
122 result.
dynamics = janus::Function(config.function_name, inputs, {xdot_mx});
126 if (config.generate_jacobian) {
127 Scalar J_sym = janus::jacobian({xdot_mx}, {x_mx});
128 result.
jacobian_x = janus::Function(
"jacobian_x", inputs, {J_sym});
132 if (n_controls > 0 && config.generate_jacobian) {
133 Scalar Ju_sym = janus::jacobian({xdot_mx}, {u_mx});
134 result.
jacobian_u = janus::Function(
"jacobian_u", inputs, {Ju_sym});
153 const std::size_t n_states = sym_sim_.GetStateSize();
156 auto [x_vec, x_mx] = janus::sym_vec_pair(
"x",
static_cast<int>(n_states));
157 Scalar t_sym = janus::sym(
"t");
161 auto compute_xdot = [
this](
const JanusVector<Scalar> &x,
Scalar t) {
162 sym_sim_.SetState(x);
164 return sym_sim_.ComputeDerivatives();
168 JanusVector<Scalar> k1 = compute_xdot(x_vec, t_sym);
171 JanusVector<Scalar> x_mid1 = x_vec + dt_sym *
Scalar(0.5) * k1;
172 JanusVector<Scalar> k2 = compute_xdot(x_mid1, t_sym + dt_sym *
Scalar(0.5));
175 JanusVector<Scalar> x_mid2 = x_vec + dt_sym *
Scalar(0.5) * k2;
176 JanusVector<Scalar> k3 = compute_xdot(x_mid2, t_sym + dt_sym *
Scalar(0.5));
179 JanusVector<Scalar> x_end = x_vec + dt_sym * k3;
180 JanusVector<Scalar> k4 = compute_xdot(x_end, t_sym + dt_sym);
183 JanusVector<Scalar> x_next =
184 x_vec + dt_sym * (
Scalar(1.0 / 6.0) * k1 +
Scalar(1.0 / 3.0) * k2 +
188 std::vector<Scalar> x_next_elements;
189 x_next_elements.reserve(n_states);
190 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(n_states); ++i) {
191 x_next_elements.push_back(x_next(i));
193 Scalar x_next_mx = Scalar::vertcat(x_next_elements);
195 return janus::Function(
"step", {t_sym, x_mx}, {x_next_mx});
202 std::vector<std::string> names;
203 const auto &bindings = sym_sim_.GetStateBindings();
204 names.reserve(bindings.size());
205 for (
const auto &binding : bindings) {
206 names.push_back(binding.name);
214 [[nodiscard]] std::size_t
GetStateSize()
const {
return sym_sim_.GetStateSize(); }
Core type definitions, concepts, and configuration for Icarus.
Core types for staging subsystem (trim, linearization, symbolic).
Lightweight symbolic simulator for graph extraction.
Lightweight symbolic simulator for graph extraction.
Definition SymbolicSimulatorCore.hpp:48
void SetTime(Scalar t)
Set time (symbolic).
Definition SymbolicSimulatorCore.hpp:90
void SetState(const JanusVector< Scalar > &x)
Set state vector (symbolic).
Definition SymbolicSimulatorCore.hpp:80
void SetSignal(const std::string &name, Scalar value)
Write signal value (symbolic).
Definition SymbolicSimulatorCore.hpp:177
std::size_t GetStateSize() const
Get total state size.
Definition SymbolicSimulatorCore.hpp:149
Symbolic graph generator.
Definition SymbolicStager.hpp:50
janus::Function GenerateStepFunction(double dt)
Generate discrete-time step function.
Definition SymbolicStager.hpp:152
std::vector< std::string > GetStateNames() const
Get state variable names in order.
Definition SymbolicStager.hpp:201
SymbolicDynamics GenerateDynamics(const SymbolicStagerConfig &config={})
Generate symbolic dynamics representation.
Definition SymbolicStager.hpp:69
SymbolicStager(SymbolicSimulatorCore &sym_sim)
Construct stager with symbolic simulator.
Definition SymbolicStager.hpp:59
janus::SymbolicScalar Scalar
Definition SymbolicStager.hpp:52
std::size_t GetStateSize() const
Get total state size.
Definition SymbolicStager.hpp:214
Definition Simulator.hpp:53
SymbolicDynamics GenerateSymbolicDynamics(const SimulatorConfig &config)
Generate dynamics graph from simulator config.
Definition SymbolicStager.hpp:232
Complete simulation configuration.
Definition SimulatorConfig.hpp:673
Symbolic dynamics representation.
Definition StagingTypes.hpp:54
std::optional< janus::Function > jacobian_u
df/du (if controls specified)
Definition StagingTypes.hpp:57
std::optional< janus::Function > jacobian_x
df/dx
Definition StagingTypes.hpp:56
std::vector< std::string > state_names
Definition StagingTypes.hpp:59
std::optional< janus::Function > dynamics
f(t, x) -> xdot
Definition StagingTypes.hpp:55
std::vector< std::string > control_names
Definition StagingTypes.hpp:60
Configuration for symbolic graph generation.
Definition SymbolicStager.hpp:30
std::vector< std::string > control_signals
Signals to treat as controls (inputs).
Definition SymbolicStager.hpp:37
bool generate_dynamics
Generate dynamics function f(t, x) -> xdot.
Definition SymbolicStager.hpp:31
double step_dt
Step size for discrete step function.
Definition SymbolicStager.hpp:34
bool include_time
Include time as explicit input.
Definition SymbolicStager.hpp:36
std::string function_name
Definition SymbolicStager.hpp:35
bool generate_jacobian
Generate state Jacobian df/dx.
Definition SymbolicStager.hpp:32
bool generate_step
Generate discrete step function.
Definition SymbolicStager.hpp:33