Skip to content

Commit f79e7f2

Browse files
Initial commit
1 parent 1efb5c7 commit f79e7f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2258
-2084
lines changed

.gitignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ venv/
6060
*.vscode_debug_path/
6161
lib/*
6262

63-
# Headers staged by sdk/tools/sync_headers.py (duplicates of src/)
64-
sdk/src/bsk_sdk/include/Basilisk/architecture/_GeneralModuleFiles/
65-
sdk/src/bsk_sdk/include/Basilisk/architecture/messaging/
66-
sdk/src/bsk_sdk/include/Basilisk/architecture/utilities/
67-
6863
# Python packaging
6964
*.egg-info
7065
build/

docs/source/Support/Developer/bskSdkV1.rst

Lines changed: 1 addition & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -7,156 +7,4 @@ Basilisk SDK Version 1
77
Purpose
88
-------
99

10-
The Basilisk SDK (``bsk-sdk``) defines the public surface that external plugin
11-
authors can rely on when integrating new simulation capabilities with the
12-
core runtime. Version 1 focuses on establishing a stable contract for Python
13-
and C++ plugin authors and capturing the minimal tooling that ships inside the
14-
Basilisk source tree.
15-
16-
Scope and Deliverables
17-
----------------------
18-
19-
Version 1 guarantees the following artifacts:
20-
21-
- ``bsk_core.plugins``: the runtime registry responsible for discovering
22-
entry-point advertised plugins and exposing them under ``Basilisk.modules``.
23-
- ``bsk-sdk``: a small Python package that publishes the SDK headers, declares a
24-
dependency on the ``pybind11`` headers required by the helper macros, and
25-
provides :func:`bsk_sdk.include_dir` / :func:`bsk_sdk.include_dirs` helpers for
26-
build scripts.
27-
- A companion ``sync_headers.py`` utility (``sdk/tools``) keeps the vendored
28-
Basilisk ``architecture`` headers in sync with the main source tree.
29-
- ``sdk/include/bsk/sdk.hpp``: a single header that wraps the pybind11
30-
boilerplate required for C++ factories and enforces the default constructible
31-
+ ``Reset``/``UpdateState`` interface contract. The same header is shipped by
32-
:mod:`bsk-sdk`.
33-
- A consolidated ``plugins`` example package containing both Python and C++
34-
implementations that demonstrate the expected packaging and registration
35-
patterns.
36-
37-
Any other files in the repository are explicitly *not* part of the SDK
38-
agreement for this release.
39-
40-
Plugin Registry API
41-
-------------------
42-
43-
The ``bsk_core.plugins.PluginRegistry`` class is the primary integration
44-
point for third-party plugins. The registry is responsible for staging plugin
45-
definitions until the runtime exports them under ``Basilisk.modules``.
46-
47-
The public methods guaranteed in v1 are:
48-
49-
.. code-block:: python
50-
51-
class PluginRegistry:
52-
def register_python_module(self, name: str, cls: type[sysModel.SysModel]) -> None: ...
53-
def register_factory(self, name: str, factory: Any) -> None: ...
54-
55-
``register_python_module`` accepts any subclass of
56-
``Basilisk.architecture.sysModel.SysModel`` and exposes it as a class on
57-
``Basilisk.modules`` using the provided name. ``register_factory`` stores an
58-
opaque object under the supplied name. Factories are expected to be callables
59-
returning Basilisk-compatible module instances, but v1 defers any runtime shape
60-
validation to keep the surface area small.
61-
62-
Plugins must advertise a ``register(registry)`` callable through the
63-
``basilisk.plugins`` entry-point group. During startup Basilisk resolves the
64-
entry-point, imports the containing module, and invokes the callable with the
65-
shared registry instance.
66-
67-
Python Plugin Pattern
68-
---------------------
69-
70-
Pure-Python plugins should follow the pattern demonstrated in
71-
``plugins/src/python/Basilisk/ExternalModules/customPythonModule.py``:
72-
73-
.. code-block:: python
74-
75-
from Basilisk.architecture import sysModel
76-
77-
class ExamplePluginModule(sysModel.SysModel):
78-
def Reset(self, current_sim_nanos):
79-
...
80-
81-
def UpdateState(self, current_sim_nanos, call_time):
82-
...
83-
84-
def register(registry):
85-
registry.register_python_module("ExamplePluginModule", ExamplePluginModule)
86-
87-
The distribution's ``pyproject.toml`` must expose the ``register`` function via
88-
89-
.. code-block:: toml
90-
91-
[project.entry-points."basilisk.plugins"]
92-
example = "bsk_example_plugin.simple:register"
93-
94-
At runtime users import the module from ``Basilisk.modules``:
95-
96-
.. code-block:: python
97-
98-
from Basilisk import modules
99-
100-
plugin_cls = modules.ExamplePluginModule
101-
instance = plugin_cls()
102-
instance.Reset(0)
103-
instance.UpdateState(0, 0)
104-
105-
C++ Plugin Pattern
106-
------------------
107-
108-
Native extensions should include ``sdk/include/bsk/sdk.hpp`` to inherit
109-
the pybind11 binding helpers. When building outside the Basilisk source tree
110-
the :mod:`bsk-sdk` package exposes the headers via
111-
``import bsk_sdk; bsk_sdk.include_dir()`` (or ``include_dirs()`` to also capture
112-
the ``Basilisk`` subdirectory and ``pybind11`` include path). Version 1
113-
guarantees the availability of:
114-
115-
- ``bsk::plugin::register_basic_plugin``
116-
- ``BSK_PLUGIN_PYBIND_MODULE``
117-
118-
The ``BSK_PLUGIN_PYBIND_MODULE`` macro defines both the pybind11 module and the
119-
``create_factory`` callable consumed by the Basilisk runtime. The expected class
120-
contract mirrors the Python case: default constructible with ``Reset`` and
121-
``UpdateState`` methods.
122-
123-
.. code-block:: cpp
124-
125-
#include <bsk/sdk.hpp>
126-
127-
class ExampleCppModule {
128-
public:
129-
void Reset(double current_sim_nanos);
130-
void UpdateState(double current_sim_nanos, double call_time);
131-
};
132-
133-
BSK_PLUGIN_PYBIND_MODULE(_example_cpp, ExampleCppModule, "ExampleCppModule");
134-
135-
The companion Python package should lazily import the extension, extract the
136-
factory, and register it:
137-
138-
.. code-block:: python
139-
140-
from importlib import import_module
141-
142-
def register(registry):
143-
ext = import_module("bsk_example_plugin_cpp._example_cpp")
144-
factory = ext.create_factory()
145-
registry.register_factory("ExampleCppFactory", factory)
146-
147-
Limitations and Future Work
148-
---------------------------
149-
150-
Version 1 intentionally leaves several items out of scope so they can be
151-
designed with real-world feedback:
152-
153-
- The SDK header is distributed from the Basilisk source tree and is not
154-
published as a standalone artifact.
155-
- Factories registered via ``register_factory`` are treated as opaque callables;
156-
Basilisk does not verify their type or interface beyond name collisions.
157-
- The helper header requires C++17 and a compatible pybind11 toolchain.
158-
- Plugin lifecycle hooks beyond ``Reset``/``UpdateState`` will be designed as
159-
future Basilisk modules adopt richer interfaces.
160-
161-
Feedback on these gaps is welcome and will inform the roadmap for subsequent
162-
SDK revisions.
10+
TODO, this all changed now since just using SWIG directly.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
cmake_minimum_required(VERSION 3.18)
2+
project(bsk_plugin_exponential_atmosphere LANGUAGES CXX)
3+
4+
find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module NumPy)
5+
6+
# Locate bsk-sdk's CMake config dir from the active Python env
7+
execute_process(
8+
COMMAND "${Python3_EXECUTABLE}" -c "import bsk_sdk; print(bsk_sdk.cmake_config_dir(), end='')"
9+
OUTPUT_VARIABLE bsk_sdk_dir
10+
RESULT_VARIABLE rc
11+
)
12+
if(NOT rc EQUAL 0 OR bsk_sdk_dir STREQUAL "")
13+
message(FATAL_ERROR "bsk-sdk not found (is it installed in this Python environment?)")
14+
endif()
15+
16+
set(bsk-sdk_DIR "${bsk_sdk_dir}")
17+
find_package(bsk-sdk CONFIG REQUIRED)
18+
19+
# Where scikit-build-core wants wheel outputs
20+
set(PLUGIN_PKG_DIR "${SKBUILD_PLATLIB_DIR}/custom_atm")
21+
22+
# Plugin sources
23+
file(GLOB PLUGIN_SOURCES CONFIGURE_DEPENDS
24+
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.c"
25+
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc"
26+
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx"
27+
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
28+
)
29+
30+
# Build the SWIG module
31+
bsk_add_swig_module(
32+
TARGET customExponentialAtmosphere
33+
INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/swig/customExponentialAtmosphere.i"
34+
SOURCES ${PLUGIN_SOURCES}
35+
INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src"
36+
OUTPUT_DIR "${PLUGIN_PKG_DIR}"
37+
)
38+
39+
target_include_directories(customExponentialAtmosphere PRIVATE
40+
"${CMAKE_CURRENT_SOURCE_DIR}/src"
41+
"${CMAKE_CURRENT_SOURCE_DIR}/messages"
42+
)
43+
44+
# Generate message bindings into custom_atm/messaging
45+
bsk_generate_messages(
46+
OUTPUT_DIR "${PLUGIN_PKG_DIR}/messaging"
47+
MSG_HEADERS
48+
"${CMAKE_CURRENT_SOURCE_DIR}/messages/CustomAtmStatusMsgPayload.h"
49+
)
50+
51+
# Link against SDK-provided Basilisk minimal libs (if your plugin needs them)
52+
target_link_libraries(customExponentialAtmosphere PRIVATE bsk::runtime_min bsk::arch_min)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#
2+
# ISC License
3+
#
4+
# Copyright (c) 2026, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
5+
#
6+
# Permission to use, copy, modify, and/or distribute this software for any
7+
# purpose with or without fee is hereby granted, provided that the above
8+
# copyright notice and this permission notice appear in all copies.
9+
#
10+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
#
18+
19+
import sys
20+
from Basilisk.architecture import cSysModel as _cSysModel
21+
from . import customExponentialAtmosphere
22+
23+
sys.modules.setdefault("cSysModel", _cSysModel)
24+
25+
__all__ = ["customExponentialAtmosphere"]

example-plugins/external-module-plugin/msgPayloadDefC/CustomModuleMsgPayload.h renamed to example-plugins/custom-atm-plugin/messages/customAtmStatusMsgPayload.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
ISC License
33
4-
Copyright (c) 2016, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
4+
Copyright (c) 2026, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
55
66
Permission to use, copy, modify, and/or distribute this software for any
77
purpose with or without fee is hereby granted, provided that the above
@@ -17,15 +17,20 @@
1717
1818
*/
1919

