Skip to content
This repository was archived by the owner on May 18, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
"mkdocs",
"mypy",
"OMPL",
"proto",
"Protobuf",
"protofiles",
"Raye",
"rclcpp",
"roscd",
"roslaunch",
"rosrun",
"srcnew",
"srcraye",
"srcs",
"struct",
"Structs",
"uncrustify",
Expand Down
107 changes: 107 additions & 0 deletions docs/current/network_systems/repo_structure.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like most, if not all of this information in this file, might belong on the project README rather than the docs website. How do others feel about this? @patrick-5546 @hhenry01?

Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Repository Structure

## root

The Network Systems directory is similar to the following (READMEs and CMakeLists excluded):

```
network_systems
| package.xml
|
└───.github
| | ...
|
└───launch
| | ...
|
└───lib
| └───protofiles
| | message.proto
| | ...
|
└───projects
└───example
| └───inc
| | | example.h
| | | ...
| |
| └───src
| | | example.cpp
| | | example_subscriber.cpp
| | | ...
| |
| └───test
| | | test_example.cpp
| | | ...
|
└───...

```

At the root of the directory is a `package.xml`. This file tells ROS2 that the network_systems package exists. It is
what allows us to run, for example: `ros2 run network_systems main_launch.py`.

`.github/` contains Github specific files like workflows for continuous integration.

`launch/` contains ROS launch files.

## lib

The lib is where we will place static libraries that we want to be accessible to all programs. This means they do not
generate their own executable and will always link to a program in the projects directory.

To add new libraries, create a folder and add it to `lib/CMakeLists.txt`. Add a `CMakeLists.txt` file to your newly
created folder and fill it out accordingly.

## projects

Each directory found under projects is module directory. For example, the CAN transceiver will have its own folder in
this directory. Each module will define its executable, unit test executable, and (optionally) its public interface.

Additionally, we will separate the functional source file (`example.cpp`) from the the ROS communication interface file
(`example_subscriber.cpp`). The point is to make the unit tests cover only the functional code, while the communication
code is tackled by integration testing.

To add a new module, create a folder and add it to `projects/CMakeLists.txt`. In your new module folder, add an `inc/`
(optional), `src/`, and `test/` folder, as well as a `CMakeLists.txt` which will need to be filled out accordingly.

??? example
This is the `CMakeLists.txt` for an example module where the source files are for a Cached Fibonacci program.

```cmake
set(module example)

# Create module library
set(srcs
${CMAKE_CURRENT_LIST_DIR}/src/cached_fib.cpp
)
# Make the header accessible to other modules
add_library(${module} ${srcs})
target_include_directories(${module} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ${PROTOBUF_INCLUDE_PATH})

# Create module ROS executable
set(bin_module bin_${module})
set(bin_srcs
${srcs}
${CMAKE_CURRENT_LIST_DIR}/src/cached_fib_subscriber.cpp
)
add_executable(${bin_module} ${bin_srcs})
ament_target_dependencies(${bin_module} rclcpp std_msgs)
target_include_directories(${bin_module} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ${PROTOBUF_INCLUDE_PATH})
install(TARGETS ${bin_module} DESTINATION lib/${PROJECT_NAME})
# Rename the output binary to just be the module name
set_target_properties(${bin_module} PROPERTIES OUTPUT_NAME ${module})

# Create unit test
set(test_module test_${module})
set(test_srcs
${srcs}
${CMAKE_CURRENT_LIST_DIR}/test/test_cached_fib.cpp
)
add_executable(${test_module} ${test_srcs})
target_include_directories(${test_module} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/inc ${PROTOBUF_INCLUDE_PATH})
target_link_libraries(${test_module} ${GTEST_LINK_LIBS})
# Make the unit test runnable with CTest (invoked via test.sh)
add_test(NAME ${test_module} COMMAND ${test_module})

```
64 changes: 45 additions & 19 deletions docs/reference/cpp/differences.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ For most use cases, you can think of C++ as a superset of C. While this is not t
you are able to write standard C code for a C++ program without issues. However, doing so ignores a lot of the benefits
and reasons to use C++.

