diff --git a/conf/abi.xml b/conf/abi.xml
index ef168328fc..8d30861fb6 100644
--- a/conf/abi.xml
+++ b/conf/abi.xml
@@ -104,6 +104,14 @@
+
+
+
+
+
+
+
+
diff --git a/conf/modules/decawave_anchorless_communication.xml b/conf/modules/decawave_anchorless_communication.xml
new file mode 100644
index 0000000000..019eccf319
--- /dev/null
+++ b/conf/modules/decawave_anchorless_communication.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ Decawave DWM1000 module serial communication for use in anchorless network where the UWB modules are attached to MAVs
+ and need to communicate on - board values with each - other(for purposes such as relative localization, co - ordination,
+ or collision avoidance).
+ This module must be used together with the Decawave DWM1000 running the appropriate Serial Communication code,
+ which can be flashed on the Arduino board.
+ The arduino library can be found at :
+ https://github.com/StevenH2812/arduino-dw1000/tree/UWB_localization_v1.0
+ The example file to flash the Arduino Micro can be found in
+ examples/UWB_localization_v1_0/UWB_localization_v1_0.ino
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sw/airborne/modules/decawave/decawave_anchorless_communication.c b/sw/airborne/modules/decawave/decawave_anchorless_communication.c
new file mode 100644
index 0000000000..ee1cfd23c4
--- /dev/null
+++ b/sw/airborne/modules/decawave/decawave_anchorless_communication.c
@@ -0,0 +1,276 @@
+/*
+ * Serial_Communication.c
+ *
+ * Created on: Jul 25, 2017
+ * Author: Steven van der Helm
+ */
+
+/*
+ * Copyright (C) C. DW
+ *
+ * This file is part of paparazzi
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, see
+ * .
+ */
+/**
+ * @file "modules/decawave_anchorless_communication.h"
+ * @author S. vd H, C. DW
+ *
+ Decawave DWM1000 module serial communication for use in anchorless network where the UWB modules are attached to MAVs and need to communicate
+ on-board values with each-other (for purposes such as relative localization, co-ordination, or collision avoidance).
+ This module must be used together with the Decawave DWM1000 running the appropriate Serial Communication code, which can be flashed on the Arduino board.
+ The arduino library can be found at:
+ https://github.com/StevenH2812/arduino-dw1000/tree/UWB_localization_v1.0
+ The example file to flash the Arduino Micro can be found in
+ examples/UWB_localization_v1_0/UWB_localization_v1_0.ino
+ */
+
+#include "decawave_anchorless_communication.h"
+#include "subsystems/datalink/telemetry.h"
+#include "subsystems/radio_control.h"
+#include "state.h"
+#include "mcu_periph/uart.h"
+#include "subsystems/abi.h"
+#include
+
+#define UWB_SERIAL_PORT (&((SERIAL_UART).device))
+struct link_device *external_device = UWB_SERIAL_PORT;
+
+// Some meta data for serial communication
+#define UWB_SERIAL_COMM_MAX_MESSAGE 10
+#define UWB_SERIAL_COMM_END_MARKER 255
+#define UWB_SERIAL_COMM_SPECIAL_BYTE 253
+#define UWB_SERIAL_COMM_START_MARKER 254
+#define UWB_SERIAL_COMM_NODE_STATE_SIZE 4
+
+#define UWB_SERIAL_COMM_NUM_NODES 3 // How many nodes actually are in the network
+#define UWB_SERIAL_COMM_DIST_NUM_NODES UWB_SERIAL_COMM_NUM_NODES-1 // How many distant nodes are in the network (one less than the toal number of nodes)
+
+// Serial message types
+#define UWB_SERIAL_COMM_VX 0
+#define UWB_SERIAL_COMM_VY 1
+#define UWB_SERIAL_COMM_Z 2
+#define UWB_SERIAL_COMM_RANGE 3
+
+struct nodeState {
+ uint8_t nodeAddress;
+ float vx;
+ float vy;
+ float z;
+ float r;
+ bool state_updated[UWB_SERIAL_COMM_NODE_STATE_SIZE];
+};
+
+static struct nodeState states[UWB_SERIAL_COMM_DIST_NUM_NODES];
+
+/**
+ * Function that is called when over the serial a new state value from a remote node is received
+ */
+static void handleNewStateValue(uint8_t nodeIndex, uint8_t msg_type, float value)
+{
+ struct nodeState *node = &states[nodeIndex];
+ switch (msg_type) {
+ case UWB_SERIAL_COMM_VX :
+ node->vx = value;
+ node->state_updated[UWB_SERIAL_COMM_VX] = true;
+ break;
+ case UWB_SERIAL_COMM_VY :
+ node->vy = value;
+ node->state_updated[UWB_SERIAL_COMM_VY] = true;
+ break;
+ case UWB_SERIAL_COMM_Z :
+ node->z = value;
+ node->state_updated[UWB_SERIAL_COMM_Z] = true;
+ break;
+ case UWB_SERIAL_COMM_RANGE :
+ node->r = value;
+ node->state_updated[UWB_SERIAL_COMM_RANGE] = true;
+ break;
+ }
+}
+
+/**
+ * Function for decoding the high bytes of received serial data and saving the message.
+ * Since the start and end marker could also be regular payload bytes (since they are simply the values
+ * 254 and 255, which could also be payload data) the payload values 254 and 255 have been encoded
+ * as byte pairs 253 1 and 253 2 respectively. Value 253 itself is encoded as 253 0.
+ * This function will decode these back into values the original payload values.
+ */
+static void decodeHighBytes(uint8_t bytes_received, uint8_t *received_message)
+{
+ static uint8_t receive_buffer[4];
+ float tempfloat;
+ uint8_t data_received_count = 0;
+ uint8_t this_address = received_message[1];
+ uint8_t msg_from = received_message[2];
+ uint8_t msg_type = received_message[3];
+ uint8_t nodeIndex = msg_from - 1 - (uint8_t)(this_address < msg_from);
+ for (uint8_t i = 4; i < bytes_received - 1; i++) {
+ // Skip the begin marker (0), this address (1), remote address (2), message type (3), and end marker (bytes_received-1)
+ uint8_t var_byte = received_message[i];
+ if (var_byte == UWB_SERIAL_COMM_SPECIAL_BYTE) {
+ i++;
+ var_byte = var_byte + received_message[i];
+ }
+ if (data_received_count <= 4) {
+ receive_buffer[data_received_count] = var_byte;
+ }
+ data_received_count++;
+ }
+ if (data_received_count == 4) {
+ // Move memory from integer buffer to float variable
+ memcpy(&tempfloat, &receive_buffer, 4);
+ // Set the variable to the appropriate type and store it in state
+ handleNewStateValue(nodeIndex, msg_type, tempfloat);
+ }
+}
+
+/**
+ * Function that encodes the high bytes of the serial data to be sent.
+ * Start and end markers are reserved values 254 and 255. In order to be able to send these values,
+ * the payload values 253, 254, and 255 are encoded as 2 bytes, respectively 253 0, 253 1, and 253 2.
+ */
+static void encodeHighBytes(uint8_t *send_data, uint8_t msg_size, uint8_t *data_send_buffer, uint8_t *data_total_send)
+{
+ uint8_t data_send_count = msg_size;
+ *data_total_send = 0;
+ for (uint8_t i = 0; i < data_send_count; i++) {
+ if (send_data[i] >= UWB_SERIAL_COMM_SPECIAL_BYTE) {
+ data_send_buffer[*data_total_send] = UWB_SERIAL_COMM_SPECIAL_BYTE;
+ (*data_total_send)++;
+ data_send_buffer[*data_total_send] = send_data[i] - UWB_SERIAL_COMM_SPECIAL_BYTE;
+ } else {
+ data_send_buffer[*data_total_send] = send_data[i];
+ }
+ (*data_total_send)++;
+ }
+}
+
+/**
+ * Function that will send a float over serial. The actual message that will be sent will have
+ * a start marker, the message type, 4 bytes for the float, and the end marker.
+ */
+static void sendFloat(uint8_t msg_type, float data)
+{
+ static uint8_t data_send_buffer[UWB_SERIAL_COMM_MAX_MESSAGE];
+ static uint8_t data_total_send = 0;
+
+ // Make bytes of the float
+ uint8_t floatbyte[4];
+ memcpy(floatbyte, &data, 4);
+ encodeHighBytes(floatbyte, 4, data_send_buffer, &data_total_send);
+
+ UWB_SERIAL_PORT->put_byte(UWB_SERIAL_PORT->periph, 0, UWB_SERIAL_COMM_START_MARKER);
+ UWB_SERIAL_PORT->put_byte(UWB_SERIAL_PORT->periph, 0, msg_type);
+
+ for (uint8_t i = 0; i < data_total_send; i++) {
+ UWB_SERIAL_PORT->put_byte(UWB_SERIAL_PORT->periph, 0, data_send_buffer[i]);
+ }
+
+ UWB_SERIAL_PORT->put_byte(UWB_SERIAL_PORT->periph, 0, UWB_SERIAL_COMM_END_MARKER);
+}
+
+/**
+ * Helper function that sets the boolean that tells whether a remote drone has a new state update to false.
+ */
+static void setNodeStatesFalse(uint8_t index)
+{
+ for (uint8_t j = 0; j < UWB_SERIAL_COMM_NODE_STATE_SIZE; j++) {
+ states[index].state_updated[j] = false;
+ }
+}
+
+/**
+ * This function checks if all the states of all the distant nodes have at least once been updated.
+ * If all the states are updated, then do something with it! AKA CALLBACK TO MARIO
+ */
+static void checkStatesUpdated(void)
+{
+ bool checkbool;
+ for (uint8_t i = 0; i < UWB_SERIAL_COMM_DIST_NUM_NODES; i++) {
+ checkbool = true;
+ for (uint8_t j = 0; j < UWB_SERIAL_COMM_NODE_STATE_SIZE; j++) {
+ checkbool = checkbool && states[i].state_updated[j];
+ }
+ if (checkbool) {
+ AbiSendMsgUWB_COMMUNICATION(UWB_COMM_ID, i, states[i].r, states[i].vx, states[i].vy, states[i].z);
+ setNodeStatesFalse(i);
+ }
+ }
+}
+
+/**
+ * Function for receiving serial data.
+ * Only receives serial data that is between the start and end markers. Discards all other data.
+ * Stores the received data in received_message, and after decodes the high bytes and copies the final
+ * message to the corresponding message in _messages.
+ */
+static void getSerialData(uint8_t *bytes_received)
+{
+ static bool in_progress = false;
+ static uint8_t var_byte;
+ static uint8_t received_message[UWB_SERIAL_COMM_MAX_MESSAGE];
+
+ while (external_device->char_available(external_device->periph)) {
+ var_byte = UWB_SERIAL_PORT->get_byte(UWB_SERIAL_PORT->periph);
+
+ if (var_byte == UWB_SERIAL_COMM_START_MARKER) {
+ (*bytes_received) = 0;
+ in_progress = true;
+ }
+
+ if (in_progress) {
+ received_message[*bytes_received] = var_byte;
+ (*bytes_received)++;
+ }
+
+ if (var_byte == UWB_SERIAL_COMM_END_MARKER) {
+ in_progress = false;
+ decodeHighBytes(*bytes_received, received_message);
+ }
+ }
+}
+
+/**
+ * Initialization functio
+ */
+void decawave_anchorless_communication_init(void)
+{
+ // Set all nodes to false
+ for (uint8_t i = 0; i < UWB_SERIAL_COMM_DIST_NUM_NODES; i++) {
+ setNodeStatesFalse(i);
+ }
+}
+
+/**
+ * This function periodically sends state data over the serial (which is received by the arduino)
+ */
+void decawave_anchorless_communication_periodic(void)
+{
+ sendFloat(UWB_SERIAL_COMM_VX, stateGetSpeedEnu_f()->y);
+ sendFloat(UWB_SERIAL_COMM_VY, stateGetSpeedEnu_f()->x);
+ sendFloat(UWB_SERIAL_COMM_Z, stateGetPositionEnu_f()->z);
+}
+
+/**
+ * Event function currently checks for serial data and whether an update of states is available for a distant drone.
+ * If these cases are true, then actions are taken.
+ */
+void decawave_anchorless_communication_event(void)
+{
+ static uint8_t bytes_received;
+ getSerialData(&bytes_received);
+ checkStatesUpdated();
+}
diff --git a/sw/airborne/modules/decawave/decawave_anchorless_communication.h b/sw/airborne/modules/decawave/decawave_anchorless_communication.h
new file mode 100644
index 0000000000..d4c6081458
--- /dev/null
+++ b/sw/airborne/modules/decawave/decawave_anchorless_communication.h
@@ -0,0 +1,15 @@
+/*
+ * Serial_Communication.h
+ *
+ * Created on: Jul 25, 2017
+ * Author: Steven van der Helm
+ */
+
+#ifndef DECAWAVE_ANCHORLESS_COMMUNICATION_H_
+#define DECAWAVE_ANCHORLESS_COMMUNICATION_H_
+
+extern void decawave_anchorless_communication_init(void);
+extern void decawave_anchorless_communication_periodic(void);
+extern void decawave_anchorless_communication_event(void);
+
+#endif /* DECAWAVE_ANCHORLESS_COMMUNICATION_H_ */
diff --git a/sw/airborne/subsystems/abi_sender_ids.h b/sw/airborne/subsystems/abi_sender_ids.h
index 8dc186fb2c..c61cdd4cce 100644
--- a/sw/airborne/subsystems/abi_sender_ids.h
+++ b/sw/airborne/subsystems/abi_sender_ids.h
@@ -302,6 +302,12 @@
#define MAG_CALIB_UKF_ID 20
#endif
+/*
+ * UWB communication (message 19)
+*/
+#ifndef UWB_COMM_ID
+#define UWB_COMM_ID 1
+#endif
/*
* IDs of Computer Vision Calculated variables