20-
#ifndef _CUSTOM_MODULE_OUT_H_
21-
#define _CUSTOM_MODULE_OUT_H_
20+
#pragma once
2221

22+
#include <stdint.h>
2323

24-
/*! @brief Structure used to define the output of the sub-module. This is the same
25-
output message that is used by all sub-modules in the module folder. */
26-
typedef struct {
27-
double dataVector[3]; //!< [units] sample output vector
28-
}CustomModuleMsgPayload;
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
2927

28+
typedef struct {
29+
double density; //!< kg/m^3
30+
double scaleHeight; //!< m
31+
int32_t modelValid; //!< 1 = ok, 0 = invalid
32+
} CustomAtmStatusMsgPayload;
3033

34+
#ifdef __cplusplus
35+
} // extern "C"
3136
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[build-system]
2+
requires = ["scikit-build-core>=0.9.3", "bsk-sdk>=1.0.0"]
3+
build-backend = "scikit_build_core.build"
4+
5+
[project]
6+
name = "bsk-plugin-exponential-atmosphere"
7+
version = "0.1.0"
8+
9+
[tool.scikit-build]
10+
wheel.packages = ["custom_atm"]
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
ISC License
3+
4+
Copyright (c) 2026, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
5+
6+
Permission to use, copy, modify, and/or distribute this software for any
7+
purpose with or without fee is hereby granted, provided that the above
8+
copyright notice and this permission notice appear in all copies.
9+
10+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
18+
*/
19+
20+
21+
#include "customExponentialAtmosphere.h"
22+
23+
/*! The constructor method initializes the dipole parameters to zero, resuling in a zero magnetic field result by default.
24+
25+
*/
26+
CustomExponentialAtmosphere::CustomExponentialAtmosphere()
27+
{
28+
//! - Set the default atmospheric properties to yield a zero response
29+
this->baseDensity = 0.0; // [T]
30+
this->scaleHeight = 1.0; // [m]
31+
this->planetRadius = 0.0; // [m]
32+
this->localTemp = 1.0; // [K]
33+
34+
return;
35+
}
36+
37+
/*! Empty destructor method.
38+
39+
*/
40+
CustomExponentialAtmosphere::~CustomExponentialAtmosphere()
41+
{
42+
return;
43+
}
44+
45+
/*! This method is evaluates the centered dipole magnetic field model.
46+
@param msg magnetic field message structure
47+
@param currentTime current time (s)
48+
49+
*/
50+
void CustomExponentialAtmosphere::evaluateAtmosphereModel(AtmoPropsMsgPayload* msg, double currentTime)
51+
{
52+
(void)currentTime;
53+
54+
static bool firstCall = true;
55+
if (firstCall) {
56+
this->bskLogger.bskLog(BSK_INFORMATION,
57+
"ExponentialAtmosphere (plugin): model active; using AtmosphereBase altitude.");
58+
firstCall = false;
59+
}
60+
61+
bool statusApplied = false;
62+
if (this->atmStatusInMsg_.isLinked()) {
63+
const CustomAtmStatusMsgPayload status = this->atmStatusInMsg_(); // payload copy
64+
if (status.modelValid) {
65+
this->baseDensity = status.density;
66+
this->scaleHeight = status.scaleHeight;
67+
statusApplied = true;
68+
} else {
69+
this->bskLogger.bskLog(BSK_WARNING,
70+
"ExponentialAtmosphere (plugin): CustomAtmStatusMsgPayload invalid; ignoring.");
71+
}
72+
}
73+
74+
const double exponent = -(this->orbitAltitude) / this->scaleHeight;
75+
msg->neutralDensity = this->baseDensity * std::exp(exponent);
76+
msg->localTemp = this->localTemp;
77+
78+
if (statusApplied) {
79+
this->bskLogger.bskLog(BSK_INFORMATION,
80+
"ExponentialAtmosphere (plugin): applied status msg; alt=%.3g m rho=%.3g",
81+
this->orbitAltitude, msg->neutralDensity);
82+
}
83+
}
84+
85+
void CustomExponentialAtmosphere::connectAtmStatus(Message<CustomAtmStatusMsgPayload>* msg)
86+
{
87+
this->atmStatusInMsg_.subscribeTo(msg);
88+
}

0 commit comments

Comments
 (0)