C++ Module: dynamicObject
DynamicObject is the base for models whose continuous states are integrated,
including spacecraft and MuJoCo scenes. It owns a DynParamManager and an integrator,
coordinates synchronized objects, and provides drift, diffusion, pre-integration, and
post-integration extension hooks.
Subclass responsibilities
Reset() declares and initializes states, calls finalizeStates(), and finishes
model setup. Later resets reuse those states and update values directly. An initialization
exception may leave partial values; complete setup successfully before integrating.
UpdateState() normally delegates propagation to integrateState(). The subclass
defines equationsOfMotion() and, for stochastic models, equationsOfMotionDiffusion().
These callbacks read candidate states and write derivatives or noise tangents. They may
run several times within one requested interval.
preIntegration() and postIntegration() perform model-specific work around the
integrator call. Configure topology and synchronization before the first integration step.
Callbacks must not change ownership, destroy participating objects, or replace the integrator.
Synchronization and ownership
syncDynamicsIntegration() adds another object to the primary object’s integration
group before binding. The primary owns the group’s integrator. setIntegrator() transfers
the dynamics list and destroys the old numerical method; borrowed pointers to it expire.
Both setIntegrator(method) and Python integrator = method transfer ownership of a
new method, including when it is rejected. Reinstalling the active method is a no-op.
Keep the dynamics object alive while using its borrowed manager or integrator.
Python retains synchronized secondaries. Native connections are detached when either object is destroyed. A surviving primary rebuilds its workspace before the next step; a surviving secondary resumes independent integration. Repeating an existing connection is a no-op.
See Creating DynamicObject Basilisk Modules for a Reset example and Dynamics state and integrator architecture for the storage and workspace design.
Model lifecycle, synchronized integration, and protected dynamics extension hooks.
-
class DynamicObject : public SysModel
- #include <dynamicObject.h>
A model that owns continuous states and coordinates their integration.
Reset registers and initializes states, then calls DynParamManager::finalizeStates(). Dynamics callbacks write drift and diffusion; the integrator advances the values in fixed contiguous storage. One primary object can integrate several synchronized objects. Configure this group before its first step. Python retains synchronized secondaries; native connections are detached when either object is destroyed. Reset and integration exceptions propagate to callers.
Public Functions
-
DynamicObject() = default
-
DynamicObject(const DynamicObject&) = delete
-
DynamicObject &operator=(const DynamicObject&) = delete
-
DynamicObject(DynamicObject&&) = delete
-
DynamicObject &operator=(DynamicObject&&) = delete
-
virtual ~DynamicObject()
-
virtual void UpdateState(uint64_t callTime) = 0
Hooks the dyn-object into Basilisk architecture
-
virtual void equationsOfMotion(double t, double timeStep) = 0
Computes the time derivative of the states:
\[ dx = f(t,x)\,dt \]equationsOfMotioncomputes \(f(t,x)\) in the equation above.
-
inline virtual void equationsOfMotionDiffusion(double t, double timeStep)
Computes the diffusion of the states:
\[ dx = f(t,x)\,dt + g_0(t,x)\,dW_0 + g_1(t,x)\,dW_1 + \cdots + g_{n-1}(t,x)\,dW_{n-1} \]equationsOfMotionDiffusionis equivalent to evaluating \(g_0(t,x), g_1(t,x), \ldots, g_{n-1}(t,x)\) in the equation above.Note that not all
DynamicObjectsmay support this functionality.
-
virtual void preIntegration(uint64_t callTimeNanos) = 0
Performs pre-integration steps
-
virtual void postIntegration(uint64_t callTimeNanos) = 0
Performs post-integration steps
-
inline virtual void computeEnergyMomentum(double t)
Computes energy and momentum of the system
-
void integrateState(uint64_t t)
Prepares the dynamic object to be integrated, integrates the states forward in time, and finally performs the post-integration steps.
This is only done if the DynamicObject integration is not sync’d to another DynamicObject
-
void setIntegrator(std::unique_ptr<StateVecIntegrator> newIntegrator)
Take exclusive ownership of a replacement integrator from C++.
Note
Ownership is consumed even when the replacement is rejected. A null pointer or an integrator with missing or mismatched dynamics raises BasiliskError. A synchronized secondary instead logs a warning and discards the replacement. The current integrator remains installed in each rejection case.
Note
Replacing a primary’s integrator preserves its synchronized dynamics and invalidates borrowed pointers to the previous integrator.
- Parameters:
newIntegrator – Owning pointer to an integrator constructed for this dynamics object.
-
void setIntegrator(StateVecIntegrator *newIntegrator)
Transfer a raw integrator pointer through the Python and compatibility interface.
Note
A newly supplied integrator is destroyed if it is rejected. Passing the active integrator again is a no-op. C++ callers must not pass an integrator owned by another object; prefer the unique_ptr overload for new integrators.
- Parameters:
newIntegrator – Integrator constructed for this dynamics object, with ownership available for transfer, or its currently active integrator.
-
StateVecIntegrator *getIntegrator() const noexcept
Borrow the active integrator until its replacement or this object’s destruction.
- Returns:
Active integrator, or nullptr if no integrator has been installed.
-
void syncDynamicsIntegration(DynamicObject *dynPtr)
Integrate another dynamics object with this object’s numerical method.
Note
Repeating an existing connection is a no-op. Configure new connections before the first integration step and outside dynamics callbacks. Python calls require an owning primary proxy and retain the supplied secondary for its lifetime. Borrowed primary proxies are rejected before creating a connection. Native connections are removed during destruction.
- Parameters:
dynPtr – Secondary object; must be independent, non-null, and different from this object.
-
DynamicObject *getIntegrationOwner() const noexcept
Borrow the primary object, or return nullptr for independent integration.
Note
The returned pointer does not retain the primary.
Public Members
-
DynParamManager dynManager
Dynamics parameter manager for all effectors
-
BSKLogger bskLogger
BSK Logging
-
double timeStep = 0.0
[s] integration time step
-
double timeBefore = 0.0
[s] prior time value
-
uint64_t timeBeforeNanos = 0
[ns] prior time value
Protected Functions
-
void requireMutableTopology(const char *operation) const
Reject changes that would invalidate the fixed state layout.
Private Members
-
std::unique_ptr<StateVecIntegrator> integrator
Owned numerical method and workspaces.
-
DynamicObject *integrationOwner = nullptr
Borrowed primary object, or null for independent integration.
Friends
- friend class StateVecIntegrator
-
DynamicObject() = default