API Reference
The API reference is generated from source docstrings with mkdocstrings.
Mission And Execution
octavian.mission
Mission composition primitives.
Mission
dataclass
Top-level user-facing mission container.
Source code in octavian/mission.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
add_phase(phase: Phase) -> None
Append a phase to the mission.
Args: phase: Phase to append.
Source code in octavian/mission.py
44 45 46 47 48 49 50 | |
solve(*, plan: RunPlan | None = None, retry: RetryPolicy | None = None, solve_config: SolveConfig | None = None, solver_options: SolverOptions | None = None) -> Solution
Solve the mission using the configured runner.
Args: plan: Optional continuation or staging plan override. retry: Optional retry-policy override. solve_config: Optional solve-configuration override. solver_options: Optional backend solver-options override.
Returns: The mission solution wrapper.
Source code in octavian/mission.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
validate() -> None
Validate mission structure before solving.
Raises: ValueError: If the mission has no phases or a phase is invalid.
Source code in octavian/mission.py
52 53 54 55 56 57 58 59 60 61 | |
octavian.runner
Mission runner and backend mapping logic.
MissionBuildError
Bases: ValueError
Raised when a mission cannot be mapped to a supported solver.
Source code in octavian/runner.py
20 21 | |
MissionRunner
dataclass
Coordinate mission validation, backend selection, and retry behavior.
Source code in octavian/runner.py
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | |
solve(mission: Mission) -> Solution
Solve a mission through validation, staging, backend dispatch, and retry.
| Parameters: |
|
|---|
| Returns: |
|
|---|
Source code in octavian/runner.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
octavian.solution
Solution and reporting.
Solution is Octavian's stable output contract.
It wraps backend-specific result objects (currently RendezvousResult) and
adds:
- attempt history
- a consistent summary string
- a small viz namespace
AttemptLog
dataclass
One solver attempt recorded by MissionRunner.
Attributes:
stage: Runner stage label, or "default" when no staged plan is used.
attempt: One-based attempt number within the stage.
status: Short status string such as "ok" or "fail".
message: Optional failure or diagnostic message.
Source code in octavian/solution.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
Solution
dataclass
Stable user-facing wrapper around a backend solve result.
Solution keeps backend result objects from leaking directly into mission
scripts. Successful solves expose the backend result through result and
convenience accessors such as traj. Failed solves still return structured
attempt logs when SolveConfig.raise_on_fail is false.
Source code in octavian/solution.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | |
attitude_phase_trajectories: tuple[np.ndarray, ...]
property
Return Euler attitude histories for kinematic-attitude phases.
Each array contains [yaw, pitch, roll, time, yaw_rate, pitch_rate,
roll_rate] in radians, seconds, and radians per second.
chief_trajectory_eci: np.ndarray
property
Return the propagated chief absolute history for relative solves.
cr3bp_dimensional: bool | None
property
Return the solved CR3BP unit mode, or None for other dynamics.
cr3bp_system: CR3BPSystem | None
property
Return the solved CR3BP system, or None for other dynamics.
deputy_trajectory_eci: np.ndarray
property
Return the propagated deputy absolute history for relative solves.
frame: CoordinateFrame | None
property
Return the reference frame declared by the solver result.
native_relative_phase_trajectories: tuple[np.ndarray, ...]
property
Return one control-free native state/time array per relative phase.
A stitched native trajectory is unavailable when phase layouts change, for example when an initial coast does not carry mass but a later finite-burn chain does. This accessor always preserves each phase's declared native representation.
native_relative_trajectory: np.ndarray
property
Return the solver's native relative state and time history.
For a D'Amico phase, for example, columns are
[δa, δλ, δex, δey, δix, δiy, t]. The ordinary :attr:traj
accessor always remains the reconstructed [RIC state, t] view.
phase_control_trajectories: tuple[np.ndarray, ...]
property
Return [time, controls...] arrays for every compiled phase.
Vector-throttle components and scalar throttle are dimensionless. Euler-rate columns are converted from normalized optimizer variables to physical radians per second.
relative_propagation_mode: str | None
property
Return the selected relative formulation, or None if inertial.
scaling: SolverScaling | None
property
Return characteristic units used by the solver, when available.
traj: np.ndarray
property
Return the solved trajectory array, or an empty array on failure.
export_ephemeris(path: str | Path, *, trajectory: str = 'auto', epoch: str | datetime | float | int | None = None, frame_name: str | None = None, center_name: str | None = None, object_name: str | None = None, object_id: int = -100000, center_id: int | None = None, format: EphemerisFormat | None = None, overwrite: bool = False, interpolation_degree: int = 7) -> Path
Export a solved, chief, or deputy trajectory to an ephemeris file.
The output extension selects STK .e, CCSDS .oem, SPICE
.bsp/.spk, or SI-unit .csv. See :meth:to_ephemeris for
trajectory and frame semantics.
Returns: The resolved path written by the selected exporter.
Source code in octavian/solution.py
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | |
summary() -> str
Return a human-readable solve summary.
Source code in octavian/solution.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
to_ephemeris(*, trajectory: str = 'auto', epoch: str | datetime | float | int | None = None, frame_name: str | None = None, center_name: str | None = None, object_name: str | None = None, object_id: int = -100000, center_id: int | None = None) -> Ephemeris
Return a validated ephemeris selected from this solution.
Args:
trajectory: "auto" (the deputy for relative solutions,
otherwise the solved trajectory), "solved", "chief",
or "deputy". Chief and deputy histories are absolute ECI
trajectories reconstructed by exact relative formulations.
epoch: Epoch corresponding to trajectory time zero. When omitted,
use the originating mission's initial_epoch.
frame_name: Frame label for the state values. This does not rotate
coordinates. Absolute ECI histories default to "J2000".
center_name: Center-of-motion label, normally inferred from the
solution metadata.
object_name: Exported object label.
object_id: NAIF object ID used by BSP output.
center_id: NAIF center ID used by BSP output, inferred for Earth,
Moon, and Sun when omitted.
Returns:
An :class:octavian.exports.Ephemeris ready to write.
Raises: RuntimeError: If the solution has no result. ValueError: If the selected trajectory or epoch is unavailable.
Note:
File export labels the selected data but does not perform a frame
rotation. Select "chief" or "deputy" when exporting a
relative solution to an inertial OEM or BSP.
Source code in octavian/solution.py
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | |
viz()
Namespace-style access to visualization helpers.
Source code in octavian/solution.py
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | |
octavian.config
Declarative JSON and YAML mission configuration.
The config layer only constructs Octavian's existing Python objects. Python mission scripts remain the primary and most expressive interface.
MissionConfigError
Bases: ValueError
A mission configuration file is malformed or internally inconsistent.
Source code in octavian/config/errors.py
6 7 | |
load_mission(path: str | Path) -> Mission
Load a JSON or YAML file and construct its :class:~octavian.Mission.
Args:
path: Path to a .json, .yaml, or .yml mission file.
Returns: A validated mission built from the public Python configuration objects.
Source code in octavian/config/__init__.py
19 20 21 22 23 24 25 26 27 28 | |
load_mission_mapping(value: Mapping[str, Any]) -> Mission
Construct a mission from an already-parsed configuration mapping.
Source code in octavian/config/__init__.py
31 32 33 | |
mission_from_dict(value: Mapping[str, Any]) -> Mission
Construct a validated mission from a schema-versioned mapping.
The mapping names states, spacecraft, and dynamics, then references those objects from ordered phase declarations. Unknown keys are rejected so misspellings cannot silently change a mission.
Args: value: Parsed JSON/YAML mapping using schema version 1.
Returns: A mission composed from Octavian's existing public Python objects.
Raises: MissionConfigError: If the mapping is malformed or references are invalid.
Source code in octavian/config/builder.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
read_config_file(path: str | Path) -> Mapping[str, Any]
Read a JSON or YAML configuration file into a mapping.
JSON support uses the Python standard library. YAML support is optional and
uses yaml.safe_load from PyYAML; install it with octavian[yaml].
Args:
path: File ending in .json, .yaml, or .yml.
Returns: The parsed top-level mapping.
Raises: MissionConfigError: If the extension, syntax, or top-level value is invalid.
Source code in octavian/config/io.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
Mission Building Blocks
octavian.phase
Phase definitions for mission composition.
Phase
dataclass
One dynamics segment in a composable mission.
initial_state and final_state are seed anchors unless matching
constraints are declared; this distinction permits free-time and partial
terminal targets. Relative-element phases may therefore keep convenient
RIC seed anchors while applying native ROE constraints.
Args:
name: Human-readable phase identifier.
mode: Coast, relative-coast, or powered phase semantics.
spacecraft: Vehicle configuration or registry name.
dynamics: Translational dynamics configuration.
initial_state: Optional Cartesian state used to seed the phase.
final_state: Optional Cartesian state used to seed the phase.
constraints: Boundary, path, geometry, and element constraints.
tof_bounds_s: Lower and upper phase-end time or duration.
initial_guess: Optional specialized guess configuration, including an
explicit dense history from guesses.trajectory(...).
thrust_control: Optional finite-thrust direction or kinematic-attitude
representation. Linked phases inherit the previous declaration.
Source code in octavian/phase.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
has_impulse(where: str) -> bool
Return whether the phase declares an impulse at a boundary.
Args:
where: Boundary name such as "Front" or "Back".
Returns:
True if the phase has an impulse event at that boundary.
Source code in octavian/phase.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
inherit_defaults() -> None
Inherit spacecraft, dynamics, and default link from the previous phase.
Source code in octavian/phase.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
validate() -> None
Validate that the phase has the required data to solve.
Raises: ValueError: If the phase is missing dynamics, spacecraft, or valid time-of-flight bounds.
Source code in octavian/phase.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
state(r_m: Sequence[float], v_mps: Sequence[float]) -> BoundaryState
Create a boundary state from position and velocity vectors.
Args: r_m: Position vector in meters. v_mps: Velocity vector in meters per second.
Returns:
A boundary-state object with reshaped (3,) vectors.
Source code in octavian/phase.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
octavian.constraints
User-facing constraint declarations for composable missions.
The constraint objects in this module are intentionally small, explicit, and
Pythonic. They describe what the user wants and keep the corresponding solver
formula close by in apply; compiler-owned contexts provide phase-specific
backend data without being retained by the declarations.
ApproachCone
dataclass
Bases: Constraint
Keep position inside a one-sided cone extending from a vertex.
Source code in octavian/constraints.py
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 | |
value: dict[str, Any]
property
Return the normalized cone declaration.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply the cone-angle inequality and retain its forward half.
Source code in octavian/constraints.py
645 646 647 648 649 650 651 652 653 654 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the maximum solved angle from the cone axis.
Source code in octavian/constraints.py
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 | |
Constraint
Bases: ABC
Abstract base class for all mission constraints.
Concrete constraints own their ASSET compilation formula in :meth:apply.
The compiler supplies phase-specific data through a transient context.
Source code in octavian/constraints.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
value: Any
abstractmethod
property
Return the canonical constraint payload.
apply(phase: Any, context: ConstraintApplicationContext) -> None
abstractmethod
Apply this declaration to a compiled solver phase.
Source code in octavian/constraints.py
205 206 207 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Return solved-value report rows when this constraint supports them.
Source code in octavian/constraints.py
209 210 211 212 | |
ConstraintApplicationContext
Bases: Protocol
Compiler-owned data available while a constraint is applied.
Source code in octavian/constraints.py
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
ConstraintReportContext
Bases: Protocol
Solved phase data available to constraint reporting methods.
Source code in octavian/constraints.py
41 42 43 44 45 46 47 48 49 50 51 52 | |
Eccentricity
dataclass
Bases: OrbitalElementConstraint
Constrain orbital eccentricity.
Circular targets are intentionally rejected for now because they need a non-singular formulation.
Source code in octavian/constraints.py
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | |
element_name: str
property
Return the compiler-facing element identifier.
value: dict[str, float | None]
property
Return the dimensionless target and optional tolerance.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply eccentricity through its non-negative squared expression.
Source code in octavian/constraints.py
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report solved eccentricity at the selected boundary.
Source code in octavian/constraints.py
364 365 366 367 368 | |
InclinationDeg
dataclass
Bases: OrbitalElementConstraint
Constrain orbital inclination in degrees.
Equatorial targets are intentionally rejected for now because they need a non-singular formulation.
Source code in octavian/constraints.py
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | |
element_name: str
property
Return the compiler-facing element identifier.
value: dict[str, float | None]
property
Return the target and optional tolerance in degrees.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply inclination using the angular-momentum direction cosine.
Source code in octavian/constraints.py
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report solved inclination at the selected boundary.
Source code in octavian/constraints.py
440 441 442 443 444 445 446 447 448 449 450 451 452 | |
JacobiConstant
dataclass
Bases: Constraint
Constrain the Jacobi integral of a CR3BP phase.
The compiler evaluates the invariant directly from the phase's synodic Cartesian state. Canonical targets are convenient for comparison with CR3BP literature; dimensional targets use square meters per square second.
Args:
target: Desired Jacobi constant.
where: "Front", "Back", or "Path".
tolerance: Optional symmetric non-negative tolerance in the selected
unit system. Omitting it creates an equality.
dimensional: Interpret target and tolerance as m²/s² when
true or canonical CR3BP units when false.
Source code in octavian/constraints.py
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 | |
value: dict[str, float | bool | None]
property
Return the target, tolerance, and selected unit system.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply the CR3BP Jacobi integral in canonical solver units.
Source code in octavian/constraints.py
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the worst solved Jacobi target error at the selected location.
Source code in octavian/constraints.py
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 | |
KeepOutSphere
dataclass
Bases: Constraint
Keep Cartesian position outside a sphere centered in the phase frame.
Source code in octavian/constraints.py
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | |
value: dict[str, Any]
property
Return the keep-out radius and center.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply radius² - ||position - center||² <= 0.
Source code in octavian/constraints.py
585 586 587 588 589 590 591 592 593 594 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the minimum solved separation from the keep-out center.
Source code in octavian/constraints.py
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | |
LightingAngle
dataclass
Bases: Constraint
Bound the angle from position to a fixed illumination direction.
sun_direction is expressed in the same frame as the phase position and
points from the constraint origin toward the light source.
Source code in octavian/constraints.py
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | |
value: dict[str, Any]
property
Return the fixed-direction lighting declaration.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply lower and upper angle bounds to a fixed light direction.
Source code in octavian/constraints.py
720 721 722 723 724 725 726 727 728 729 730 731 732 733 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report solved extrema of the fixed-direction lighting angle.
Source code in octavian/constraints.py
735 736 737 738 739 740 741 742 | |
MinRadius
dataclass
Bases: Constraint
Constrain the trajectory radius norm from below.
Source code in octavian/constraints.py
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | |
value: float
property
Return the minimum radius in meters.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply a lower bound to the Cartesian position norm.
Source code in octavian/constraints.py
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | |
OrbitalElementConstraint
Bases: Constraint
Marker base class for orbital-element constraints.
Source code in octavian/constraints.py
215 216 217 218 219 220 221 222 223 | |
element_name: str
abstractmethod
property
Human-readable orbital element name.
PeriodicState
dataclass
Bases: Constraint
Require selected Cartesian components to match at both phase ends.
The equality is imposed directly between the phase's front and back state in its declared frame. Time is intentionally excluded: periodicity closes the physical state while allowing a positive orbit period. At least one independent front-boundary phase condition is normally needed to remove the arbitrary time shift of an autonomous periodic orbit.
Args: components: Cartesian components to close. The default closes the full position and velocity state.
Source code in octavian/constraints.py
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | |
value: dict[str, tuple[str, ...]]
property
Return the components equated between the phase boundaries.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Equate selected native Cartesian components at both boundaries.
Source code in octavian/constraints.py
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | |
Position
dataclass
Bases: Constraint
Constrain a Cartesian boundary position.
Source code in octavian/constraints.py
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | |
value: np.ndarray
property
Return the constrained position as a three-vector.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Fix Cartesian position at the selected phase location.
Source code in octavian/constraints.py
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | |
RelativeOrbitalElementConstraint
dataclass
Bases: Constraint
Constrain one native relative orbital element.
D'Amico names are delta_a, delta_lambda, delta_ex,
delta_ey, delta_ix, and delta_iy. Classical-difference names
are delta_a_m, delta_e, delta_i, delta_raan,
delta_argp, and delta_mean_anomaly. Angles are radians.
Source code in octavian/constraints.py
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | |
value: dict[str, float | str | None]
property
Return the normalized relative-element target payload.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply one scalar native relative-orbital-element target.
Source code in octavian/constraints.py
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the worst solved error for one relative orbital element.
Source code in octavian/constraints.py
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | |
RelativeOrbitalElementsConstraint
dataclass
Bases: Constraint
Constrain all six native relative orbital elements at one location.
Source code in octavian/constraints.py
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 | |
value: dict[str, Any]
property
Return the normalized six-element target payload.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Fix all six native relative orbital elements at one location.
Source code in octavian/constraints.py
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the worst solved error for each relative orbital element.
Source code in octavian/constraints.py
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 | |
RelativeStateComponent
dataclass
Bases: Constraint
Constrain one native RIC position or velocity component.
Components are R, I, C, Rdot, Idot, and Cdot.
The target and optional tolerance use meters for position and meters per
second for velocity. The compiler applies this constraint directly to a
native RIC formulation; it never reconstructs an absolute deputy state.
Source code in octavian/constraints.py
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | |
value: dict[str, float | str | None]
property
Return the normalized component target payload.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply a scalar target to one native RIC component.
Source code in octavian/constraints.py
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report the worst solved error for one RIC component.
Source code in octavian/constraints.py
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | |
SemiMajorAxis
dataclass
Bases: OrbitalElementConstraint
Constrain semi-major axis in meters.
Source code in octavian/constraints.py
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | |
element_name: str
property
Return the compiler-facing element identifier.
value: dict[str, float | None]
property
Return the target and optional tolerance in meters.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply the two-body specific-energy definition of semi-major axis.
Source code in octavian/constraints.py
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report solved semi-major axis at the selected boundary.
Source code in octavian/constraints.py
286 287 288 289 290 | |
SolarPhaseAngle
dataclass
Bases: Constraint
Bound the relative position angle to the ephemeris Sun direction.
Unlike :class:LightingAngle, the direction is not stored as a fixed
vector. The composable relative-motion compiler samples the bundled SPICE
BSP at Mission.initial_epoch and rotates the Sun line into the chief's
RIC frame throughout the phase. CWH dynamics must therefore provide a
chief initial inertial state.
Source code in octavian/constraints.py
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | |
value: dict[str, Any]
property
Return solar-phase angle bounds and origin.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply angle bounds to the time-varying SPICE Sun line in RIC.
Source code in octavian/constraints.py
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | |
report(context: ConstraintReportContext) -> list[dict[str, Any]]
Report solved extrema of the time-varying solar phase angle.
Source code in octavian/constraints.py
838 839 840 841 842 843 844 845 846 847 | |
State
dataclass
Bases: Constraint
Constrain a Cartesian boundary state.
Source code in octavian/constraints.py
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 | |
value: dict[str, Any]
property
Return the Cartesian state and selected groups.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Fix the selected position, velocity, or time boundary groups.
Source code in octavian/constraints.py
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 | |
StateComponent
dataclass
Bases: Constraint
Constrain one Cartesian state component in the phase's native frame.
Position components are x, y, and z; velocity components are
vx, vy, and vz. Position targets and tolerances use meters,
while velocity targets and tolerances use meters per second. The
constraint is applied directly to the phase state without changing frames.
Source code in octavian/constraints.py
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 | |
value: dict[str, float | str | None]
property
Return the normalized component target payload.
apply(phase: Any, context: ConstraintApplicationContext) -> None
Apply one native Cartesian state component target.
Source code in octavian/constraints.py
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 | |
approach_cone(axis: Sequence[float], half_angle_deg: float, *, vertex_m: Sequence[float] = (0.0, 0.0, 0.0), where: str = 'Path') -> ApproachCone
Create a one-sided conical approach-corridor constraint.
Source code in octavian/constraints.py
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 | |
eccentricity(e: float, where: str = 'Path', tol: float | None = None) -> Eccentricity
Create an eccentricity constraint.
Source code in octavian/constraints.py
1891 1892 1893 | |
inclination_deg(inc_deg: float, where: str = 'Path', tol_deg: float | None = None) -> InclinationDeg
Create an inclination constraint.
Source code in octavian/constraints.py
1896 1897 1898 1899 1900 | |
jacobi_constant(target: float, *, where: str = 'Front', tolerance: float | None = None, dimensional: bool = True) -> JacobiConstant
Create a direct Jacobi-constant constraint for a CR3BP phase.
Args:
target: Desired Jacobi constant.
where: "Front", "Back", or "Path".
tolerance: Optional symmetric non-negative tolerance.
dimensional: Interpret the target and tolerance as m²/s² when
true. Set false for the canonical values normally published with
nondimensional CR3BP states.
Returns: A declarative CR3BP invariant constraint.
Source code in octavian/constraints.py
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 | |
keep_out_sphere(radius_m: float, *, center_m: Sequence[float] = (0.0, 0.0, 0.0), where: str = 'Path') -> KeepOutSphere
Create an offset spherical keep-out-zone constraint.
Source code in octavian/constraints.py
1908 1909 1910 1911 1912 1913 1914 1915 | |
lighting_angle(sun_direction: Sequence[float], *, min_angle_deg: float = 0.0, max_angle_deg: float = 180.0, origin_m: Sequence[float] = (0.0, 0.0, 0.0), where: str = 'Path') -> LightingAngle
Create a fixed-direction lighting-angle constraint.
Source code in octavian/constraints.py
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 | |
min_radius(r_min_m: float, where: str = 'Path') -> MinRadius
Create a minimum-radius constraint.
Source code in octavian/constraints.py
1903 1904 1905 | |
periodic_state(components: Sequence[str] = ('x', 'y', 'z', 'vx', 'vy', 'vz')) -> PeriodicState
Create a direct front-to-back Cartesian periodicity constraint.
Args: components: Cartesian components to equate between the phase boundaries. The default closes all six position/velocity components while leaving time unconstrained.
Returns: A periodic-state declaration for the composable ASSET compiler.
Notes: Autonomous periodic-orbit problems normally need an additional phase condition, such as a fixed front position component, to remove the arbitrary time shift around the orbit.
Source code in octavian/constraints.py
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | |
position(r_m: Sequence[float], where: str = 'Front') -> Position
Create a boundary position constraint.
Source code in octavian/constraints.py
1746 1747 1748 | |
relative_orbital_element(element: str, target: float, *, representation: RelativeElementRepresentation | str = 'damico', where: str = 'Back', tolerance: float | None = None) -> RelativeOrbitalElementConstraint
Create a direct scalar relative-orbital-element constraint.
Source code in octavian/constraints.py
1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 | |
relative_orbital_elements(elements: Any, *, representation: RelativeElementRepresentation | str | None = None, where: str = 'Front') -> RelativeOrbitalElementsConstraint
Create a direct six-element relative-orbit boundary constraint.
elements may be a six-value sequence or one of the relative-element
dataclasses from :mod:octavian.relative.
Source code in octavian/constraints.py
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 | |
ric_state(component: str, target: float, *, where: str = 'Back', tolerance: float | None = None) -> RelativeStateComponent
Create a direct constraint on one native RIC state component.
Use a native RIC propagation mode (CWH, "nonlinear_ric", or
"coupled_ric") so the optimizer applies the target without converting
through absolute coordinates.
Source code in octavian/constraints.py
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 | |
semi_major_axis(a_m: float, where: str = 'Path', tol_m: float | None = None) -> SemiMajorAxis
Create a semi-major-axis constraint.
Source code in octavian/constraints.py
1886 1887 1888 | |
solar_phase_angle(*, min_angle_deg: float = 0.0, max_angle_deg: float = 180.0, origin_m: Sequence[float] = (0.0, 0.0, 0.0), where: str = 'Path') -> SolarPhaseAngle
Create an ephemeris-driven RIC solar-phase-angle constraint.
Source code in octavian/constraints.py
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 | |
state(x: BoundaryState, where: str = 'Front', groups: Sequence[str] = ('R', 'V')) -> State
Create a boundary state constraint.
Source code in octavian/constraints.py
1741 1742 1743 | |
state_component(component: str, target: float, *, where: str = 'Front', tolerance: float | None = None) -> StateComponent
Create a native-frame Cartesian component constraint.
Args:
component: Position component x, y, or z; or velocity
component vx, vy, or vz. Common spellings such as
xdot are normalized.
target: Component target in meters or meters per second.
where: "Front", "Back", or "Path".
tolerance: Optional symmetric non-negative tolerance in the
component's units. Omitting it creates an equality.
Returns: A declarative constraint applied without a coordinate conversion.
Source code in octavian/constraints.py
1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 | |
octavian.variables
Decision-variable declarations for composable missions.
ImpulsiveDeltaV
dataclass
Bases: Variable
Declare an impulsive delta-v at a phase boundary.
The composable compiler interprets this variable declaration to free the boundary velocity and add the appropriate objective terms.
Source code in octavian/variables.py
28 29 30 31 32 33 34 35 36 37 38 39 40 | |
Variable
Marker base class for composable decision variables.
Source code in octavian/variables.py
21 22 23 24 25 | |
impulsive_delta_v(*, at: str = 'Front') -> ImpulsiveDeltaV
Create an impulsive delta-v declaration.
Args:
at: Boundary location, such as "Front" or "Back".
Returns: An impulsive delta-v variable declaration.
Source code in octavian/variables.py
43 44 45 46 47 48 49 50 51 52 | |
octavian.objectives
Objective declarations for missions.
MinimizeDeltaV
dataclass
Bases: Objective
Minimize the sum of impulsive maneuver magnitudes.
Source code in octavian/objectives.py
20 21 22 23 24 | |
MinimizePropellant
dataclass
Bases: Objective
Minimize propellant consumed by finite-thrust phases.
Source code in octavian/objectives.py
34 35 36 37 38 | |
MinimizeTime
dataclass
Bases: Objective
Minimize total time of flight.
Source code in octavian/objectives.py
27 28 29 30 31 | |
Objective
dataclass
Base class for user-facing mission objectives.
Source code in octavian/objectives.py
8 9 10 11 12 13 14 15 16 17 | |
minimize_propellant(weight: float = 1.0) -> MinimizePropellant
Create a total propellant-use objective.
The compiler applies this objective once, to the final mass state in the powered phase chain. This avoids double-counting mass across multiple burn phases while remaining equivalent to maximizing final spacecraft mass.
Args: weight: Scalar weight applied by the solver backend.
Returns: A propellant objective declaration.
Source code in octavian/objectives.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
minimize_total_delta_v(weight: float = 1.0) -> MinimizeDeltaV
Create a total delta-v objective.
Args: weight: Scalar weight applied by the solver backend.
Returns: A delta-v objective declaration.
Source code in octavian/objectives.py
41 42 43 44 45 46 47 48 49 50 | |
minimize_total_time(weight: float = 1.0) -> MinimizeTime
Create a total time-of-flight objective.
Args: weight: Scalar weight applied by the solver backend.
Returns: A time objective declaration.
Source code in octavian/objectives.py
53 54 55 56 57 58 59 60 61 62 | |
octavian.guesses
Typed initial-guess declarations for mission phases.
LowThrustSpiralGuess
dataclass
Configure a near-circular tangential spiral initial guess.
Args:
throttle: Constant throttle magnitude used only to integrate the seed.
direction: "auto" chooses prograde for raising and retrograde for
lowering. The direction may also be specified explicitly.
steps_per_orbit: Minimum RK4 integration steps per initial orbit.
time_scale: Multiplier on the circular-spiral burn-time estimate before
it is clamped to the phase time bounds.
Source code in octavian/guesses.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
TrajectoryGuess
dataclass
Provide an explicit dense state/time history to seed a phase.
Rows contain at least [x, y, z, vx, vy, vz, time]. Extra columns are
retained for phase formulations that carry additional states or controls.
Times must be strictly increasing.
Source code in octavian/guesses.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
low_thrust_spiral(*, throttle: float = 0.8, direction: str = 'auto', steps_per_orbit: int = 120, time_scale: float = 1.0) -> LowThrustSpiralGuess
Create a tangential low-thrust spiral seed declaration.
Source code in octavian/guesses.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
trajectory(rows: ArrayLike) -> TrajectoryGuess
Create an explicit dense trajectory seed declaration.
Source code in octavian/guesses.py
92 93 94 | |
octavian.links
Phase-linking semantics for composable missions.
Link
dataclass
Describe continuity requirements across a phase boundary.
Source code in octavian/links.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
is_continuous() -> bool
Return whether the link enforces full state continuity.
Source code in octavian/links.py
20 21 22 | |
is_impulsive() -> bool
Return whether the link allows a boundary velocity jump.
Source code in octavian/links.py
16 17 18 | |
continuous(*, name: str = 'continuous') -> Link
Create a continuous link between phases.
Args: name: Human-readable name for the link object.
Returns: A link that enforces continuity in position, velocity, and time.
Source code in octavian/links.py
25 26 27 28 29 30 31 32 33 34 | |
impulsive(*, dv_max_mps: float | None = None, name: str = 'impulsive') -> Link
Create an impulsive link between phases.
Args: dv_max_mps: Optional delta-v cap metadata for the link. name: Human-readable name for the link object.
Returns: A link that enforces continuity in position and time while allowing a velocity jump at the boundary.
Notes:
In v0.x solvers, delta-v is represented implicitly by allowing
front/back boundary velocities to differ and optionally adding a
delta-v objective term. If dv_max_mps is provided, current solvers
treat it as soft metadata unless a solver adds an explicit hard bound.
Source code in octavian/links.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
octavian.events
Boundary-event declarations for phases.
BoundaryEvent
Marker base class for boundary events.
Source code in octavian/events.py
21 22 23 24 25 | |
Impulse
dataclass
Bases: BoundaryEvent
Declare an impulsive event at a phase boundary.
Source code in octavian/events.py
28 29 30 31 32 33 34 35 36 37 | |
impulse(where: str, dv_max_mps: float | None = None) -> Impulse
Create an impulsive boundary event.
Args:
where: Boundary location, such as "Front" or "Back".
dv_max_mps: Optional delta-v cap metadata for the event.
Returns: An impulse event declaration.
Source code in octavian/events.py
40 41 42 43 44 45 46 47 48 49 50 | |
octavian.control
User-facing finite-thrust direction and kinematic-attitude configuration.
ThrustControl
dataclass
Configure how a finite-thrust phase represents its direction.
vector preserves Octavian's original three-component vector-throttle
control while allowing those components to be expressed in inertial or RIC
axes. fixed removes direction from the decision vector and optimizes
only scalar throttle along a prescribed direction. euler adds
yaw-pitch-roll kinematic states and angular-rate controls; it does not model
torque, inertia, or six-degree-of-freedom rotational dynamics.
Euler angles use a 3-2-1 yaw-pitch-roll convention relative to frame.
The vehicle body +X axis is the thrust axis. Roll is therefore retained for
attitude continuity and constraints even though it does not change the
translational thrust direction.
Args:
representation: "vector", "fixed", or "euler".
frame: Reference axes for the direction or Euler angles. Common
inertial/ECI and RIC/RTN/LVLH spellings are accepted.
direction: Fixed direction components; valid only for "fixed".
initial_angles_rad: Initial yaw, pitch, and roll for Euler control.
max_slew_rate_radps: Maximum magnitude of the Euler-angle-rate vector.
yaw_bounds_rad: Path bounds for yaw.
pitch_bounds_rad: Path bounds for pitch.
roll_bounds_rad: Path bounds for roll.
Source code in octavian/control.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
carries_attitude: bool
property
Return whether this representation adds Euler attitude states.
euler(*, frame: str = 'inertial', initial_angles_rad: Sequence[float] = (0.0, 0.0, 0.0), max_slew_rate_radps: float = math.radians(1.0), yaw_bounds_rad: Sequence[float] = (-math.pi, math.pi), pitch_bounds_rad: Sequence[float] = (-0.5 * math.pi, 0.5 * math.pi), roll_bounds_rad: Sequence[float] = (-math.pi, math.pi)) -> ThrustControl
classmethod
Create yaw-pitch-roll states with bounded angular-rate controls.
Args: frame: Reference frame for the 3-2-1 Euler angles. initial_angles_rad: Initial yaw, pitch, and roll in radians. max_slew_rate_radps: Maximum Euler-rate-vector magnitude. yaw_bounds_rad: Lower and upper yaw path bounds. pitch_bounds_rad: Lower and upper pitch path bounds. roll_bounds_rad: Lower and upper roll path bounds.
Returns: A kinematic-attitude scalar-throttle configuration.
Source code in octavian/control.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
fixed(direction: Sequence[float], *, frame: str = 'inertial') -> ThrustControl
classmethod
Create a prescribed direction with optimized scalar throttle.
Args:
direction: Non-zero direction components in frame. The vector
is normalized automatically.
frame: Reference frame for direction.
Returns: A fixed-direction scalar-throttle configuration.
Source code in octavian/control.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
to_dict() -> dict[str, object]
Return JSON-serializable control metadata for solution reports.
Source code in octavian/control.py
167 168 169 | |
vector(*, frame: str = 'inertial') -> ThrustControl
classmethod
Create a free three-component vector-throttle control.
Args: frame: Frame in which the optimizer's vector components are expressed.
Returns: A vector-throttle configuration.
Source code in octavian/control.py
88 89 90 91 92 93 94 95 96 97 98 99 | |
euler_thrust_direction(angles_rad: Sequence[float]) -> np.ndarray
Return the body +X thrust direction in the Euler reference frame.
Args:
angles_rad: [yaw, pitch, roll] using the 3-2-1 convention.
Returns: Unit direction components in the configured attitude reference frame.
Source code in octavian/control.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
Models
octavian.models
High-level configuration models.
These classes exist to keep user scripts readable while still allowing advanced solving behavior (continuation / retries) via sensible defaults.
Dynamics
dataclass
Environment and dynamics configuration.
model selects an alternate translational model such as CWH. frame
records the meaning of Cartesian states throughout compilation and
reporting. scaling optionally overrides the solver's automatic
characteristic units while preserving SI inputs and outputs.
cr3bp_dimensional records whether a CR3BP phase uses SI or canonical
variables and is set by :meth:Dynamics.cr3bp.
A spherical-harmonic field with published GM supplies mu_m3ps2
automatically, taking precedence over general central-body constants.
third_body_table_margin_s extends Sun/Moon and solar-geometry tables
beyond the mission's cumulative absolute upper time bound.
Source code in octavian/models.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
active_perturbations() -> Perturbations
Return normalized perturbation flags for solver compilation.
Source code in octavian/models.py
306 307 308 309 310 311 312 313 314 315 316 317 | |
cr3bp(*, primary: CelestialBody | str = 'earth', secondary: CelestialBody | str = 'moon', separation_m: float = 384400000.0, dimensional: bool = True, **kwargs: Any) -> Dynamics
classmethod
Create barycentric-synodic CR3BP dynamics.
Args:
primary: More massive body or catalog name.
secondary: Less massive body or catalog name.
separation_m: Constant circular body separation.
dimensional: Use SI states and seconds when true. Set false to
solve directly with canonical CR3BP states and time units.
**kwargs: Additional :class:Dynamics metadata. Perturbations are
not supported by this first-order CR3BP model.
Returns: Dynamics configured for the selected CR3BP units and a synodic frame.
Source code in octavian/models.py
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | |
cwh(*, chief_orbit_radius_m: float, central_body: CelestialBody | str = 'earth', chief_name: str = 'chief', reference_length_m: float = 1000.0, chief_initial_state_eci: BoundaryState | None = None, **kwargs: Any) -> Dynamics
classmethod
Create circular-chief Clohessy-Wiltshire relative dynamics.
Source code in octavian/models.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
for_body(body: CelestialBody | str, **kwargs: Any) -> Dynamics
classmethod
Create dynamics from a built-in or custom central body.
Body constants intentionally override raw mu_m3ps2, radius, and J2
keyword values so a named body cannot silently become inconsistent.
Source code in octavian/models.py
154 155 156 157 158 159 160 161 162 | |
relative(*, chief_initial_state_eci: BoundaryState, central_body: CelestialBody | str = 'earth', chief_name: str = 'chief', chief_spacecraft: Spacecraft | None = None, reference_length_m: float = 1000.0, propagation_mode: str = 'coupled_eci', **kwargs: Any) -> Dynamics
classmethod
Create nonlinear or relative-element dynamics.
Args:
chief_initial_state_eci: Absolute chief state defining the RIC frame.
central_body: Central body name or object.
chief_name: Name used for the returned chief-centered frame.
chief_spacecraft: Optional chief mass and cannonball properties.
Omit it to model a gravity-only chief while drag or SRP acts
on the phase spacecraft (the deputy).
reference_length_m: Characteristic relative distance for scaling.
propagation_mode: One of "coupled_eci" (default),
"coupled_ric", "nonlinear_ric", "damico", or
"classical_elements". Select "coupled_eci" for J2,
third-body perturbations, or finite-thrust relative phases.
**kwargs: Additional :class:Dynamics configuration.
Returns: A dynamics configuration whose public reporting frame is RIC.
Source code in octavian/models.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
Perturbations
dataclass
Perturbation flags for translational dynamics.
The composable ASSET backend supports the core Earth-orbit perturbations:
J2 or a spherical-harmonic field, lunar and solar third-body gravity,
exponential-atmosphere cannonball
drag, and cannonball solar radiation pressure. moon and sun are
convenience flags; third_bodies=("moon", "sun") remains accepted for
scripts that prefer a body list.
Args:
j2: Enable central-body J2.
spherical_harmonics: Fully normalized gravity field; mutually exclusive with j2.
moon: Enable lunar third-body gravity.
sun: Enable solar third-body gravity.
srp: Enable cannonball solar radiation pressure. This does not
implicitly enable solar third-body gravity.
drag: Enable exponential-atmosphere cannonball drag.
third_bodies: Additional normalized third-body gravity names.
atmosphere: Atmosphere used by drag. None selects Octavian's
simple Earth model for Earth-centered dynamics; non-Earth central
bodies must supply a model explicitly.
solar_pressure_at_1au_Npm2: Radiation pressure at one astronomical unit.
Source code in octavian/models.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
active_third_bodies() -> tuple[str, ...]
Return normalized third-body names requested by this config.
Source code in octavian/models.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
RetryPolicy
dataclass
Retry behavior when a solve fails.
Source code in octavian/models.py
350 351 352 353 354 355 356 357 358 359 360 | |
default() -> RetryPolicy
staticmethod
Return the default enabled retry policy.
Source code in octavian/models.py
357 358 359 360 | |
RunPlan
dataclass
Continuation / crawl-walk-run plan.
Source code in octavian/models.py
338 339 340 341 342 343 344 345 346 347 | |
default() -> RunPlan
staticmethod
Return an empty continuation plan.
Source code in octavian/models.py
344 345 346 347 | |
SolveConfig
dataclass
Runner behavior settings.
Source code in octavian/models.py
320 321 322 323 324 325 326 | |
Stage
dataclass
A single continuation stage (minimal in v0.x).
Source code in octavian/models.py
329 330 331 332 333 334 335 | |
TranslationalModel
Bases: Protocol
Configuration contract for non-default translational dynamics models.
Source code in octavian/models.py
23 24 25 26 27 28 29 30 31 32 33 34 | |
frame: CoordinateFrame
property
Return the coordinate frame used by the model.
scaling: SolverScaling
property
Return the model's recommended solver scaling.
octavian.gravity
Fully normalized spherical-harmonic gravity in a uniformly rotating body frame.
Coefficients use geodetic normalization, without the Condon--Shortley phase: Pbar_nm = sqrt((2-delta_m0)(2n+1)*(n-m)!/(n+m)!) * P_nm. Only degrees 2 and above are perturbations; central gravity is supplied by the EOM.
SphericalHarmonics
dataclass
A central body's static, fully normalized gravity coefficients.
cosine[n][m] and sine[n][m] are dimensionless Cbar/Sbar arrays.
Supply square arrays, including zero entries above the diagonal. C00 may
be 0 or 1 and is ignored; degree one must be zero (center-of-mass origin).
For J2 alone, Cbar20 = -J2 / sqrt(5).
The body rotates about the inertial +Z axis. Its prime-meridian angle is
reference_angle_rad + rotation_rate_radps * (time_s-reference_time_s).
Times are mission-relative seconds, not UTC or SPICE epochs. This simple
model does not include precession, nutation, polar motion, or tidal changes.
The coefficient reference radius is independent of the body's mean radius;
a field with a published GM supplies that constant to both central and
harmonic gravity. Custom fields without GM use the EOM parameter.
backend='python' builds ASSET expressions using the same recurrence as
numerical evaluation. backend='cpp' (the default) uses the bundled native extension
with analytic derivatives, without Python callbacks during integration.
Degree/order default to the full supplied array. Use SphericalHarmonics.earth()
to load the bundled measured EGM2008 field through 200x200.
Source code in octavian/gravity.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
acceleration(position_m, *, mu_m3ps2: float | None = None, time_s: float = 0.0)
Return perturbing acceleration in m/s², using the field GM when available.
Source code in octavian/gravity.py
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
asset_acceleration(position, time, *, mu_m3ps2: float | None = None)
Compose an ASSET inertial acceleration, including rotation derivatives.
Source code in octavian/gravity.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
earth(*, degree: int = 200, order: int | None = None, backend: str = 'cpp', rotation_rate_radps: float = 7.292115e-05, reference_angle_rad: float = 0.0, reference_time_s: float = 0.0)
classmethod
Load NGA EGM2008 (tide-free), offline, truncated to at most 200x200.
No coefficient calculations or downloads are needed. Central and harmonic gravity automatically use the model's published GM. Set the prime-meridian angle at the mission epoch explicitly; rotation is uniform about Z, not a full ITRF model.
Source code in octavian/gravity.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
resolve_mu(mu_m3ps2: float | None = None) -> float
Use the field's published GM, or the supplied GM for a custom field.
Published coefficients and GM define one gravity model. A model GM takes precedence over general central-body defaults and EOM arguments.
Source code in octavian/gravity.py
139 140 141 142 143 144 145 146 147 148 149 150 | |
octavian.bodies.catalog
Small, explicit catalog of central-body physical constants.
CelestialBody
dataclass
Physical constants and naming metadata for a central body.
Source code in octavian/bodies/catalog.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
inertial_frame(*, orientation: str | None = None) -> CoordinateFrame
Return an inertial frame centered on this body.
Source code in octavian/bodies/catalog.py
47 48 49 50 51 52 53 | |
resolve(body: CelestialBody | str) -> CelestialBody
Resolve a body object or case-insensitive catalog name.
Source code in octavian/bodies/catalog.py
94 95 96 97 98 99 100 101 102 103 | |
octavian.spacecraft
Spacecraft and propulsion models.
These objects are intentionally "config-like": they are meant to read well in Python scripts and to remain stable even as solver backends evolve.
Spacecraft
dataclass
Spacecraft mass, propulsion, and simple force-model properties.
Args: name: Human-readable spacecraft name. dry_mass_kg: Dry mass in kilograms. thrusters: Available propulsion models. info: Free-form user metadata. cannonball: Constant projected areas and coefficients used when drag or solar radiation pressure is enabled.
Source code in octavian/spacecraft.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
initial_mass_kg: float
property
Return dry mass plus configured propellant masses.
| Returns: |
|
|---|
get_thruster(name: str) -> Thruster | None
Return a named thruster if it exists.
| Parameters: |
|
|---|
| Returns: |
|
|---|
Source code in octavian/spacecraft.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
thruster(name: str) -> Thruster
Return a named thruster.
| Parameters: |
|
|---|
| Returns: |
|
|---|
| Raises: |
|
|---|
Source code in octavian/spacecraft.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
Thruster
dataclass
Simple thruster model (data-only).
Source code in octavian/spacecraft.py
15 16 17 18 19 20 21 22 23 | |
octavian.forces
Simple non-gravitational force models.
The models in this module are deliberately small and explicit. They provide useful first-order drag and solar-radiation-pressure behavior without implying high-fidelity atmosphere, geometry, shadowing, or attitude modeling.
Cannonball
dataclass
Spacecraft properties for simple drag and SRP acceleration.
Areas are projected constant areas. They do not vary with attitude. A zero area produces no corresponding acceleration. Composable phases require a positive area on their primary spacecraft when that force is enabled, while an optional relative chief may intentionally keep zero area.
Args:
drag_area_m2: Constant projected area used by atmospheric drag.
drag_coefficient: Dimensionless drag coefficient.
srp_area_m2: Constant projected area used by solar radiation pressure.
reflectivity_coefficient: Dimensionless SRP coefficient, commonly
called Cr.
Source code in octavian/forces.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
ExponentialAtmosphere
dataclass
Single-scale-height co-rotating atmosphere.
Density follows
rho(h) = reference_density * exp(-(h - reference_altitude) / scale_height).
The rotation rate defines the atmosphere velocity as omega × r in the
central-body inertial frame. This is a screening and preliminary-design
model, not a substitute for a space-weather-driven atmosphere.
Args:
reference_density_kgpm3: Density at reference_altitude_m.
reference_altitude_m: Reference altitude above the central body.
scale_height_m: Constant density scale height.
rotation_rate_radps: Central-body atmosphere rotation rate about +Z.
Source code in octavian/forces.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
density_kgpm3(altitude_m: float) -> float
Return atmospheric density at an altitude in meters.
The exponent is clipped only to keep exploratory numerical propagation finite far outside the model's useful altitude range.
Source code in octavian/forces.py
131 132 133 134 135 136 137 138 139 140 141 | |
cannonball_drag_acceleration(position_m: ArrayLike, velocity_mps: ArrayLike, *, mass_kg: float, central_body_radius_m: float, cannonball: Cannonball, atmosphere: ExponentialAtmosphere = EARTH_EXPONENTIAL_ATMOSPHERE) -> NDArray[np.float64]
Return simple cannonball drag acceleration in an inertial frame.
Args: position_m: Central-body inertial position. velocity_mps: Central-body inertial velocity. mass_kg: Instantaneous spacecraft mass. central_body_radius_m: Radius used to convert position to altitude. cannonball: Spacecraft projected area and drag coefficient. atmosphere: Exponential, co-rotating atmosphere model.
Returns: Three-component inertial acceleration in m/s².
Source code in octavian/forces.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
cannonball_srp_acceleration(position_m: ArrayLike, sun_position_m: ArrayLike, *, mass_kg: float, cannonball: Cannonball, solar_pressure_at_1au_Npm2: float = SOLAR_PRESSURE_AT_1_AU_NPM2) -> NDArray[np.float64]
Return cannonball solar-radiation-pressure acceleration.
The acceleration points away from the Sun and varies with inverse-square distance. This first-order model intentionally omits eclipses and penumbra transitions.
Args: position_m: Spacecraft position in a central-body inertial frame. sun_position_m: Sun position in the same frame. mass_kg: Instantaneous spacecraft mass. cannonball: Spacecraft projected area and reflectivity coefficient. solar_pressure_at_1au_Npm2: Radiation pressure at one astronomical unit.
Returns: Three-component inertial acceleration in m/s².
Source code in octavian/forces.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | |
octavian.dynamics
Dynamics models.
Octavian's primary optimal-control backend is ASSET. To keep the rest of the package importable (for utilities, studies, and result I/O), ASSET is treated as an optional runtime dependency at import time.
If ASSET is not installed, constructing ASSET-backed dynamics will raise a clear error, but importing this module will still succeed.
FiniteThrustECI
Bases: ODEBase if oc is not None else object
Finite-thrust dynamics with configurable direction representation.
The default retains the original three-component inertial vector-throttle control. RIC vectors are rotated into inertial coordinates from the current state. Fixed direction uses one scalar throttle. Euler mode augments the state with yaw, pitch, and roll and uses throttle plus three angular rates.
Source code in octavian/dynamics.py
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | |
MassCoastECI
Bases: ODEBase if oc is not None else object
Ballistic coast dynamics carrying spacecraft mass as a constant state.
This ODE is used between finite-burn phases so ASSET continuity links can preserve the spacecraft mass state across burn-coast-burn transfers. The mass derivative is identically zero; translational acceleration still uses the configured gravity and perturbation model. A phase using Euler thrust control also carries its kinematic attitude through the coast.
Source code in octavian/dynamics.py
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 | |
PerturbedECI
Bases: ODEBase if oc is not None else object
Point-mass gravity with optional perturbation accelerations.
Currently implemented perturbations: - J2 zonal harmonic or a fully normalized spherical-harmonic field - Sun and Moon third-body point-mass gravity through interpolation tables - Exponential-atmosphere cannonball drag - Cannonball solar radiation pressure
The state is [r(3), v(3)]. Time remains ASSET's phase time variable, not
a state, which is why ephemeris tables are sampled with XtU.TVar().
Spacecraft mass is constant in this coast formulation.
Source code in octavian/dynamics.py
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | |
ThirdBodyTable
dataclass
Interpolated third-body ephemeris used by ASSET dynamics.
Attributes:
name: Normalized body name, currently "sun" or "moon".
mu_m3ps2: Gravitational parameter for the third body in SI units.
position_table: ASSET vector function that returns the body's
Earth-centered position in meters at the current phase time.
times_s: Optional numeric sample times used for result conversion.
positions_eci_m: Optional numeric positions paired with times_s.
Source code in octavian/dynamics.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
position_at(time_s: float) -> NDArray[np.float64]
Interpolate position, clipping endpoint time roundoff up to 1e-8 s.
Source code in octavian/dynamics.py
58 59 60 61 62 63 64 65 66 67 68 | |
TwoBodyECI
Bases: ODEBase if oc is not None else object
Two-body point-mass gravity in ECI.
backend="cpp" (default) uses ASSET's specialized C++ Kepler
integrator for propagation. backend="expression" uses the generic
ASSET expression integrator. Both run without Python force callbacks;
phase construction retains the existing expressions and variable groups.
ODE state has 6 components: [r(3), v(3)].
Time is the phase time variable (ODEArguments.TVar()), not a state component.
Vgroups:
- R: position (3)
- V: velocity (3)
- t: phase time variable
Source code in octavian/dynamics.py
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | |
integrator(*args)
Create an ASSET integrator with step_s or method, step_s.
The C++ backend specializes the complete adaptive integration loop
for point-mass dynamics. The returned integrator supports ASSET's
existing tolerance controls, integrate, and integrate_dense.
Source code in octavian/dynamics.py
497 498 499 500 501 502 503 504 505 506 | |
gravity_acceleration_components(position_m: ArrayLike, *, time_s: float = 0.0, mu_m3ps2: float, include_j2: bool = False, spherical_harmonics: SphericalHarmonics | None = None, central_body_radius_m: float = 6378136.3, j2_coefficient: float = 0.00108262668, third_body_tables: Sequence[ThirdBodyTable] = ()) -> NDArray[np.float64]
Evaluate the full configured acceleration numerically.
This is the numeric counterpart of :func:_gravity_acceleration. It is
used when converting solved coupled chief/deputy histories to the
instantaneous RIC frame, where the chief acceleration determines the
frame's cross-track angular rate.
Source code in octavian/dynamics.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
j2_acceleration_components(position_m, *, mu_m3ps2: float, radius_m: float = 6378136.3, j2: float = 0.00108262668)
Return the Cartesian J2 acceleration components for an ECI position.
This follows the standard oblate-body acceleration model used by the ASSET vector-function implementation below, and is intentionally numpy-free so it can be used in lightweight validation tests.
Source code in octavian/dynamics.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
third_body_acceleration_components(spacecraft_position_m, body_position_m, *, mu_m3ps2: float)
Return third-body acceleration in an Earth-centered frame.
The expression includes both the third body's gravity on the spacecraft and the same body's gravity on the Earth-centered frame origin. It mirrors the ASSET vector-function implementation used by coast and burn EOMs.
Source code in octavian/dynamics.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
translational_acceleration_components(position_m: ArrayLike, velocity_mps: ArrayLike, *, time_s: float = 0.0, mass_kg: float, mu_m3ps2: float, include_j2: bool = False, spherical_harmonics: SphericalHarmonics | None = None, central_body_radius_m: float = 6378136.3, j2_coefficient: float = 0.00108262668, third_body_tables: Sequence[ThirdBodyTable] = (), include_drag: bool = False, include_srp: bool = False, cannonball: Cannonball | None = None, atmosphere: ExponentialAtmosphere | None = None, sun_table: ThirdBodyTable | None = None, solar_pressure_at_1au_Npm2: float = SOLAR_PRESSURE_AT_1_AU_NPM2) -> NDArray[np.float64]
Evaluate gravity plus optional cannonball drag and SRP numerically.
This function is the numerical counterpart of the common ASSET force expression. It is used by relative propagation and by RIC conversion, where the chief acceleration determines the instantaneous frame rate.
Args: position_m: Central-body inertial position. velocity_mps: Central-body inertial velocity. time_s: Mission-relative time used by ephemeris tables. mass_kg: Instantaneous spacecraft mass. mu_m3ps2: Central-body gravitational parameter. include_j2: Include central-body J2. spherical_harmonics: Optional normalized gravity field, mutually exclusive with J2. central_body_radius_m: Central-body radius. j2_coefficient: Central-body J2 coefficient. third_body_tables: Gravity ephemeris tables. include_drag: Include exponential-atmosphere drag. include_srp: Include cannonball solar radiation pressure. cannonball: Spacecraft area and coefficient properties. atmosphere: Required when drag is enabled. sun_table: Required when SRP is enabled. solar_pressure_at_1au_Npm2: Radiation pressure at one AU.
Returns: Three-component inertial acceleration in m/s².
Source code in octavian/dynamics.py
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
octavian.coordinates.frames
Reference-frame metadata carried by dynamics and solved trajectories.
CoordinateFrame
dataclass
Describe the origin and orientation used by a trajectory.
This object is metadata, not a coordinate transformation by itself. Frame transformation services are added alongside dynamics that need them, while every solver result can already state what its coordinates mean.
Source code in octavian/coordinates/frames.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
from_dict(value: dict[str, str]) -> CoordinateFrame
classmethod
Reconstruct frame metadata stored in a result archive.
Source code in octavian/coordinates/frames.py
38 39 40 41 42 43 44 45 46 | |
to_dict() -> dict[str, str]
Return JSON-serializable frame metadata.
Source code in octavian/coordinates/frames.py
34 35 36 | |
inertial(origin: str, *, orientation: str = 'ICRF', name: str | None = None) -> CoordinateFrame
Create an inertial Cartesian frame centered on origin.
Source code in octavian/coordinates/frames.py
49 50 51 52 53 54 55 56 57 | |
lvlh(chief: str = 'chief', *, name: str | None = None) -> CoordinateFrame
Create a chief-centered local-vertical/local-horizontal frame.
The orientation follows the RTN convention used by Octavian's relative dynamics: x is radial, y is along track, and z is orbit normal.
Source code in octavian/coordinates/frames.py
60 61 62 63 64 65 66 67 68 69 70 71 72 | |
ric(chief: str = 'chief', *, name: str | None = None) -> CoordinateFrame
Create a chief-centered radial/in-track/cross-track frame.
RIC, RTN, and the LVLH convention used by Octavian describe the same
right-handed axes: radial R points away from the central body,
in-track I follows the chief's motion, and cross-track C follows
the chief's angular momentum. This named constructor lets mission scripts
use the terminology most common in relative-motion analysis.
Source code in octavian/coordinates/frames.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | |
synodic(primary: str, secondary: str, *, name: str | None = None) -> CoordinateFrame
Create a barycentric primary-secondary rotating frame.
The +X axis points from primary to secondary and +Z follows the circular system angular momentum.
Source code in octavian/coordinates/frames.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
octavian.coordinates.layouts
Named state and control layouts used at the compiler boundary.
StateLayout
dataclass
Describe state/control columns without hard-coded solver indices.
Group indices refer to either state or control columns. Time remains the
ASSET phase-time column immediately after the state columns and is exposed
through :attr:time_column.
Source code in octavian/coordinates/layouts.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
control_dim: int
property
Return the number of controls.
state_dim: int
property
Return the number of differential states.
time_column: int
property
Return the trajectory column containing phase time.
control_indices(group: str) -> tuple[int, ...]
Return control indices for a named semantic group.
Source code in octavian/coordinates/layouts.py
50 51 52 | |
public_rvt_columns() -> tuple[int, ...]
Return position, velocity, and time columns for Cartesian reporting.
Source code in octavian/coordinates/layouts.py
54 55 56 | |
state_indices(group: str) -> tuple[int, ...]
Return state indices for a named semantic group.
Source code in octavian/coordinates/layouts.py
46 47 48 | |
octavian.coordinates.scaling
Characteristic scaling metadata for dimensional solver problems.
SolverScaling
dataclass
Characteristic units used to condition one compiled problem.
Source code in octavian/coordinates/scaling.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
acceleration_mps2: float
property
Return the implied characteristic acceleration.
force_N: float
property
Return the implied characteristic force.
to_dict() -> dict[str, float]
Return JSON-serializable scaling metadata.
Source code in octavian/coordinates/scaling.py
34 35 36 | |
octavian.relative.cwh
Clohessy-Wiltshire dynamics for motion near a circular chief orbit.
ClohessyWiltshire
dataclass
Linear time-invariant relative dynamics about a circular chief.
States use a chief-centered LVLH/RTN frame with radial x, along-track y,
and orbit-normal z. reference_length_m controls numerical scaling; it
is not a validity limit for the linear model.
Source code in octavian/relative/cwh.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
frame: CoordinateFrame
property
Return the LVLH frame in which this model's states are expressed.
scaling: SolverScaling
property
Return physically consistent characteristic units for this model.
from_circular_orbit(radius_m: float, *, body: CelestialBody = EARTH, chief_name: str = 'chief', reference_length_m: float = 1000.0, chief_initial_state_eci: BoundaryState | None = None) -> ClohessyWiltshire
classmethod
Construct CWH parameters from a circular chief-orbit radius.
Source code in octavian/relative/cwh.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
cwh_derivative(state: ArrayLike, mean_motion_radps: float) -> StateVector
Evaluate the six-state unforced CWH differential equation.
Source code in octavian/relative/cwh.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
cwh_rendezvous_velocity(initial_position_m: ArrayLike, final_position_m: ArrayLike, tof_s: float, mean_motion_radps: float) -> StateVector
Return the initial velocity that connects two CWH positions in time.
Source code in octavian/relative/cwh.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
cwh_state_transition(dt_s: float, mean_motion_radps: float) -> StateMatrix
Return the analytic 6x6 CWH state-transition matrix.
Source code in octavian/relative/cwh.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | |
propagate_cwh(state: ArrayLike, dt_s: float, mean_motion_radps: float) -> StateVector
Propagate one relative state with the analytic CWH solution.
Source code in octavian/relative/cwh.py
158 159 160 161 162 | |
octavian.relative.transforms
Cartesian inertial and chief-centered RIC state transformations.
Octavian uses the common RIC/RTN/LVLH convention: radial, in-track, and cross-track axes. State transforms include the rotating-frame velocity term; simply rotating an inertial velocity difference is not a valid relative velocity transformation.
absolute_to_relative_history(chief_history: ArrayLike, deputy_history: ArrayLike, *, chief_acceleration_history_mps2: ArrayLike | None = None) -> StateHistory
Convert matching absolute histories to [rho_RIC, rho_dot_RIC, t].
Input rows may contain either six state columns or seven columns with time. If time is present in both histories, values must match and are preserved.
Source code in octavian/relative/transforms.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | |
absolute_to_relative_state(chief: BoundaryState, deputy: BoundaryState, *, chief_acceleration_mps2: ArrayLike | None = None) -> BoundaryState
Alias for :func:inertial_to_relative_state with explicit terminology.
Source code in octavian/relative/transforms.py
118 119 120 121 122 123 124 125 126 127 128 129 | |
chief_ric_angular_velocity(chief: BoundaryState, chief_acceleration_mps2: ArrayLike | None = None) -> NDArray[np.float64]
Return the chief RIC frame angular velocity expressed in RIC.
With chief acceleration, the result is [r*a_C/h, 0, h/r²] and includes
orbit-plane rotation caused by cross-track acceleration. Omitting
acceleration assumes a fixed orbit plane.
Source code in octavian/relative/transforms.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
inertial_to_relative_state(chief: BoundaryState, deputy: BoundaryState, *, chief_acceleration_mps2: ArrayLike | None = None) -> BoundaryState
Transform a deputy inertial state to the chief's instantaneous RIC frame.
Source code in octavian/relative/transforms.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
lvlh_basis(chief_position_m: ArrayLike, chief_velocity_mps: ArrayLike) -> Matrix3
Return the inertial-to-LVLH/RTN matrix.
This compatibility name is exactly equivalent to :func:ric_basis.
Source code in octavian/relative/transforms.py
42 43 44 45 46 47 | |
relative_to_absolute_history(chief_history: ArrayLike, relative_history: ArrayLike, *, chief_acceleration_history_mps2: ArrayLike | None = None) -> StateHistory
Reconstruct deputy absolute history from matching chief and RIC rows.
Input rows may contain either six state columns or seven columns with time. If time is present in both histories, values must match and are preserved.
Source code in octavian/relative/transforms.py
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
relative_to_absolute_state(chief: BoundaryState, relative: BoundaryState, *, chief_acceleration_mps2: ArrayLike | None = None) -> BoundaryState
Return the reconstructed deputy absolute Cartesian state.
Source code in octavian/relative/transforms.py
132 133 134 135 136 137 138 139 140 141 142 143 | |
relative_to_inertial_state(chief: BoundaryState, relative: BoundaryState, *, chief_acceleration_mps2: ArrayLike | None = None) -> BoundaryState
Transform a chief-centered RIC state to inertial Cartesian coordinates.
Source code in octavian/relative/transforms.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
ric_basis(chief_position_m: ArrayLike, chief_velocity_mps: ArrayLike) -> Matrix3
Return the inertial-to-RIC direction-cosine matrix.
Matrix rows are radial, in-track, and cross-track unit vectors. Left multiplication therefore rotates an inertial vector into RIC coordinates; the transpose rotates a RIC vector back to inertial coordinates.
Source code in octavian/relative/transforms.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
octavian.relative.elements
Relative orbital-element types, conversions, and two-body propagation.
ClassicalRelativeOrbitalElements
dataclass
Differences between deputy and chief classical orbital elements.
The vector is [Δa, Δe, Δi, ΔΩ, Δω, ΔM]. Δa is meters and all
angular differences are radians. This representation is intuitive but
inherits the circular/equatorial singularities of classical elements; use
:class:RelativeOrbitalElements for D'Amico's quasi-nonsingular form.
Source code in octavian/relative/elements.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
as_vector() -> NDArray[np.float64]
Return [Δa, Δe, Δi, ΔΩ, Δω, ΔM] in meters/radians.
Source code in octavian/relative/elements.py
97 98 99 100 101 102 103 104 105 106 107 108 109 | |
from_vector(values: ArrayLike) -> ClassicalRelativeOrbitalElements
classmethod
Construct classical relative elements from a six-value vector.
Source code in octavian/relative/elements.py
111 112 113 114 | |
RelativeElementPropagationResult
dataclass
Paired osculating-element and RIC histories from one propagation.
Attributes:
elements: (N, 7) native relative-element and elapsed-time rows.
ric: (N, 7) equivalent RIC Cartesian state and elapsed-time rows.
representation: "damico" or "classical_elements".
Source code in octavian/relative/elements.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
times_s: NDArray[np.float64]
property
Return elapsed output times without copying the history.
RelativeOrbitalElements
dataclass
D'Amico-style quasi-nonsingular relative orbital elements.
The dimensionless/angular vector is [δa, δλ, δex, δey, δix, δiy]:
δa = (a_d - a_c) / a_c;δλ = (u_d - u_c) + (Ω_d - Ω_c) cos(i_c);δex, δeyare differences of eccentricity-vector components;δix = i_d - i_c;δiy = (Ω_d - Ω_c) sin(i_c).
Angles are radians and wrapped to [-π, π) when constructed from
Cartesian states.
Source code in octavian/relative/elements.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
as_vector() -> NDArray[np.float64]
Return [δa, δλ, δex, δey, δix, δiy].
Source code in octavian/relative/elements.py
55 56 57 58 59 60 61 62 63 64 65 66 67 | |
from_vector(values: ArrayLike) -> RelativeOrbitalElements
classmethod
Construct relative orbital elements from a six-value vector.
Source code in octavian/relative/elements.py
69 70 71 72 | |
absolute_to_classical_relative_orbital_elements(chief: BoundaryState, deputy: BoundaryState, *, mu_m3ps2: float) -> ClassicalRelativeOrbitalElements
Convert two absolute Cartesian states to classical element differences.
Source code in octavian/relative/elements.py
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
absolute_to_relative_orbital_elements(chief: BoundaryState, deputy: BoundaryState, *, mu_m3ps2: float) -> RelativeOrbitalElements
Convert chief/deputy absolute Cartesian states to relative elements.
Source code in octavian/relative/elements.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | |
classical_relative_orbital_elements_to_absolute_state(chief: BoundaryState, relative_elements: ClassicalRelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> BoundaryState
Reconstruct the deputy from chief state and classical differences.
Source code in octavian/relative/elements.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
classical_relative_orbital_elements_to_relative_state(chief: BoundaryState, relative_elements: ClassicalRelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> BoundaryState
Convert classical element differences directly to a deputy RIC state.
Source code in octavian/relative/elements.py
366 367 368 369 370 371 372 373 374 375 376 377 378 | |
classical_to_damico_relative_orbital_elements(chief: BoundaryState, relative_elements: ClassicalRelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> RelativeOrbitalElements
Convert classical element differences to D'Amico elements at one epoch.
Source code in octavian/relative/elements.py
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | |
damico_to_classical_relative_orbital_elements(chief: BoundaryState, relative_elements: RelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> ClassicalRelativeOrbitalElements
Convert D'Amico elements to classical differences at one epoch.
Source code in octavian/relative/elements.py
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | |
propagate_relative_element_history(initial_elements: RelativeElements | ArrayLike, times_s: ArrayLike, *, chief_initial_state_eci: BoundaryState, mu_m3ps2: float, representation: str = 'damico', central_body: CelestialBody | str = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> RelativeElementPropagationResult
Propagate relative elements and return both native and RIC histories.
This is the consolidated analysis entry point for relative orbital elements. Perturbed propagation advances the coupled chief/deputy states only once, then derives both output representations from that history. The older representation-specific functions remain available for scripts that need only one array.
Args:
initial_elements: Initial D'Amico or classical relative elements.
times_s: Requested elapsed output times.
chief_initial_state_eci: Chief Cartesian state at elapsed time zero.
mu_m3ps2: Central-body gravitational parameter.
representation: "damico" or "classical_elements".
central_body: Body constants used by numerical perturbations.
perturbations: Optional differential force model.
initial_epoch: UTC or SPICE ET at time zero. Required for Sun, Moon,
or SRP.
max_step_s: Maximum internal RK4 step for numerical propagation.
ephemeris_step_s: Sun/Moon interpolation spacing.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties.
deputy_spacecraft: Deputy mass and cannonball properties, required for
drag or SRP.
Returns: Native relative elements and equivalent RIC states sharing one time vector.
Source code in octavian/relative/elements.py
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | |
propagate_relative_elements_to_ric(initial_elements: RelativeElements | ArrayLike, times_s: ArrayLike, *, chief_initial_state_eci: BoundaryState, mu_m3ps2: float, representation: str = 'damico', central_body: CelestialBody | str = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> NDArray[np.float64]
Propagate relative elements and return equivalent RIC state history.
With perturbations=None this uses analytical two-body element drift and
supports arbitrary finite output times, including negative analysis times.
Supplying :class:octavian.Perturbations selects coupled numerical
chief/deputy propagation; those output times must be strictly monotonic
with zero at one endpoint.
Args:
initial_elements: Initial D'Amico or classical relative elements.
times_s: Requested elapsed output times.
chief_initial_state_eci: Chief Cartesian state at elapsed time zero.
mu_m3ps2: Central-body gravitational parameter.
representation: "damico" or "classical_elements".
central_body: Body constants used by numerical central gravity and J2.
perturbations: Optional differential gravity, drag, and SRP configuration.
initial_epoch: UTC or SPICE ET at time zero. Required for Sun, Moon,
or SRP.
max_step_s: Maximum internal RK4 step for numerical propagation.
ephemeris_step_s: Sun/Moon interpolation spacing.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties.
deputy_spacecraft: Deputy mass and cannonball properties, required for
drag or SRP.
Returns:
An (N, 7) RIC state-and-time history ready for plotting.
Source code in octavian/relative/elements.py
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | |
propagate_relative_orbital_elements(initial_elements: RelativeElements | ArrayLike, times_s: ArrayLike, *, chief_initial_state_eci: BoundaryState, mu_m3ps2: float, representation: str = 'damico', central_body: CelestialBody | str = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> NDArray[np.float64]
Propagate relative elements at requested elapsed times.
The returned rows contain six relative elements followed by elapsed time.
Without perturbations, the fast analytical two-body model keeps every
element constant except D'Amico δλ or classical ΔM. With a
perturbation configuration, the chief and deputy are instead propagated
as coupled absolute states and converted back to osculating relative
elements at every requested output time.
Args:
initial_elements: Initial D'Amico or classical relative elements.
times_s: Finite elapsed output times. Perturbed propagation requires
strictly monotonic values with zero at one endpoint.
chief_initial_state_eci: Chief Cartesian state at elapsed time zero.
mu_m3ps2: Central-body gravitational parameter.
representation: "damico" or "classical_elements".
central_body: Body constants used by numerical central gravity and J2.
perturbations: Optional differential gravity, drag, and SRP configuration.
initial_epoch: UTC or SPICE ET at time zero. Required for Sun, Moon,
or SRP.
max_step_s: Maximum internal RK4 step for numerical propagation.
ephemeris_step_s: Sun/Moon interpolation spacing.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties.
deputy_spacecraft: Deputy mass and cannonball properties, required for
drag or SRP.
Returns:
An (N, 7) array of native element states and time.
Source code in octavian/relative/elements.py
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 | |
propagate_two_body_state(initial_state: BoundaryState, elapsed_time_s: float, mu_m3ps2: float) -> BoundaryState
Propagate an elliptic Cartesian state analytically under two-body gravity.
Source code in octavian/relative/elements.py
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | |
relative_orbital_elements_to_absolute_state(chief: BoundaryState, relative_elements: RelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> BoundaryState
Reconstruct a deputy absolute state from chief state and ROE.
Equatorial chief orbits cannot encode right-ascension separation through
δiy. The conversion accepts them only when δiy is effectively
zero; use Cartesian RIC states when the missing node geometry matters.
Source code in octavian/relative/elements.py
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | |
relative_orbital_elements_to_relative_state(chief: BoundaryState, relative_elements: RelativeOrbitalElements | ArrayLike, *, mu_m3ps2: float) -> BoundaryState
Convert D'Amico relative elements directly to a deputy RIC state.
Source code in octavian/relative/elements.py
336 337 338 339 340 341 342 343 344 345 346 347 348 | |
relative_state_to_classical_relative_orbital_elements(chief: BoundaryState, relative_state_ric: BoundaryState, *, mu_m3ps2: float) -> ClassicalRelativeOrbitalElements
Convert a deputy RIC state to classical orbital-element differences.
Source code in octavian/relative/elements.py
351 352 353 354 355 356 357 358 359 360 361 362 363 | |
relative_state_to_relative_orbital_elements(chief: BoundaryState, relative_state_ric: BoundaryState, *, mu_m3ps2: float) -> RelativeOrbitalElements
Convert a deputy RIC state directly to D'Amico relative elements.
Source code in octavian/relative/elements.py
321 322 323 324 325 326 327 328 329 330 331 332 333 | |
octavian.relative.propagation
Coupled absolute-state propagation for perturbed relative motion.
The public result remains chief-centered RIC, while the numerical integration advances chief and deputy absolute states under the same force model. Taking the difference only after propagation naturally retains differential J2 and third-body accelerations without embedding frame-rotation approximations in the force model.
RelativePropagationResult
dataclass
Coupled chief/deputy propagation histories.
Attributes:
times_s: Elapsed seconds from the supplied initial states.
chief_states_eci: Absolute chief states with shape (N, 6).
deputy_states_eci: Absolute deputy states with shape (N, 6).
relative_states_ric: Deputy-minus-chief RIC states with shape (N, 6).
Source code in octavian/relative/propagation.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
chief_trajectory_eci: StateHistory
property
Return [chief ECI state, time] rows.
deputy_trajectory_eci: StateHistory
property
Return [deputy ECI state, time] rows.
relative_trajectory_ric: StateHistory
property
Return [relative RIC state, time] rows ready for plotting.
coupled_relative_ric_derivative(stacked_state: ArrayLike, *, mu_m3ps2: float) -> NDArray[np.float64]
Evaluate exact two-body chief-ECI/deputy-RIC stacked dynamics.
Args:
stacked_state: [chief_r, chief_v, rho_RIC, rho_dot_RIC] in SI.
mu_m3ps2: Central-body gravitational parameter.
Returns: Twelve derivatives in the same state ordering.
Source code in octavian/relative/propagation.py
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | |
nonlinear_relative_ric_derivative(relative_state_ric: ArrayLike, *, mu_m3ps2: float, chief_orbit_radius_m: float) -> NDArray[np.float64]
Evaluate exact circular-chief RIC dynamics before linearization.
Args:
relative_state_ric: [R, I, C, Rdot, Idot, Cdot] in SI units.
mu_m3ps2: Central-body gravitational parameter.
chief_orbit_radius_m: Circular chief radius in meters.
Returns: Six state derivatives in SI units.
Source code in octavian/relative/propagation.py
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | |
propagate_nonlinear_relative_ric(initial_state_ric: ArrayLike, times_s: ArrayLike, *, mu_m3ps2: float, chief_orbit_radius_m: float, max_step_s: float = 10.0) -> NDArray[np.float64]
Propagate the exact autonomous circular-chief RIC equations with RK4.
Args: initial_state_ric: Initial six-state RIC vector in SI units. times_s: Strictly increasing elapsed times beginning at zero. mu_m3ps2: Central-body gravitational parameter. chief_orbit_radius_m: Circular chief radius in meters. max_step_s: Maximum internal Runge-Kutta step.
Returns:
An (N, 7) history containing RIC state and elapsed time.
Source code in octavian/relative/propagation.py
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | |
propagate_relative_numerical(chief_initial_eci: BoundaryState, relative_initial_ric: BoundaryState | None, times_s: ArrayLike, *, deputy_initial_eci: BoundaryState | None = None, central_body: CelestialBody = EARTH, perturbations: Any | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> RelativePropagationResult
Propagate chief and deputy together and report their RIC separation.
The integrator is fixed-step fourth-order Runge-Kutta with exact output at each requested time. Both spacecraft receive central gravity plus the requested gravitational and cannonball accelerations. This coupled absolute-state formulation keeps differential drag and SRP physical without inserting approximations into rotating-frame equations.
Args:
chief_initial_eci: Chief absolute Cartesian state at elapsed time zero.
relative_initial_ric: Deputy state relative to the chief in RIC. Pass
None when supplying deputy_initial_eci directly.
times_s: Strictly monotonic output times with zero at either endpoint.
Forward histories normally begin at zero; backward histories may
be requested as either [0, ..., negative] or
[negative, ..., 0].
deputy_initial_eci: Optional absolute deputy state at time zero. This
avoids a frame-velocity round trip when osculating elements define
the deputy under a perturbed force model. Exactly one deputy
initial-state representation must be supplied.
central_body: Central-body constants used by gravity and J2.
perturbations: An :class:octavian.Perturbations configuration.
initial_epoch: UTC or SPICE ET corresponding to time zero. Required
when lunar/solar gravity or SRP is enabled.
max_step_s: Maximum internal RK4 step in seconds.
ephemeris_step_s: Sun/Moon interpolation sample spacing in seconds.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties. When
omitted, non-gravitational forces act only on the deputy.
deputy_spacecraft: Deputy mass and cannonball properties. Required
when drag or SRP is enabled.
Returns: Absolute chief/deputy histories and the equivalent RIC history.
Source code in octavian/relative/propagation.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
octavian.relative.solar
SPICE-driven Sun directions for chief-centered RIC geometry.
SolarDirectionTable
dataclass
Sampled Sun geometry for relative constraints and diagnostics.
Queries within 1e-8 s of an endpoint are clipped to that endpoint to tolerate optimized time roundoff. Queries farther outside coverage fail.
Source code in octavian/relative/solar.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
at(times_s: ArrayLike) -> NDArray[np.float64]
Interpolate and renormalize Sun directions at elapsed times.
Source code in octavian/relative/solar.py
50 51 52 53 54 55 56 57 58 59 60 61 62 | |
sun_position_at(times_s: ArrayLike) -> NDArray[np.float64]
Interpolate the SPICE-derived Sun position in ECI.
Source code in octavian/relative/solar.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
circular_chief_state(initial_state_eci: BoundaryState, elapsed_time_s: float, mean_motion_radps: float) -> BoundaryState
Propagate a circular chief reference state analytically.
Source code in octavian/relative/solar.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
sample_solar_directions_ric(*, chief_initial_state_eci: BoundaryState, mean_motion_radps: float, initial_epoch: str | datetime | float | int, duration_s: float, step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP) -> SolarDirectionTable
Sample the SPICE Sun line and rotate it into the chief's RIC frame.
The chief state and bundled BSP both use Octavian's Earth-centered
ECI_TOD orientation for this calculation.
Source code in octavian/relative/solar.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
octavian.propagate
One discoverable namespace for Octavian's analysis propagators.
Use this module as from octavian import propagate. Existing specialized
functions remain available in :mod:octavian.relative, :mod:octavian.astro,
and :mod:octavian.cislunar; this namespace provides consistent history
outputs and a shorter path for common analysis workflows.
cr3bp(initial_state: BoundaryState, times: Sequence[float], *, system: CR3BPSystem, dimensional: bool = True, max_step: float | None = None) -> StateHistory
Propagate a state in a circular restricted three-body system.
Args:
initial_state: Synodic state at times[0].
times: Strictly monotonic SI or canonical output times.
system: Primary-secondary CR3BP system.
dimensional: Use dimensional SI state and time units when true.
max_step: Maximum internal RK4 step in selected units.
Returns:
(N, 7) rows of [synodic state, time].
Source code in octavian/propagate.py
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | |
cwh(initial_state_ric: ArrayLike, times_s: ArrayLike, *, mean_motion_radps: float) -> StateHistory
Propagate a relative RIC state with the analytic CWH solution.
Args: initial_state_ric: Six-component RIC state at elapsed time zero. times_s: Finite elapsed output times. mean_motion_radps: Circular chief mean motion.
Returns:
(N, 7) rows of [RIC state, elapsed_time].
Source code in octavian/propagate.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | |
inertial(initial_state: BoundaryState, times_s: ArrayLike, *, central_body: CelestialBody = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, spacecraft: Spacecraft | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP) -> StateHistory
Numerically propagate an unpowered inertial Cartesian state.
Uses the same force model as :func:relative and fixed-step RK4, with
shortened steps to hit each output time exactly. Circular and equatorial
states are integrated directly without singular orbital elements.
Args: initial_state: Central-body inertial position/velocity at time zero. times_s: Strictly monotonic elapsed seconds, with zero at either end. Forward and backward propagation are supported. central_body: Gravity/J2 defaults; defaults to Earth. A harmonic field with published GM takes precedence for central and harmonic gravity. perturbations: Optional spherical harmonics or J2, Moon/Sun gravity, drag, and SRP. initial_epoch: UTC or SPICE ET at time zero, required for third-body gravity or SRP. Ephemeris positions use the Earth-centered TOD frame. spacecraft: Constant mass and cannonball properties, required for drag or SRP. This analysis propagator does not apply thrust. max_step_s: Maximum internal RK4 step in seconds. ephemeris_step_s: Sun/Moon interpolation spacing in seconds. bsp_path: BSP containing Earth-centered Sun/Moon states.
Returns:
(N, 7) rows [r, v, elapsed_time] in SI units, in requested order.
Source code in octavian/propagate.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | |
nonlinear_ric(initial_state_ric: ArrayLike, times_s: ArrayLike, *, mu_m3ps2: float, chief_orbit_radius_m: float, max_step_s: float = 10.0) -> StateHistory
Propagate the exact circular-chief RIC equations before linearization.
Args: initial_state_ric: Six-component RIC state at elapsed time zero. times_s: Strictly increasing elapsed times beginning at zero. mu_m3ps2: Central-body gravitational parameter. chief_orbit_radius_m: Circular chief radius. max_step_s: Maximum internal RK4 step.
Returns:
(N, 7) rows of [RIC state, elapsed_time].
Source code in octavian/propagate.py
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | |
relative(chief_initial_eci: BoundaryState, relative_initial_ric: BoundaryState | None, times_s: ArrayLike, *, deputy_initial_eci: BoundaryState | None = None, central_body: CelestialBody = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> RelativePropagationResult
Propagate exact coupled chief/deputy states and report RIC motion.
Args:
chief_initial_eci: Chief absolute state at elapsed time zero.
relative_initial_ric: Deputy state in chief RIC axes. Pass None
when supplying deputy_initial_eci.
times_s: Strictly monotonic times with zero at one endpoint.
deputy_initial_eci: Optional absolute deputy state at time zero.
central_body: Central-body gravity and radius constants.
perturbations: Optional J2, third-body, drag, and SRP model.
initial_epoch: Required for Moon, Sun, or SRP.
max_step_s: Maximum internal RK4 step.
ephemeris_step_s: Sun/Moon interpolation spacing.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties.
deputy_spacecraft: Deputy mass and cannonball properties, required for
drag or SRP.
Returns: Absolute chief/deputy histories and their equivalent RIC history.
Source code in octavian/propagate.py
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | |
relative_elements(initial_elements: RelativeOrbitalElements | ClassicalRelativeOrbitalElements | ArrayLike, times_s: ArrayLike, *, chief_initial_state_eci: BoundaryState, mu_m3ps2: float, representation: str = 'damico', central_body: CelestialBody | str = EARTH, perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | int | None = None, max_step_s: float = 10.0, ephemeris_step_s: float = 600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP, chief_spacecraft: Spacecraft | None = None, deputy_spacecraft: Spacecraft | None = None) -> RelativeElementPropagationResult
Propagate relative elements and return native plus RIC histories.
Perturbed propagation advances the coupled absolute states once. Use
result.elements for osculating D'Amico/classical elements and
result.ric for plotting or Cartesian relative analysis.
Args:
initial_elements: Initial D'Amico or classical relative elements.
times_s: Requested elapsed output times.
chief_initial_state_eci: Chief absolute state at elapsed time zero.
mu_m3ps2: Central-body gravitational parameter.
representation: "damico" or "classical_elements".
central_body: Body constants used by perturbations.
perturbations: Optional differential force model.
initial_epoch: Required for Moon, Sun, or SRP.
max_step_s: Maximum internal RK4 step.
ephemeris_step_s: Sun/Moon interpolation spacing.
bsp_path: SPICE BSP containing Earth-centered Sun/Moon states.
chief_spacecraft: Optional chief mass and cannonball properties.
deputy_spacecraft: Deputy mass and cannonball properties, required for
drag or SRP.
Returns: Paired native-element and equivalent RIC histories.
Source code in octavian/propagate.py
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | |
two_body(initial_state: BoundaryState, times_s: ArrayLike, *, mu_m3ps2: float) -> StateHistory
Propagate an elliptic inertial Cartesian state at elapsed times.
Args: initial_state: Cartesian state at elapsed time zero. times_s: Finite elapsed output times. Analytical evaluation permits either order and negative times. mu_m3ps2: Central-body gravitational parameter.
Returns:
(N, 7) rows of [r, v, elapsed_time] in SI units.
Source code in octavian/propagate.py
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
octavian.cislunar.model
Physical system definition and equilibrium geometry for the CR3BP.
CR3BPSystem
dataclass
Circular restricted three-body problem physical configuration.
The synodic frame is barycentric. Its +X axis points from primary to
secondary, +Z follows their orbital angular momentum, and it rotates at
the pair's constant CR3BP mean motion.
Args: primary: More massive body or catalog name. secondary: Less massive body or catalog name. separation_m: Constant circular separation between the bodies. name: Optional display name.
Source code in octavian/cislunar/model.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
frame: CoordinateFrame
property
Return barycentric synodic frame metadata.
mass_parameter: float
property
Return nondimensional secondary mass fraction mu.
mean_motion_radps: float
property
Return constant synodic angular rate in radians per second.
period_s: float
property
Return the circular primary-secondary period in seconds.
primary_position_m: Vector3
property
Return the primary's fixed dimensional synodic position.
primary_position_nondimensional: Vector3
property
Return the primary's fixed nondimensional synodic position.
scaling: SolverScaling
property
Return natural dimensional CR3BP solver units.
secondary_position_m: Vector3
property
Return the secondary's fixed dimensional synodic position.
secondary_position_nondimensional: Vector3
property
Return the secondary's fixed nondimensional synodic position.
time_scale_s: float
property
Return the nondimensional CR3BP time unit in seconds.
total_mu_m3ps2: float
property
Return the sum of the primary and secondary gravitational parameters.
velocity_scale_mps: float
property
Return the nondimensional CR3BP velocity unit in m/s.
earth_moon(*, separation_m: float = 384400000.0) -> CR3BPSystem
classmethod
Return the conventional circular Earth–Moon CR3BP system.
Source code in octavian/cislunar/model.py
58 59 60 61 62 63 64 65 | |
lagrange_points(*, dimensional: bool = True, tolerance: float = 1e-13) -> dict[str, Vector3]
Return the five equilibrium points in the synodic frame.
Args: dimensional: Return meters when true, nondimensional coordinates when false. tolerance: Collinear-root bisection tolerance in nondimensional distance.
Source code in octavian/cislunar/model.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
octavian.cislunar.transforms
CR3BP dimensional scaling and synodic/inertial transformations.
dimensionalize_state(state_nondimensional: BoundaryState, system: CR3BPSystem) -> BoundaryState
Convert a canonical CR3BP state to dimensional synodic SI units.
Source code in octavian/cislunar/transforms.py
25 26 27 28 29 30 31 32 33 | |
dimensionalize_time(time_nondimensional: float | Sequence[float], system: CR3BPSystem)
Convert canonical CR3BP time to seconds.
Source code in octavian/cislunar/transforms.py
42 43 44 45 | |
inertial_to_synodic_state(state_inertial: BoundaryState, *, time_s: float, system: CR3BPSystem, origin: str = 'primary', phase_at_epoch_rad: float = 0.0, inertial_basis_at_epoch: Sequence[Sequence[float]] | None = None) -> BoundaryState
Rotate an origin-centered inertial state into barycentric synodic axes.
inertial_basis_at_epoch has the same convention as
:func:synodic_to_inertial_state.
Source code in octavian/cislunar/transforms.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
nondimensionalize_state(state_synodic: BoundaryState, system: CR3BPSystem) -> BoundaryState
Convert a dimensional synodic state to CR3BP canonical units.
Source code in octavian/cislunar/transforms.py
14 15 16 17 18 19 20 21 22 | |
nondimensionalize_time(time_s: float | Sequence[float], system: CR3BPSystem)
Convert seconds to canonical CR3BP time.
Source code in octavian/cislunar/transforms.py
36 37 38 39 | |
synodic_to_inertial_state(state_synodic: BoundaryState, *, time_s: float, system: CR3BPSystem, origin: str = 'primary', phase_at_epoch_rad: float = 0.0, inertial_basis_at_epoch: Sequence[Sequence[float]] | None = None) -> BoundaryState
Rotate a dimensional barycentric synodic state into inertial axes.
Args:
state_synodic: Dimensional barycentric synodic state.
time_s: Seconds from the frame alignment epoch.
system: CR3BP system.
origin: "barycenter", "primary", or "secondary".
phase_at_epoch_rad: Inertial angle of synodic +X at time zero.
inertial_basis_at_epoch: Optional right-handed orthonormal matrix whose
columns are the synodic X, Y, and Z axes expressed in inertial
coordinates at time zero. This supports inclined primary-secondary
planes; the default is the inertial XYZ basis.
Returns: State in inertial axes relative to the selected origin.
Source code in octavian/cislunar/transforms.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
octavian.cislunar.propagation
Numerical propagation and invariants for CR3BP trajectories.
cr3bp_derivative(state: ArrayLike, *, system: CR3BPSystem, dimensional: bool = True) -> NDArray[np.float64]
Return a six-state CR3BP derivative in synodic coordinates.
Args:
state: [x, y, z, xdot, ydot, zdot].
system: Physical primary-secondary system.
dimensional: Interpret and return SI units when true; canonical CR3BP
units otherwise.
Source code in octavian/cislunar/propagation.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
jacobi_constant(state: ArrayLike, *, system: CR3BPSystem, dimensional: bool = True) -> float
Return the Jacobi integral for one synodic CR3BP state.
Source code in octavian/cislunar/propagation.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
propagate_cr3bp(initial_state: BoundaryState, times: Sequence[float], *, system: CR3BPSystem, dimensional: bool = True, max_step: float | None = None) -> StateHistory
Propagate a CR3BP state with deterministic fourth-order Runge-Kutta.
Requested times must be strictly monotonic and may run forward or
backward. The returned columns are [x, y, z, xdot, ydot, zdot, time].
Args:
initial_state: State at times[0].
times: Output times in seconds or canonical time.
system: Physical primary-secondary system.
dimensional: Use SI state/time units when true.
max_step: Maximum internal step in the selected time units. Defaults
to 900 seconds or 0.0025 canonical time.
Source code in octavian/cislunar/propagation.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
octavian.cislunar.guessing
Initial-guess builders for dimensional or canonical CR3BP phases.
cr3bp_hermite_guess(initial_state: BoundaryState, final_state: BoundaryState, *, t0_s: float, tf_s: float, npts: int) -> list[np.ndarray]
Build a boundary-matching cubic Hermite state guess.
This geometric seed matches both endpoint positions and velocities. It is intended for CR3BP collocation initialization; the optimizer enforces the actual equations of motion.
Args:
initial_state: Synodic state at t0_s.
final_state: Synodic state at tf_s.
t0_s: Initial phase time in the state's consistent unit convention.
tf_s: Final phase time in the state's consistent unit convention.
npts: Number of returned rows, including endpoints.
Source code in octavian/cislunar/guessing.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
octavian.cislunar.dynamics
ASSET equations of motion for dimensional or canonical CR3BP phases.
CR3BPODE
Bases: ODEBase if oc is not None else object
Barycentric-synodic CR3BP equations in SI or canonical units.
Args: system: Primary-secondary physical system. dimensional: Use SI state and time variables when true, or canonical CR3BP variables when false.
Source code in octavian/cislunar/dynamics.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
Quick Builders And Specs
octavian.quick
Low-friction mission builders.
relative_hop(initial_state_ric: BoundaryState, final_state_ric: BoundaryState, *, chief_initial_state_eci: BoundaryState, departure_coast_time_bounds_s: TimeBounds = (1.0, 600.0), transfer_time_bounds_s: TimeBounds = (600.0, 3600.0), dynamics: Dynamics | None = None, central_body: CelestialBody | str = EARTH, propagation_mode: str = 'coupled_eci', perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | None = None, spacecraft: Spacecraft | None = None, reference_length_m: float = 1000.0, nsegs_coast: int = 30, nsegs_transfer: int = 60, seed_grid_size: int = 60, w_time: float = 0.0, name: str = 'Relative hop', solver_options: SolverOptions | None = None) -> Mission
Build a relative coast–impulse–transfer–impulse mission.
The first phase lets the deputy coast on its initial relative orbit. An impulsive link starts the transfer phase, and a terminal impulse matches the requested final RIC velocity. Both optimized dynamics phases remain chief-centered and use the same native relative formulation.
Args:
initial_state_ric: Initial deputy state in the chief RIC frame.
final_state_ric: Desired post-arrival deputy state in RIC.
chief_initial_state_eci: Absolute chief state at mission time zero.
departure_coast_time_bounds_s: Bounds on the initial coast duration.
transfer_time_bounds_s: Bounds on transfer duration after departure.
dynamics: Optional preconfigured relative dynamics. When omitted,
Dynamics.relative is built from the remaining dynamics inputs.
central_body: Central body used when constructing default dynamics.
propagation_mode: Relative formulation used by default dynamics.
perturbations: Optional differential perturbation configuration.
initial_epoch: Mission epoch required by Sun, Moon, or SRP.
spacecraft: Optional deputy configuration.
reference_length_m: Relative-distance scaling for default dynamics.
nsegs_coast: Mesh segments on the initial coast.
nsegs_transfer: Mesh segments on the transfer.
seed_grid_size: Number of CWH seed times evaluated per target.
w_time: Optional total-time objective weight.
name: Human-readable mission name.
solver_options: Optional solver configuration.
Returns:
A two-phase mission ready for mission.solve().
Source code in octavian/quick.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |
relative_transfer_chain(initial_state_ric: BoundaryState, target_states_ric: Sequence[BoundaryState], *, chief_initial_state_eci: BoundaryState, transfer_time_bounds_s: TimeBoundsInput = (600.0, 3600.0), coast_time_bounds_s: TimeBoundsInput | None = None, departure_coast_time_bounds_s: TimeBounds | None = None, dynamics: Dynamics | None = None, central_body: CelestialBody | str = EARTH, propagation_mode: str = 'coupled_eci', perturbations: Perturbations | None = None, initial_epoch: str | datetime | float | None = None, spacecraft: Spacecraft | None = None, reference_length_m: float = 1000.0, nsegs_coast: int = 30, nsegs_transfer: int = 60, seed_grid_size: int = 60, w_time: float = 0.0, name: str = 'Relative transfer chain', solver_options: SolverOptions | None = None) -> Mission
Build one or more impulsive relative transfers with coasts between.
Each target is a post-arrival RIC state. For nonterminal targets, an impulsive link inserts the arrival burn and starts a natural coast at that exact state. A later impulsive link departs that coast for the next transfer. This yields four burns for two ordinary two-burn transfers, or can be adapted into a three-burn design by editing the returned phases.
A single time-bound pair is repeated for every applicable phase. Pass a sequence of pairs to configure individual transfers or intermediate coasts.
Args:
initial_state_ric: Initial deputy state in the chief RIC frame.
target_states_ric: Ordered post-arrival RIC targets.
chief_initial_state_eci: Absolute chief state at mission time zero.
transfer_time_bounds_s: One duration bound or one per target.
coast_time_bounds_s: One duration bound or one per intermediate target.
Defaults to (300, 900) when multiple targets are supplied.
departure_coast_time_bounds_s: Optional coast before the first burn.
dynamics: Optional preconfigured relative dynamics.
central_body: Central body used when constructing default dynamics.
propagation_mode: Relative formulation used by default dynamics.
perturbations: Optional differential perturbation configuration.
initial_epoch: Mission epoch required by Sun, Moon, or SRP.
spacecraft: Optional deputy configuration.
reference_length_m: Relative-distance scaling for default dynamics.
nsegs_coast: Mesh segments used for coast phases.
nsegs_transfer: Mesh segments used for transfer phases.
seed_grid_size: Number of CWH seed times evaluated per target.
w_time: Optional total-time objective weight.
name: Human-readable mission name.
solver_options: Optional solver configuration.
Returns:
A linked relative mission ready for mission.solve().
Raises: ValueError: If no targets are supplied, bounds counts are inconsistent, or perturbations are supplied alongside preconfigured dynamics.
Source code in octavian/quick.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | |
state(r_m: np.ndarray | Sequence[float], v_mps: np.ndarray | Sequence[float]) -> BoundaryState
Create a boundary state from Cartesian position and velocity vectors.
Args: r_m: Position vector in meters. v_mps: Velocity vector in meters per second.
Returns: A boundary-state object that can be passed to quick builders, ConOps helpers, or lower-level specs.
Source code in octavian/quick.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
two_burn_rendezvous(x0: BoundaryState, xf: BoundaryState, *, mu_m3ps2: float = 398600441800000.0, central_body: CelestialBody | str | None = None, tf_bounds_s: tuple[float, float] = (600.0, 7200.0), nsegs: int = 60, lambert_grid_size: int = 60, nrevs_to_try: tuple[int, ...] = (0, 1), w_time: float = 0.0, precoast: bool = False, t1_bounds_s: tuple[float, float] = (0.0, 1800.0), precoast_grid_size: int = 10, limit_precoast_to_one_period: bool = True, name: str = 'Two-burn rendezvous', constraints: Sequence[object] | None = None, solver_options: SolverOptions | None = None) -> Mission
Create a ready-to-solve impulsive rendezvous mission.
Args:
x0: Initial boundary state.
xf: Final boundary state.
mu_m3ps2: Central-body gravitational parameter in m^3/s^2.
central_body: Optional built-in or custom body. When provided, its
gravity, radius, J2, and inertial frame replace mu_m3ps2 and
the legacy Earth defaults.
tf_bounds_s: Bounds on elapsed mission time at rendezvous, including
any precoast. Transfer duration is final time minus precoast time.
nsegs: Number of mesh segments used by the transfer phase.
lambert_grid_size: Number of Lambert time-of-flight samples to try.
nrevs_to_try: Revolution counts to include in the Lambert seed search.
w_time: Weight on final time in the objective.
precoast: If True, build a precoast-plus-transfer mission instead
of a single transfer phase.
t1_bounds_s: Bounds on precoast duration in seconds when precoast
is enabled. A zero lower bound is allowed; the two-phase solver
uses its positive minimum phase duration when constructing seeds.
precoast_grid_size: Number of precoast candidates to test when seeding.
limit_precoast_to_one_period: Whether to cap the precoast seed sweep to
one orbital period when possible.
name: Human-readable mission name.
constraints: Additional constraints attached to the rendezvous phase.
solver_options: Optional solver overrides attached to the mission.
Returns:
A configured mission object ready for mission.solve().
Source code in octavian/quick.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
octavian.conops
Concept-of-operations mission builders.
rendezvous_precoast_then_transfer(*, spacecraft: Spacecraft, dynamics: Dynamics, initial_state: BoundaryState, final_state: BoundaryState, t1_bounds_s: tuple[float, float] = (0.0, 1800.0), tf_bounds_s: tuple[float, float] = (600.0, 7200.0), nsegs_precoast: int = 30, nsegs_transfer: int = 60, precoast_grid_size: int = 10, limit_precoast_to_one_period: bool = True, lambert_grid_size: int = 60, nrevs_to_try: tuple[int, ...] = (0, 1), w_time: float = 0.0, name: str = 'Precoast + two-impulse rendezvous', constraints_precoast: Sequence[object] | None = None, constraints_rendezvous: Sequence[object] | None = None) -> Mission
Build a two-phase mission with a precoast before rendezvous.
Args: spacecraft: Spacecraft used by the mission. dynamics: Dynamics model shared by both phases. initial_state: Initial state fixed at the start of the precoast phase. final_state: Final state target applied at the end of the transfer phase. t1_bounds_s: Bounds on precoast duration in seconds. tf_bounds_s: Bounds on elapsed mission time at rendezvous, including the precoast; these are not bounds on transfer duration alone. nsegs_precoast: Number of mesh segments for the precoast phase. nsegs_transfer: Number of mesh segments for the transfer phase. precoast_grid_size: Number of precoast seed candidates to evaluate. limit_precoast_to_one_period: Whether to cap the seed sweep to one orbital period when the initial orbit period is known. lambert_grid_size: Number of Lambert seed samples per candidate. nrevs_to_try: Revolution counts included in the Lambert seed search. w_time: Weight on final time in the objective. name: Human-readable mission name. constraints_precoast: Additional constraints for the precoast phase. constraints_rendezvous: Additional constraints for the transfer phase.
Returns: A mission with a precoast phase followed by an impulsive rendezvous phase.
Source code in octavian/conops.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
rendezvous_two_impulse(*, spacecraft: Spacecraft, dynamics: Dynamics, initial_state: BoundaryState, final_state: BoundaryState, tf_bounds_s: tuple[float, float] = (600.0, 7200.0), nsegs: int = 60, lambert_grid_size: int = 60, nrevs_to_try: tuple[int, ...] = (0, 1), w_time: float = 0.0, name: str = 'Two-impulse rendezvous', constraints: Sequence[object] | None = None) -> Mission
Build a single-phase impulsive rendezvous mission.
Args: spacecraft: Spacecraft used by the mission. dynamics: Dynamics model applied to the phase. initial_state: Initial state fixed at the front boundary. final_state: Final state target applied at the back boundary. tf_bounds_s: Bounds on total transfer time in seconds. nsegs: Number of transfer mesh segments. lambert_grid_size: Number of Lambert seed samples. nrevs_to_try: Revolution counts included in the Lambert seed search. w_time: Weight on final time in the objective. name: Human-readable mission name. constraints: Additional constraints for the rendezvous phase.
Returns: A mission configured for the built-in two-impulse rendezvous solver.
Source code in octavian/conops.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
octavian.specs
BoundaryState
dataclass
Dimensional Cartesian boundary state in the mission dynamics frame.
Attributes: r_m: Position in meters, shape (3,). v_mps: Velocity in meters per second, shape (3,).
Source code in octavian/specs.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
TwoImpulseFreeTimeSpec
dataclass
Problem specification for two-impulse rendezvous with free final time.
Source code in octavian/specs.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
final_state: BoundaryState
property
Alias for xf with a clearer name.
final_time_bounds_s: tuple[float, float]
property
Alias for tf_bounds_s with a clearer name.
initial_state: BoundaryState
property
Alias for x0 with a clearer name.
TwoImpulsePreCoastSpec
dataclass
Problem specification for two-impulse rendezvous with variable pre-coast.
Source code in octavian/specs.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
final_state: BoundaryState
property
Alias for xf with a clearer name.
final_time_bounds_s: tuple[float, float]
property
Alias for tf_bounds_s with a clearer name.
initial_state: BoundaryState
property
Alias for x0 with a clearer name.
precoast_time_bounds_s: tuple[float, float]
property
Alias for t1_bounds_s with a clearer name.
octavian.solvers.options
Solver configuration objects.
Octavian's philosophy is that Python is the GUI: - User-facing configuration is explicit and typed. - Mission/solver scripts are readable and composable. - Internals remain small and unsurprising.
This module defines small option dataclasses that keep optimizer knobs out of solver implementations.
SolverOptions
dataclass
Common options shared across ASSET-backed solvers.
Attributes:
print_level: ASSET optimizer PrintLevel. 0 is quiet.
max_ls_iters: ASSET optimizer MaxLSIters (line-search iterations).
qp_ordering_mode: QP ordering mode used by ASSET (string passed to
optimizer.set_QPOrderingMode).
enable_auto_scaling: Whether to enable ASSET phase auto-scaling.
enable_adaptive_mesh: Whether to allow adaptive mesh refinement.
asset_threads: Optional (optimizer_threads, mesh_threads) pair passed
to ASSET's ocp.setThreads. Use (1, 1) for deterministic
regression tests when ASSET's multi-threaded solve path is noisy.
Source code in octavian/solvers/options.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
octavian.solvers.preconfigured
Preconfigured impulsive transfer solvers built on ASSET's UpdatedInterface.
Key correctness notes (from ASSET source/examples):
- Time is not a state. Time is the phase time variable (ODEArguments.TVar()) and
appears in the phase variable stack after X: for XVars=6, the time index is 6.
- Use Vgroups in the ODE ("R", "V", "t"/"time") so constraints can refer
to semantic groups (see examples/UpdatedInterface/Delta3Launch.py in ASSET).
This module owns Octavian's built-in, preconfigured two-impulse problem shapes. It is separate from the composable compiler: callers provide a typed problem specification, and this backend builds one of the fixed ASSET OCP layouts below. Everything remains dimensional at the user API and relies on ASSET auto-scaling.
RendezvousResult
dataclass
Result returned by ASSET-backed transfer solvers.
Attributes:
converged: Whether ASSET reported convergence.
traj: Dense trajectory array. For the current impulsive problems this is
typically [x0..x5, t] where t is the phase time variable.
maneuvers: Maneuver markers derived from the solution.
last_obj: Last objective value returned by ASSET.
info: Free-form metadata (seed selection, bounds used, etc.).
The result object is designed to be the currency of studies: it supports human-readable summaries and simple persistence.
Source code in octavian/solvers/preconfigured.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
from_npz(path: str | Path) -> RendezvousResult
classmethod
Load a result from a compressed .npz file.
Args:
path: Path previously written by :meth:to_npz.
Returns: The reconstructed result object.
Source code in octavian/solvers/preconfigured.py
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
summary() -> str
Build a compact human-readable summary of the result.
Returns: A multiline summary string containing convergence status, timing, delta-v, and selected metadata.
Source code in octavian/solvers/preconfigured.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
tf_s() -> float
Return the final trajectory time.
Returns:
The last sample in seconds, or in TU for a canonical CR3BP solve.
The _s suffix is retained for API compatibility.
Source code in octavian/solvers/preconfigured.py
72 73 74 75 76 77 78 79 80 81 | |
to_json(*, indent: int | None = None) -> str
Serialize summary metadata to JSON.
Args:
indent: Optional indentation level passed to json.dumps.
Returns: A JSON string containing summary fields, maneuvers, and metadata.
Source code in octavian/solvers/preconfigured.py
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
to_npz(path: str | Path) -> None
Save this result to a compressed .npz file.
Args: path: Output file path.
Notes:
The archive stores the trajectory, convergence flag, objective
value, maneuver fields, and JSON-serialized info metadata.
Source code in octavian/solvers/preconfigured.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | |
total_dv_mps() -> float
Return the total maneuver delta-v magnitude.
Returns:
The sum in m/s, or in VU for a canonical CR3BP solve. Returns
0.0 when no maneuvers are stored. The _mps suffix is
retained for API compatibility.
Source code in octavian/solvers/preconfigured.py
83 84 85 86 87 88 89 90 91 92 93 | |
solve(spec: TwoImpulseFreeTimeSpec | TwoImpulsePreCoastSpec, *, options: SolverOptions | None = None) -> RendezvousResult
Solve a preconfigured transfer specification with the matching backend.
This dispatcher is intentionally small: the typed spec determines which fixed OCP layout is built. More open-ended mission scripts should enter through the composable backend instead.
Args: spec: Rendezvous problem specification. options: Optional solver configuration overrides.
Returns: The solver result for the provided specification.
Raises:
TypeError: If spec is not a supported rendezvous spec type.
Source code in octavian/solvers/preconfigured.py
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
solve_two_impulse_free_time(spec: TwoImpulseFreeTimeSpec, *, options: SolverOptions | None = None) -> RendezvousResult
Solve a single-phase two-impulse transfer with bounded final time.
The initial guess is Lambert-seeded, then propagated into an ASSET LGL mesh with the Lambert departure velocity. Boundary position constraints are hard; optional velocity constraints are applied only when the spec disables the corresponding impulsive boundary. Delta-v objectives are expressed as boundary velocity mismatches.
Args: spec: Single-phase rendezvous specification. options: Optional solver configuration overrides.
Returns: The optimized rendezvous result.
Raises: RuntimeError: If ASSET is not installed. ValueError: If the time bounds are invalid.
Source code in octavian/solvers/preconfigured.py
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | |
solve_two_impulse_precoast(spec: TwoImpulsePreCoastSpec, *, options: SolverOptions | None = None) -> RendezvousResult
Solve a two-phase transfer with a variable coast before the impulse arc.
The backend sweeps candidate precoast durations, propagates the initial state to each candidate link point, scores Lambert transfers from that point to the terminal position, and uses the best candidate to seed two ASSET phases. The compiled OCP then optimizes the precoast duration, transfer duration, link impulse, and optional boundary impulses together.
Args: spec: Precoast rendezvous specification. options: Optional solver configuration overrides.
Returns: The optimized rendezvous result.
Raises: RuntimeError: If ASSET is not installed or no feasible seed is found. ValueError: If the precoast or transfer time bounds are invalid.
Source code in octavian/solvers/preconfigured.py
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | |
Astrodynamics Helpers
octavian.astro.kepler
cartesian_to_classic(*, r_m: Vec3, v_mps: Vec3, mu_m3ps2: float) -> dict[str, float]
Convert Cartesian position and velocity to classical orbital elements.
Source code in octavian/astro/kepler.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
classic_to_cartesian(*, a_m: float, e: float, inc_deg: float, raan_deg: float, argp_deg: float, true_anomaly_deg: float, mu_m3ps2: float) -> tuple[np.ndarray, np.ndarray]
Convert classical orbital elements to Cartesian position and velocity.
Source code in octavian/astro/kepler.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
classical_to_cartesian(*, a_m: float, e: float, inc_deg: float, raan_deg: float, argp_deg: float, true_anomaly_deg: float, mu_m3ps2: float) -> tuple[np.ndarray, np.ndarray]
Alias for :func:classic_to_cartesian using a more explicit name.
Source code in octavian/astro/kepler.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
estimate_orbital_period_s(r_m: Vec3, v_mps: Vec3, mu_m3ps2: float) -> float | None
Estimate orbital period for elliptic orbit; else None.
Source code in octavian/astro/kepler.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
kepler_dense_guess(*, r0_m: Vec3, v0_mps: Vec3, t0_s: float, tf_s: float, npts: int, mu_m3ps2: float) -> list[np.ndarray]
Dense guess [x(6), t] built via repeated Kepler propagation.
Source code in octavian/astro/kepler.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
propagate_cartesian_rv(rv6: np.ndarray, dt_s: float, mu_m3ps2: float) -> np.ndarray
Propagate a 6D Cartesian state under two-body dynamics using ASSET.
Source code in octavian/astro/kepler.py
168 169 170 171 172 173 174 | |
octavian.astro.lambert
LambertSeed
dataclass
One Lambert branch and its endpoint velocity cost.
Source code in octavian/astro/lambert.py
15 16 17 18 19 20 21 22 23 24 25 | |
select_best_lambert_seed(*, r0_m: Vec3, rf_m: Vec3, v0_mps: Vec3, vf_mps: Vec3, mu_m3ps2: float, tmin_s: float, tmax_s: float, n_tofs: int = 50, nrevs: Sequence[int] = (0, 1)) -> LambertSeed
Sweep Lambert solutions and return the seed with minimum total delta-v.
This helper is designed for initial guess generation in impulsive transfers. It evaluates a grid of time-of-flight samples and Lambert branch options, then chooses the solution that minimizes::
|v1 - v0| + |vf - v2|
where (v1, v2) is the Lambert departure/arrival velocity pair.
Args:
r0_m: Initial position [m].
rf_m: Final position [m].
v0_mps: Initial velocity [m/s].
vf_mps: Final velocity [m/s].
mu_m3ps2: Gravitational parameter [m^3/s^2].
tmin_s: Minimum time-of-flight to test [s].
tmax_s: Maximum time-of-flight to test [s]. Set equal to tmin_s
to compare Lambert branches at one fixed flight time.
n_tofs: Number of TOF samples in [tmin_s, tmax_s].
nrevs: Sequence of integer revolution counts to attempt.
Returns: The best Lambert seed found.
Raises: ValueError: If bounds are invalid. RuntimeError: If no Lambert solution succeeds over the sweep.
Notes: Exactly parallel or antiparallel positions do not define a unique Lambert plane. For seed generation only, Octavian rotates the target by a tiny deterministic angle in the plane suggested by the boundary velocities. The optimization boundary remains the original position.
Source code in octavian/astro/lambert.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | |
octavian.astro.units
Dimensional scaling helpers for ASSET-backed solves.
default_scaling(spec: Any) -> SolverScaling
Choose characteristic units for a dimensional solver problem.
An explicit spec.scaling declaration wins. Otherwise the legacy
endpoint-derived length, velocity, and time rules are preserved, with an
optional mass scale read from mass_unit_kg.
Source code in octavian/astro/units.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
default_units(spec: Any) -> tuple[float, float, float]
Choose default dimensional units for solver auto-scaling.
Args:
spec: Object with boundary states x0 and xf and optional unit
overrides such as r_unit_m, v_unit_mps, and t_unit_s.
Returns:
A tuple (r_unit_m, v_unit_mps, t_unit_s) suitable for ASSET phase
scaling.
Source code in octavian/astro/units.py
55 56 57 58 59 60 61 62 63 64 65 66 67 | |
octavian.astro.types
Shared numeric types for astrodynamics helpers.
as_vec3(value: Any) -> Vec3
Convert an input into a length-3 float64 NumPy vector.
Args: value: Array-like object with three elements.
Returns:
A (3,) NumPy array of dtype float64.
Source code in octavian/astro/types.py
13 14 15 16 17 18 19 20 21 22 | |
octavian.data.ephemeris
Runtime ephemeris helpers for Sun/Moon third-body perturbations.
epoch_to_datetime_utc(epoch: str | datetime | float | int) -> datetime
Convert a user epoch to a timezone-aware UTC datetime.
String and :class:datetime.datetime inputs are interpreted as UTC.
Numeric inputs are SPICE ephemeris seconds past J2000, matching
:func:epoch_to_et. If a leap-second kernel is loaded, SpiceyPy performs
the conversion. Otherwise Octavian uses the same built-in leap-second
history as :func:epoch_to_et, neglecting only the millisecond-scale
periodic TDB-minus-TT term.
Args: epoch: UTC string, datetime, or SPICE ET seconds past J2000.
Returns: A timezone-aware UTC datetime.
Source code in octavian/data/ephemeris.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
epoch_to_et(epoch: str | datetime | float | int) -> float
Convert a user epoch to SPICE ephemeris seconds past J2000.
Numeric inputs are treated as ET seconds. String and datetime inputs are
interpreted as UTC. If a SPICE leap-second kernel is loaded, SpiceyPy
performs the conversion; otherwise a built-in UTC-to-TT fallback using the
published leap-second history is used.
Source code in octavian/data/ephemeris.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
get_sun_moon_states_eci_tod(et: float) -> tuple[np.ndarray, np.ndarray]
Return Earth-centered geometric Sun and Moon states in ECI_TOD.
States are returned in SPICE units: position in kilometers and velocity in kilometers per second.
Source code in octavian/data/ephemeris.py
72 73 74 75 76 77 78 79 80 | |
load_reduced_ephemeris(bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP) -> None
Load the reduced Earth-centered Sun/Moon BSP and ECI_TOD frame.
Source code in octavian/data/ephemeris.py
64 65 66 67 68 69 | |
sample_sun_moon_positions_eci_tod(*, initial_epoch: str | datetime | float | int, duration_s: float, step_s: float = 3600.0, bsp_path: str | Path = DEFAULT_EPHEMERIS_BSP) -> tuple[np.ndarray, dict[str, np.ndarray]]
Sample Earth-centered Sun/Moon positions in ECI_TOD for table building.
Returns (times_s, positions_m) where positions_m has "sun" and
"moon" arrays with shape (N, 3) in meters.
Source code in octavian/data/ephemeris.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
Output, Visualization, And Studies
octavian.exports.ephemeris
Validated trajectory exports for common ephemeris file formats.
Ephemeris
dataclass
A Cartesian state history with the metadata needed for file export.
Octavian stores positions in meters, velocities in meters per second, and elapsed times in seconds. Writers perform any format-required unit conversion at the file boundary.
Attributes:
times_s: Strictly increasing elapsed seconds from epoch.
states_m_mps: Cartesian rows [x, y, z, vx, vy, vz] in SI units.
epoch: UTC string/datetime or SPICE ET seconds at times_s == 0.
frame_name: Name of the frame already represented by the state rows.
Export does not rotate coordinates; this label must describe the
supplied data.
center_name: Human-readable center of motion.
object_name: Human-readable ephemeris object name.
object_id: NAIF object ID used by the BSP writer.
center_id: NAIF center ID used by the BSP writer.
Source code in octavian/exports/ephemeris.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
epochs_et: NDArray[np.float64]
property
Return one SPICE ET epoch per state row.
from_trajectory(trajectory: ArrayLike, *, epoch: Epoch, frame_name: str = 'J2000', center_name: str = 'EARTH', object_name: str = 'SPACECRAFT', object_id: int = -100000, center_id: int = 399) -> Ephemeris
classmethod
Construct an ephemeris from Octavian [R, V, t] rows.
Args:
trajectory: Array with shape (N, 7) and columns
[x, y, z, vx, vy, vz, elapsed_time] in SI units.
epoch: Epoch corresponding to elapsed time zero.
frame_name: Frame already represented by the trajectory.
center_name: Human-readable center of motion.
object_name: Human-readable ephemeris object name.
object_id: NAIF object ID for BSP output.
center_id: NAIF center ID for BSP output.
Returns: A validated ephemeris ready for one or more exports.
Source code in octavian/exports/ephemeris.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
write(path: str | Path, *, format: EphemerisFormat | None = None, overwrite: bool = False, interpolation_degree: int = 7) -> Path
Write this ephemeris, inferring the format from the extension.
Supported extensions are .e (STK), .oem (CCSDS OEM), .bsp
or .spk (SPICE type-9 SPK), and .csv.
Args:
path: Output file.
format: Explicit format override, normally inferred from path.
overwrite: Replace an existing file when true.
interpolation_degree: Requested Lagrange degree for OEM metadata
and BSP interpolation. It is reduced when the history contains
too few samples.
Returns: The resolved output path.
Source code in octavian/exports/ephemeris.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
write_csv_ephemeris(ephemeris: Ephemeris, path: str | Path, *, overwrite: bool = False) -> Path
Write a portable SI-unit CSV ephemeris with UTC and elapsed time.
Source code in octavian/exports/ephemeris.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | |
write_ephemeris(ephemeris: Ephemeris, path: str | Path, *, format: EphemerisFormat | None = None, overwrite: bool = False, interpolation_degree: int = 7) -> Path
Write an ephemeris using an explicit format or output extension.
Source code in octavian/exports/ephemeris.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
write_oem(ephemeris: Ephemeris, path: str | Path, *, overwrite: bool = False, interpolation_degree: int = 7, originator: str = 'OCTAVIAN') -> Path
Write a CCSDS OEM 2.0 KVN file in kilometers and UTC.
Source code in octavian/exports/ephemeris.py
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | |
write_spice_bsp(ephemeris: Ephemeris, path: str | Path, *, overwrite: bool = False, interpolation_degree: int = 7) -> Path
Write a SPICE type-9 SPK segment (normally named .bsp).
SPICE stores positions in kilometers, velocities in kilometers per second,
and epochs as TDB-compatible ephemeris seconds. frame_name must be a
frame recognized by SPICE, such as "J2000".
Source code in octavian/exports/ephemeris.py
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | |
write_stk_ephemeris(ephemeris: Ephemeris, path: str | Path, *, overwrite: bool = False, interpolation_degree: int = 7) -> Path
Write an STK ASCII ephemeris (.e) in meters and seconds.
Source code in octavian/exports/ephemeris.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
octavian.viz.plotly
Plotly-based trajectory visualization helpers.
cr3bp_trajectory_figure(traj: np.ndarray, *, system: CR3BPSystem, dimensional: bool = True, lagrange_point_names: Sequence[str] | None = None, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian CR3BP trajectory') -> Any
Build an interactive barycentric-synodic CR3BP trajectory figure.
Args:
traj: Rows [x, y, z, xdot, ydot, zdot, time].
system: Primary-secondary CR3BP system.
dimensional: Interpret positions as meters when true or canonical
distance units otherwise.
lagrange_point_names: Lagrange points to include. The default includes
all five; pass an empty sequence to omit them.
maneuvers: Optional maneuver markers in the trajectory's units.
phase_segments: Optional phase interval dictionaries with name,
t_start_s, t_end_s, and optional color keys.
reference_trajectories: Optional dictionaries with name and
traj keys plus an optional Plotly color. These are useful
for plotting departure and arrival periodic orbits around a
solved transfer.
title: Figure title.
Returns: A Plotly 3D figure with independently selectable body and Lagrange-point traces.
Source code in octavian/viz/plotly.py
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | |
relative_trajectory_figure(traj: np.ndarray, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian relative trajectory', chief_radius_m: float = 0.0) -> Any
Build an interactive 3D RIC trajectory figure.
Args:
traj: Relative trajectory rows [R, I, C, Rdot, Idot, Cdot, t] in
meters, meters per second, and seconds.
maneuvers: Optional maneuver markers expressed in the same RIC frame.
phase_segments: Optional phase interval dictionaries with name,
t_start_s, t_end_s, and optional color keys.
reference_trajectories: Dashed overlays with traj position rows
in the same frame and units, plus optional name and color.
Velocity and time columns are ignored.
title: Plot title.
chief_radius_m: Optional physical or keep-out radius drawn about the
chief. Zero draws a marker without a surrounding sphere.
Returns:
A :class:plotly.graph_objects.Figure with equal RIC axis scaling.
Raises: ValueError: If the trajectory shape, values, or chief radius is invalid. RuntimeError: If Plotly is not installed.
Source code in octavian/viz/plotly.py
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 | |
save_cr3bp_trajectory_html(traj: np.ndarray, out_html: str, *, system: CR3BPSystem, dimensional: bool = True, lagrange_point_names: Sequence[str] | None = None, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian CR3BP trajectory') -> None
Save a barycentric-synodic CR3BP trajectory as interactive HTML.
Args:
traj: Rows [x, y, z, xdot, ydot, zdot, time].
out_html: Destination HTML path.
system: Primary-secondary CR3BP system.
dimensional: Interpret trajectory and marker positions as meters when
true or canonical distance units otherwise.
lagrange_point_names: Lagrange points to include. The default includes
all five; pass an empty sequence to omit them.
maneuvers: Optional maneuver markers in the trajectory's units.
phase_segments: Optional phase interval dictionaries with name,
t_start_s, t_end_s, and optional color keys.
reference_trajectories: Optional named trajectory dictionaries to
overlay, such as departure and arrival periodic orbits.
title: Figure title.
Source code in octavian/viz/plotly.py
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | |
save_relative_trajectory_html(traj: np.ndarray, out_html: str, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian relative trajectory', chief_radius_m: float = 0.0) -> None
Save an interactive chief-centered RIC trajectory as HTML.
This is the relative-motion counterpart to :func:save_trajectory_html.
It labels the RIC axes explicitly, places the chief at the origin, and does
not draw Earth in a frame where that geometry would be misleading.
Source code in octavian/viz/plotly.py
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | |
save_trajectory_diagnostics_html(traj: np.ndarray, out_html: str, *, frame_kind: str, mu_m3ps2: float | None = None, solar_directions_ric: np.ndarray | None = None, cr3bp_system: CR3BPSystem | None = None, cr3bp_dimensional: bool = True, title: str = 'octavian trajectory diagnostics') -> None
Save frame-aware trajectory time histories as interactive HTML.
Source code in octavian/viz/plotly.py
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 | |
save_trajectory_html(traj: np.ndarray, out_html: str, *, x0_r_m: np.ndarray | None = None, x0_v_mps: np.ndarray | None = None, xf_r_m: np.ndarray | None = None, xf_v_mps: np.ndarray | None = None, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian trajectory', earth_radius_m: float = EARTH_RADIUS_M, use_earth_texture: bool = True, earth_texture_path: str | None = None) -> None
Save a 3D Plotly HTML visualization of an ECI trajectory.
Args:
traj: Trajectory array with columns [rx, ry, rz, vx, vy, vz, t] in
meters, meters per second, and seconds.
out_html: Output HTML path.
x0_r_m: Optional initial position override in meters.
x0_v_mps: Optional initial velocity override in meters per second.
xf_r_m: Optional final position override in meters.
xf_v_mps: Optional final velocity override in meters per second.
maneuvers: Optional maneuver markers.
phase_segments: Optional phase interval dictionaries with name,
t_start_s, t_end_s, and optional color keys.
reference_trajectories: Dashed overlays with traj position rows
in the same frame and units, plus optional name and color.
Velocity and time columns are ignored.
title: Plot title.
earth_radius_m: Earth radius used for the sphere in meters.
use_earth_texture: Whether to render Earth with a texture map.
earth_texture_path: Optional path to an equirectangular Earth texture.
None uses the packaged default and "" disables the texture.
Raises:
ValueError: If traj is not a 2D array with at least seven columns.
Source code in octavian/viz/plotly.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | |
trajectory_diagnostics_figure(traj: np.ndarray, *, frame_kind: str, mu_m3ps2: float | None = None, solar_directions_ric: np.ndarray | None = None, cr3bp_system: CR3BPSystem | None = None, cr3bp_dimensional: bool = True, title: str = 'octavian trajectory diagnostics') -> Any
Build stacked, shared-time plots appropriate to the trajectory frame.
Source code in octavian/viz/plotly.py
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | |
octavian.viz.matplotlib
Matplotlib-based trajectory and diagnostic visualization helpers.
The functions in this module mirror Octavian's Plotly views while producing
ordinary Matplotlib figures. Figure builders support further customization,
save_*_image helpers write PNG or JPEG files, and show_* helpers open
the active Matplotlib GUI backend.
cr3bp_trajectory_figure(traj: np.ndarray, *, system: CR3BPSystem, dimensional: bool = True, lagrange_point_names: Sequence[str] | None = None, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian CR3BP trajectory', projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0)) -> Any
Build a static barycentric-synodic CR3BP trajectory figure.
projection accepts "3d", "xy", "xz", or "yz".
reference_trajectories contains dictionaries with traj position
rows in the same frame/units and optional name and color.
Source code in octavian/viz/matplotlib.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | |
relative_trajectory_figure(traj: np.ndarray, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian relative trajectory', chief_radius_m: float = 0.0, projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0)) -> Any
Build a static chief-centered RIC trajectory figure.
projection accepts "3d", "xy" (radial/in-track), "xz"
(radial/cross-track), or "yz" (in-track/cross-track).
reference_trajectories contains dictionaries with traj position
rows in RIC meters and optional name and color for dashed overlays.
Source code in octavian/viz/matplotlib.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
save_cr3bp_trajectory_image(traj: np.ndarray, out_image: str | Path, *, system: CR3BPSystem, dimensional: bool = True, lagrange_point_names: Sequence[str] | None = None, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian CR3BP trajectory', projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0), dpi: int = 160) -> None
Save a barycentric-synodic CR3BP trajectory as PNG or JPEG.
Source code in octavian/viz/matplotlib.py
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | |
save_figure_image(figure: Any, out_image: str | Path, *, dpi: int = 160) -> None
Save an existing Matplotlib figure as PNG or JPEG, then close it.
Source code in octavian/viz/matplotlib.py
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 | |
save_relative_trajectory_image(traj: np.ndarray, out_image: str | Path, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian relative trajectory', chief_radius_m: float = 0.0, projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0), dpi: int = 160) -> None
Save a chief-centered RIC trajectory as PNG or JPEG.
Source code in octavian/viz/matplotlib.py
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | |
save_trajectory_diagnostics_image(traj: np.ndarray, out_image: str | Path, *, frame_kind: str, mu_m3ps2: float | None = None, solar_directions_ric: np.ndarray | None = None, cr3bp_system: CR3BPSystem | None = None, cr3bp_dimensional: bool = True, title: str = 'octavian trajectory diagnostics', figsize: tuple[float, float] | None = None, dpi: int = 160) -> None
Save frame-aware trajectory diagnostic panels as PNG or JPEG.
Source code in octavian/viz/matplotlib.py
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | |
save_trajectory_image(traj: np.ndarray, out_image: str | Path, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian trajectory', earth_radius_m: float = EARTH_RADIUS_M, projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0), dpi: int = 160) -> None
Save an Earth-centered trajectory as PNG or JPEG.
Source code in octavian/viz/matplotlib.py
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | |
show_cr3bp_trajectory(traj: np.ndarray, **kwargs: Any) -> Any
Open a barycentric-synodic trajectory with the active GUI backend.
Source code in octavian/viz/matplotlib.py
521 522 523 | |
show_figure(figure: Any) -> Any
Display an existing figure with the active Matplotlib GUI backend.
Source code in octavian/viz/matplotlib.py
810 811 812 813 | |
show_relative_trajectory(traj: np.ndarray, **kwargs: Any) -> Any
Open a chief-centered RIC trajectory with the active GUI backend.
Source code in octavian/viz/matplotlib.py
516 517 518 | |
show_trajectory(traj: np.ndarray, **kwargs: Any) -> Any
Open an Earth-centered trajectory with the active GUI backend.
Source code in octavian/viz/matplotlib.py
511 512 513 | |
show_trajectory_diagnostics(traj: np.ndarray, **kwargs: Any) -> Any
Open frame-aware trajectory diagnostics with the active GUI backend.
Source code in octavian/viz/matplotlib.py
526 527 528 | |
trajectory_diagnostics_figure(traj: np.ndarray, *, frame_kind: str, mu_m3ps2: float | None = None, solar_directions_ric: np.ndarray | None = None, cr3bp_system: CR3BPSystem | None = None, cr3bp_dimensional: bool = True, title: str = 'octavian trajectory diagnostics', figsize: tuple[float, float] | None = None) -> Any
Build static, shared-time diagnostic panels for a trajectory frame.
Source code in octavian/viz/matplotlib.py
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | |
trajectory_figure(traj: np.ndarray, *, maneuvers: Sequence[Maneuver] | None = None, phase_segments: Sequence[dict[str, object]] | None = None, reference_trajectories: Sequence[dict[str, object]] | None = None, title: str = 'octavian trajectory', earth_radius_m: float = EARTH_RADIUS_M, projection: str = '3d', figsize: tuple[float, float] = (9.0, 7.0)) -> Any
Build a static Earth-centered inertial trajectory figure.
Args:
traj: Rows [rx, ry, rz, vx, vy, vz, time] in SI units.
maneuvers: Optional maneuver markers.
phase_segments: Optional phase dictionaries with name,
t_start_s, t_end_s, and optional color keys.
reference_trajectories: Dashed overlays with traj position rows,
optional name and color. Use the same ECI frame and SI
units as traj; velocity and time columns are ignored.
title: Figure title.
earth_radius_m: Earth radius in meters.
projection: "3d" or a 2D "xy", "xz", or "yz"
projection.
figsize: Matplotlib figure size in inches.
Returns:
A :class:matplotlib.figure.Figure. Positions are displayed in km.
Source code in octavian/viz/matplotlib.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
octavian.study
Study helpers for repeatable parameter sweeps.
best_by(results: Iterable[RendezvousResult], key: str = 'total_dv_mps', *, require_converged: bool = True) -> RendezvousResult
Select the best result in a study by a named metric.
Args:
results: Results to compare.
key: Metric name. Supported values are "total_dv_mps", "tf_s",
and "last_obj".
require_converged: Whether to discard non-converged results before
ranking.
Returns: The best result under the requested metric.
Raises: ValueError: If no results remain after filtering or the metric name is unsupported.
Source code in octavian/study.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
grid(base_spec: Spec, overrides: Sequence[dict[str, Any]], *, options: SolverOptions | None = None, save_dir: str | Path | None = None, save_prefix: str = 'run') -> list[RendezvousResult]
Run a grid study by applying overrides to a base spec.
Args:
base_spec: Baseline problem specification.
overrides: Override dictionaries passed to
dataclasses.replace(base_spec, **override).
options: Shared solver options. If omitted, defaults are used.
save_dir: Optional directory where each result is saved as .npz and
companion JSON.
save_prefix: Prefix for output filenames.
Returns:
Results in the same order as overrides.
Source code in octavian/study.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |