Skip to content

Commit d36a18a

Browse files
authored
Merge pull request #142 from cactusdynamics/updated-readme
Updated readme
2 parents e086208 + 73ccce8 commit d36a18a

File tree

1 file changed

+169
-23
lines changed

1 file changed

+169
-23
lines changed

README.md

Lines changed: 169 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,174 @@ cactus-rt: a Linux real-time app framework
33

44
Relevant blog posts: [Part 1](https://shuhaowu.com/blog/2022/01-linux-rt-appdev-part1.html) | [Part 2](https://shuhaowu.com/blog/2022/02-linux-rt-appdev-part2.html) | [Part 3](https://shuhaowu.com/blog/2022/03-linux-rt-appdev-part3.html) | [Part 4](https://shuhaowu.com/blog/2022/04-linux-rt-appdev-part4.html)
55

6-
`cactus_rt` library
7-
-------------------
8-
9-
This is a library that refactors a lot of the boilerplate code needed for
10-
writing a real-time Linux application. Some key features are:
11-
12-
* `cactus_rt::App`: Implements logic for memory locking, memory reservation, and
13-
`malloc` tuning.
14-
* The memory reservation and `malloc` tuning may not be needed if an O(1)
15-
allocator is not used. See [this discussion](https://github.com/ros-realtime/ros2-realtime-examples/issues/9>).
16-
* `cactus_rt::Thread<SchedulerT>`: Implements a thread class. Applications are
17-
expected to create a derived class for their custom threads. The `SchedulerT`
18-
template argument specifies the scheduler class the thread can use. Right now,
19-
`cactus_rt::schedulers::Fifo`, `cactus_rt::schedulers::Deadline`, and
20-
`cactus_rt::schedulers::Other` (non-RT) can be used.
21-
* `cactus_rt::CyclicThread<SchedulerT>`: Implements a looping thread.
22-
* For applications with extra low-jitter requirements, it implements a busy
23-
wait method to reduce wakeup jitter. See [this](https://shuhaowu.com/blog/2022/04-linux-rt-appdev-part4.html#trick-to-deal-with-wake-up-jitter)
24-
for more details. In the future, this will be a scheduler
25-
(`cactus_rt::schedulers::FifoBusyWait`) but it is not yet implemented.
26-
* `cactus_rt::mutex`: A priority-inheriting mutex that is a drop-in replacement
27-
for `std::mutex`.
6+
Developing real-time applications is already difficult due to the need to
7+
validate all parts of the system from hardware to the application. On a
8+
general-purpose operating system such as Linux, the complexity increases further
9+
due to most APIs being optimized for throughput as opposed to maximum latency.
10+
11+
cactus-rt is a C++ library that aims to make writing real-time Linux
12+
applications as easy as writing Arduino programs. Real-time application
13+
developers simply have to fill out a `Loop` function achieve 1000 Hz on Linux.
14+
The library should make most of the tedious decisions for you and provide sane defaults for everything.
15+
16+
How?
17+
----
18+
19+
### Core library
20+
21+
The core of cactus-rt consists of code that wraps the underlying OS-level
22+
real-time APIs so your application do not have to call them manually. These
23+
components includes:
24+
25+
- `cactus_rt::App`: memory locking, malloc tuning, service thread creation.
26+
- `cactus_rt::Thread`: pthreads API for real-time thread creation
27+
- `cactus_rt::CyclicThread`: real-time-safe clock to implement real-time timer
28+
- `signal_handler`: handle signals
29+
30+
These are the bare minimum needed to create a real-time application. The
31+
interface is simple enough that all the application developer needs to do is to
32+
fill out `Loop` methods on classes derived from `CyclicThread`.
33+
34+
Example (full example in [examples/simple_example](examples/simple_example/)):
35+
36+
```c++
37+
class ExampleRTThread : public cactus_rt::CyclicThread {
38+
public:
39+
ExampleRTThread() : CyclicThread("ExampleRTThread", MakeConfig()) {}
40+
41+
protected:
42+
LoopControl Loop(int64_t elapsed_ns) noexcept final {
43+
// Your code here...
44+
return LoopControl::Continue;
45+
}
46+
47+
// ... MakeConfig definition omitted
48+
};
49+
50+
```
51+
52+
### Asynchronous logging integration via [Quill][quill]
53+
54+
Debugging logic bugs in real-time applications during development can be tedious
55+
as logging via STL logging facilities (`std::cout`, `std::print`) are not
56+
real-time-safe in general. To get around this problem, cactus-rt natively
57+
integrates with [Quill][quill], which is an asynchronous, lock-free, and
58+
allocation-free logging library that also allows for simple usability with
59+
template strings. cactus-rt sets up Quill to run in non-allocating mode which is
60+
safe for real-time usage.
61+
62+
Since printf debugging is a critical feature to debug during development (and
63+
beyond), having Quill integrated directly in cactus-rt makes debugging real-time
64+
applications as easy as normal applications.
65+
66+
Example (full example in [examples/simple_example](examples/simple_example/)):
67+
68+
```c++
69+
LoopControl Loop(int64_t elapsed_ns) noexcept final {
70+
LOG_INFO(Logger(), "Hello {} {}", "world", 123); // Hello world 123
71+
return LoopControl::Continue;
72+
}
73+
```
74+
75+
[quill]: https://github.com/odygrd/quill
76+
77+
### Runtime performance tracing and visualization
78+
79+
Debugging timing bugs in real-time applications is critical as missed deadlines
80+
can have catastrophic consequences. One of the design goal of this library is to
81+
make debugging timing problems as easy as printf debugging. To accomplish this,
82+
cactus-rt includes a real-time-safe tracing system (implemented in a lock-free
83+
and allocation-free manner) that can measure the timing of spans within the
84+
code.
85+
86+
This system is designed to be safe to run for real-time application in
87+
production, as many timing issues can only be debugged within production. For
88+
certain applications, the entire run session can theoretically be traced to
89+
enable detailed analysis in post.
90+
91+
Example (full example in [examples/tracing_example](examples/tracing_example/)):
92+
93+
```c++
94+
void Plan noexcept {
95+
// span will use RAII to emit a start and end event to be used for visualization
96+
// For this span, it would be the duration of this function
97+
auto span = Tracer().WithSpan("Plan");
98+
// ... your code
99+
}
100+
```
101+
102+
The tracing system emits data in [Perfetto][perfetto]-compatible format.
103+
Perfetto has likely the best tracing visualization and analysis system in the
104+
world. All you need to do is load up the generated trace file in a web UI
105+
(hosted on https://cactusdynamics.github.io/perfetto or https://ui.perfetto.dev;
106+
the analysis UI is entirely client side so no data is uploaded to any servers)
107+
the above code looks like the following in Perfetto:
108+
109+
<img src=docs/imgs/perfetto1.png />
110+
111+
You can also use SQL and [Vega-Lite](https://vega.github.io/vega-lite/) to
112+
further analyze your data. For more information, see [the tracing
113+
document](docs/tracing.md).
114+
115+
With this system in place, debugging timing issues for real-time applications
116+
becomes as simple as loading up a web UI.
117+
118+
[perfetto]: https://perfetto.dev/
119+
120+
### Native [ROS 2][ros2] support
121+
122+
Many real-time applications are written for robotics applications where
123+
interaction with ROS 2 is required. cactus-rt provides builtin support to publish
124+
and subscribe to ROS 2 topics from the real-time thread with a simple API. This
125+
API is designed to allow information to be passed to and from the real-time
126+
thread without impacting the real-time thread's maximum latency. An example use
127+
case maybe passing a goal pose to a real-time thread from ROS 2 and passing
128+
robot metrics collected by the real-time thread to ROS 2.
129+
130+
Example (full examples in [examples/ros2](examples/ros2/)):
131+
132+
```c++
133+
LoopControl Loop(int64_t elapsed_ns) noexcept final {
134+
StampedValue<Velocity2D> msg = cmd_vel_sub_->ReadLatest();
135+
136+
Velocity2D achieved_velocity = Drive(msg.value.vx, msg.value.vy, msg.value.w);
137+
feedback_pub_->Publish(achieved_velocity);
138+
139+
return LoopControl::Continue;
140+
}
141+
```
142+
143+
This significantly simplifies real-time robotics application development with ROS 2.
144+
145+
[ros2]: https://ros.org/
146+
147+
### Real-time-safe inter-thread communication
148+
149+
Passing messages between real-time and non-real-time threads is very common use
150+
case in real-time applications. Yet, it is quite difficult to do this in a
151+
real-time-safe manner. The simplest method, `std::mutex` is not even usable due
152+
to [priority inversion](https://en.wikipedia.org/wiki/Priority_inversion).
153+
cactus-rt solves this with a few different (yet non-exhaustive) approaches:
154+
155+
- The inclusion of `cactus_rt::mutex` which is a mutex that respects priority inheritance.
156+
- Lockless data structures that allows for a single value to be shared between a
157+
single non-real-time and a single real-time-thread under
158+
`cactus_rt::experimental::lockless`.
159+
- Some of these algorithms are developed by [Dave Rowland and Fabien Renn-Giles](https://www.youtube.com/watch?v=PoZAo2Vikbo). We also formally analyzed these algorithms with [TLA+](tla) which gives high confidence of their correctness.
160+
161+
Further, cactus-rt extensively uses and therefore links to
162+
[`moodycamel::readerwriterqueue`](https://github.com/cameron314/readerwriterqueue),
163+
which is a SPSC lockless, allocation-free queue. This can also solve a number of
164+
communication problems.
165+
166+
The integration of inter-thread communication APIs is designed to make life
167+
easier as then developers no longer have to manually implement or include
168+
libraries that do the same thing.
169+
170+
### Others and future work
171+
172+
There are some other utilities in cactus-rt other than the above, and there are always more ideas to allow for simpler real-time application development.
173+
28174
29175
Examples
30176
--------
@@ -156,7 +302,7 @@ compile your app in release mode.
156302
LICENSE
157303
-------
158304

159-
Open source projects and some commercial projects can use [MPL 2.0](https://www.mozilla.org/MPL/2.0/).
305+
Open source projects and some commercial projects can use [MPL 2.0](https://www.mozilla.org/MPL/2.0/). Please note the license's section 6 and 7 where it is noted that the software is provided "as is" and is not liable for any damages (the license text supersedes this excerpt).
160306

161307
If you need commercial, closed-sourced modifications, please obtain a license from [Cactus Dynamics](https://cactusdynamics.com).
162308

0 commit comments

Comments
 (0)