Update Readme.md #3

Merged
melfely merged 1 commits from Readme-update into master 2026-07-31 02:47:17 +00:00
+122 -15
View File
@@ -1,27 +1,134 @@
# *RNavP* ## RNavP
**RNavP** - *Robotics Navigation and Control Via Postcard*
## Robotics Navigation and Control Via Postcard The project is intended to be a Protocol layer between an MCU and a Host system. The system will support other systems including but not limited to; Host to Host, MCU to MCU. The system will be designed to accept a byte buffer from any transport layer. The transport layer is **NOT** a design part of RNavP it will support any transport layer that can implement the "Endpoint" trait.
This is a crate designed to assit in development for the entire stack from the MCU(Running Embassy) to a STD computer talking to that MCU Via postcard for Drivetrain control. ## Concept
Designed for intergration with ROS2 but is *NOT* required and will work for any STD enviroment for the control system
A discovery based, protocol layer that supports many generic byte based transport layer and many Serialization Codecs
Will be Server (MCU) <-> Client (Host).
A client will ask a server, what devices it has, the server will respond with a list of devices. The client can then inquire about more information about each device respectively.
The intended goal is for a Ros2 Based host SBC (Like a Rasbperry Pi5) communicating with a MCU (Like a Raspberry Pico 2) Over UART. The API will be designed to be INCREDIBLY generic, support many different device setups and frameworks.
## Basic Implementations
The basic idea is for there to be a simple header that heads EVERY packet. Extra data, but the cost gets paid for 10 fold later.
Basic header as a rust struct snippet
### Header
```rust
struct Header {
packet_size: u16, //Supports up to 65535 bytes, in a single packet. This value includes the entire header.
port: u16, //The communication port. Allows for multiple connections even on a simple protocol like UART
context: u8, //A simple short u8 rolling transfer count. Each type a transfer happens on the same port, this increments
packet_type: PacketType, // A u8 enum that defines the packet contents
}
#[repr(u8)]
enum PacketType {
CommunicationInfo,
Discovery,
Request,
Command,
Error,
ClosePort,
OpenPort,
Config,
Shutdown,
... //Many more
}
```
- Packet Size => The size of the packet, while it will technically be a u16 so therefore a packet size of 65535 bytes, this is INSANE sizes of packets. A packet should never need to be that large.
- Port => Supports a port number, working similar to TCP and UDP ports, allowing for multi device to device communication on a larger variety of protocols. Ports by default presume the common Privileged port concept from OS.
Where ports 0 to 1023 are Privileged, where they are only allowed by the MCU talking to itself. NOT allowed when an external device communicates with it.
- Context => A small rolling count of the communication state. This is intended just for a small syncing cost. Dropping a signifciant number of messages where a single byte u8 can't keep a sync means there is more wrong than that.
- Packet type. Will be a defined enum, that will contain all supported message types that can be sent.
### Packet Type Examples
An example of the CommunicationInfo Packet
```rust
struct CommunicationInfo {
codec: Codec,
version: u32,
magic_num: 0x1337,
}
```
An example of the Error Packet
The reasoning behind the error packet design is simple.
The error will always contain the magic num of 0x1337 at the end. Which is a simple 16 bit number. But why? Simple, the MCU (which is the server side) Should ONLY contain one codec (but can contain all), they will be set at COMPILE time. The host (which is the client side) should contain ALL (but can contain one) codecs. This allows for the host to send a invalid packet. Which will trigger an error response.
This error response will then broadcast out the generic error response. Which a host can then use to test all known codecs to attempt to decode the codec if it is unknown. This should NEVER be required, but WILL help someone at some point if it is ever needed. Errors should be RARE. So the cost of 2 bytes extra in a error packet should be low. If you have lots of errors. Fix the problem, that is usually a good idea.
```rust
struct ErrorPacket {
err: Error,
codec: Codec,
magic_num: u16 = 0x1337,
}
```
## Communication Start
Communication will start by the client (Host) sending a 5 byte magic packet
0x00 0x00 0x37 0x13 0xFF
This allows the MCU to know to respond to this packet, with a very simple response packet.
0x00 0x00 0x(number of codecs) (list of codec IDs) 0xFF
This will then allow for the host to know HOW to send a valid packet to the MCU which should then be a simpleCommunication Info Packet. Which is a the equal of a "ping" in this context
| | Packet Size | Port | Context | Packet Type | Codec | Version | Magic Num |
| ----- | ----------- | --------- | ------- | ----------------- | ------------------ | ------------------- | --------- |
| Hex | 0x0D 0x00 | 0x00 0x04 | 0x00 | 0x00 | 0x01 | 0x01 0x00 0x00 0x00 | 0x37 0x13 |
| Human | 13 | 1024 | 0 | CommunicationInfo | Postcard (Default) | 1 | 0x1337 |
Explanation of all the numbers
## Project Goals Packet size -> there are 13 total bytes in this packet. Including the header
Port -> Must be above 1023, as 1024 is the first non-privileged port.
Context -> MCU (Server) starts context value, it will pick a random value within the 255 value range, expecting the Host (Client) to start from that, NOT 1 or 0. 0 Is ONLY valid for a CommunicationInfo Packet.
Be Able to drive just about anything, 2 wheel differential drive, simple we got that. 4 Wheeled OmniDirectional? We got that to. 9 Wheeled Abomination? Why? But, *We gotcha bro!* ## Wire Rules
Simulation system, Define the upper level logic, and the placement of the wheels and the motor specs and we can give you a low fidilety simulation output on the Host Computer no MCU needed. ### Endianness
Want to see it ON something? Well use the outputs and hook into the SIM of your choice! Verify your robot design and logic systems, before even ordering the MCU, or having to design how the ESC works. The protocol is strictly little-endian. Most modern systems are little-endian including micro-controllers, there is zero reason for a NEW protocol to come out as big-endian.
Entirely Rust, this uses a full RUST eco system from the ground up, keeping the Your code safe, and your robots doing exactly what you intended for them to do.
Uses Embassy. Since this is designed to have a single function init, you WILL have to pass in your embassy executor spawning item so you can't spawn anything new once this is started. It is just another sync problem. For the most part, most Codec Library's for most languages support choosing the output mode, and they default to the same as the host system. Which in 95% of cases on modern devices, will be little-endian.
BUT, you can easily just throw this entire system on core 1 (The Second core) of your MCU, and not care about it anymore. Handle the rest of your logic, read some data, run a HMI using the wonderful SLINT crate.
Who knows? What we do know is that, your entire drivetrain and sensor system you asked us to handle. We handled.
## Packet Header
The importance of the header design is vital in a good protocol. This header is designed to be short and sweet.
## Licensing There is already a example of this in rust code in the [[#Basic Implementations]] section of the document this section will go into more detail about the concepts and the whys.
Licensed under either Apache License, Version 2.0 (LICENSE-APACHE) or MIT license (LICENSE-MIT). ### Packet Size
The packet size, why a u 16? That is a giant packet size, most MCU will not be able to handle it. Yes, BUT the next size is a very restrictive u 8. 255 bytes is quite a few, until you need KB sized packets. Containing large states and device names.
Another thing, the Packet Size struct ALSO holds the header. Not the sync packet structure that starts with (0 x 00 0 x 00) no valid packet can start with this, why? Because the header is at least 6 bytes or (0 x 06 0 x 00). So there is NO way any valid communication can happen in the 1 to 5 byte "packet size" range.
### Port
To make things simple I am taking a Desktop OS style of port rules. Anything less than 1024 is privileged anything above it, is not.
Privileged ports will be designed for a specific things that only the MCU itself should be doing in most cases, or some form of external control should trigger it (IE an IRQ for a limit switch). These "Privileged" ports are HIGHER priority and control specific state levels that ONLY the device should control.
A good point of this, is privileged ports should be thought of as IRQ, only used by the MCU when things are going wrong or emergencies. NOT as a way to influence the devices, that should be left up to the host
### Context
The importance of communication order can be hard to keep track of. So this protocol is simple, the context MUST match the next expected one, for the MCU to execute, it will NOT execute anything out of order. Even a data request. This is to protect the integrity of expected state, thing A must happen before thing B.
To make this reasonable, we must queue a few packets. The number of packets queued will depend on the settings set by the MCU itself, along with a timeout. It will wait the Timeout duration for the expected packet, if not received it will Error DROPPING ALL PACKETS IT HAS RECEIVED.
This is again to protect the importance of state. Since the goal of this Protocol is to merge state between an MCU and a Host device. Making it SEEM like there is not even a wire bridge between them.
## Discovery
The MCU (Server) will on a basic discovery request will send the upper device tree. Which is the list of devices TYPES it has, along with the count of each.
This will let the Host (Client) Decided which devices it wants more information on. Rather than forcing a massive state sync upfront. The default will be Lazy Cache, where a device is only requested from the host on its first use, then stored. Rather than Upfront collection. This will make large massive device counts much more reliable while keeping the concept simple.
### The goal of Discovery
The MAJOR goal of discovery is to facilitate taking MCU devices, and giving them to a host for near transparent control. It should on the Host side, once setup feel like a native Object, rather than a