update satrs book

This commit is contained in:
Robin Mueller
2026-08-25 18:55:52 +02:00
parent 2cf39a0e1c
commit d2b8bc6afb
14 changed files with 2826 additions and 66 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
<p align="center"> <img src="misc/satrs-logo-v2.png" width="40%"> </p>
[![sat-rs website](https://img.shields.io/badge/sat--rs-website-darkgreen?style=flat)](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
<!-- [![sat-rs website](https://img.shields.io/badge/sat--rs-website-darkgreen?style=flat)](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/) -->
[![sat-rs book](https://img.shields.io/badge/sat--rs-book-darkgreen?style=flat)](https://robamu.github.io/sat-rs/book/)
[![Crates.io](https://img.shields.io/crates/v/satrs)](https://crates.io/crates/satrs)
[![docs.rs](https://img.shields.io/docsrs/satrs)](https://docs.rs/satrs)
+4
View File
@@ -35,3 +35,7 @@ docs-satrs:
RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p satrs --all-features
docs: docs-satrs
[working-directory:"satrs-book"]
book *args:
mdbook build {{args}}
+8 -1
View File
@@ -1,9 +1,16 @@
[book]
authors = ["Robin Mueller"]
language = "en"
multilingual = false
src = "src"
title = "The sat-rs book"
[output.html]
additional-js = ["mermaid.min.js", "mermaid-init.js"]
[output.linkcheck]
command = "mdbook-linkcheck2"
[preprocessor]
[preprocessor.mermaid]
command = "mdbook-mermaid"
+39
View File
@@ -0,0 +1,39 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
(() => {
const darkThemes = ['ayu', 'navy', 'coal'];
const lightThemes = ['light', 'rust'];
const classList = document.getElementsByTagName('html')[0].classList;
let lastThemeWasLight = true;
for (const cssClass of classList) {
if (darkThemes.includes(cssClass)) {
lastThemeWasLight = false;
break;
}
}
const theme = lastThemeWasLight ? 'default' : 'dark';
mermaid.initialize({ startOnLoad: true, theme });
// Simplest way to make mermaid re-render the diagrams in the new theme is via refreshing the page
for (const darkTheme of darkThemes) {
document.getElementById('mdbook-theme-' + darkTheme).addEventListener('click', () => {
if (lastThemeWasLight) {
window.location.reload();
}
});
}
for (const lightTheme of lightThemes) {
document.getElementById('mdbook-theme-' + lightTheme).addEventListener('click', () => {
if (!lastThemeWasLight) {
window.location.reload();
}
});
}
})();
+2609
View File
File diff suppressed because one or more lines are too long
+6 -1
View File
@@ -1,11 +1,11 @@
# Summary
- [Introduction](./introduction.md)
- [Design](./design.md)
# Basic concepts and components
- [Communication with Space Systems](./communication.md)
- [TMTC modelling](./tmtc-modelling.md)
- [Working with Constrained Systems](./constrained-systems.md)
- [Actions](./actions.md)
- [Modes and Health](./modes-and-health.md)
@@ -15,3 +15,8 @@
# Example project
- [The satrs-example application](./example.md)
# Additional information
- [Design](./design.md)
+5 -36
View File
@@ -3,40 +3,9 @@
Space systems generally need to be commanded regularly. This can include commands periodically
required to ensure a healthy system, or commands to reach the mission goals.
These commands can be modelled using the concept of Actions. the ECSS PUS standard also provides
the PUS service 8 for actions, but provides few concrete subservices and specification on how
action commanding could look like.
`sat-rs` proposes two recommended ways to perform action commanding:
1. Target ID and Action ID based. The target ID is a 32-bit unsigned ID for an OBSW object entity
which can also accept Actions. The action ID is a 32-bit unsigned ID for each action that a
target is able to perform.
2. Target ID and Action String based. The target ID is the same as in the first proposal, but
the unique action is identified by a string.
The library provides an `ActionRequest` abstraction to model both of these cases.
## Commanding with ECSS PUS 8
`sat-rs` provides a generic ECSS PUS 8 action command handler. This handler can convert PUS 8
telecommands which use the commanding scheme 1 explained above to an `ActionRequest` which is
then forwarded to the target specified by the Target ID.
There are 3 requirements for the PUS 8 telecommand:
1. The subservice 128 must be used
2. Bytes 0 to 4 of application data must contain the target ID in `u32` big endian format.
3. Bytes 4 to 8 of application data must contain the action ID in `u32` big endian format.
4. The rest of the application data are assumed to be command specific additional parameters. They
will be added to an IPC store and the corresponding store address will be sent as part of the
`ActionRequest`.
## Sending back telemetry
There are some cases where the regular verification provided by PUS in response to PUS action
commands is not sufficient and some additional telemetry needs to be sent to ground. In that
case, it is recommended to chose some custom subservice for action TM data and then send the
telemetry using the same scheme as shown above, where the first 8 bytes of the application
data is reserved for the target ID and action ID.
These commands can be modelled using the concept of Actions. If you have not read the
[TMTC modelling](./tmtc-modelling.md) chapter yet, it is recommended to read it first.
For a low number of actions, it is recommended to add the actions as `enum` variants of your
`Request` type. For a higher number of actions, you can create a dedicated `ActionRequest`
structure.
+54 -16
View File
@@ -8,14 +8,9 @@ most of these systems have internet access during development cycle. There are v
provided by CCSDS and ECSS which can be useful to determine how to communicate with the satellite
and the primary On-Board Software.
# Application layer
Most communication with space systems is usually packet based. For example, the CCSDS space
packet standard only specifies a 6 byte header with at least 1 byte payload. The PUS packet
standard is a subset of the space packet standard, which adds some fields and a 16 bit CRC, but
it is still centered around small packets. `sat-rs` provides support for these ECSS and CCSDS
standards and also attempts to fill the gap to the internet protocol by providing the following
components.
packet standard only specifies a 6 byte header with at least 1 byte payload. The `sat-rs` library
provides some support for the [CCSDS space packet protocol](https://ccsds.org/Pubs/133x0b2e2.pdf).
1. [UDP TMTC Server](https://docs.rs/satrs/latest/satrs/hal/std/udp_server/index.html).
UDP is already packet based which makes it an excellent fit for exchanging space packets.
@@ -31,21 +26,65 @@ components.
# Working with telemetry and telecommands (TMTC)
The commands sent to a space system are commonly called telecommands (TC) while the data received
from it are called telemetry (TM). Keeping in mind the previous section, the concept of a TC source
and a TM sink can be applied to most satellites. The TM sink is the one entity where all generated
telemetry arrives in real-time. The most important task of the TM sink usually is to send all
arriving telemetry to the ground segment of a satellite mission immediately. Another important
task might be to store all arriving telemetry persistently. This is especially important for
space systems which do not have permanent contact like low-earth-orbit (LEO) satellites.
from it are called telemetry (TM). One way to model the packet handling is to introduce the concept
of a TC source and a TM sink can be applied to most satellites. The TM sink is the one entity where
all generated telemetry arrives in real-time. The most important task of the TM sink usually is to
send all arriving telemetry to the ground segment of a satellite mission immediately.
Another important task might be to store all arriving telemetry persistently. This is especially
important for space systems which do not have permanent contact like low-earth-orbit (LEO)
satellites.
The diagram below shows one concrete example of how this could look like.
```mermaid
flowchart LR
Dev[Device Handlers] --> Sink[TM Sink]
Sub[Subsystem Handlers] --> Sink
Sink --> Ground[Ground Link]
Sink --> Store[Persistent Storage]
Sink --> Udp[UDP Server]
Sink --> Tcp[TCP Server]
```
The most important task of a TC source is to deliver the telecommands to the correct recipients.
For component oriented software using message passing, this usually includes staged demultiplexing
components to determine where a command needs to be sent.
For component oriented software using message passing, this usually includes demultiplexing
to determine where a command needs to be sent.
The diagram below shows one concrete example of how this could look like.
```mermaid
flowchart LR
Udp[UDP Server] --> Source[TC Source]
Tcp[TCP Server] --> Source
Radio[Radio Handler] --> Source
Source --> Dev[Device Handlers]
Source --> Sub[Subsystem Handlers]
Source --> File[File Service Handler]
```
Using a generic concept of a TC source and a TM sink as part of the software design simplifies
the flexibility of the TMTC infrastructure: Newly added TM generators and TC receiver only have to
forward their generated or received packets to those handler objects.
# Packet format
We talked about some basic support for the CCSDS space packet protocol. This is a really simple
protocol which just specifies a header that every exchanged TMTC packet has:
![Space Packet Header](./images/space-packet-standard.png)
This is a protocol which already provides us with some useful fields:
- ID field provided by the Application Process Identifier (APID). This can also be useful for packet
multiplexing
- Basic sequence counter which can be used to determine missed packets
However, how does the actual payload that we want to send to or from the satellite actually look
like? While there are standards like the Packet Utilisation Standard (PUS), we recommend a payload
format which is created with the excellent [`serde`](https://serde.rs/) library. The
[TMTC modelling](./tmtc-modelling.md) chapter provides more information.
# Low-level protocols and the bridge to the communcation subsystem
Many satellite systems usually use the lower levels of the OSI layer in addition to the application
@@ -55,4 +94,3 @@ might provide components to handle standard like the Unified Space Data Link Sta
software but most of the time the handling of communication is performed through custom
software and hardware. Still, connecting this custom software and hardware to `sat-rs` can mostly
be done by using the concept of TC sources and TM sinks mentioned previously.
+7 -1
View File
@@ -3,7 +3,7 @@
Software for space systems oftentimes has different requirements than the software for host
systems or servers. Currently, most space systems are considered embedded systems.
For these systems, the computation power and the available heap are important resources
For these systems, the computation power and the available memory are important resources
which are also constrained. This might make completeley heap based memory management schemes which
are oftentimes used on host and server based systems unfeasable. Still, completely forbidding
heap allocations might make software development unnecessarilly difficult, especially in a
@@ -14,6 +14,12 @@ initialization time and avoid frequent run-time allocations. This prevents issue
running out of memory (something even Rust can not protect from) or heap fragmentation on systems
without a MMU.
# Using an embedded allocator
The [`embedded-alloc`](https://github.com/rust-embedded/embedded-alloc) library provides
a global allocator based on statically sized memory blocks. It also exposes an API
which allows run-time tracking of the memory usage.
# Using pre-allocated pool structures
A candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all
+1 -2
View File
@@ -3,8 +3,7 @@
Satellites and space systems in general are complex systems with a wide range of requirements for
both the hardware and the software. Consequently, the general design of the library is centered
around many light-weight components which try to impose as few restrictions as possible on how to
solve certain problems. This is also the reason why sat-rs is explicitely called a library
instead of a framework.
solve certain problems.
There are still a lot of common patterns and architectures across these systems where guidance
of how to solve a problem and a common structure would still be extremely useful to avoid pitfalls
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

+6 -7
View File
@@ -14,23 +14,22 @@ The primary goal of the sat-rs library is to provide re-usable components
to write on-board software for remote systems like rovers or satellites. It is specifically written
for the special requirements for these systems.
It should be noted that sat-rs is early-stage software. Important features are missing. New releases
with breaking changes are released regularly, with all changes documented inside respective
changelog files. You should only use this library if your are willing to work in this
environment.
A lot of the architecture and general design considerations are based on the
Some architecture and general design considerations are based on the
[FSFW](https://egit.irs.uni-stuttgart.de/fsfw/fsfw) C++ framework which has flight heritage
through the 2 missions [FLP](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and-instruments/smallsatelliteprogram/flying-laptop/)
and [EIVE](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and-instruments/smallsatelliteprogram/EIVE/).
However, `sat-rs` has a significantly reduced scope compared to those frameworks. Rust provides
a great ecosystem and a powerful standard library which reduced the need of large and complex
frameworks.
# Getting started with the example
The [`satrs-example`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example)
provides various practical usage examples of the `sat-rs` framework. If you are more interested in
the practical application of `sat-rs` inside an application, it is recommended to have a look at
the example application. The [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim)
applicatin complements the example application and can be used to simulate some physical devices
application complements the example application and can be used to simulate some physical devices
for the `satrs-example` device handlers.
# Flight Heritage
-1
View File
@@ -1 +0,0 @@
# Serialization
+86
View File
@@ -0,0 +1,86 @@
# TMTC modelling using Rust
Before we talk about how to model telecommand and telemetry data using Rust, we are going
to present some basic concepts and useful libraries first.
## Serialization
Serialization and deserialization is the process of converting (Rust) data structures into
some format which can be stored or transmitted. We can use this system for generating the payload
of our telecommand and telemetry packets. This allows us to model our payloads with Rust data
structures, fits perfectly into the data-driven approach that Rust programs tend to favor and
allows us to use the excellent type system.
The Rust ecosystem provides the [`serde`](https://serde.rs/) library for this task. The library
makes it trivial to add serialization support to custom datastructures by providing a
[`derive`](https://serde.rs/derive.html) macro. In almost all cases, you can just add this derive
macro to a data structure to make it serializable with any `serde` compatible serializer.
There are various serializers available which are well suited to the requirements of space systems.
- Generally, we try to minimize the payload size to save data bandwidth.
- The data does not necessarily have to be human-readable
We recommend the [`postcard`](https://github.com/jamesmunns/postcard) serializer, which fulfills
these requirements and also works well for embedded systems.
## Modelling telecommands and telemetry
Using a serializer library like `serde` allows us to do some interesting things. For example,
let's assume you have a `Camera` object in software that you want to send some commands to.
This object should have the following capability:
- Process a ping command
- Capture an image
- Send back configuration data
You can now model a request to your `Camera` object using the following data structure
```rust
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum CameraRequest {
Ping,
CaptureImage,
RequestConfig,
}
```
This data structure models all the requests that the `Camera` provides.
On the telemetry side, you would have a similar object
```rust
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum CameraResponse {
Ok,
Config(ConfigStructure)
}
```
where `ConfigStructure` would be some other wrapped configuration structure, and the `Ok` response
would be the reply for successful execution for all other commands which do not have additional
telemetry information.
Rust makes it trivial to move components into a new shared library. You can now put these data
structures in a shared `types` or `data` library which can be re-used by both a ground system
library and by the on-board software.
On the ground system, you could use a function like [`postcard::to_allocvec`](https://docs.rs/postcard/latest/postcard/fn.to_allocvec.html)
to generate the byte representation of a `CameraRequest`, which is then sent as the payload
inside a CCSDS space packet. On the on-board software side, you can use
[`postcard::from_bytes`](https://docs.rs/postcard/latest/postcard/fn.from_bytes.html) to deserialize
the `CameraRequest` from the raw payload bytes. In both cases, you do not need to hand-write
the serialization and de-serialization code anymore. The only trade-off is that you need a Rust
conversion layer if you want to create your telecommands in another language like Python.
Using Rust structures like this also has other advantages. Once you have the `CameraRequest`
structure, you can `match` on it to cover **all** commands that the device handler needs to cover.
If you add a new field, you have to handle the new field variant as well and you can not forget
to handle a variant.
One trade-off to keep in mind is that a Rust `enum` will always have the size of its largest variant
in memory. If you need to send large payload to and from the on-board software, you can also
add this data as a secondary data blob behind the primary `serde` payload, and still send something
like small metadata as part of the payload. `postcard` can tell you the size of the deserialized
payload which helps with determining the size of any additional payload data.
We recommend this approach for all TMTC definitions where you control all sides of the communication.