Skip to content

Commit ecaf284

Browse files
committed
docs: update README.md
1 parent c68991f commit ecaf284

3 files changed

Lines changed: 53 additions & 200 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Copyright (c) 2023 Dmitry Ponomarev
2-
# Distributed under the MIT License, available in the file LICENSE.
2+
# Distributed under the MPL v2.0 License, available in the file LICENSE.
33
# Author: Dmitry Ponomarev <ponomarevda96@gmail.com>
44

55
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

README.md

Lines changed: 47 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1,186 +1,48 @@
1-
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=PonomarevDA_dronecan_application&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=PonomarevDA_dronecan_application) [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=PonomarevDA_dronecan_application&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=PonomarevDA_dronecan_application) [![build](https://github.com/PonomarevDA/dronecan_application/actions/workflows/build.yml/badge.svg)](https://github.com/PonomarevDA/dronecan_application/actions/workflows/build.yml) [![check_crlf](https://github.com/PonomarevDA/dronecan_application/actions/workflows/check_crlf.yml/badge.svg)](https://github.com/PonomarevDA/dronecan_application/actions/workflows/check_crlf.yml)
2-
3-
# DroneCAN application
4-
5-
This is a C library with C++ helpers that brings up the [libcanard](https://github.com/dronecan/libcanard), platform-specific drivers and serialization together to build a minimal DroneCAN application.
6-
7-
A minimal application includes the following protocol-features:
8-
9-
|| type | message |
10-
| - | --------- | -------- |
11-
| 1 | broadcast | [uavcan.protocol.NodeStatus](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#nodestatus) |
12-
| 2 | RPC-service | [uavcan.protocol.GetNodeInfo](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#getnodeinfo) |
13-
| 3 | RPC-service | [uavcan.protocol.param.*](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#uavcanprotocolparam) |
14-
| 4 | RPC-service | [uavcan.protocol.RestartNode](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#restartnode) |
15-
| 5 | RPC-service | [uavcan.protocol.GetTransportStats](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#gettransportstats) |
16-
17-
The following auxiliary features should be provided as well:
18-
19-
- [x] actuator
20-
- [x] airspeed
21-
- [x] baro
22-
- [x] circuit status
23-
- [x] fuel tank
24-
- [x] esc
25-
- [x] ice
26-
- [x] indication
27-
- [x] power
28-
- [x] rangefinder
29-
- [ ] gnss
30-
- [x] mag
31-
- [ ] etc
32-
33-
The library should support the following platforms:
34-
- [x] Ubuntu: socketcan
35-
- [x] stm32f103: BXCAN based on platform specific
36-
- [x] stm32g0: FDCAN based on STM32 HAL
37-
- [ ] stm32f103: DroneCAN/Serial based on STM32 HAL
38-
39-
## Dependencies
40-
41-
- [libparams](https://github.com/PonomarevDA/libparams) v0.8.4 library.
42-
- [dronecan/libcanard](https://github.com/dronecan/libcanard)
43-
44-
## How to integrate the library into a project
45-
46-
Add the following lines into CMakeLists.txt of your project:
47-
48-
```cmake
49-
# 1. libdcnode
50-
add_subdirectory(${ROOT_DIR} ${CMAKE_BINARY_DIR}/libdcnode)
51-
52-
# 2. libcanver
53-
set(CAN_PLATFORM socketcan) # Options: bxcan, fdcan or socketcan
54-
include(${ROOT_DIR}/platform_specific/${CAN_PLATFORM}/config.cmake)
55-
56-
# 3. libparams
57-
set(LIBPARAMS_PLATFORM ubuntu) # Options: stm32f103, stm32g0b1, ubuntu
58-
include(libparams.cmake)
59-
60-
# 4. Application
61-
add_executable(${PROJECT_NAME}
62-
...
63-
${DRONECAN_PLATFORM_SOURCES}
64-
...
65-
)
66-
target_include_directories(${PROJECT_NAME} PRIVATE
67-
...
68-
${DRONECAN_PLATFORM_HEADERS}
69-
...
70-
)
71-
target_link_libraries(${PROJECT_NAME} PRIVATE
72-
libdcnode::libdcnode
73-
)
74-
```
75-
76-
77-
## Usage example
1+
# libdcnode [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=PonomarevDA_libdcnode&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=PonomarevDA_libdcnode) [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=PonomarevDA_libdcnode&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=PonomarevDA_libdcnode) [![build](https://github.com/PonomarevDA/libdcnode/actions/workflows/build.yml/badge.svg)](https://github.com/PonomarevDA/libdcnode/actions/workflows/build.yml)
782

79-
**1. Initialize**
3+
Lightweight [DroneCAN / UAVCAN v0](https://dronecan.github.io/) node toolkit built on top of [libcanard](https://github.com/dronecan/libcanard), [platform_specific](platform_specific) and [libparams](https://github.com/PonomarevDA/libparams). It wraps the transport, exposes a small C API for node setup/spin, and offers C++ helpers for typed publishers/subscribers and logging.
804

81-
Include `dronecan.hpp` header and call `uavcanInitApplication` in the beginning of the application. Call `uavcanSpinOnce` periodically.
82-
83-
```c++
84-
// Include dronecan.hpp header file
85-
#include "libdcnode/dronecan.h"
86-
87-
// Initialize the library somewhere
88-
const uint8_t node_id = 42;
89-
auto init_res = uavcanInitApplication(node_id);
90-
if (init_res < 0) {
91-
// handle error here
92-
}
93-
94-
// Spin it periodically:
95-
while (true) {
96-
...
97-
uavcanSpinOnce();
98-
...
99-
}
100-
```
5+
## Features
1016

102-
**2. Add publisher**
7+
- Implements core DroneCAN services out of the box: [NodeStatus](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#nodestatus), [GetNodeInfo](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#getnodeinfo), [Param.GetSet and Param.ExecuteOpcode](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#uavcanprotocolparam), [RestartNode](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#restartnode), and [GetTransportStats](https://legacy.uavcan.org/Specification/7._List_of_standard_data_types/#gettransportstats).
8+
- Platform abstraction (`include/libdcnode/platform.hpp`) so you can plug in your own timing, reset, unique-ID, and CAN driver callbacks.
9+
- Templated C++ wrappers for publishing/subscribing (`include/libdcnode/pub.hpp`, `include/libdcnode/sub.hpp`) with optional filters and periodic senders; legacy interfaces remain in `include/libdcnode/publisher.hpp` and `include/libdcnode/subscriber.hpp`.
10+
- Debug logger (`include/libdcnode/logger.hpp`) that publishes `uavcan.protocol.debug.LogMessage` with severity helpers.
11+
- DSDL compiler baked into the build (`Libs/dronecan_dsdlc`) so message code is generated during CMake configure.
10312

104-
Adding a publisher is very easy. Include `publisher.hpp` header, create an instance of the required publisher and just call `publish` when you need. Here is a BatteryInfo publisher example:
13+
## Repository layout
10514

106-
```c++
107-
#include "libdcnode/dronecan.h"
108-
#include "libdcnode/publisher.hpp"
15+
- `src/`: core node implementation (`dronecan.cpp`) and logger.
16+
- `include/libdcnode/`: public headers (C API, C++ helpers, platform/params interfaces).
17+
- `Libs/`: bundled third-party: libcanard, DroneCAN DSDL set, DSDL compiler.
18+
- `examples/`: reference applications (`ubuntu` SITL, `stm32_hal` skeleton).
19+
- `tests/`: Python smoke tests using `dronecan` + SocketCAN.
20+
- `scripts/`: helpers for DSDL regeneration, coding style, and `vcan` setup.
10921

110-
// Create an instance of the publisher
111-
DronecanPublisher<BatteryInfo_t> battery_info_pub;
112-
113-
// Modify the message
114-
battery_info_pub.msg.voltage = 10.0f;
115-
116-
// Publish the message
117-
battery_info_pub.publish();
118-
```
119-
120-
Alternatively, you can create a periodic publisher:
121-
122-
```c++
123-
const auto PUBLISH_RATE_HZ = 1.0f;
124-
DronecanPeriodicPublisher<BatteryInfo_t> battery_info_pub(PUBLISH_RATE_HZ);
125-
126-
while (true) {
127-
...
128-
battery_info_pub.spinOnce();
129-
...
130-
}
131-
```
22+
## Build the library
13223

133-
**3. Add subscriber**
134-
135-
Adding a subscriber is easy as well. Let's consider a RawCommand subscriber example. Include `subscriber.hpp` header, create a callback for your application and instance of the required subscriber, then initilize it.
136-
137-
```c++
138-
// Include necessary header files
139-
#include "libdcnode/dronecan.h"
140-
#include "libdcnode/subscriber.hpp"
141-
142-
// Add a callback handler function
143-
void rc_callback(const RawCommand_t& msg) {
144-
std::cout << "Get RawCommand with " << (int)msg.size << " commands." << std::endl;
145-
}
146-
147-
// Add the subscription:
148-
DronecanSubscriber<RawCommand_t> raw_command_sub;
149-
if (raw_command_sub.init(&rc_callback) < 0) {
150-
// handle error
151-
}
24+
```bash
25+
mkdir -p build && cd build
26+
cmake ..
27+
cmake --build . -j
15228
```
15329

154-
Sometimes for subscriber you want to specify a filter. For example, you may want to subscribe on a specific command channel or sensor ID. Let's consider an ArrayCommand example with filter that will only pass the messages with actuator ID = 0.
155-
156-
```c++
157-
static const uint8_t FILTER_ACTUATOR_ID = 0;
158-
159-
void ac_callback(const ArrayCommand_t& msg) {
160-
std::cout << "Get ArrayCommand_t with " << msg.size << "commands." << std::endl;
161-
}
162-
bool ac_filter(const ArrayCommand_t& msg) {
163-
for (size_t idx = 0; idx < msg.size; idx++) {
164-
if (msg.commands[idx].actuator_id == FILTER_ACTUATOR_ID) {
165-
return true;
166-
}
167-
}
168-
return false;
169-
}
170-
171-
DronecanSubscriber<ArrayCommand_t> array_command_sub;
172-
array_command_sub.init(&ac_callback, &ac_filter);
173-
```
30+
During configure, DSDL code is generated into `build/generated/libdcnode/serialization` using `Libs/dronecan_dsdlc/dronecan_dsdlc.py`. If you add custom DSDL namespaces, point `DSDL_IN_DIR` (see `CMakeLists.txt`) to your set or rerun `scripts/code_generation.sh` with your paths.
17431

175-
**Run example**
32+
## Usage example
17633

177-
You can run a provided example in SITL mode. Just run:
34+
The `examples/ubuntu` target demonstrates the C API plus the modern C++ pub/sub wrappers.
17835

17936
```bash
180-
git clone git@github.com:PonomarevDA/dronecan_application.git --recursive
37+
# Prepare a virtual CAN iface once (uses sudo):
38+
scripts/vcan.sh slcan0
39+
40+
# Build and run the example:
18141
make ubuntu
18242
```
18343

44+
The example wires a simple parameter set, binds platform callbacks, subscribes to actuator/ESC/light commands, and periodically publishes battery and circuit status messages while spinning the node.
45+
18446
In gui_tool you will see:
18547

18648
<img src="https://raw.githubusercontent.com/wiki/PonomarevDA/dronecan_application/assets/ubuntu_minimal.gif" alt="drawing">
@@ -189,39 +51,28 @@ In gui_tool you will see:
18951
<img src="https://raw.githubusercontent.com/wiki/PonomarevDA/dronecan_application/assets/ubuntu_publisher.gif" alt="drawing">
19052

19153

192-
> You can find the provided SITL application in [examples/ubuntu](examples/ubuntu) folder.
54+
## Testing
19355

194-
## Platform specific notes
195-
196-
There are a few functions that require an implementation. They are declared in [include/application/internal.h](include/application/internal.h).
56+
```bash
57+
python3 -m venv .venv && source .venv/bin/activate
58+
pip install -r requirements-dev.txt
59+
scripts/vcan.sh slcan0 # once, requires sudo
60+
pytest tests/smoke_socketcan.py
61+
```
19762

198-
A user must provide the following function implementation:
63+
The smoke tests expect the Ubuntu example (node ID 50 on `slcan0`) to be running; they verify `NodeStatus` and `GetNodeInfo` responses via the `dronecan` Python client.
19964

200-
```c++
201-
/**
202-
* @return the time in milliseconds since the application started.
203-
* @note This function must be provided by a user!
204-
*/
205-
uint32_t platformSpecificGetTimeMs();
206-
```
65+
## Changelog
20766

208-
A user may also provide the implementation of the optional functions. These function have a weak implementation in [src/weak.c](src/weak.c).
209-
210-
```c++
211-
/**
212-
* @return whether the request will be processed
213-
* True - the application will be restarted soon.
214-
* False - the restarted is not supported or can't be handled at the moment.
215-
* @note Implementation is recommended, but optional.
216-
*/
217-
bool platformSpecificRequestRestart();
218-
219-
/**
220-
* @param[out] out_id - hardware Unique ID
221-
* @note Implementation is recommended, but optional.
222-
*/
223-
void platformSpecificReadUniqueID(uint8_t out_uid[16]);
224-
```
67+
| Version | Date | Note |
68+
| ------- | ------------ | ---- |
69+
| [v0.7.0](https://github.com/PonomarevDA/libdcnode/tree/v0.7.0) | 2025-12-28 | Added DSDL ser/des generator |
70+
| [v0.6.0](https://github.com/PonomarevDA/libdcnode/tree/v0.6.0) | 2025-10-17 | Build model changed: standalone library; platform hooks provided by user (no more source-include mode). |
71+
| [v0.5.0](https://github.com/PonomarevDA/libdcnode/tree/v0.5.0) | 2024-09-26 | Decoupled the platform specific functions from the library |
72+
| [v0.4.0](https://github.com/PonomarevDA/libdcnode/tree/v0.4.0) | 2024-07-29 | Added macro helpers for pub and sub traits |
73+
| [v0.3.*](https://github.com/PonomarevDA/libdcnode/tree/v0.3.0) | 2024-01-06 | Incremental serialization additions |
74+
| [v0.2.0](https://github.com/PonomarevDA/libdcnode/tree/v0.2.0) | 2024-01-06 | Add bxcan and fdcan drivers |
75+
| [v0.1.0](https://github.com/PonomarevDA/libdcnode/tree/v0.1.0) | 2023-12-22 | First public drop; pure C, manual serialization, and source-include usage (include the C sources into your app). |
22576

22677
## License
22778

src/logger.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
/*
2-
* Copyright (C) 2024 Anastasiia Stepanova <asiiapine@gmail.com>
3-
* Distributed under the terms of the GPL v3 license, available in the file LICENSE.
4-
*/
2+
* Copyright (C) 2024 Anastasiia Stepanova <asiiapine@gmail.com>
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
57

68
#include "libdcnode/logger.hpp"
79
#include "libdcnode/legacy/uavcan/protocol/debug/LogMessage.h"

0 commit comments

Comments
 (0)