Newer
Older
The MicroCART project uses custom packets to communicate with the quad. This may seem complex at first
but the structure of all packets is the same it is just the way the data is formatted that changes
between packets.
## Introduction ##
All packets are the same in the sense that they have consistent headers with a start character and all end with a checksum.
The basic structure is shown below.
| Index | 0 | 1 | 2 | 3 | 4 | 5 |
|:-----------------:|:---------------:|:------------:|:----------:|:-----------:|:----:|:--------:|
| Message Parameter | Begin Character | Message Type | Message ID | Data Length | Data | Checksum |
| Bytes | 1 | 2 | 2 | 2 | var | 1 |
The begin character is defined in the Message enum in [commands.h](../../quad/src/commands/commands.h). Message types
are defined within the MessageTypeID enum in [commands.h](../../quad/src/commands/commands.h). Message ID is managed within the backend
[backend.c](../../groundStation/src/backend/backend.c) and is just a counter that is used in client_recv to number packets. Data length
varies with the command that is being sent, but the length of a command is constant. The data is sent in a specific format set by commands.
Lastly, checksum is computed within [packet.c](../../groundStation/src/backend/packet.c).
All packets sent within the system are commands, defined by the MessageTypeID enum referenced earlier, or a VPRN packet. Much of the time when
flying autonomously the commands that the user is responsible for are the getparam and setparam packets that are used to set waypoints or change
values within the computation graph, see [control_algorithm.c](../../quad/src/quad_app/control_algorithm.c) for the PID blocks.
## Adding a new packet and/or command (CLI or GUI to Backend/Quad) ##
There are many files that need to be created and changed to add a packet and/or a command. If only adding a command that does not send a packet only
the CLI and GUI, frontend, and backend must be changed. If also sending a packet then commands and quad_app must also be changed. The instructions below
will take you through what must be changed in all the different areas to support new functionality. Many times a good method to creating the new files is
to copy the files from another command and change what you need.
### CLI and GUI ###
**CLI**
Adding to the CLI is an easy process as most of the code is used to display help messages to the user so that correct information is entered to be sent to the frontend
function that is talked about next. First, create a c file and c header file for your new commands. The [cli.c](../../groundStation/src/cli/cli.c) does not need to be editted
at all, but the header [cli.h](../../groundStation/src/cli/cli.h) needs to be changed to recognize the command that you enter. Include your new header file and add to
CommandNameIds, cli_functions, and commandsNames. The header file you create only needs the functions your intend to create. Inside the c write the functions declared in the
h file and make sure that you have all the checks for help and display the correct usage if need be. Then call the frontend function you create in the next step and print
out the return if there is one.
**GUI**
The GUI is programmed using QT as such it is written in C++ and uses a thread to do communication with the backend. The main files of the GUI to edit are
[controlworker.h](../../groundStation/gui/MicroCART/controlworker.h) and [mainwindow.h](../../groundStation/gui/MicroCART/mainwindow.h) and the corresponding
source files. To add connectivity to the backend add a slot and signal to the controlworker.h file and add a corresponding signal and slot on the mainwindow.h. Next,
connect the slots and signals in the mainwindow.cpp file and add any additional UI to the mainwindow.ui form.
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
### Frontend ###
The frontend handles the writing of the command to the backend. You must create a new c file and c header file with the new functions that will be called from
the clients.
The frontend functions always take in a connection to the backend from the client and can be configured to take in the other parameters you desire.
Functions in [frontend_common.h](../../groundStation/src/frontend/frontend_common.h) handle physically writing to the backend connection, meaning that your functions
must only structure your commands to be parsed in the backend later. If this command expects a response then your method must execute a blocking condition until the
response is obtained, parsed, and whatever action you plan for it taken. Also if you will be defining structs for the data passed into your method, add the structs to
either your header file or [frontend_common.h](../../groundStation/src/frontend/frontend_common.h).
### Backend ###
The file that contains the main function in the backend is [backend.c](../../groundStation/src/backend/backend.c) and the message that is written by the frontend
is passed here. If a client connection sent the message that is being the function client_recv() will be called to handle the request. This function decides how
to process the data based upon the first word. If it is a command the is meant for the quadcopter a different path will be taken than if it is data being send from
the VRPN system. If you intend to send a packet this is where the first difference comes in, a command for the quadcopter should be declared in commands in the
quad directory (discussed later) so that it is recognized by the findCommand() function. If your function is not intended to send a packet your changes should be made
in the condition that has msg_type = -1, otherwise take a look at the else condition.
**The rest of the description is only needed when sending a packet**. You must create a file for encoding your new command. This will require a c file and c header
file. The function that should be made is an Encode<Name> for your new command. If also expecting a response from the quadcopter a Decode<Name> function will also
have to be made. The main point of the encode function is to take the written command and parse it so that the values can be added to the data of the packet, decode
reads the response data and populates a string for the frontend to parse.
If getting a response the backend will call the quad_recv() function in [backend.c](../../groundStation/src/backend/backend.c) which must be configured for your new msg_type.
The backend uses the handle_response() function to call the correct decode function and the return of the decode function will be written back to the frontend.
**Note: If not sending a packet you should not make the changes that the below areas suggest, as stated in the intro.**
### Commands ###
From this point onword you will be working in the quad/src directory instead of the backend/src directory. The commands files are meant to define commands that the quadcopter
and backend will be communicating with. Inside [commands.h](../../quad/src/commands/commands.h) add a MessageTypeID for your new command that will be used to distinguish
the message sent from all the others. Inside [commands.c](../../quad/src/commands/commands.c) is where a callback must be defined for the new message type and you must also
add to the MessageTypes array so that the command, data type, and callback are all connected.
### Quad_app ###
The only thing that needs to be done here is add the callback you defined in [commands.c](../../quad/src/commands/commands.c) to [callbacks.c](../../quad/src/quad_app/callbacks.c).
This callback should parse the data sent and all send a response if that is required. Here is also where you should define the data portion of the packet sent in a table so that
it can be understood by the next MicroCART team. Also remember to add the created tables to this markdown file to provide an easier means of seeing all the packets currently defined
in the system.
## Data Format ##
For all commands other than the message bundle packet there is a defined length and format for sending and receiving packets. Many of the formats
will be discussed below. These packet formats are referenced from [callbacks.c](../../quad/src/quad_app/callbacks.c).
**Note:** this document may get out of date, [callbacks.c](../../quad/src/quad_app/callbacks.c) should have all the up to data packet formats.
### setparam ###
| data index | 0 - 1 | 2 - 3 | 4 - 7 |
|:----------:|:-----------:|:-----------:|:-----------:|
| parameter | node ID | node parmID | param val |
| bytes | 2 | 2 | 4 |
Does not send any response.
### getparam and getoutput ###
| data index | 0 - 1 | 2 - 3 |
|:-----------:|:-------------:|:-----------:|
| parameter | node ID | node parmID |
| bytes | 2 | 2 |
The response will be of type RESPPARAM_ID.
| data index | 0 - 1 | 2 - 3 | 4 - 7 |
|:-----------:|:------------:|:-----------:|:-----------:|
| parameter | node ID | node parmID | param val |
| bytes | 2 | 2 | 4 |
### setsource ###
| data index | 0 - 1 | 2 - 3 | 4 - 5 | 6 - 7 |
|:----------:|:------------:|:-------------:|:-----------:|:-------------:|
| parameter | dest node ID | dest input ID | src node ID | src output ID |
| bytes | 2 | 2 | 2 | 2 |
Does not send any response.
### getsource ###
| data index | 0 - 1 | 2 - 3 |
|:-----------:|:-------------:|:-----------:|
| parameter | node ID | node parmID |
| bytes | 2 | 2 |
The response will be of type RESPSOURCE_ID.
| data index | 0 - 1 | 2 - 3 | 4 - 5 | 6 - 7 |
|:----------:|:------------:|:-------------:|:-----------:|:-------------:|
| parameter | dest node ID | dest input ID | src node ID | src output ID |
| bytes | 2 | 2 | 2 | 2 |
### getnodes ###
| data index | 0 - 2*N-1 | 2*N - 4*N-1 | 4*N - (< 4096) |
|:-----------:|:------------:|:--------------:|:---------------:|
| parameter | Node IDs | Node type Is | Node names |
| bytes | 2*N | 2*N | < 4096 |
### addnode ###
| data index | 0 - 1 | 2 + |
|:-----------:|:------------:|:-------------:|
| parameter | type ID | New node name |
| bytes | 2 | var |
| data index | 0 - 1 |
|:-----------:|:------------:|
| parameter | node ID |
| bytes | 2 |
### msgbundle ###
**Sent from Ground Station**
| data index | 0+ | var |
|:----------:|:--------:|:------------------:|
| parameter | packet 1 | end or next packet |
| bytes | var | var |
**Response to Ground Station**
Currently msgbundle packets cannot capture packets that give a response back to the backend.