Skip to content

Commit 1556ad6

Browse files
Fix clang-tidy in CI, add further documentation (#18)
* modify cpp file to check clang-tidy * try fixing clang-tidy * add docs skeleton and transform sensor documentation * east const * pre-commit fixes * change humble to run on 22.04 * remove clang-format install
1 parent 19d5703 commit 1556ad6

371 files changed

Lines changed: 2373 additions & 2294 deletions

File tree

Some content is hidden

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

.clang-format

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ NamespaceIndentation: None
1515
ContinuationIndentWidth: 4
1616
IndentCaseLabels: true
1717
IndentFunctionDeclarationAfterType: false
18+
QualifierAlignment: Right
1819

1920
AlignEscapedNewlinesLeft: false
2021
AlignTrailingComments: true

.github/workflows/ci.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ permissions:
1919
jobs:
2020
build-ws:
2121
name: Build colcon workspace
22-
runs-on: ubuntu-24.04
22+
runs-on: ubuntu-22.04
2323
steps:
2424
- name: Checkout source
2525
uses: actions/checkout@v4
@@ -54,7 +54,7 @@ jobs:
5454
needs:
5555
# Ensure the test job runs after the build job finishes instead of attempting to run in parallel
5656
- build-ws
57-
runs-on: ubuntu-24.04
57+
runs-on: ubuntu-22.04
5858
container:
5959
# Run on the Docker image we tagged and pushed to a private repo in the job above
6060
image: ghcr.io/picknikrobotics/fuse:${{ github.run_id }}
@@ -79,7 +79,7 @@ jobs:
7979
# Ensure the test job runs after the build job finishes instead of attempting to run in parallel
8080
- build-ws
8181
name: clang-tidy
82-
runs-on: ubuntu-24.04
82+
runs-on: ubuntu-22.04
8383
container:
8484
# Run on the Docker image we tagged and pushed to a private repo in the job above
8585
image: ghcr.io/picknikrobotics/fuse:${{ github.run_id }}
@@ -93,7 +93,8 @@ jobs:
9393
**.cpp
9494
**.hpp
9595
- if: ${{ steps.changed-cpp-files.outputs.all_changed_files != '' }}
96-
run: run-clang-tidy -j $(nproc --all) -p build/ -export-fixes clang-tidy-fixes.yaml -config "$(cat src/fuse/.clang-tidy)" ${{ steps.changed-cpp-files.outputs.all_changed_files }}
96+
# https://stackoverflow.com/questions/48404289/using-clang-tidy-to-check-c17-code
97+
run: run-clang-tidy -j $(nproc --all) -p build/ -export-fixes clang-tidy-fixes.yaml -config "$(cat src/fuse/.clang-tidy)" -extra-arg=-std=c++17 ${{ steps.changed-cpp-files.outputs.all_changed_files }}
9798
working-directory: /colcon_ws
9899
- uses: asarium/clang-tidy-action@v1.0
99100
with:

.github/workflows/pre-commit.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ on:
1212
jobs:
1313
pre-commit:
1414
name: Format
15-
runs-on: ubuntu-24.04
15+
runs-on: ubuntu-22.04
1616
steps:
1717
- uses: actions/checkout@v4
1818
- uses: actions/setup-python@v5
1919
with:
2020
python-version: '3.10'
21-
- name: Install clang-format-18
22-
run: sudo apt-get install clang-format-18
2321
- uses: pre-commit/action@v3.0.1
2422
id: precommit
2523
- name: Upload pre-commit changes

README.md

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Welcome to PickNik Robotics's fork of fuse!
44

5+
This branch is for ROS Humble.
6+
57
## Getting Started
68

79
Using the Dockerfile is the easiest way to get started. Once inside, simply `rosdep update` and `colcon build` and you're ready to get started! Try `ros2 launch fuse_tutorials fuse_3d_tutorial.launch.py` and look at its pertinent code for a crash course in fuse and its capabilities.
@@ -40,7 +42,7 @@ optimizer will cache the constraints and process them in small batches on some s
4042
require considerable processing time, introducing a delay between the completion of the optimization cycle and the
4143
publishing of data to the ROS topic.
4244

43-
![fuse sequence diagram](doc/fuse_sequence_diagram.png)
45+
![fuse sequence diagram](doc/images/fuse_sequence_diagram.png)
4446

4547
## Example
4648

@@ -74,14 +76,14 @@ time. This is enough to construct our first `fuse` system. Below is the constrai
7476
system. The large circles represent state variables at a given time, while the small squares represent measurements.
7577
The graph connectivity indicates which variables are involved in what measurements.
7678

77-
![fuse graph](doc/fuse_graph_1.png)
79+
![fuse graph](doc/images/fuse_graph_1.png)
7880

7981
The two sensor models are configured as plugins to an optimizer implementation. The optimizer performs the required
8082
computation to generate the optimal state variable values based on the provided sensor constraints. We will never be
8183
able to exactly satisfy both the wheel encoder constraints and the laserscan constraints. Instead we minimize the error
8284
of all the constraints using nonlinear least squares optimization.
8385

84-
![fuse optimizer](doc/fuse_optimizer_1.png)
86+
![fuse optimizer](doc/images/fuse_optimizer_1.png)
8587

8688
While our `fuse` system is optimizing constraints from two different sensors, it is not yet publishing any data back
8789
out to ROS. In order to publish data to ROS, we derive a `fuse_core::Publisher` class and add it to the
@@ -90,7 +92,7 @@ implementation determines what type of messages are published and at what freque
9092
we would like visualize the current pose of the robot in RViz, so we create a `fuse` publisher that finds the most
9193
recent pose and converts it into a `geometry_msgs::msg::PoseStamped` message, then publishes the message to a topic.
9294

93-
![fuse optimizer](doc/fuse_optimizer_2.png)
95+
![fuse optimizer](doc/images/fuse_optimizer_2.png)
9496

9597
We finally have something that is starting to be useful.
9698

@@ -100,38 +102,38 @@ Typically the laser measurements and the wheel encoder measurements are not sync
100102
sampled faster than the laser, and are sampled at different times using a different clock. If we do not do anything
101103
different in this situation, the constraint graph becomes disconnected.
102104

103-
![fuse graph](doc/fuse_graph_2.png)
105+
![fuse graph](doc/images/fuse_graph_2.png)
104106

105107
This is where motion models come into play. A motion model differs from a sensor model in that constraints can be
106108
generated between any two requested timestamps. Motion model constraints are generated upon request, not due to their
107109
own internal clock. We use the motion model to connect the states introduced by the other sensor measurements. We
108110
derive a class from the `fuse_core::MotionModel` base class and implement a differential drive kinematic
109111
constraint for our robot.
110112

111-
![fuse optimizer](doc/fuse_optimizer_3.png)
113+
![fuse optimizer](doc/images/fuse_optimizer_3.png)
112114

113115
The motion models are also configured as plugins to the optimizer. The optimizer requests motion models constraints
114116
from the configured plugins whenever new states are created by the sensor models.
115117

116-
![fuse graph](doc/fuse_graph_3.png)
118+
![fuse graph](doc/images/fuse_graph_3.png)
117119

118120
### Adaptation #2: Full path publishing
119121

120122
Nothing about the `fuse` framework limits you to having a single publisher. What if you want to visualize the entire
121123
robot trajectory, instead of just the most recent pose? Well, we can create a new derived `fuse_core::Publisher` class
122124
that publishes all of the robot poses using a `nav_msgs::msg::Path` message.
123125

124-
![fuse optimizer](doc/fuse_optimizer_4.png)
126+
![fuse optimizer](doc/images/fuse_optimizer_4.png)
125127

126128
### Adaptation #3: Changing kinematics
127129

128130
In your spare time, you also build [autonomous power wheels racers](http://www.powerracingseries.org/). But race cars
129131
don't use differential drive; you need a different motion model. Easy enough. We simply derive a new
130132
`fuse_core::MotionModel` class that implements an Ackermann steering model. Everything else can be reused.
131133

132-
![fuse optimizer](doc/fuse_optimizer_5.png)
134+
![fuse optimizer](doc/images/fuse_optimizer_5.png)
133135

134-
![fuse graph](doc/fuse_graph_4.png)
136+
![fuse graph](doc/images/fuse_graph_4.png)
135137

136138
### Adaptation #4: Online calibration
137139

@@ -146,9 +148,9 @@ how the wheel diameter is expected to change over time. Maybe some sort of expon
146148
derive a new publisher plugin from `fuse_core::Publisher` that publishes the current wheel diameter. This allows us to
147149
plot how the wheel diameter changes over the length of the race.
148150

149-
![fuse optimizer](doc/fuse_optimizer_6.png)
151+
![fuse optimizer](doc/images/fuse_optimizer_6.png)
150152

151-
![fuse graph](doc/fuse_graph_5.png)
153+
![fuse graph](doc/images/fuse_graph_5.png)
152154

153155
Now our system estimates the wheel diameters at each time step as well as the robot's pose.
154156

@@ -167,11 +169,27 @@ end users to concentrate on modeling the robot, sensor, system, etc. and spend l
167169
sensor models together into runable code. And since all of the models are implemented as plugins, separate plugin
168170
libraries can be shared or kept private at the discretion of their authors.
169171

170-
## API Concepts
172+
## Documentation
173+
174+
### API Concepts
171175

172-
* [Variables](doc/Variables.md)
173-
* [Constraints](doc/Constraints.md)
176+
* Optimizers -- coming soon
177+
* [Variables](doc/concepts/Variables.md)
178+
* Graphs -- coming soon
174179
* Sensor Models -- coming soon
175180
* Motion Models -- coming soon
176181
* Publishers -- coming soon
177-
* Optimizers -- coming soon
182+
* [Constraints](doc/concepts/Constraints.md)
183+
184+
### Implementation Documentation
185+
186+
This is documentation of specific implementations of the above concepts.
187+
188+
Documentation in progress, see [this issue](https://github.com/PickNikRobotics/fuse/issues/23).
189+
190+
* [Optimizers](./fuse_optimizers/doc/optimizers.md)
191+
* [Variables](./fuse_variables/doc/variables.md)
192+
* [Graphs](./fuse_graphs/doc/graphs.md)
193+
* [Motion Models](./fuse_models/doc/motion_models/motion_models.md)
194+
* [Sensor Models](./fuse_models/doc/sensor_models/sensor_models.md)
195+
* [Constraints](./fuse_constraints/doc/constraints.md)
File renamed without changes.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ the system. There are several reasons multiple identities of a Variable will be
1717

1818
* The Variable may represent a property common to multiple entity types. Both a robot and a visual landmark have a
1919
position in space. Different identities of the same Variable may be used to describe these different entities.
20-
![common property](variables-common_property.png)
20+
![common property](../images/variables-common_property.png)
2121
* Similarly, there may be multiple occurrences of the same entity type within the system. A multi-robot configuration
2222
will want to track the pose of each robot, and thus different identities of a Variable will be used for each robot
2323
in the system.
24-
![multiple occurrences](variables-multiple_occurrences.png)
24+
![multiple occurrences](../images/variables-multiple_occurrences.png)
2525
* Most commonly, a Variable will represent a time-varying process. A different identity will be required for each
2626
time instant for which the process value is to be estimated. For example, the pose of the robot will change over
2727
time, so we need a unique identity representing the robot pose at time `t1` **and** another unique identity
2828
representing the robot pose at time `t2`. Any time-varying process must be discretized within the fuse stack.
29-
![time series](variables-time_series.png)
29+
![time series](../images/variables-time_series.png)
3030

3131
The identity takes the form of a UUID or hash, and is generally derived from a set of additional properties that
3232
describe what makes each occurrence unique from other occurrences. In the case of a time-varying process, this will

0 commit comments

Comments
 (0)