Version 2.11 Release Notes
Version 2.11.0 (July 7, 2026)
Compatibility and migration
Split off the
opNavbuild from the core BSK distribution wheels to reduce the wheel file size to be less than 100Mb. Updated documentation to discuss how to usepipinstall withopNavmodules.Deprecated AU2KM in favor of AU and added AU2M for astronomical unit in meters in astroConstants.h.
MeanRevertingNoiseabstract base class moved tomujocoDynamics/_GeneralModuleFiles; importable asMJMeanRevertingNoisefor Python subclassingStochasticAtmDensityis now a standalone BSK module (MJStochasticAtmDensity) in its own folderStochasticDragCoeffis now a standalone BSK module (MJStochasticDragCoeff) in its own folderPIDControllersfolder renamed toJointPIDController; SWIG module renamed toMJJointPIDControllerScenario simulation, plotting, data-shaping, and Eigen conversion helpers now live in the pytest-free simHelpers module while remaining available from
unitTestSupportas deprecated compatibility wrappers, so example scenarios no longer require thepytestpackage just to import or run.Changed C++ Module: fuelTank to hold its tank model via a
std::shared_ptrinstead of a raw pointer (issue #282). The model is created in Python and handed to the tank throughsetTankModel(); previously, dropping the Python reference left a dangling C++ pointer (undefined behaviour). The tank now co-owns the model, so it stays valid for the life of the simulation. C++ code callingFuelTank::setTankModel()must now pass astd::shared_ptr<FuelTankModel>; Python usage is unchanged.Fixed a latent double-free (issue #643). Several simulation modules own dynamically-allocated output messages that are freed in their destructors, but inherited the compiler-generated copy operations. Copying such a module shallow-copied the raw message pointers, so two instances would each free the same messages.
SysModel-derived modules are now non-copyable by default, while message recorders keep explicit copy-construction support for value-returning recorder APIs.Changed message recorders to store their recorded message and time history in
std::dequerather thanstd::vector. This removes the periodicUpdateStatetiming spikes that previously occurred at power-of-two record counts and grew with recording length, which could disrupt soft real-time and hardware-in-the-loop simulations. The Python recorder interface is unchanged. As a consequence, the C++Recorderaccessors changed:times()andtimesWritten()now return a copiedstd::vector<unsigned long long>(previously astd::vector<uint64_t>&reference), andrecord()now returns astd::deque<messageType>&. C++ callers relying on the old reference return types must adapt; a newrecordList()accessor returns the recorded-payload history as a copiedstd::vector.Added setter and getter methods for C++ Module: fuelTank configuration variables and deprecated direct Python access to
nameOfMassState,dcm_TB,r_TB_B,updateOnly, andfuelLeakRate.Removed the standalone MuJoCo
replayvisualization tool, themujoco.visualizehelper, and the--mujocoReplaybuild option. MuJoCo MJScene simulations are now visualized through Vizard viaenableUnityVisualization, so the separate replay utility is no longer needed.Moved
jointThrAllocationinto the standardBasilisk.fswAlgorithmsimport path.Moved
stateMergeinto the standardBasilisk.simulationimport path.Moved
thrFiringRoundinto the standardBasilisk.fswAlgorithmsimport path.
Build, installation, and CI
Fixed the
Nightly WheelsGitHub Actions workflow so gh-pages history trimming uses a fullgh-pagescheckout and no longer fails after sparsedevelopcheckout.Added release-guide instructions to manually run
Nightly Wheelsviaworkflow_dispatchafter merging the next beta branch to republish the nightly package index.Fixed Linux wheels to include the MuJoCo runtime and SWIG bindings.
CONAN_ARGSwas set in the wheel build workflow but never reached the manylinux container, so MuJoCo was silently disabled on Linux while macOS and Windows shipped the full payload. Addedenvironment-passto the cibuildwheel Linux configuration so the option propagates.Fixed nightly wheel builds on
macos-26andwindows-2025-vs2026runners. Conan 2.23.0 did not recognise apple-clang 21 or Visual Studio 2026. This would cause macOS builds to abort and Windows builds to fall back to MinGW gcc.Aligned the
cmake,setuptools,setuptools-scm, andpackagingupper bounds inpyproject.tomlwithrequirements_dev.txt.Removed
--mujocoReplay Truefrom wheel buildCONAN_ARGSinpublish-wheels.ymlandnightly-wheels.yml. The replay binary is not packaged into wheels and building it inside the manylinux container requires X11 devel packages that are not present there.Fixed a build issue where modifying a single message payload header triggered a near-full recompile of unrelated translation units. The auto-generated payload equality used by
recordOnChange()is no longer aggregated into a global umbrella header pulled in throughmessaging.h. Now, each payload’sPayloadEqualityTraitsis included only in that payload’s own SWIG module.Updated the development requirements to allow Conan 2.28.1.
Hardened CI builds by configuring short Conan network retries for third-party source downloads.
Added a Conan source backup URL so CI can fall back to mirrored third-party source archives.
Updated Python requirement version caps to include the latest dependency releases.
Pinned pull request and wheel CI runners to macOS 26, Ubuntu 24.04, and Windows 2025 with Visual Studio 2026.
Updated CI sccache setup to use a Node.js 24-compatible GitHub Action release.
Made CI builds continue without
sccachewhen compiler-cache setup is unavailable.Fixed
fswDefinitions.hso it can be included on macOS without aboolean_ttypedef redefinition error. On Apple platforms,boolean_tis now sourced from<mach/boolean.h>(which defines it idempotently) instead of redefining it as an enum that conflicts with the system type.Fixed Linux and Windows wheel builds by configuring Conan system package installation inside cibuildwheel’s manylinux containers, disabling unused OpenCV Wayland support, and matching the PR Windows build’s Ninja generator.
Distributed Linux and Windows wheels now have OpenCV and MuJoCo support included as well.
Fixed
libclangnot being available to cmake on macOS and Windows CI runners by installing it viaCIBW_BEFORE_BUILDin the shared setup action, resolving nightly and release wheel build failures on those platforms.Added Slack failure notifications for the Nightly Wheels workflow.
Updated
publish-wheelsCI workflow to route release candidate tags (v*rc*) to TestPyPI instead of PyPI.Added a manual
workflow_dispatchtrigger so wheels can be published from the GitHub UI without requiring a tag push.Added packaging support for pure Python BSK modules under
src/fswAlgorithmsandsrc/simulation, and for Python support files undersrc/architecture.Raised the supported SWIG 4.x build requirement to 4.4.1, providing SWIG ABI 5 support between BSK and BSK extensions.
Simulation framework and module development
Replaced SWIG XML-based message payload struct parsing with a libclang-backed metadata pipeline that generates JSON for *Payload.h definitions.
Improved generated payload Python bindings with typed keyword-only constructors, typed properties, and a __fields__ classmethod derived from header metadata.
Added a compile-time guard to the generated C message structs ensuring the payload immediately follows the message header with no padding. The C message read path (used by message recorders and C-to-C subscriptions) relies on this layout via pointer arithmetic; the guard turns any future layout change into a build error instead of a silent mis-read (issue #338).
Fixed SWIG memory leaks (issue #422) where several modules exposed C++ members without a destructor visible to SWIG, so reading them from Python leaked an un-destructed proxy (
swig/python detected a memory leak of type ...). Internal-only members are now private or hidden with%ignore, and public value-type members now include the required Eigen, STL, enum, and BSpline wrapper support. This clears the leak ondynParamManagerand its dependent modules (spacecraftand the state/dynamic effectors), the thruster modules,imuSensor,smallBodyNavEKF,sphericalHarmonicsGravityModel,dataFileToViz,constrainedAttitudeManeuver,linkBudget,ReactionWheelPower,motorThermalandsimpleInstrument.Added a regression test that instantiates affected modules and wrapped data classes, and fails if SWIG reports a member leak.
Generated message bindings now resolve peer message classes from their own module, fixing custom extension messages built with
bsk_generate_messages(GENERATE_C_INTERFACE)outsideBasilisk.architecture.messaging.Added
NumbaModelto support Basilisk modules written in Python whoseUpdateStateImplmethods are JIT-compiled with Numba for near-C execution speed.Added zero-copy payload dtype metadata and raw message-pointer accessors to support efficient NumPy and Numba views of Basilisk message data.
Added
StatefulNumbaModelto combine Numba-compiled Python modules withStatefulSysModelcontinuous-time state registration and integration in MuJoCoMJScenedynamics.Added
RigidBodyKinematicsNumbaas annjit-compatible rigid-body kinematics utility library for use inside compiled Numba kernels.Added the Making Numba Modules user guide together with scenarioAttitudePointingNumba, scenarioAttitudeFeedbackNumba, and scenarioBenchmarkNumba examples to demonstrate the new Numba-based module workflow.
BSKLoggernow flushesstdoutafter emitting warning-level (and higher) messages, so warnings are not lost or reordered when output is redirected to a file or pipe (and are observable to test harnesses).Added
BSKLogger::bskError()as a non-returning C++ fatal logging method, with safe Python and C fatal logging wrappers, while preserving existingbskLog(BSK_ERROR, ...)behavior.Added Pythonic
BSKLoggerconvenience methodsdebug(),info(),warning(), anderror()tobskLogging.Added a
setLevel()alias forsetLogLevel().Added a
LogLevelIntEnum, and short log-level aliases (ex.bskLogging.WARNING) that mirror Python’s standardloggingmodule naming.Fixed Monte Carlo nested dispersion paths and randomized
RNGSeedapplication.Tuned scenarioMonteCarloAttRW dispersions to show subtler run-to-run variations without saturated response.
Added reusable Eigen validation helpers
eigenIsRotationMatrix,eigenIsUnitVector, andeigenIsValidInertiaMatrixinavsEigenSupportfor use in module configuration checks.Fixed a memory leak in simHelpers
timeStringToGregorianUTCMsg. The SWIG-allocated scratchdoubleArrayused to receive thestr2et_cresult was never released (about 32 bytes leaked per call); it is now freed withdelete_doubleArrayonce the value has been read (issue #548).Added
SimulationBaseClasshelpers to extract and visualize Basilisk module message connections, including stand-alone source messages supplied throughextraMessages, optional recorder module filtering, and Matplotlib or Graphviz rendering. The Graphviz renderer supports compact vertical or horizontal layouts. The new Visualizing Message Connections tutorial explains the available options.Fixed several BSK modules to deallocate dynamically allocated output message objects with C++
delete.Made
StateData::setDerivativevirtual and added aStateData::perComponentErrorControlflag, so a state can both customize how its derivative is interpreted and request that an adaptive integrator measure its truncation error per scalar component (used by the MuJoCo bulk position and velocity states).
Spacecraft dynamics and effectors
Fixed the
thrusterDataattribute of C++ Module: thrusterDynamicEffector and C++ Module: thrusterStateEffector being returned to Python as an opaque object. AfterTHRSimConfigbecame a shared pointer, the SWIG interface no longer wrappedstd::vector<std::shared_ptr<THRSimConfig>>, sothrusterDatacould not be indexed or iterated. It is now exposed as an iterable list ofTHRSimConfigobjects.Added a new C++ Module: facetedSRPEffector module to compute the aggregate force and torque acting on the spacecraft due to impinging photons from the Sun. Unlike the original C++ Module: facetSRPDynamicEffector module, this new module (1) requires the facet data to be externally projected into the spacecraft body frame, (2) expects the facet sunlit projected areas to be provided externally; it does not compute projected area internally, and (3) does not read facet articulation-angle messages directly.
Fixed a reaction wheel unit error in scenarioAttitudeConstrainedManeuver and scenarioAttitudeConstraintViolation. The
maxSpeedvalue was pre-converted to rad/s before being passed torwFactory.create(), which already expectsOmega_maxin RPM and converts internally. The double conversion set the wheel saturation speed about an order of magnitude too low, and since the derived wheel inertia ismaxMomentum / Omega_maxit came out about an order of magnitude too high;maxSpeedis now passed in RPM as expected.C++ Module: spinningBodyOneDOFStateEffector, C++ Module: spinningBodyTwoDOFStateEffector, and C++ Module: spinningBodyNDOFStateEffector now validate in
Reset()that each user-provided DCM is a proper rotation matrix and that each inertia tensor is symmetric and positive definite (the inertia check is skipped for massless bodies), raising a descriptive error when the configuration is inconsistent (issue #469).Fixed C++ Module: hingedRigidBodyStateEffector and C++ Module: nHingedRigidBodyStateEffector constructors that called
Eigen’s staticIdentity()factory as a statement and discarded the result, leaving the defaultdcm_HB(andIPntS_Sfor the single hinged effector) uninitialized instead of identity (issue #469).C++ Module: spacecraft and C++ Module: spacecraftSystem now validate the user-supplied hub configuration on reset: the hub mass
mHubmust be strictly positive and the hub inertia tensorIHubPntBc_Bmust be symmetric and positive definite, raising a descriptive error when the configuration is inconsistent (issue #469). Previously a zero hub mass or singular hub inertia silently producedNaNstates, and a negative hub mass silently reversed the translational response to applied forces.Fixed C++ Module: spacecraft reporting
NaNfornonConservativeAccelpntB_Bon the first integration step. The body-frame non-conservative acceleration divides the accumulated velocity change by the integration time step, which is zero on the first step; it is now set to zero when the time step is zero, matching the existing guard used foromegaDot_BN_B.Add the
fuelLeakRateparameter to the C++ Module: fuelTank module to simulate fuel leaks that cause a loss of fuel mass without imparting momentum.Add the
MassFlowRateMsgPayloadC message type and optional C++ Module: fuelTankfuelLeakRateInMsginput to override the configured leak rate.Stop C++ Module: fuelTank leak depletion when the available tank propellant reaches zero and log a
BSK_WARNING.Fixed N-DoF getter assertions in C++ Module: linearTranslationNDOFStateEffector and C++ Module: spinningBodyNDOFStateEffector.
Improved the runtime performance of C++ Module: spinningBodyNDOFStateEffector and C++ Module: linearTranslationNDOFStateEffector by computing the degree-of-freedom mass-matrix inverse once per
updateContributionscall instead of three times. Results are numerically identical; the speedup grows with the number of degrees of freedom.
Environment, gravity, and ephemerides
Added Earth Radiation Pressure model with C++ Module: earthRadiationModel module.
Added C++ Module: planetRadiationBase base class for planet radiation models and albedo.
Updated C++ Module: albedo module to use new planetRadiationBase.
Added regression coverage for albedo and eclipse in
test_albedo.py.C++ Module: gravityEffector now logs a
BSK_WARNINGinReset()when a gravity body uses an orientation-dependent gravity model – a spherical-harmonic field with tesseral/sectoral terms (order \(\ge 1\)), or a polyhedral shape model – but has no planet-orientation message connected. Without one the planet is silently treated as non-rotating, so the orientation-dependent terms no longer average out and produce spurious secular drift in eccentricity and inclination (issue #1352).Added
GravityModel::dependsOnOrientation(), overridden bySphericalHarmonicsGravityModel(true when any retained coefficient of order \(\ge 1\) is non-zero) and byPolyhedralGravityModel(always true).Added scenarioOrbitConsistencyVerification, which propagates a sun-synchronous LEO orbit under the GGM03S field with and without a connected planet-orientation message and shows that supplying Earth rotation keeps the eccentricity and inclination bounded, recovering consistency with external propagators (Orekit, GMAT, SpOCK).
Documented in scenarioBasicOrbit that spherical-harmonic fields with tesseral terms require a planet-orientation message to be physically correct.
Added a new C++ Module: spacecraftChargingDynamics module which integrates the electric potential of two spacecraft (a servicer and a target) in a plasma environment using a first order ordinary differential equation for each spacecraft. The charging model includes plasma electron current, plasma ion current, photoelectric current, and an optional electron beam current.
Added a new C++ Module: spaceWeatherData C++ module that loads CelesTrak space-weather CSV data and publishes the 23-message weather set required by C++ Module: msisAtmosphere.
Sensors and flight software
Refactored the C++ Module: motorThermal unit test to validate the module against analytically derived temperatures instead of a stored vector of regression “truth” values. The test now drives the module with a stand-alone reaction wheel state message and isolates each term of the heat balance (dissipation, motor power inefficiency, and friction) in separate scenarios, comparing the recorded temperatures to the closed-form heat-balance recurrence.
Fixed the post-fit residual dimension in C Module: sunlineSEKF and C Module: okeefeEKF. The residual term
Hx = measMat * xused the fullSKF_N_STATESwidth instead of the reduced state width each filter actually carries (EKF_N_STATES_SWITCHfor the SEKF,SKF_N_STATES_HALFfor okeefe), so the multiply strode the measurement matrix across the wrong row width and over-read the state-error vector, corrupting the reportedpostFitResduring the convergence transient. The state and covariance estimates were unaffected (issue #1353).Updated the Python Module: thrFiringRound module to include an optional minimum fire time setting.
Fixed camera module to properly process and publish images loaded from the filename parameter, ensuring they follow the same processing pipeline as images from imageInMsg.
Updated the C++ Module: hingedJointArrayMotor module to perform full tracking control.
Added the C++ Module: jointArrayRefProfiler device-interface module to generate low-pass or time-profiled joint angle, rate, and acceleration references from scalar joint state inputs and a desired joint-array command.
Fixed variable semantic mismatch in InertialUKF where
wheelAccelstored torque units; renamed towheelTorqueto correctly reflect the stored physical quantity.Fixed the use of a static vector between the hub center of mass and the system center of mass in Python Module: jointThrAllocation. The vector is now computed from the current articulated-arm configuration, which corrects the thruster mapping and resulting optimization solution for a given set of joint angles.
Added C++ Module: downlinkHandling with a validated configuration interface (setters/getters), finite-value guards, and bounded outputs to prevent non-physical downlink rates.
Added DownlinkHandlingMsgPayload diagnostics and dedicated unit-test coverage for equation parity, receiver-path selection, storage-limited behavior, and invalid-input handling.
Improved storage-target selection robustness across connected storage status messages and aligned module documentation with implemented behavior and validation interface.
Fixed the camera module to release its retained image output buffer on destruction.
Fixed camera PNG encoding option handling for OpenCV 4.13 compatibility in OpNav image processing.
Fixed typo in C Module: attTrackingError documentation
MuJoCo and stochastic integration
Added
.rstdocumentation pages forNBodyGravity,JointPIDController,StochasticAtmDensity, andStochasticDragCoeffFixed the
<body>_comsite in MJScene bodies reporting the body frame origin instead of the true center of mass. MuJoCo latches a site’s frame alignment at compile time, so the center-of-mass site (created at the body origin) ignored the later center-of-mass offset, producing incorrect_comstate messages and an off-center-of-mass gravity force that spuriously torqued hinge-rooted bodies such as deploying panels.Fixed MJScene body inertia not rescaling when the body mass changes. The mass-proportional inertia update divided by the already-updated mass, making the scale factor always one, so the inertia tensor never tracked mass changes.
Improved MuJoCo adaptive-integration error control without growing the integrated state count. A MJScene integrates exactly four bulk states regardless of how many bodies or joints it contains: the whole position vector (
qpos), the whole velocity vector (qvel), the actuator state, and one mass entry per body. The bulk position and velocity states opt into per-component adaptive error control (seeStateData::perComponentErrorControl), so each degree of freedom is scaled by its own magnitude. This fixes cases where orbital translation magnitudes dominated the unified state norm and let stiff hinge dynamics drift unflagged, while keeping the per-stage integrator bookkeeping independent of model size.Added the
MJScene.highOrderAttitudeIntegrationflag (defaultFalse). When enabled, free- and ball-joint orientation quaternions are integrated as a four-component quaternion rate evaluated per integrator substep, so the attitude inherits the integrator’s full order (for example fourth order with RK4) and an adaptive integrator’s tolerance controls the attitude error. By default the quaternion is still advanced by a single exponential map of the stage-averaged body rate, which is second-order accurate on SO(3) regardless of the integrator and reproduces MuJoCo’s own native RK4 attitude stepping.Updated the MuJoCo dynamics wrapper to use MuJoCo 3.7 element-name APIs when reading and writing spec object names.
Improved MuJoCo orbital free-body propagation and adaptive integrator handling for gravity-driven scenes, including reusable state-specific tolerance controls and safer Python/C++ integrator ownership transfer.
Fixed scenarioRoboticArm and scenarioFlexiblePanel where standalone reference messages created inside setup helper functions were garbage collected before the simulation ran. In scenarioRoboticArm this left every robotic-arm joint stuck at zero; in scenarioFlexiblePanel the attitude controller read an unwritten vehicle-configuration message. The messages are now retained on the simulation object, following the guidance in Basilisk Known Issues (issue #1107).
Added an integrated test for scenarioRoboticArm that verifies each joint reaches its commanded angle.
Visualization and data handling
Fixed C++ Module: dataFileToViz and C++ Module: vizInterface SWIG wrapper compatibility so shared Vizard thruster configuration types work regardless of import order.
Fixed the Vizard interface to release retained image output buffers on destruction.
Added MJScene Vizard support to vizSupport, including Python body and geom introspection, MuJoCo body hierarchy discovery, multiple spacecraft roots, and automatic Vizard model generation from supported MuJoCo geoms.
Expanded MuJoCo example Vizard coverage with a new scenarioMJSceneVizard example and visualization support for planets, thruster plumes, asteroid custom models, textured geometry, and deployed multi-body spacecraft.
Updated message recorders so
updateTimeInterval()reschedules the next recording opportunity when the minimum update time is changed between simulation runs.Added a message recorder mode to record only when message payload content changes after the minimum update time has elapsed.
Added explicit errors when change-only recording is requested for payload types without supported equality comparison.
Added shallow metadata comparison support for
CameraImageMsgPayloadwithout comparing pointed-to image bytes.Added support-data backup URLs and shorter retries for externally hosted downloads used by CI.
Added retry hardening for Basilisk support data downloads.
Added Vizard plume placement for thrusters mounted on a non-hub body. C++ Module: thrusterDynamicEffector and C++ Module: thrusterStateEffector now expose a
r_PcP_Pmember, and simIncludeThruster’saddToSpacecraftSubcomponentaccepts ar_PcP_Pargument.Added support for Vizard 2.4.0 features
Added instructions on how to build Vizard from source code
Documentation, examples, and validation
Added the
bsk-module-ioSphinx directive to generate module I/O diagrams and tables from RST.Added C, C++, and Python type labels to generated BSK module documentation pages.
Updated the C and C++ module templates and draft module generator to use generated module I/O diagrams and tables.