mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-08-17 17:12:33 +08:00
* [decawave] split driver from filter * [decawave] rename dw1000_arduino to uwb_positioning * [decawave] rename dw1000_arduino_periph to dw1000_range_arduino * [decawave] Add pdec driver. --------- Co-authored-by: Fabien-B <Fabien-B@github.com> Co-authored-by: Gautier Hattenberger <gautier.hattenberger@enac.fr>
This commit is contained in:
co-authored by
Fabien-B
Gautier Hattenberger
parent
fa97bcc52d
commit
134bc165d2
@@ -281,6 +281,21 @@
|
||||
<field name="values" type="int32_t *">Pointer to force sensor values (driver raw units)</field>
|
||||
</message>
|
||||
|
||||
<message name="UWB_RANGING" id="43">
|
||||
<field name="stamp" type="uint32_t" unit="us">Timestamp in micro-seconds</field>
|
||||
<field name="src_id" type="uint16_t">Ranging initiator</field>
|
||||
<field name="dst_id" type="uint16_t">Ranging responder</field>
|
||||
<field name="range" type="float" unit="m">Distance between the devices</field>
|
||||
</message>
|
||||
|
||||
<message name="UWB_TDOA" id="44">
|
||||
<field name="stamp" type="uint32_t" unit="us">Timestamp in micro-seconds</field>
|
||||
<field name="blink_id" type="uint16_t"/>
|
||||
<field name="count" type="uint8_t">Number of beacons in the array</field>
|
||||
<field name="src_id" type="uint16_t*">Beacons ids</field>
|
||||
<field name="range_diff" type="float*" unit="m">Range difference with the closest beacon</field>
|
||||
</message>
|
||||
|
||||
</msg_class>
|
||||
|
||||
</protocol>
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
|
||||
<module name="dw1000_arduino" dir="decawave">
|
||||
<doc>
|
||||
<description>
|
||||
Driver to get ranging data from Decawave DW1000 modules connected to Arduino
|
||||
|
||||
Decawave DW1000 modules (http://www.decawave.com/products/dwm1000-module) are Ultra-Wide-Band devices that can be used for communication and ranging.
|
||||
Especially, using 3 modules as anchors can provide data for a localization system based on trilateration.
|
||||
The DW1000 is using a SPI connection, but an arduino-compatible board can be used with the library https://github.com/thotro/arduino-dw1000 to hyde the low level drivers and provide direct ranging informations.
|
||||
|
||||
See https://hal-enac.archives-ouvertes.fr/hal-01936955 for more information on the EKF filtering.
|
||||
</description>
|
||||
<configure name="DW1000_ARDUINO_UART" value="UARTX" description="UART on which arduino and its DW1000 module is connected"/>
|
||||
<configure name="DW1000_ARDUINO_BAUD" value="B115200" description="UART Baudrate, default to 115200"/>
|
||||
<configure name="DW1000_USE_AS_LOCAL_POS" value="FALSE|TRUE" description="use as a local positioning system (default: TRUE)"/>
|
||||
<configure name="DW1000_USE_AS_GPS" value="FALSE|TRUE" description="use as a fake GPS positioning system (default: FALSE)"/>
|
||||
<section name="DW1000" prefix="DW1000_">
|
||||
<define name="ANCHORS_IDS" value="1, 2, 3" type="int[]" description="Comma separated list of anchors ID"/>
|
||||
<define name="ANCHORS_POS_X" value="0., 0., 5." type="float[]" description="Comma separated list of anchors ID over X axis"/>
|
||||
<define name="ANCHORS_POS_Y" value="0., 5., 0." type="float[]" description="Comma separated list of anchors ID over Y axis"/>
|
||||
<define name="ANCHORS_POS_Z" value="0., 0., 0." type="float[]" description="Comma separated list of anchors ID over Z axis"/>
|
||||
<define name="OFFSET" value="0., 0., 0." type="float[]" description="Position offset other X, Y and Z axis"/>
|
||||
<define name="SCALE" value="1., 1., 1." type="float[]" description="Position scale factor other X, Y and Z axis"/>
|
||||
<define name="INITIAL_HEADING" value="0." description="Initial heading correction between anchors frame and global frame"/>
|
||||
<define name="NB_ANCHORS" value="3" description="Set number of anchors, only 3 are required/supported at the moment"/>
|
||||
<define name="USE_EKF" value="FALSE|TRUE" description="Enable EKF filtering, required to estimate speed"/>
|
||||
<define name="EKF_Q" value="1.0" description="EKF process noise"/>
|
||||
<define name="EKF_R_DIST" value="0.1" description="EKF noise on distance measurements"/>
|
||||
<define name="EKF_R_SPEED" value="0.1" description="EKF noise on speed measurements (if available)"/>
|
||||
<define name="NOISE_X|Y|Z" value="0.1" description="Noise level reported by the POSITION_ESTIMATE message when USE_AS_LOCAL_POS is activated"/>
|
||||
<define name="VEL_NOISE_X|Y|Z" value="0.1" description="Noise level reported by the VELOCITY_ESTIMATE message when USE_AS_LOCAL_POS is activated"/>
|
||||
</section>
|
||||
</doc>
|
||||
<settings>
|
||||
<dl_settings>
|
||||
<dl_settings name="dw1000">
|
||||
<dl_setting max="1" min="0" step="1" module="decawave/dw1000_arduino" var="dw1000_use_ekf" shortname="use_ekf" values="FALSE|TRUE"/>
|
||||
<dl_setting max="5.0" min="0.01" step="0.01" module="decawave/dw1000_arduino" var="dw1000_ekf_q" shortname="q_noise" handler="update_ekf_q"/>
|
||||
<dl_setting max="1.0" min="0.01" step="0.01" module="decawave/dw1000_arduino" var="dw1000_ekf_r_dist" shortname="r_dist" handler="update_ekf_r_dist"/>
|
||||
<dl_setting max="1.0" min="0.01" step="0.01" module="decawave/dw1000_arduino" var="dw1000_ekf_r_speed" shortname="r_speed" handler="update_ekf_r_speed"/>
|
||||
</dl_settings>
|
||||
</dl_settings>
|
||||
</settings>
|
||||
<header>
|
||||
<file name="dw1000_arduino.h"/>
|
||||
</header>
|
||||
<init fun="dw1000_arduino_init()"/>
|
||||
<periodic fun="dw1000_arduino_periodic()" freq="10"/>
|
||||
<periodic fun="dw1000_arduino_report()" freq="10" autorun="FALSE"/>
|
||||
<periodic fun="dw1000_reset_heading_ref()" freq="1" autorun="FALSE"/>
|
||||
<event fun="dw1000_arduino_event()"/>
|
||||
<makefile>
|
||||
<configure name="DW1000_ARDUINO_UART" case="upper|lower"/>
|
||||
<configure name="DW1000_ARDUINO_BAUD" default="B115200"/>
|
||||
<configure name="DW1000_USE_AS_LOCAL_POS" default="TRUE"/>
|
||||
<configure name="DW1000_USE_AS_GPS" default="FALSE"/>
|
||||
<file name="dw1000_arduino.c"/>
|
||||
<file name="trilateration.c"/>
|
||||
<file name="ekf_range.c"/>
|
||||
<define name="DW1000_USE_AS_LOCAL_POS" value="$(DW1000_USE_AS_LOCAL_POS)"/>
|
||||
<define name="DW1000_USE_AS_GPS" value="$(DW1000_USE_AS_GPS)"/>
|
||||
<raw>
|
||||
ifeq (,$(findstring $(DW1000_USE_AS_GPS),0 FALSE))
|
||||
ifdef SECONDARY_GPS
|
||||
ifneq (,$(findstring $(SECONDARY_GPS), dw1000))
|
||||
# this is the secondary GPS
|
||||
$(TARGET).CFLAGS += -DGPS_SECONDARY_TYPE_H=\"modules/decawave/dw1000_arduino.h\"
|
||||
$(TARGET).CFLAGS += -DSECONDARY_GPS=GPS_DW1000
|
||||
else
|
||||
$(TARGET).CFLAGS += -DGPS_TYPE_H=\"modules/decawave/dw1000_arduino.h\"
|
||||
$(TARGET).CFLAGS += -DPRIMARY_GPS=GPS_DW1000
|
||||
endif
|
||||
else
|
||||
# plain old single GPS usage
|
||||
$(TARGET).CFLAGS += -DGPS_TYPE_H=\"modules/decawave/dw1000_arduino.h\"
|
||||
endif
|
||||
endif
|
||||
</raw>
|
||||
</makefile>
|
||||
<makefile target="ap">
|
||||
<define name="USE_$(DW1000_ARDUINO_UART_UPPER)"/>
|
||||
<define name="DW1000_ARDUINO_DEV" value="$(DW1000_ARDUINO_UART_LOWER)"/>
|
||||
<define name="$(DW1000_ARDUINO_UART_UPPER)_BAUD" value="$(DW1000_ARDUINO_BAUD)"/>
|
||||
</makefile>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
<module name="dw1000_range_arduino" dir="decawave" task="sensors">
|
||||
<doc>
|
||||
<description>Driver to get ranging data from Decawave DW1000 modules connected to Arduino
|
||||
|
||||
Decawave DW1000 modules (http://www.decawave.com/products/dwm1000-module) are Ultra-Wide-Band devices that can be used for communication and ranging.
|
||||
Especially, using 3 modules as anchors can provide data for a localization system based on trilateration.
|
||||
The DW1000 is using a SPI connection, but an arduino-compatible board can be used with the library https://github.com/thotro/arduino-dw1000 to hyde the low level drivers and provide direct ranging informations.
|
||||
</description>
|
||||
<configure name="DW1000_RANGE_ARDUINO_UART" value="UARTX" description="UART on which arduino and its DW1000 module is connected"/>
|
||||
<configure name="DW1000_RANGE_ARDUINO_BAUD" value="B115200" description="UART Baudrate, default to 115200"/>
|
||||
</doc>
|
||||
<dep>
|
||||
<depends>uart</depends>
|
||||
<provides>ranging</provides>
|
||||
<suggests>uwb_positioning</suggests>
|
||||
</dep>
|
||||
<header>
|
||||
<file name="dw1000_range_arduino.h"/>
|
||||
</header>
|
||||
<init fun="dw1000_range_arduino_init()"/>
|
||||
<event fun="dw1000_range_arduino_event()"/>
|
||||
<makefile target="ap">
|
||||
<configure name="DW1000_RANGE_ARDUINO_UART" case="upper|lower"/>
|
||||
<configure name="DW1000_RANGE_ARDUINO_BAUD" default="B115200"/>
|
||||
<define name="USE_$(DW1000_RANGE_ARDUINO_UART_UPPER)"/>
|
||||
<define name="DW1000_RANGE_ARDUINO_DEV" value="$(DW1000_RANGE_ARDUINO_UART_LOWER)"/>
|
||||
<define name="$(DW1000_RANGE_ARDUINO_UART_UPPER)_BAUD" value="$(DW1000_RANGE_ARDUINO_BAUD)"/>
|
||||
<define name="UWB_POSITIONING_TAG_ID" value="0" />
|
||||
<file name="dw1000_range_arduino.c"/>
|
||||
<test>
|
||||
<define name="DW1000_RANGE_ARDUINO_DEV" value="uart3"/>
|
||||
<define name="USE_UART3"/>
|
||||
<define name="UWB_POSITIONING_TAG_ID" value="0" />
|
||||
</test>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
<module name="pdec" dir="decawave" task="sensors">
|
||||
<doc>
|
||||
<description>
|
||||
Driver for the Pprz Decawave module, based on the DWM3001C. Allows ranging, as well as TDOA.
|
||||
</description>
|
||||
</doc>
|
||||
<dep>
|
||||
<depends>uart</depends>
|
||||
<provides>ranging</provides>
|
||||
<suggests>uwb_positioning</suggests>
|
||||
</dep>
|
||||
<header>
|
||||
<file name="pdec.h"/>
|
||||
</header>
|
||||
<init fun="pdec_init()"/>
|
||||
<periodic fun="pdec_periodic_report()" freq="10" autorun="FALSE"/>
|
||||
<event fun="pdec_event()"/>
|
||||
<makefile>
|
||||
<configure name="PDEC_UART" default="UART3" case="upper|lower"/>
|
||||
<define name="$(PDEC_UART_UPPER)_BAUD" value="B115200"/>
|
||||
<define name="PDEC_UART_DEV" value="$(PDEC_UART_LOWER)"/>
|
||||
<define name="USE_$(PDEC_UART_UPPER)"/>
|
||||
<file name="pdec.c"/>
|
||||
<test>
|
||||
<define name="PDEC_UART_DEV" value="uart3"/>
|
||||
<define name="USE_UART3"/>
|
||||
<define name="DOWNLINK_TRANSPORT" value="pprz_tp"/>
|
||||
<define name="DOWNLINK_DEVICE" value="uart0"/>
|
||||
<define name="USE_UART0"/>
|
||||
</test>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
|
||||
<module name="uwb_positioning" dir="decawave">
|
||||
<doc>
|
||||
<description>
|
||||
Estimate local position from UWB anchor measurements.
|
||||
|
||||
UWB devices can be used for communication, ranging, and positioning.
|
||||
This module consumes anchor measurements and estimates a local position.
|
||||
With range measurements, 3 anchors are required/supported by the current trilateration path.
|
||||
|
||||
See https://hal-enac.archives-ouvertes.fr/hal-01936955 for more information on the EKF filtering.
|
||||
</description>
|
||||
<configure name="UWB_POSITIONING_USE_AS_LOCAL_POS" value="FALSE|TRUE" description="use as a local positioning system (default: TRUE)"/>
|
||||
<configure name="UWB_POSITIONING_USE_AS_GPS" value="FALSE|TRUE" description="use as a fake GPS positioning system (default: FALSE)"/>
|
||||
<section name="UWB_POSITIONING" prefix="UWB_POSITIONING_">
|
||||
<define name="ANCHORS_IDS" value="1, 2, 3" type="int[]" description="Comma separated list of anchors ID"/>
|
||||
<define name="ANCHORS_POS_X" value="0., 0., 5." type="float[]" description="Comma separated list of anchors ID over X axis"/>
|
||||
<define name="ANCHORS_POS_Y" value="0., 5., 0." type="float[]" description="Comma separated list of anchors ID over Y axis"/>
|
||||
<define name="ANCHORS_POS_Z" value="0., 0., 0." type="float[]" description="Comma separated list of anchors ID over Z axis"/>
|
||||
<define name="RANGE_OFFSET" value="0., 0., 0." type="float[]" description="Offset applied to individual range measurements"/>
|
||||
<define name="RANGE_SCALE" value="1., 1., 1." type="float[]" description="Scale factor applied to individual range measurements"/>
|
||||
<define name="INITIAL_HEADING" value="0." description="Initial heading correction between anchors frame and global frame"/>
|
||||
<define name="NB_ANCHORS" value="3" description="Set number of anchors, only 3 are required/supported at the moment"/>
|
||||
<define name="USE_EKF" value="FALSE|TRUE" description="Enable EKF filtering, required to estimate speed"/>
|
||||
<define name="EKF_Q" value="1.0" description="EKF process noise"/>
|
||||
<define name="EKF_R_DIST" value="0.1" description="EKF noise on distance measurements"/>
|
||||
<define name="EKF_R_SPEED" value="0.1" description="EKF noise on speed measurements (if available)"/>
|
||||
<define name="NOISE_X|Y|Z" value="0.1" description="Noise level reported by the POSITION_ESTIMATE message when USE_AS_LOCAL_POS is activated"/>
|
||||
<define name="VEL_NOISE_X|Y|Z" value="0.1" description="Noise level reported by the VELOCITY_ESTIMATE message when USE_AS_LOCAL_POS is activated"/>
|
||||
</section>
|
||||
</doc>
|
||||
<dep>
|
||||
<depends>@ranging</depends>
|
||||
</dep>
|
||||
<settings>
|
||||
<dl_settings>
|
||||
<dl_settings name="uwb_positioning">
|
||||
<dl_setting max="1" min="0" step="1" module="decawave/uwb_positioning" var="uwb_positioning_use_ekf" shortname="use_ekf" values="FALSE|TRUE"/>
|
||||
<dl_setting max="5.0" min="0.01" step="0.01" module="decawave/uwb_positioning" var="uwb_positioning_ekf_q" shortname="q_noise" handler="update_ekf_q"/>
|
||||
<dl_setting max="1.0" min="0.01" step="0.01" module="decawave/uwb_positioning" var="uwb_positioning_ekf_r_dist" shortname="r_dist" handler="update_ekf_r_dist"/>
|
||||
<dl_setting max="1.0" min="0.01" step="0.01" module="decawave/uwb_positioning" var="uwb_positioning_ekf_r_speed" shortname="r_speed" handler="update_ekf_r_speed"/>
|
||||
</dl_settings>
|
||||
</dl_settings>
|
||||
</settings>
|
||||
<header>
|
||||
<file name="uwb_positioning.h"/>
|
||||
</header>
|
||||
<init fun="uwb_positioning_init()"/>
|
||||
<periodic fun="uwb_positioning_periodic()" freq="10"/>
|
||||
<periodic fun="uwb_positioning_range_periodic()" freq="10"/>
|
||||
<periodic fun="uwb_positioning_report()" freq="10" autorun="FALSE"/>
|
||||
<periodic fun="uwb_positioning_reset_heading_ref()" freq="1" autorun="FALSE"/>
|
||||
<makefile>
|
||||
<configure name="UWB_POSITIONING_USE_AS_LOCAL_POS" default="TRUE"/>
|
||||
<configure name="UWB_POSITIONING_USE_AS_GPS" default="FALSE"/>
|
||||
<file name="uwb_positioning.c"/>
|
||||
<file name="trilateration.c"/>
|
||||
<file name="ekf_range.c"/>
|
||||
<define name="UWB_POSITIONING_USE_AS_LOCAL_POS" value="$(UWB_POSITIONING_USE_AS_LOCAL_POS)"/>
|
||||
<define name="UWB_POSITIONING_USE_AS_GPS" value="$(UWB_POSITIONING_USE_AS_GPS)"/>
|
||||
<raw>
|
||||
ifeq (,$(findstring $(UWB_POSITIONING_USE_AS_GPS),0 FALSE))
|
||||
ifdef SECONDARY_GPS
|
||||
ifneq (,$(findstring $(SECONDARY_GPS), uwb_positioning))
|
||||
# this is the secondary GPS
|
||||
$(TARGET).CFLAGS += -DGPS_SECONDARY_TYPE_H=\"modules/decawave/uwb_positioning.h\"
|
||||
$(TARGET).CFLAGS += -DSECONDARY_GPS=GPS_UWB
|
||||
else
|
||||
$(TARGET).CFLAGS += -DGPS_TYPE_H=\"modules/decawave/uwb_positioning.h\"
|
||||
$(TARGET).CFLAGS += -DPRIMARY_GPS=GPS_UWB
|
||||
endif
|
||||
else
|
||||
# plain old single GPS usage
|
||||
$(TARGET).CFLAGS += -DGPS_TYPE_H=\"modules/decawave/uwb_positioning.h\"
|
||||
endif
|
||||
endif
|
||||
</raw>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -304,8 +304,8 @@
|
||||
#define GPS_IMCU_ID 14
|
||||
#endif
|
||||
|
||||
#ifndef GPS_DW1000_ID
|
||||
#define GPS_DW1000_ID 15
|
||||
#ifndef GPS_UWB_ID
|
||||
#define GPS_UWB_ID 15
|
||||
#endif
|
||||
|
||||
#ifndef GPS_UBX2_ID
|
||||
@@ -528,12 +528,20 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* UWB communication (message 19)
|
||||
* UWB communication and ranging (messages 19, 43, 44)
|
||||
*/
|
||||
#ifndef UWB_COMM_ID
|
||||
#define UWB_COMM_ID 1
|
||||
#endif
|
||||
|
||||
#ifndef UWB_DW1000_ARDUINO_ID
|
||||
#define UWB_DW1000_ARDUINO_ID 2
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef UWB_PDEC_ID
|
||||
#define UWB_PDEC_ID 3
|
||||
#endif
|
||||
/*
|
||||
* IDs of Obstacle detection systems
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (C) 2026 Fabien-B <fabien-b@github.com>
|
||||
* This file is part of paparazzi. See LICENCE file.
|
||||
*
|
||||
* @file "modules/decawave/dw1000_range_arduino.c"
|
||||
* @author Fabien-B <fabien-b@github.com>
|
||||
*
|
||||
* Driver to get ranging data from Decawave DW1000 modules connected to Arduino
|
||||
* Decawave DW1000 modules (http://www.decawave.com/products/dwm1000-module) are Ultra-Wide-Band devices that can be used for communication and ranging.
|
||||
* Especially, using 3 modules as anchors can provide data for a localization system based on trilateration.
|
||||
* The DW1000 is using a SPI connection, but an arduino-compatible board can be used with the library https://github.com/thotro/arduino-dw1000 to hyde the low level drivers and provide direct ranging informations.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "modules/decawave/dw1000_range_arduino.h"
|
||||
|
||||
#include "std.h"
|
||||
#include "mcu_periph/uart.h"
|
||||
#include "modules/core/abi.h"
|
||||
#include "modules/core/abi_sender_ids.h"
|
||||
#include "modules/decawave/trilateration.h"
|
||||
#include "generated/airframe.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/** frame sync byte */
|
||||
#define DW_STX 0xFE
|
||||
|
||||
/** Parsing states */
|
||||
#define DW_WAIT_STX 0
|
||||
#define DW_GET_DATA 1
|
||||
#define DW_GET_CK 2
|
||||
#define DW_NB_DATA 6
|
||||
|
||||
/** DW1000 Arduino range parser state */
|
||||
struct DW1000RangeArduino {
|
||||
struct uart_periph *dev;
|
||||
uint8_t buf[DW_NB_DATA]; ///< incoming data buffer
|
||||
uint8_t idx; ///< buffer index
|
||||
uint8_t ck; ///< checksum
|
||||
uint8_t state; ///< parser state
|
||||
};
|
||||
|
||||
struct DW1000RangeArduino dw1000_range_arduino;
|
||||
|
||||
|
||||
/** Utility function to get float from buffer */
|
||||
static inline float float_from_buf(uint8_t* b) {
|
||||
float f;
|
||||
memcpy((uint8_t*)(&f), b, sizeof(float));
|
||||
return f;
|
||||
}
|
||||
|
||||
/** Utility function to get uint16_t from buffer */
|
||||
static inline uint16_t uint16_from_buf(uint8_t* b) {
|
||||
uint16_t u16;
|
||||
memcpy ((uint8_t*)(&u16), b, sizeof(uint16_t));
|
||||
return u16;
|
||||
}
|
||||
|
||||
/** Send range data decoded from the serial frame */
|
||||
static void send_anchor_data(struct DW1000RangeArduino *dw) {
|
||||
uint16_t dst_id = uint16_from_buf(dw->buf);
|
||||
uint16_t src_id = UWB_POSITIONING_TAG_ID;
|
||||
float raw_dist = float_from_buf(dw->buf + 2);
|
||||
uint32_t now_ts = get_sys_time_usec();
|
||||
|
||||
AbiSendMsgUWB_RANGING(UWB_DW1000_ARDUINO_ID, now_ts, src_id, dst_id, raw_dist);
|
||||
}
|
||||
|
||||
/** Data parsing function */
|
||||
static void dw1000_range_arduino_parse(struct DW1000RangeArduino *dw, uint8_t c)
|
||||
{
|
||||
switch (dw->state) {
|
||||
|
||||
case DW_WAIT_STX:
|
||||
/* Waiting Synchro */
|
||||
if (c == DW_STX) {
|
||||
dw->idx = 0;
|
||||
dw->ck = 0;
|
||||
dw->state = DW_GET_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_GET_DATA:
|
||||
/* Read Bytes */
|
||||
dw->buf[dw->idx++] = c;
|
||||
dw->ck += c;
|
||||
if (dw->idx == DW_NB_DATA) {
|
||||
dw->state = DW_GET_CK;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_GET_CK:
|
||||
/* Checksum */
|
||||
if (dw->ck == c) {
|
||||
send_anchor_data(dw);
|
||||
}
|
||||
dw->state = DW_WAIT_STX;
|
||||
break;
|
||||
|
||||
default:
|
||||
dw->state = DW_WAIT_STX;
|
||||
}
|
||||
}
|
||||
|
||||
void dw1000_range_arduino_init(void)
|
||||
{
|
||||
dw1000_range_arduino.dev = &DW1000_RANGE_ARDUINO_DEV;
|
||||
}
|
||||
|
||||
void dw1000_range_arduino_event(void)
|
||||
{
|
||||
// Look for data on serial link and send to parser
|
||||
while (uart_char_available(dw1000_range_arduino.dev)) {
|
||||
uint8_t ch = uart_getch(dw1000_range_arduino.dev);
|
||||
dw1000_range_arduino_parse(&dw1000_range_arduino, ch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (C) 2026 Fabien-B <fabien-b@github.com>
|
||||
* This file is part of paparazzi. See LICENCE file.
|
||||
*
|
||||
* @file "modules/decawave/dw1000_range_arduino.h"
|
||||
* @author Fabien-B <fabien-b@github.com>
|
||||
*
|
||||
* Driver to get ranging data from Decawave DW1000 modules connected to Arduino
|
||||
* Decawave DW1000 modules (http://www.decawave.com/products/dwm1000-module) are Ultra-Wide-Band devices that can be used for communication and ranging.
|
||||
* Especially, using 3 modules as anchors can provide data for a localization system based on trilateration.
|
||||
* The DW1000 is using a SPI connection, but an arduino-compatible board can be used with the library https://github.com/thotro/arduino-dw1000 to hyde the low level drivers and provide direct ranging informations.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DW1000_RANGE_ARDUINO_H
|
||||
#define DW1000_RANGE_ARDUINO_H
|
||||
|
||||
extern void dw1000_range_arduino_init(void);
|
||||
extern void dw1000_range_arduino_event(void);
|
||||
|
||||
#endif // DW1000_RANGE_ARDUINO_H
|
||||
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Fabien-B <fabien-b@github.com>
|
||||
*
|
||||
* This file is part of paparazzi. See LICENCE file.
|
||||
*
|
||||
* Pprz Decawave driver. Allows ranging, as well as TDOA.
|
||||
*/
|
||||
|
||||
#include "modules/decawave/pdec.h"
|
||||
#include "mcu_periph/uart.h"
|
||||
#include "modules/datalink/downlink.h"
|
||||
#include "modules/core/abi.h"
|
||||
#include "modules/core/abi_sender_ids.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PDEC_SYNC_BYTE 0xff
|
||||
#define PDEC_FRAME_OVERHEAD 4
|
||||
#define PDEC_PACKED __attribute__((packed))
|
||||
|
||||
pdec_t pdec;
|
||||
|
||||
static void _pdec_init(pdec_t *pdec);
|
||||
static void _pdec_periodic_report(pdec_t *pdec);
|
||||
static void _pdec_event(pdec_t *pdec);
|
||||
|
||||
struct pdec_cmd_payload {
|
||||
uint8_t id;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_target_cmd_payload {
|
||||
uint8_t id;
|
||||
uint16_t dst_id;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_error_payload {
|
||||
uint8_t id;
|
||||
uint8_t command;
|
||||
uint8_t status;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_distance_payload {
|
||||
uint8_t id;
|
||||
uint16_t dst_id;
|
||||
uint8_t status;
|
||||
float distance;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_device_list_payload {
|
||||
uint8_t id;
|
||||
uint8_t count;
|
||||
uint16_t device_ids[];
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_send_data_result_payload {
|
||||
uint8_t id;
|
||||
uint16_t dst_id;
|
||||
uint8_t status;
|
||||
uint8_t sent_len;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_ranging_event_payload {
|
||||
uint8_t id;
|
||||
uint8_t kind;
|
||||
uint16_t src_id;
|
||||
uint16_t dst_id;
|
||||
float distance;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_tdoa_report_payload {
|
||||
uint16_t reporter_id;
|
||||
float distance;
|
||||
} PDEC_PACKED;
|
||||
|
||||
struct pdec_tdoa_report_event_payload {
|
||||
uint8_t id;
|
||||
uint32_t blink_id;
|
||||
uint8_t expected_count;
|
||||
uint8_t count;
|
||||
uint8_t timed_out;
|
||||
struct pdec_tdoa_report_payload reports[];
|
||||
} PDEC_PACKED;
|
||||
|
||||
static bool pdec_send_frame(pdec_t *pdec, const uint8_t *payload, uint8_t payload_len)
|
||||
{
|
||||
uint8_t frame[PDEC_FRAME_OVERHEAD + PDEC_MAX_PAYLOAD_LEN];
|
||||
uint8_t checksum = payload_len;
|
||||
uint16_t frame_len = (uint16_t)payload_len + PDEC_FRAME_OVERHEAD;
|
||||
long fd = 0;
|
||||
|
||||
if (payload_len == 0) {
|
||||
pdec->counters.tx_drops++;
|
||||
return false;
|
||||
}
|
||||
|
||||
frame[0] = PDEC_SYNC_BYTE;
|
||||
frame[1] = PDEC_SYNC_BYTE;
|
||||
frame[2] = payload_len;
|
||||
for (uint8_t i = 0; i < payload_len; i++) {
|
||||
frame[3 + i] = payload[i];
|
||||
checksum ^= payload[i];
|
||||
}
|
||||
frame[3 + payload_len] = checksum;
|
||||
|
||||
uart_put_buffer(pdec->dev, fd, frame, frame_len);
|
||||
pdec->counters.tx_frames++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pdec_parse_distance_result(struct pdec_distance_result *result,
|
||||
const struct pdec_distance_payload *payload)
|
||||
{
|
||||
result->dst_id = payload->dst_id;
|
||||
result->status = (enum pdec_status)payload->status;
|
||||
result->distance = payload->distance;
|
||||
result->updated = true;
|
||||
}
|
||||
|
||||
static void pdec_dispatch_frame(pdec_t *pdec)
|
||||
{
|
||||
const uint8_t *payload = pdec->rx_payload;
|
||||
uint8_t len = pdec->rx_len;
|
||||
uint8_t msg_id;
|
||||
|
||||
if (len == 0) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
|
||||
msg_id = payload[0];
|
||||
switch (msg_id) {
|
||||
case PDEC_MSG_ERROR: {
|
||||
if (len != sizeof(struct pdec_error_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
const struct pdec_error_payload *msg = (const struct pdec_error_payload *)payload;
|
||||
pdec->last_error.command = msg->command;
|
||||
pdec->last_error.status = (enum pdec_status)msg->status;
|
||||
pdec->last_error.updated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PDEC_MSG_RANGE_RESULT:
|
||||
if (len != sizeof(struct pdec_distance_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
pdec_parse_distance_result(&pdec->last_range, (const struct pdec_distance_payload *)payload);
|
||||
break;
|
||||
|
||||
case PDEC_MSG_DISTANCE:
|
||||
if (len != sizeof(struct pdec_distance_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
pdec_parse_distance_result(&pdec->last_distance, (const struct pdec_distance_payload *)payload);
|
||||
break;
|
||||
|
||||
case PDEC_MSG_DEVICE_LIST: {
|
||||
if (len < sizeof(struct pdec_device_list_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
const struct pdec_device_list_payload *msg = (const struct pdec_device_list_payload *)payload;
|
||||
uint8_t total_count = msg->count;
|
||||
if (total_count > ((PDEC_MAX_PAYLOAD_LEN - sizeof(struct pdec_device_list_payload)) / sizeof(msg->device_ids[0])) ||
|
||||
len != (uint8_t)(sizeof(struct pdec_device_list_payload) + (total_count * sizeof(msg->device_ids[0])))) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
pdec->devices.total_count = total_count;
|
||||
pdec->devices.count = total_count > PDEC_MAX_DEVICES ? PDEC_MAX_DEVICES : total_count;
|
||||
pdec->devices.truncated = pdec->devices.total_count > pdec->devices.count;
|
||||
for (uint8_t i = 0; i < pdec->devices.count; i++) {
|
||||
pdec->devices.device_ids[i] = msg->device_ids[i];
|
||||
}
|
||||
pdec->devices.updated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PDEC_MSG_SEND_DATA_RESULT: {
|
||||
if (len != sizeof(struct pdec_send_data_result_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
const struct pdec_send_data_result_payload *msg = (const struct pdec_send_data_result_payload *)payload;
|
||||
pdec->last_send_data.dst_id = msg->dst_id;
|
||||
pdec->last_send_data.status = (enum pdec_status)msg->status;
|
||||
pdec->last_send_data.sent_len = msg->sent_len;
|
||||
pdec->last_send_data.updated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PDEC_MSG_RANGING_EVENT: {
|
||||
if (len != sizeof(struct pdec_ranging_event_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
const struct pdec_ranging_event_payload *msg = (const struct pdec_ranging_event_payload *)payload;
|
||||
pdec->last_ranging_event.kind = (enum pdec_event_kind)msg->kind;
|
||||
pdec->last_ranging_event.src_id = msg->src_id;
|
||||
pdec->last_ranging_event.dst_id = msg->dst_id;
|
||||
pdec->last_ranging_event.distance = msg->distance;
|
||||
pdec->last_ranging_event.updated = true;
|
||||
AbiSendMsgUWB_RANGING(UWB_PDEC_ID,
|
||||
get_sys_time_usec(),
|
||||
msg->src_id,
|
||||
msg->dst_id,
|
||||
msg->distance
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case PDEC_MSG_TDOA_REPORT_EVENT: {
|
||||
if (len < sizeof(struct pdec_tdoa_report_event_payload)) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
const struct pdec_tdoa_report_event_payload *msg = (const struct pdec_tdoa_report_event_payload *)payload;
|
||||
uint8_t total_count = msg->count;
|
||||
if (total_count > ((PDEC_MAX_PAYLOAD_LEN - sizeof(struct pdec_tdoa_report_event_payload)) /
|
||||
sizeof(struct pdec_tdoa_report_payload)) ||
|
||||
len != (uint8_t)(sizeof(struct pdec_tdoa_report_event_payload) +
|
||||
(total_count * sizeof(struct pdec_tdoa_report_payload)))) {
|
||||
pdec->counters.rx_length_errors++;
|
||||
return;
|
||||
}
|
||||
pdec->last_tdoa_report_event.blink_id = msg->blink_id;
|
||||
pdec->last_tdoa_report_event.expected_count = msg->expected_count;
|
||||
pdec->last_tdoa_report_event.total_count = total_count;
|
||||
pdec->last_tdoa_report_event.count = total_count > PDEC_MAX_TDOA_REPORTS ? PDEC_MAX_TDOA_REPORTS : total_count;
|
||||
pdec->last_tdoa_report_event.timed_out = msg->timed_out != 0;
|
||||
pdec->last_tdoa_report_event.truncated = pdec->last_tdoa_report_event.total_count > pdec->last_tdoa_report_event.count;
|
||||
uint16_t src_id[PDEC_MAX_TDOA_REPORTS];
|
||||
float range_diff[PDEC_MAX_TDOA_REPORTS];
|
||||
for (uint8_t i = 0; i < pdec->last_tdoa_report_event.count; i++) {
|
||||
src_id[i] = msg->reports[i].reporter_id;
|
||||
range_diff[i] = msg->reports[i].distance;
|
||||
pdec->last_tdoa_report_event.reports[i].reporter_id = src_id[i];
|
||||
pdec->last_tdoa_report_event.reports[i].distance = range_diff[i];
|
||||
}
|
||||
pdec->last_tdoa_report_event.updated = true;
|
||||
AbiSendMsgUWB_TDOA(UWB_PDEC_ID,
|
||||
get_sys_time_usec(),
|
||||
(uint16_t)msg->blink_id,
|
||||
pdec->last_tdoa_report_event.count,
|
||||
src_id,
|
||||
range_diff
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
pdec->counters.rx_unknown_messages++;
|
||||
return;
|
||||
}
|
||||
|
||||
pdec->counters.rx_frames++;
|
||||
}
|
||||
|
||||
static void pdec_parse_byte(pdec_t *pdec, uint8_t byte)
|
||||
{
|
||||
switch (pdec->rx_state) {
|
||||
case PDEC_RX_SYNC_1:
|
||||
if (byte == PDEC_SYNC_BYTE) {
|
||||
pdec->rx_state = PDEC_RX_SYNC_2;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDEC_RX_SYNC_2:
|
||||
if (byte == PDEC_SYNC_BYTE) {
|
||||
pdec->rx_state = PDEC_RX_LEN;
|
||||
} else {
|
||||
pdec->rx_state = PDEC_RX_SYNC_1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDEC_RX_LEN:
|
||||
pdec->rx_len = byte;
|
||||
pdec->rx_idx = 0;
|
||||
pdec->rx_checksum = byte;
|
||||
pdec->rx_state = byte == 0 ? PDEC_RX_CHECKSUM : PDEC_RX_PAYLOAD;
|
||||
break;
|
||||
|
||||
case PDEC_RX_PAYLOAD:
|
||||
pdec->rx_payload[pdec->rx_idx++] = byte;
|
||||
pdec->rx_checksum ^= byte;
|
||||
if (pdec->rx_idx >= pdec->rx_len) {
|
||||
pdec->rx_state = PDEC_RX_CHECKSUM;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDEC_RX_CHECKSUM:
|
||||
if (pdec->rx_checksum == byte) {
|
||||
pdec_dispatch_frame(pdec);
|
||||
} else {
|
||||
pdec->counters.rx_checksum_errors++;
|
||||
}
|
||||
pdec->rx_state = PDEC_RX_SYNC_1;
|
||||
break;
|
||||
|
||||
default:
|
||||
pdec->rx_state = PDEC_RX_SYNC_1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _pdec_init(pdec_t *pdec)
|
||||
{
|
||||
memset(pdec, 0, sizeof(*pdec));
|
||||
pdec->dev = &PDEC_UART_DEV;
|
||||
pdec->rx_state = PDEC_RX_SYNC_1;
|
||||
}
|
||||
|
||||
static void _pdec_periodic_report(pdec_t *pdec __attribute__((unused)))
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
if(pdec->last_error.updated) {
|
||||
|
||||
|
||||
}
|
||||
if(pdec->last_range.updated) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
if(pdec->last_distance.updated) {
|
||||
|
||||
}
|
||||
if(pdec->devices.updated) {
|
||||
|
||||
}
|
||||
if(pdec->last_send_data.updated) {
|
||||
|
||||
}
|
||||
if(pdec->last_ranging_event.updated) {
|
||||
pdec->last_ranging_event.updated = false;
|
||||
|
||||
int len = snprintf(buf, sizeof(buf), "[RNG]%x->%x:%0.2f",
|
||||
pdec->last_ranging_event.src_id,
|
||||
pdec->last_ranging_event.dst_id,
|
||||
pdec->last_ranging_event.distance);
|
||||
DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, len, buf);
|
||||
}
|
||||
if(pdec->last_tdoa_report_event.updated) {
|
||||
pdec->last_tdoa_report_event.updated = false;
|
||||
int offset = snprintf(buf, sizeof(buf), "[TDOA]");
|
||||
for(int i=0; i<pdec->last_tdoa_report_event.count; i++) {
|
||||
offset += snprintf(buf+offset, sizeof(buf)-offset, "%x:%0.2f,",
|
||||
pdec->last_tdoa_report_event.reports[i].reporter_id,
|
||||
pdec->last_tdoa_report_event.reports[i].distance);
|
||||
}
|
||||
DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, offset, buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _pdec_event(pdec_t *pdec)
|
||||
{
|
||||
while (uart_char_available(pdec->dev)) {
|
||||
pdec_parse_byte(pdec, uart_getch(pdec->dev));
|
||||
}
|
||||
}
|
||||
|
||||
bool pdec_range(uint16_t dst_id)
|
||||
{
|
||||
const struct pdec_target_cmd_payload payload = {
|
||||
.id = PDEC_CMD_RANGE,
|
||||
.dst_id = dst_id,
|
||||
};
|
||||
return pdec_send_frame(&pdec, (const uint8_t *)&payload, sizeof(payload));
|
||||
}
|
||||
|
||||
bool pdec_get_distance(uint16_t dst_id)
|
||||
{
|
||||
const struct pdec_target_cmd_payload payload = {
|
||||
.id = PDEC_CMD_GET_DISTANCE,
|
||||
.dst_id = dst_id,
|
||||
};
|
||||
return pdec_send_frame(&pdec, (const uint8_t *)&payload, sizeof(payload));
|
||||
}
|
||||
|
||||
bool pdec_list_devices(void)
|
||||
{
|
||||
const struct pdec_cmd_payload payload = {
|
||||
.id = PDEC_CMD_LIST_DEVICES,
|
||||
};
|
||||
return pdec_send_frame(&pdec, (const uint8_t *)&payload, sizeof(payload));
|
||||
}
|
||||
|
||||
bool pdec_send_data(uint16_t dst_id, const uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t payload[sizeof(struct pdec_target_cmd_payload) + PDEC_MAX_DATA_LEN];
|
||||
struct pdec_target_cmd_payload header = {
|
||||
.id = PDEC_CMD_SEND_DATA,
|
||||
.dst_id = dst_id,
|
||||
};
|
||||
|
||||
if (len > PDEC_MAX_DATA_LEN || (len > 0 && data == NULL)) {
|
||||
pdec.counters.tx_drops++;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(payload, &header, sizeof(header));
|
||||
if (len > 0) {
|
||||
memcpy(&payload[sizeof(header)], data, len);
|
||||
}
|
||||
|
||||
return pdec_send_frame(&pdec, payload, (uint8_t)(sizeof(header) + len));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pdec_init(void)
|
||||
{
|
||||
_pdec_init(&pdec);
|
||||
}
|
||||
|
||||
void pdec_periodic_report(void)
|
||||
{
|
||||
_pdec_periodic_report(&pdec);
|
||||
}
|
||||
|
||||
void pdec_event(void)
|
||||
{
|
||||
_pdec_event(&pdec);
|
||||
}
|
||||
|
||||
|
||||
void uwb_range(uint16_t dst_id) {
|
||||
pdec_range(dst_id);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Fabien-B <fabien-b@github.com>
|
||||
*
|
||||
* This file is part of paparazzi. See LICENCE file.
|
||||
*
|
||||
* Pprz Decawave driver. Allows ranging, as well as TDOA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct uart_periph;
|
||||
|
||||
#ifndef PDEC_MAX_DEVICES
|
||||
#define PDEC_MAX_DEVICES 32
|
||||
#endif
|
||||
|
||||
#ifndef PDEC_MAX_TDOA_REPORTS
|
||||
#define PDEC_MAX_TDOA_REPORTS 32
|
||||
#endif
|
||||
|
||||
#define PDEC_MAX_PAYLOAD_LEN 255
|
||||
#define PDEC_MAX_DATA_LEN 252
|
||||
|
||||
enum pdec_command {
|
||||
PDEC_CMD_RANGE = 0x01,
|
||||
PDEC_CMD_GET_DISTANCE = 0x02,
|
||||
PDEC_CMD_LIST_DEVICES = 0x03,
|
||||
PDEC_CMD_SEND_DATA = 0x04,
|
||||
};
|
||||
|
||||
enum pdec_msg {
|
||||
PDEC_MSG_ERROR = 0x7F,
|
||||
PDEC_MSG_RANGE_RESULT = 0x81,
|
||||
PDEC_MSG_DISTANCE = 0x82,
|
||||
PDEC_MSG_DEVICE_LIST = 0x83,
|
||||
PDEC_MSG_SEND_DATA_RESULT = 0x84,
|
||||
PDEC_MSG_RANGING_EVENT = 0x90,
|
||||
PDEC_MSG_TDOA_REPORT_EVENT = 0x92,
|
||||
};
|
||||
|
||||
enum pdec_status {
|
||||
PDEC_STATUS_OK = 0x00,
|
||||
PDEC_STATUS_ERROR = 0x01,
|
||||
PDEC_STATUS_INVALID_LENGTH = 0x02,
|
||||
PDEC_STATUS_NOT_FOUND = 0x03,
|
||||
PDEC_STATUS_RANGE_FAILED = 0x04,
|
||||
PDEC_STATUS_MESSAGE_TOO_LONG = 0x05,
|
||||
};
|
||||
|
||||
enum pdec_event_kind {
|
||||
PDEC_EVENT_SINGLE_SIDED = 0x00,
|
||||
PDEC_EVENT_DOUBLE_SIDED = 0x01,
|
||||
PDEC_EVENT_INDIRECT = 0x02,
|
||||
};
|
||||
|
||||
enum pdec_rx_state {
|
||||
PDEC_RX_SYNC_1,
|
||||
PDEC_RX_SYNC_2,
|
||||
PDEC_RX_LEN,
|
||||
PDEC_RX_PAYLOAD,
|
||||
PDEC_RX_CHECKSUM,
|
||||
};
|
||||
|
||||
struct pdec_error_response {
|
||||
bool updated;
|
||||
uint8_t command;
|
||||
enum pdec_status status;
|
||||
};
|
||||
|
||||
struct pdec_distance_result {
|
||||
bool updated;
|
||||
uint16_t dst_id;
|
||||
enum pdec_status status;
|
||||
float distance;
|
||||
};
|
||||
|
||||
struct pdec_device_list {
|
||||
bool updated;
|
||||
uint8_t count;
|
||||
uint8_t total_count;
|
||||
bool truncated;
|
||||
uint16_t device_ids[PDEC_MAX_DEVICES];
|
||||
};
|
||||
|
||||
struct pdec_send_data_result {
|
||||
bool updated;
|
||||
uint16_t dst_id;
|
||||
enum pdec_status status;
|
||||
uint8_t sent_len;
|
||||
};
|
||||
|
||||
struct pdec_ranging_event {
|
||||
bool updated;
|
||||
enum pdec_event_kind kind;
|
||||
uint16_t src_id;
|
||||
uint16_t dst_id;
|
||||
float distance;
|
||||
};
|
||||
|
||||
struct pdec_tdoa_report {
|
||||
uint16_t reporter_id;
|
||||
float distance;
|
||||
};
|
||||
|
||||
struct pdec_tdoa_report_event {
|
||||
bool updated;
|
||||
uint32_t blink_id;
|
||||
uint8_t expected_count;
|
||||
uint8_t count;
|
||||
uint8_t total_count;
|
||||
bool timed_out;
|
||||
bool truncated;
|
||||
struct pdec_tdoa_report reports[PDEC_MAX_TDOA_REPORTS];
|
||||
};
|
||||
|
||||
struct pdec_counters {
|
||||
uint32_t rx_frames;
|
||||
uint32_t rx_checksum_errors;
|
||||
uint32_t rx_length_errors;
|
||||
uint32_t rx_unknown_messages;
|
||||
uint32_t tx_frames;
|
||||
uint32_t tx_drops;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct uart_periph *dev;
|
||||
|
||||
struct pdec_error_response last_error;
|
||||
struct pdec_distance_result last_range;
|
||||
struct pdec_distance_result last_distance;
|
||||
struct pdec_device_list devices;
|
||||
struct pdec_send_data_result last_send_data;
|
||||
struct pdec_ranging_event last_ranging_event;
|
||||
struct pdec_tdoa_report_event last_tdoa_report_event;
|
||||
struct pdec_counters counters;
|
||||
|
||||
/* Driver-owned parser state. */
|
||||
enum pdec_rx_state rx_state;
|
||||
uint8_t rx_len;
|
||||
uint8_t rx_idx;
|
||||
uint8_t rx_checksum;
|
||||
uint8_t rx_payload[PDEC_MAX_PAYLOAD_LEN];
|
||||
} pdec_t;
|
||||
|
||||
extern pdec_t pdec;
|
||||
|
||||
void pdec_init(void);
|
||||
void pdec_periodic_report(void);
|
||||
void pdec_event(void);
|
||||
|
||||
bool pdec_range(uint16_t dst_id);
|
||||
bool pdec_get_distance(uint16_t dst_id);
|
||||
bool pdec_list_devices(void);
|
||||
bool pdec_send_data(uint16_t dst_id, const uint8_t *data, uint8_t len);
|
||||
File diff suppressed because it is too large
Load Diff
+17
-19
@@ -18,42 +18,40 @@
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file "modules/decawave/dw1000_arduino.h"
|
||||
* @file "modules/decawave/uwb_positioning.h"
|
||||
* @author Gautier Hattenberger
|
||||
* Driver to get ranging data from Decawave DW1000 modules connected to Arduino
|
||||
* UWB positioning from anchor measurements.
|
||||
*/
|
||||
|
||||
#ifndef DW1000_ARDUINO_H
|
||||
#define DW1000_ARDUINO_H
|
||||
#pragma once
|
||||
|
||||
#include "std.h"
|
||||
|
||||
/** enable EKF filtering */
|
||||
extern bool dw1000_use_ekf;
|
||||
extern bool uwb_positioning_use_ekf;
|
||||
|
||||
/** process and measurements noise */
|
||||
extern float dw1000_ekf_q;
|
||||
extern float dw1000_ekf_r_dist;
|
||||
extern float dw1000_ekf_r_speed;
|
||||
extern float uwb_positioning_ekf_q;
|
||||
extern float uwb_positioning_ekf_r_dist;
|
||||
extern float uwb_positioning_ekf_r_speed;
|
||||
/** settings handler */
|
||||
extern void dw1000_arduino_update_ekf_q(float v);
|
||||
extern void dw1000_arduino_update_ekf_r_dist(float v);
|
||||
extern void dw1000_arduino_update_ekf_r_speed(float v);
|
||||
extern void uwb_positioning_update_ekf_q(float v);
|
||||
extern void uwb_positioning_update_ekf_r_dist(float v);
|
||||
extern void uwb_positioning_update_ekf_r_speed(float v);
|
||||
|
||||
extern void dw1000_arduino_init(void);
|
||||
extern void dw1000_arduino_periodic(void);
|
||||
extern void dw1000_arduino_report(void);
|
||||
extern void dw1000_arduino_event(void);
|
||||
extern void uwb_positioning_init(void);
|
||||
extern void uwb_positioning_periodic(void);
|
||||
extern void uwb_positioning_range_periodic(void);
|
||||
extern void uwb_positioning_report(void);
|
||||
|
||||
/** Reset reference heading to current heading
|
||||
* AHRS/INS should be aligned before calling this function
|
||||
*/
|
||||
extern void dw1000_reset_heading_ref(void);
|
||||
extern void uwb_positioning_reset_heading_ref(void);
|
||||
|
||||
// when used as a GPS
|
||||
#ifndef PRIMARY_GPS
|
||||
#define PRIMARY_GPS GPS_DW1000
|
||||
#endif
|
||||
|
||||
#define PRIMARY_GPS GPS_UWB
|
||||
#endif
|
||||
|
||||
void uwb_range(uint16_t id);
|
||||
Reference in New Issue
Block a user