!!! note
Function definitions and declarations shown on this page will often look like `type function_name(void);`. This is
standard in C to denote no parameters. In C++, it is considered better practice to use `type function_name();`
without the void. There is some nuance to this which you can read about [here](https://softwareengineering.stackexchange.com/questions/286490/what-is-the-difference-between-function-and-functionvoid){target=_blank}.

## Classes and Structs

In C structs can only contain member variables, but in C++ structs are basically classes but with a default member
Expand All @@ -13,7 +18,8 @@ visibility of public instead of private.
The following code blocks are equivalent.

```C++
struct foo {
struct foo
{
private:
int x;
void helper(void);
Expand All @@ -23,7 +29,8 @@ visibility of public instead of private.
```

```C++
class foo {
class foo
{
private:
int x;
void helper(void);
Expand Down Expand Up @@ -63,7 +70,8 @@ Though be aware that namespaces are not necessary everywhere. See the following
#include "A.h"
#include "B.h"

int main(void) {
int main(void)
{
int a = bar();
...
}
Expand All @@ -73,14 +81,16 @@ Though be aware that namespaces are not necessary everywhere. See the following
=== "C++"

```C++ title="A.h"
namespace a {
namespace a
{
float x;
int bar(void);
}
```

```C++ title="B.h"
namespace b {
namespace b
{
float x;
int bar(void);
}
Expand All @@ -90,7 +100,8 @@ Though be aware that namespaces are not necessary everywhere. See the following
#include "A.h"
#include "B.h"

int main(void) {
int main(void)
{
int a = a::bar();
int b = b::bar();
float xa = a::x;
Expand All @@ -107,7 +118,8 @@ Though be aware that namespaces are not necessary everywhere. See the following
using namespace std;
namespace io = std::filesystem;

int main(int argc, char* argv[]) {
int main(int argc, char* argv[])
{
bool isDirectory = io::is_directory(argv[1]); // Equivalent to std::filesystem::is_directory(argv[1])
cout << isDirectory << endl;
return 0;
Expand All @@ -124,11 +136,13 @@ Though be aware that namespaces are not necessary everywhere. See the following
=== "OK"

```C++
class string {
class string
{
// Insert implementation here
}

int main(void) {
int main(void)
{
string ourString = "Our own string implementation";
std::string stdString = "Standard Library string implementation";
...
Expand All @@ -141,7 +155,8 @@ Though be aware that namespaces are not necessary everywhere. See the following
using namespace std;

// ERROR - multiple definitions of type string
class string {
class string
{

}
```
Expand All @@ -154,6 +169,8 @@ Though be aware that namespaces are not necessary everywhere. See the following

## Constant Expressions

TL;DR use constant expressions over macros whenever possible.

In C, if we want to declare a constant or a function/expression that we want to be evaluated at compile time, we need
to use `#define` statements. One of the problems with `#define` statements is that they perform a simple copy paste
wherever they're used. For example:
Expand All @@ -164,7 +181,8 @@ wherever they're used. For example:
#define PI 3.14F
#define AREA_OF_CIRCLE(radius) ((PI) * (radius) * (radius))

int main(void) {
int main(void)
{
float area = AREA_OF_CIRCLE(2.5F);
...
}
Expand All @@ -173,7 +191,8 @@ wherever they're used. For example:
=== "After Precompile"

```C++
int main(void) {
int main(void)
{
float area = ((3.14F) * (2.5F) * (2.5F));
...
}
Expand All @@ -192,7 +211,8 @@ In C++, the use of constant expressions are preferred.

```C++
constexpr float pi = 3.14F;
constexpr float area_of_circle(float radius) {
constexpr float area_of_circle(float radius)
{
return pi * radius * radius;
}
```
Expand All @@ -201,12 +221,14 @@ Constant expressions do *not* get copy pasted, and are instead placed in program
or function. They also respect namespaces and function scopes, meaning the following code compiles.

```C++ title="Constant Expression Scoping"
void foo(void) {
void foo(void)
{
constexpr float rand = 123.456;
...
}

void bar (void) {
void bar (void)
{
constexpr float rand = 789.123;
...
}
Expand Down Expand Up @@ -236,13 +258,15 @@ costs.
```C
#include "stdio.h"

void print_contents(int *arr, int size) {
void print_contents(int *arr, int size)
{
for (int i = 0; i < size; i++) {
printf("%d\n", *arr);
}
}

int main(void) {
int main(void)
{
int arr[5] = {0, 1, 2, 3, 4};
foo(arr, 5);
return 0;
Expand All @@ -260,13 +284,15 @@ costs.
#include <array>
#include <span>

void print_contents(std::span<int> container) {
void print_contents(std::span<int> container)
{
for (const auto &e : container) {
std::cout << e << std::endl;
}
}

int main(void) {
int main(void)
{
std::array<int, 5> arr = {0, 1, 2, 3, 4};
foo(arr);
return 0;
Expand Down
Loading