Uavcan update (#3424)
Doxygen / build (push) Waiting to run

* [uavcan] Start updating UAVCAN to latest version.
Now renamed DroneCAN.

* [uavcan] Update airspeed.

* [uavcan] Update power.

* [uavcan] Update range sensor.

* [uavcan] WIP actuators.

* [dronecan] Fix makefile for new installations

- The Makefile doesn't execute the .sync .update when added to the .PHONY section
- The DSDL folder doesn't exist before the .sync .update of the DSDL

* [can] Add documentation for USE_CANx define and fix dronecan

* [dronecan] Update actuators

* [dronecan] Cleanup actuator feedback

---------

Co-authored-by: Fabien-B <Fabien-B@github.com>
Co-authored-by: Freek van Tienen <freek.v.tienen@gmail.com>
This commit is contained in:
Fabien-B
2025-03-13 10:23:13 +01:00
committed by GitHub
parent 27860ffa49
commit 776a22f459
20 changed files with 314 additions and 361 deletions
+12 -3
View File
@@ -50,6 +50,15 @@
[submodule "sw/ext/matrix"] [submodule "sw/ext/matrix"]
path = sw/ext/matrix path = sw/ext/matrix
url = https://github.com/PX4/Matrix.git url = https://github.com/PX4/Matrix.git
[submodule "sw/ext/libcanard"] [submodule "sw/ext/dronecan/DSDL"]
path = sw/ext/libcanard path = sw/ext/dronecan/DSDL
url = https://github.com/UAVCAN/libcanard.git url = https://github.com/dronecan/DSDL.git
[submodule "sw/ext/dronecan/dronecan_dsdlc"]
path = sw/ext/dronecan/dronecan_dsdlc
url = https://github.com/dronecan/dronecan_dsdlc.git
[submodule "sw/ext/dronecan/pydronecan"]
path = sw/ext/dronecan/pydronecan
url = https://github.com/dronecan/pydronecan.git
[submodule "sw/ext/dronecan/libcanard"]
path = sw/ext/dronecan/libcanard
url = https://github.com/dronecan/libcanard.git
+8
View File
@@ -17,6 +17,14 @@
<makefile target="ap"> <makefile target="ap">
<file name="actuators_uavcan.c"/> <file name="actuators_uavcan.c"/>
<file name="pprz_random.c" dir="math"/> <file name="pprz_random.c" dir="math"/>
<!-- Load DSDL generated files-->
<include name="$(PAPARAZZI_HOME)/var/include/DSDLcode/include"/>
<file name="uavcan.equipment.esc.Status.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.equipment.esc.RawCommand.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.equipment.actuator.Status.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.equipment.actuator.ArrayCommand.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.equipment.device.Temperature.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
</makefile> </makefile>
</module> </module>
+4
View File
@@ -30,5 +30,9 @@
<init fun="airspeed_uavcan_init()"/> <init fun="airspeed_uavcan_init()"/>
<makefile target="ap"> <makefile target="ap">
<file name="airspeed_uavcan.c"/> <file name="airspeed_uavcan.c"/>
<!-- Load DSDL generated files-->
<include name="$(PAPARAZZI_HOME)/var/include/DSDLcode/include"/>
<file name="uavcan.equipment.air_data.RawAirData.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
</makefile> </makefile>
</module> </module>
+1
View File
@@ -7,6 +7,7 @@
To activate a specific CAN peripheral, define flag USE_CANx where x is your CAN peripheral number To activate a specific CAN peripheral, define flag USE_CANx where x is your CAN peripheral number
</description> </description>
<configure name="USE_CANFD" value="TRUE" description="Use CANFD or just CAN"/> <configure name="USE_CANFD" value="TRUE" description="Use CANFD or just CAN"/>
<define name="USE_CANx" value="FALSE" description="Enable the CANx port"/>
</doc> </doc>
<dep> <dep>
<depends>mcu</depends> <depends>mcu</depends>
+6
View File
@@ -23,5 +23,11 @@
<init fun="power_uavcan_init()"/> <init fun="power_uavcan_init()"/>
<makefile target="ap"> <makefile target="ap">
<file name="power_uavcan.c"/> <file name="power_uavcan.c"/>
<file name="pprz_random.c" dir="math"/>
<!-- Load DSDL generated files-->
<include name="$(PAPARAZZI_HOME)/var/include/DSDLcode/include"/>
<file name="uavcan.equipment.power.BatteryInfo.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.equipment.power.CircuitStatus.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
</makefile> </makefile>
</module> </module>
+4
View File
@@ -16,5 +16,9 @@
<init fun="range_sensor_uavcan_init()"/> <init fun="range_sensor_uavcan_init()"/>
<makefile target="ap"> <makefile target="ap">
<file name="range_sensor_uavcan.c"/> <file name="range_sensor_uavcan.c"/>
<!-- Load DSDL generated files-->
<include name="$(PAPARAZZI_HOME)/var/include/DSDLcode/include"/>
<file name="uavcan.equipment.range_sensor.Measurement.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
</makefile> </makefile>
</module> </module>
+10 -2
View File
@@ -16,14 +16,22 @@
<init fun="uavcan_init()"/> <init fun="uavcan_init()"/>
<makefile target="ap"> <makefile target="ap">
<!-- Enable the CAN busses if needed --> <!-- Enable the CAN busses if needed -->
<configure name="UAVCAN_USE_CAN1" default="FALSE"/>
<configure name="UAVCAN_USE_CAN2" default="FALSE"/>
<define name="USE_CAN1" cond="ifeq ($(UAVCAN_USE_CAN1), TRUE)"/> <define name="USE_CAN1" cond="ifeq ($(UAVCAN_USE_CAN1), TRUE)"/>
<define name="USE_CAN2" cond="ifeq ($(UAVCAN_USE_CAN2), TRUE)"/> <define name="USE_CAN2" cond="ifeq ($(UAVCAN_USE_CAN2), TRUE)"/>
<define name="UAVCAN_USE_CAN1" value="$(UAVCAN_USE_CAN1)"/> <define name="UAVCAN_USE_CAN1" value="$(UAVCAN_USE_CAN1)"/>
<define name="UAVCAN_USE_CAN2" value="$(UAVCAN_USE_CAN2)"/> <define name="UAVCAN_USE_CAN2" value="$(UAVCAN_USE_CAN2)"/>
<!-- Load canard --> <!-- Load canard -->
<include name="$(PAPARAZZI_SRC)/sw/ext/libcanard"/> <include name="$(PAPARAZZI_SRC)/sw/ext/dronecan/libcanard"/>
<file name="canard.c" dir="$(PAPARAZZI_SRC)/sw/ext/libcanard"/> <file name="canard.c" dir="$(PAPARAZZI_SRC)/sw/ext/dronecan/libcanard"/>
<!-- Load DSDL generated files-->
<include name="$(PAPARAZZI_HOME)/var/include/DSDLcode/include"/>
<file name="uavcan.protocol.NodeStatus.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.protocol.GetNodeInfo_req.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<file name="uavcan.protocol.GetNodeInfo_res.c" dir="$(PAPARAZZI_HOME)/var/include/DSDLcode/src"/>
<!-- Load uavcan itself --> <!-- Load uavcan itself -->
<file_arch name="uavcan.c" dir="modules/uavcan"/> <file_arch name="uavcan.c" dir="modules/uavcan"/>
+3
View File
@@ -9,3 +9,6 @@ pyqtgraph
unidecode unidecode
matplotlib matplotlib
distro distro
empy==3.3.4
pexpect
@@ -88,6 +88,11 @@ struct uavcan_iface_t uavcan2 = {
}; };
#endif #endif
/*
* REMOVE ME - This is only here because the can driver is not yet used
*/
void can_init(void) { }
/* /*
* Receiver thread. * Receiver thread.
*/ */
+135 -206
View File
@@ -30,6 +30,13 @@
#include "modules/core/abi.h" #include "modules/core/abi.h"
#include "modules/actuators/actuators.h" #include "modules/actuators/actuators.h"
#include "uavcan.equipment.esc.Status.h"
#include "uavcan.equipment.esc.RawCommand.h"
#include "uavcan.equipment.actuator.Status.h"
#include "uavcan.equipment.actuator.ArrayCommand.h"
#include "uavcan.equipment.device.Temperature.h"
/* By default enable the usage of the current sensing in the ESC telemetry */ /* By default enable the usage of the current sensing in the ESC telemetry */
#ifndef UAVCAN_ACTUATORS_USE_CURRENT #ifndef UAVCAN_ACTUATORS_USE_CURRENT
#define UAVCAN_ACTUATORS_USE_CURRENT TRUE #define UAVCAN_ACTUATORS_USE_CURRENT TRUE
@@ -83,31 +90,6 @@ static struct actuators_uavcan_telem_t uavcan2_telem[SERVOS_UAVCAN2_NB] = {0};
/* UNUSED value for CMD */ /* UNUSED value for CMD */
#define UAVCAN_CMD_UNUSED (MIN_PPRZ-1) #define UAVCAN_CMD_UNUSED (MIN_PPRZ-1)
/* uavcan EQUIPMENT_ESC_STATUS message definition */
#define UAVCAN_EQUIPMENT_ESC_STATUS_ID 1034
#define UAVCAN_EQUIPMENT_ESC_STATUS_SIGNATURE (0xA9AF28AEA2FBB254ULL)
#define UAVCAN_EQUIPMENT_ESC_STATUS_MAX_SIZE ((110 + 7)/8)
/* uavcan EQUIPMENT_ESC_RAWCOMMAND message definition */
#define UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID 1030
#define UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE (0x217F5C87D7EC951DULL)
#define UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_SIZE ((285 + 7)/8)
/* uavcan EQUIPMENT_ACTUATOR_STATUS message definition */
#define UAVCAN_EQUIPMENT_ACTUATOR_STATUS_ID 1011
#define UAVCAN_EQUIPMENT_ACTUATOR_STATUS_SIGNATURE (0x5E9BBA44FAF1EA04ULL)
#define UAVCAN_EQUIPMENT_ACTUATOR_STATUS_MAX_SIZE ((64 + 7)/8)
/* uavcan EQUIPMENT_ACTUATOR_ARRAYCOMMAND message definition */
#define UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_ID 1010
#define UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_SIGNATURE (0xD8A7486238EC3AF3ULL)
#define UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_MAX_SIZE ((484 + 7)/8)
/* uavcan EQUIMPENT_DEVICE_TEMPERATURE message definition */
#define UAVCAN_EQUIPMENT_DEVICE_TEMPERATURE_ID 1110
#define UAVCAN_EQUIPMENT_DEVICE_TEMPERATURE_SIGNATURE (0x70261C28A94144C6ULL)
#define UAVCAN_EQUIPMENT_DEVICE_TEMPERATURE_MAX_SIZE ((40 + 7)/8)
/* private variables */ /* private variables */
static bool actuators_uavcan_initialized = false; static bool actuators_uavcan_initialized = false;
static uavcan_event esc_status_ev; static uavcan_event esc_status_ev;
@@ -179,53 +161,101 @@ static void actuators_uavcan_send_esc(struct transport_tx *trans, struct link_de
} }
#endif #endif
static struct actuators_uavcan_telem_t *get_actuator_telem(struct uavcan_iface_t *iface, uint8_t idx) {
struct actuators_uavcan_telem_t *telem = NULL;
#ifdef UAVCAN1_TELEM_NB
if (iface == &uavcan1 && idx < UAVCAN1_TELEM_NB) {
telem = &uavcan1_telem[idx];
}
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2 && idx < UAVCAN2_TELEM_NB) {
telem = &uavcan2_telem[idx];
}
#endif
return telem;
}
static uint8_t get_actuator_idx(struct uavcan_iface_t *iface, uint8_t idx) {
uint8_t actuator_idx = 255;
#ifdef UAVCAN1_TELEM_NB
if(iface == &uavcan1) {
#ifdef SERVOS_UAVCAN1_NB
// First try as RAW COMMAND
actuator_idx = get_servo_idx_UAVCAN1(idx);
#endif
#ifdef SERVOS_UAVCAN1CMD_NB
// Then try as ACTUATOR COMMAND
if(idx < SERVOS_UAVCAN1CMD_NB && actuators_uavcan1cmd_values[idx] != UAVCAN_CMD_UNUSED) {
actuator_idx = get_servo_idx_UAVCAN1CMD(idx);
}
#endif
}
#endif
#ifdef UAVCAN2_TELEM_NB
if(iface == &uavcan2) {
#ifdef SERVOS_UAVCAN2_NB
// First try as RAW COMMAND
actuator_idx = get_servo_idx_UAVCAN2(idx);
#endif
#ifdef SERVOS_UAVCAN2CMD_NB
// Then try as ACTUATOR COMMAND
if(idx < SERVOS_UAVCAN2CMD_NB && actuators_uavcan2cmd_values[idx] != UAVCAN_CMD_UNUSED) {
actuator_idx = get_servo_idx_UAVCAN2CMD(idx);
}
#endif
}
#endif
return actuator_idx;
}
/** /**
* Whevener an ESC_STATUS message from the EQUIPMENT group is received * Whevener an ESC_STATUS message from the EQUIPMENT group is received
*/ */
static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer) static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
{ {
uint8_t esc_idx; // Decode the message
uint16_t tmp_float; struct uavcan_equipment_esc_Status msg;
if(uavcan_equipment_esc_Status_decode(transfer, &msg)) {
struct actuators_uavcan_telem_t *telem = NULL; return; // Decoding error
uint8_t max_id = 0;
#ifdef UAVCAN1_TELEM_NB
if (iface == &uavcan1) {
telem = uavcan1_telem;
max_id = UAVCAN1_TELEM_NB;
} }
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2) {
telem = uavcan2_telem;
max_id = UAVCAN2_TELEM_NB;
}
#endif
canardDecodeScalar(transfer, 105, 5, false, (void *)&esc_idx); // Get the correct telemetry
//Could not find the right interface struct actuators_uavcan_telem_t *telem = get_actuator_telem(iface, msg.esc_index);
if (esc_idx >= max_id || telem == NULL || max_id == 0) { if(telem == NULL) {
return; return;
} }
telem[esc_idx].set = true;
telem[esc_idx].node_id = transfer->source_node_id; // Set the telemetry (FIXME: copy over fully)
telem[esc_idx].timestamp = get_sys_time_float(); telem->set = true;
canardDecodeScalar(transfer, 0, 32, false, (void *)&telem[esc_idx].energy); telem->node_id = transfer->source_node_id;
canardDecodeScalar(transfer, 32, 16, true, (void *)&tmp_float); telem->timestamp = get_sys_time_float();
telem[esc_idx].voltage = canardConvertFloat16ToNativeFloat(tmp_float); telem->energy = msg.error_count;
canardDecodeScalar(transfer, 48, 16, true, (void *)&tmp_float); telem->voltage = msg.voltage;
telem[esc_idx].current = canardConvertFloat16ToNativeFloat(tmp_float); telem->current = msg.current;
canardDecodeScalar(transfer, 64, 16, true, (void *)&tmp_float); telem->temperature = msg.temperature;
telem[esc_idx].temperature = canardConvertFloat16ToNativeFloat(tmp_float); telem->rpm = msg.rpm;
canardDecodeScalar(transfer, 80, 18, true, (void *)&telem[esc_idx].rpm);
/* Specification says Kelvin, but some are transmitting in Celsius */ /* Specification says Kelvin, but some are transmitting in Celsius */
if (telem[esc_idx].temperature > 230.f) { if (telem->temperature > 230.f) {
telem[esc_idx].temperature -= 273.15; telem->temperature -= 273.15;
} }
// Feedback ABI RPM messages
struct act_feedback_t feedback = {0};
feedback.idx = get_actuator_idx(iface, msg.esc_index);
feedback.rpm = telem->rpm;
feedback.set.rpm = true;
// Send ABI message
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
#if UAVCAN_ACTUATORS_USE_CURRENT #if UAVCAN_ACTUATORS_USE_CURRENT
// Update total current // Update total current based on ESC telemetry
electrical.current = 0; electrical.current = 0;
#ifdef UAVCAN1_TELEM_NB #ifdef UAVCAN1_TELEM_NB
for (uint8_t i = 0; i < UAVCAN1_TELEM_NB; ++i) { for (uint8_t i = 0; i < UAVCAN1_TELEM_NB; ++i) {
@@ -237,46 +267,6 @@ static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardR
electrical.current += uavcan2_telem[i].current; electrical.current += uavcan2_telem[i].current;
} }
#endif #endif
#endif
// Feedback ABI RPM messages
#ifdef UAVCAN1_TELEM_NB
if (iface == &uavcan1) {
struct act_feedback_t feedback = {0};
feedback.rpm = telem[esc_idx].rpm;
feedback.set.rpm = true;
#ifdef SERVOS_UAVCAN1_NB
feedback.idx = get_servo_idx_UAVCAN1(esc_idx);
#endif
#ifdef SERVOS_UAVCAN1CMD_NB
if(esc_idx < SERVOS_UAVCAN1CMD_NB && actuators_uavcan1cmd_values[esc_idx] != UAVCAN_CMD_UNUSED) {
feedback.idx = get_servo_idx_UAVCAN1CMD(esc_idx);
}
#endif
// Send ABI message
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
}
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2) {
struct act_feedback_t feedback = {0};
feedback.rpm = telem[esc_idx].rpm;
feedback.set.rpm = true;
#ifdef SERVOS_UAVCAN2_NB
feedback.idx = get_servo_idx_UAVCAN2(esc_idx);
#endif
#ifdef SERVOS_UAVCAN2CMD_NB
if(esc_idx < SERVOS_UAVCAN2CMD_NB && actuators_uavcan2cmd_values[esc_idx] != UAVCAN_CMD_UNUSED) {
feedback.idx = get_servo_idx_UAVCAN2CMD(esc_idx);
}
#endif
// Send ABI message
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
}
#endif #endif
} }
@@ -285,73 +275,29 @@ static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardR
*/ */
static void actuators_uavcan_actuator_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer) static void actuators_uavcan_actuator_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
{ {
uint8_t actuator_idx; // Decode the message
uint16_t tmp_float; struct uavcan_equipment_actuator_Status msg;
if(uavcan_equipment_actuator_Status_decode(transfer, &msg)) {
struct actuators_uavcan_telem_t *telem = NULL; return; // Decoding error
uint8_t max_id = 0;
#ifdef UAVCAN1_TELEM_NB
if (iface == &uavcan1) {
telem = uavcan1_telem;
max_id = UAVCAN1_TELEM_NB;
} }
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2) {
telem = uavcan2_telem;
max_id = UAVCAN2_TELEM_NB;
}
#endif
canardDecodeScalar(transfer, 0, 8, false, (void *)&actuator_idx); // Get the correct telemetry
//Could not find the right interface struct actuators_uavcan_telem_t *telem = get_actuator_telem(iface, msg.actuator_id);
if (actuator_idx >= max_id || telem == NULL || max_id == 0) { if(telem == NULL) {
return; return;
} }
//telem[actuator_idx].set = true; //telem[msg.actuator_id].set = true;
canardDecodeScalar(transfer, 8, 16, true, (void *)&tmp_float); telem->position = msg.position;
telem[actuator_idx].position = canardConvertFloat16ToNativeFloat(tmp_float);
#ifdef UAVCAN1_TELEM_NB // Feedback ABI position messages
if (iface == &uavcan1) { struct act_feedback_t feedback = {0};
struct act_feedback_t feedback = {0}; feedback.idx = get_actuator_idx(iface, msg.actuator_id);
feedback.position = telem[actuator_idx].position; feedback.position = telem->position;
feedback.set.position = true; feedback.set.position = true;
#ifdef SERVOS_UAVCAN1_NB // Send ABI message
feedback.idx = get_servo_idx_UAVCAN1(actuator_idx); AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
#endif
#ifdef SERVOS_UAVCAN1CMD_NB
if(actuator_idx < SERVOS_UAVCAN1CMD_NB && actuators_uavcan1cmd_values[actuator_idx] != UAVCAN_CMD_UNUSED) {
feedback.idx = get_servo_idx_UAVCAN1CMD(actuator_idx);
}
#endif
// Send ABI message
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
}
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2) {
struct act_feedback_t feedback = {0};
feedback.position = telem[actuator_idx].position;
feedback.set.position = true;
#ifdef SERVOS_UAVCAN2_NB
feedback.idx = get_servo_idx_UAVCAN2(actuator_idx);
#endif
#ifdef SERVOS_UAVCAN2CMD_NB
if(actuator_idx < SERVOS_UAVCAN2CMD_NB && actuators_uavcan2cmd_values[actuator_idx] != UAVCAN_CMD_UNUSED) {
feedback.idx = get_servo_idx_UAVCAN2CMD(actuator_idx);
}
#endif
// Send ABI message
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
}
#endif
} }
/** /**
@@ -359,34 +305,20 @@ static void actuators_uavcan_actuator_status_cb(struct uavcan_iface_t *iface, Ca
*/ */
static void actuators_uavcan_device_temperature_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer) static void actuators_uavcan_device_temperature_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
{ {
uint16_t device_id; // Decode the message
uint16_t tmp_float; struct uavcan_equipment_device_Temperature msg;
if(uavcan_equipment_device_Temperature_decode(transfer, &msg)) {
struct actuators_uavcan_telem_t *telem = NULL; return; // Decoding error
uint8_t max_id = 0;
#ifdef UAVCAN1_TELEM_NB
if (iface == &uavcan1) {
telem = uavcan1_telem;
max_id = UAVCAN1_TELEM_NB;
} }
#endif
#ifdef UAVCAN2_TELEM_NB
if (iface == &uavcan2) {
telem = uavcan2_telem;
max_id = UAVCAN2_TELEM_NB;
}
#endif
// Get the correct telemetry
canardDecodeScalar(transfer, 0, 16, false, (void*)&device_id); struct actuators_uavcan_telem_t *telem = get_actuator_telem(iface, msg.device_id);
//Could not find the right interface if(telem == NULL) {
if (device_id >= max_id || telem == NULL || max_id == 0) {
return; return;
} }
telem[device_id].set = true; telem->set = true;
canardDecodeScalar(transfer, 16, 16, false, (void*)&tmp_float); telem->temperature_dev = msg.temperature - 273.15;
telem[device_id].temperature_dev = canardConvertFloat16ToNativeFloat(tmp_float) - 273.15;
} }
@@ -413,7 +345,7 @@ void actuators_uavcan_init(struct uavcan_iface_t *iface __attribute__((unused)))
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_ESC, actuators_uavcan_send_esc); register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_ESC, actuators_uavcan_send_esc);
#endif #endif
// Set default to not set // Set default to not used
#ifdef SERVOS_UAVCAN1CMD_NB #ifdef SERVOS_UAVCAN1CMD_NB
for(uint8_t i = 0; i < SERVOS_UAVCAN1CMD_NB; i++) for(uint8_t i = 0; i < SERVOS_UAVCAN1CMD_NB; i++)
actuators_uavcan1cmd_values[i] = UAVCAN_CMD_UNUSED; actuators_uavcan1cmd_values[i] = UAVCAN_CMD_UNUSED;
@@ -435,18 +367,20 @@ void actuators_uavcan_init(struct uavcan_iface_t *iface __attribute__((unused)))
*/ */
void actuators_uavcan_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb) void actuators_uavcan_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb)
{ {
uint8_t buffer[UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_SIZE]; // Generate the message
uint32_t offset = 0; struct uavcan_equipment_esc_RawCommand msg = {0};
msg.cmd.len = nb;
// Encode the values as 14-bit signed integers
for (uint8_t i = 0; i < nb; i++) { for (uint8_t i = 0; i < nb; i++) {
canardEncodeScalar(buffer, offset, 14, (void *)&values[i]); msg.cmd.data[i] = values[i];
offset += 14;
} }
// Encode the mssage
uint8_t buffer[UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_SIZE];
uint32_t total_size = uavcan_equipment_esc_RawCommand_encode(&msg, buffer);
// Broadcast the raw command message on the interface // Broadcast the raw command message on the interface
uavcan_broadcast(iface, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID, uavcan_broadcast(iface, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID,
CANARD_TRANSFER_PRIORITY_HIGH, buffer, (offset + 7) / 8); CANARD_TRANSFER_PRIORITY_HIGH, buffer, total_size);
} }
/** /**
@@ -454,31 +388,26 @@ void actuators_uavcan_commit(struct uavcan_iface_t *iface, int16_t *values, uint
*/ */
void actuators_uavcan_cmd_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb) void actuators_uavcan_cmd_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb)
{ {
uint8_t buffer[UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_MAX_SIZE]; struct uavcan_equipment_actuator_ArrayCommand msg = {0};
uint32_t offset = 0; msg.commands.len = 0;
uint8_t command_type = 0; // 0:UNITLESS, 1:meter or radian, 2:N or Nm, 3:m/s or rad/s
// Encode the values for each command // Encode the values for each command
for (uint8_t i = 0; i < nb; i++) { for (uint8_t i = 0; i < nb; i++) {
// Skip unused commands // Skip unused commands
if(values[i] == UAVCAN_CMD_UNUSED || values[i] < MIN_PPRZ || values[i] > MAX_PPRZ) if(values[i] == UAVCAN_CMD_UNUSED || values[i] < MIN_PPRZ || values[i] > MAX_PPRZ)
continue; continue;
// Set the command id msg.commands.data[msg.commands.len].actuator_id = i;
canardEncodeScalar(buffer, offset, 8, (void*)&i); // 255 msg.commands.data[msg.commands.len].command_type = UAVCAN_EQUIPMENT_ACTUATOR_COMMAND_COMMAND_TYPE_UNITLESS;
offset += 8; msg.commands.data[msg.commands.len].command_value = (float)values[i] / (float)MAX_PPRZ;
msg.commands.len++;
// Set the command type
canardEncodeScalar(buffer, offset, 8, (void*)&command_type); // 255
offset += 8;
// Set the command value
uint16_t tmp_float = canardConvertNativeFloatToFloat16((float)values[i] / (float)MAX_PPRZ);
canardEncodeScalar(buffer, offset, 16, (void*)&tmp_float); // 32767
offset += 16;
} }
// Encode the message
uint8_t buffer[UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_MAX_SIZE];
uint32_t total_size = uavcan_equipment_actuator_ArrayCommand_encode(&msg, buffer);
// Broadcast the raw command message on the interface // Broadcast the raw command message on the interface
uavcan_broadcast(iface, UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_SIGNATURE, UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_ID, uavcan_broadcast(iface, UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_SIGNATURE, UAVCAN_EQUIPMENT_ACTUATOR_ARRAYCOMMAND_ID,
CANARD_TRANSFER_PRIORITY_HIGH, buffer, (offset + 7) / 8); CANARD_TRANSFER_PRIORITY_HIGH, buffer, total_size);
} }
+10 -19
View File
@@ -26,6 +26,7 @@
#include "airspeed_uavcan.h" #include "airspeed_uavcan.h"
#include "uavcan/uavcan.h" #include "uavcan/uavcan.h"
#include "core/abi.h" #include "core/abi.h"
#include "uavcan.equipment.air_data.RawAirData.h"
/* Enable ABI sending */ /* Enable ABI sending */
#ifndef AIRSPEED_UAVCAN_SEND_ABI #ifndef AIRSPEED_UAVCAN_SEND_ABI
@@ -52,11 +53,6 @@
static Butterworth2LowPass airspeed_filter; static Butterworth2LowPass airspeed_filter;
#endif /* USE_AIRSPEED_UAVCAN_LOWPASS_FILTER */ #endif /* USE_AIRSPEED_UAVCAN_LOWPASS_FILTER */
/* uavcan EQUIPMENT_ESC_STATUS message definition */
#define UAVCAN_EQUIPMENT_AIR_DATA_RAWAIRDATA_ID 1027
#define UAVCAN_EQUIPMENT_AIR_DATA_RAWAIRDATA_SIGNATURE (0xC77DF38BA122F5DAULL)
#define UAVCAN_EQUIPMENT_AIR_DATA_RAWAIRDATA_MAX_SIZE ((397 + 7)/8)
/* Local variables */ /* Local variables */
struct airspeed_uavcan_t airspeed_uavcan = {0}; struct airspeed_uavcan_t airspeed_uavcan = {0};
static uavcan_event airspeed_uavcan_ev; static uavcan_event airspeed_uavcan_ev;
@@ -85,21 +81,16 @@ static void airspeed_uavcan_downlink(struct transport_tx *trans, struct link_dev
#endif /* PERIODIC_TELEMETRY */ #endif /* PERIODIC_TELEMETRY */
static void airspeed_uavcan_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) { static void airspeed_uavcan_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) {
uint16_t tmp_float = 0;
float diff_p; struct uavcan_equipment_air_data_RawAirData msg;
if(uavcan_equipment_air_data_RawAirData_decode(transfer, &msg)) {
return; // decode error
}
float diff_p = msg.differential_pressure;
float static_air_temp = msg.static_air_temperature;
/* Decode the message */
//canardDecodeScalar(transfer, (uint32_t)0, 8, false, (void*)&dest->flags);
//canardDecodeScalar(transfer, (uint32_t)8, 32, false, (void*)&static_p);
canardDecodeScalar(transfer, (uint32_t)40, 32, false, (void*)&diff_p);
//canardDecodeScalar(transfer, (uint32_t)72, 16, false, (void*)&tmp_float);
//float static_temp = canardConvertFloat16ToNativeFloat(tmp_float);
//canardDecodeScalar(transfer, (uint32_t)88, 16, false, (void*)&tmp_float);
//float diff_temp = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)104, 16, false, (void*)&tmp_float);
float static_air_temp = canardConvertFloat16ToNativeFloat(tmp_float);
//canardDecodeScalar(transfer, (uint32_t)120, 16, false, (void*)&tmp_float);
//float pitot_temp = canardConvertFloat16ToNativeFloat(tmp_float);
if(!isnan(diff_p)) { if(!isnan(diff_p)) {
// Remove the offset and apply a scaling factor // Remove the offset and apply a scaling factor
+32 -101
View File
@@ -27,16 +27,9 @@
#include "uavcan/uavcan.h" #include "uavcan/uavcan.h"
#include "modules/energy/electrical.h" #include "modules/energy/electrical.h"
#include "math/pprz_random.h" #include "math/pprz_random.h"
#include "uavcan.equipment.power.BatteryInfo.h"
#include "uavcan.equipment.power.CircuitStatus.h"
/* uavcan EQUIPMENT_ESC_STATUS message definition */
#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_ID 1092
#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_SIGNATURE (0x249C26548A711966ULL)
#define UAVCAN_EQUIPMENT_POWER_BATTERYINFO_MAX_SIZE 55
/* uavcan EQUIPMENT_POWER_CIRCUITSTATUS message definition */
#define UAVCAN_EQUIPMENT_POWER_CIRCUITSTATUS_ID 1091
#define UAVCAN_EQUIPMENT_POWER_CIRCUITSTATUS_SIGNATURE (0x8313D33D0DDDA115ULL)
#define UAVCAN_EQUIPMENT_POWER_CIRCUITSTATUS_MAX_SIZE 7
/* Default maximum amount of batteries */ /* Default maximum amount of batteries */
#ifndef POWER_UAVCAN_BATTERIES_MAX #ifndef POWER_UAVCAN_BATTERIES_MAX
@@ -57,40 +50,24 @@
static uavcan_event power_uavcan_ev; static uavcan_event power_uavcan_ev;
static uavcan_event circuit_uavcan_ev; static uavcan_event circuit_uavcan_ev;
/* Batteries */ struct battery_info
struct uavcan_equipment_power_BatteryInfo { {
bool set; bool set;
uint8_t node_id; uint8_t node_id;
struct uavcan_equipment_power_BatteryInfo info;
float temperature;
float voltage;
float current;
float average_power_10sec;
float remaining_capacity_wh;
float full_charge_capacity_wh;
float hours_to_full_charge;
uint16_t status_flags;
uint8_t state_of_health_pct;
uint8_t state_of_charge_pct;
uint8_t state_of_charge_pct_stdev;
uint8_t battery_id;
uint32_t model_instance_id;
// struct { uint8_t len; uint8_t data[31]; }model_name;
}; };
static struct uavcan_equipment_power_BatteryInfo batteries[POWER_UAVCAN_BATTERIES_MAX] = {0};
/* Circuits */ /* Circuits */
struct uavcan_equipment_power_CircuitStatus { struct circuit_status {
bool set; bool set;
uint8_t node_id; uint8_t node_id;
bool is_battery; bool is_battery;
struct uavcan_equipment_power_CircuitStatus status;
uint16_t circuit_id;
float voltage;
float current;
uint8_t error_flags;
}; };
static struct uavcan_equipment_power_CircuitStatus circuits[POWER_UAVCAN_CIRCUITS_MAX] = {0};
static struct battery_info batteries[POWER_UAVCAN_BATTERIES_MAX] = {0};
static struct circuit_status circuits[POWER_UAVCAN_CIRCUITS_MAX] = {0};
/* Battery circuits */ /* Battery circuits */
struct uavcan_circuit_battery_t { struct uavcan_circuit_battery_t {
@@ -107,8 +84,8 @@ static void power_uavcan_send_power_device(struct transport_tx *trans, struct li
static uint8_t idx = 0; static uint8_t idx = 0;
// Send the circuit status // Send the circuit status
if(circuits[idx].set) { if(circuits[idx].set) {
uint8_t cid = circuits[idx].circuit_id; uint8_t cid = circuits[idx].status.circuit_id;
pprz_msg_send_POWER_DEVICE(trans, dev, AC_ID, &circuits[idx].node_id, &cid, &circuits[idx].current, &circuits[idx].voltage); pprz_msg_send_POWER_DEVICE(trans, dev, AC_ID, &circuits[idx].node_id, &cid, &circuits[idx].status.current, &circuits[idx].status.voltage);
} }
// Go to the next // Go to the next
@@ -124,41 +101,16 @@ static void power_uavcan_send_power_device(struct transport_tx *trans, struct li
static void power_uavcan_battery_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) static void power_uavcan_battery_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer)
{ {
uint16_t tmp_float = 0; struct uavcan_equipment_power_BatteryInfo msg;
if(uavcan_equipment_power_BatteryInfo_decode(transfer, &msg)) {
/* Decode the message */ return; // decode error
canardDecodeScalar(transfer, (uint32_t)0, 16, true, (void *)&tmp_float); }
float temperature = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)16, 16, true, (void *)&tmp_float);
float voltage = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)32, 16, true, (void *)&tmp_float);
float current = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)48, 16, true, (void *)&tmp_float);
float average_power_10sec = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)64, 16, true, (void *)&tmp_float);
float remaining_capacity_wh = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)80, 16, true, (void *)&tmp_float);
float full_charge_capacity_wh = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)96, 16, true, (void *)&tmp_float);
float hours_to_full_charge = canardConvertFloat16ToNativeFloat(tmp_float);
uint16_t status_flags = 0;
canardDecodeScalar(transfer, (uint32_t)112, 11, false, (void *)&status_flags);
uint8_t state_of_health_pct = 0;
canardDecodeScalar(transfer, (uint32_t)123, 7, false, (void *)&state_of_health_pct);
uint8_t state_of_charge_pct = 0;
canardDecodeScalar(transfer, (uint32_t)130, 7, false, (void *)&state_of_charge_pct);
uint8_t state_of_charge_pct_stdev = 0;
canardDecodeScalar(transfer, (uint32_t)137, 7, false, (void *)&state_of_charge_pct_stdev);
uint8_t battery_id = 0;
canardDecodeScalar(transfer, (uint32_t)144, 8, false, (void *)&battery_id);
uint32_t model_instance_id = 0;
canardDecodeScalar(transfer, (uint32_t)152, 32, false, (void *)&model_instance_id);
// Search for the battery or free spot // Search for the battery or free spot
uint8_t battery_idx = POWER_UAVCAN_BATTERIES_MAX; uint8_t battery_idx = POWER_UAVCAN_BATTERIES_MAX;
for (uint8_t i = 0; i < POWER_UAVCAN_BATTERIES_MAX; i++) { for (uint8_t i = 0; i < POWER_UAVCAN_BATTERIES_MAX; i++) {
if (batteries[i].set && batteries[i].node_id == transfer->source_node_id && if (batteries[i].set && batteries[i].node_id == transfer->source_node_id &&
batteries[i].battery_id == battery_id && batteries[i].model_instance_id == model_instance_id) { batteries[i].info.battery_id == msg.battery_id && batteries[i].info.model_instance_id == msg.model_instance_id) {
battery_idx = i; battery_idx = i;
break; break;
} }
@@ -176,51 +128,33 @@ static void power_uavcan_battery_cb(struct uavcan_iface_t *iface __attribute__((
// Set the battery info // Set the battery info
batteries[battery_idx].set = true; batteries[battery_idx].set = true;
batteries[battery_idx].node_id = transfer->source_node_id; batteries[battery_idx].node_id = transfer->source_node_id;
batteries[battery_idx].temperature = temperature; batteries[battery_idx].info = msg;
batteries[battery_idx].voltage = voltage;
batteries[battery_idx].current = current;
batteries[battery_idx].average_power_10sec = average_power_10sec;
batteries[battery_idx].remaining_capacity_wh = remaining_capacity_wh;
batteries[battery_idx].full_charge_capacity_wh = full_charge_capacity_wh;
batteries[battery_idx].hours_to_full_charge = hours_to_full_charge;
batteries[battery_idx].status_flags = status_flags;
batteries[battery_idx].state_of_health_pct = state_of_health_pct;
batteries[battery_idx].state_of_charge_pct = state_of_charge_pct;
batteries[battery_idx].state_of_charge_pct_stdev = state_of_charge_pct_stdev;
batteries[battery_idx].battery_id = battery_id;
batteries[battery_idx].model_instance_id = model_instance_id;
// Sum the battery currents // Sum the battery currents
float current_sum = 0; float current_sum = 0;
for (uint8_t i = 0; i < POWER_UAVCAN_BATTERIES_MAX; i++) { for (uint8_t i = 0; i < POWER_UAVCAN_BATTERIES_MAX; i++) {
if (batteries[i].set) { if (batteries[i].set) {
current_sum += batteries[i].current; current_sum += batteries[i].info.current;
} }
} }
electrical.current = current_sum; electrical.current = current_sum;
if (voltage > 0) { if (msg.voltage > 0) {
electrical.vsupply = voltage; electrical.vsupply = msg.voltage;
} }
} }
static void power_uavcan_circuit_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) static void power_uavcan_circuit_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer)
{ {
uint16_t tmp_float = 0;
/* Decode the message */ struct uavcan_equipment_power_CircuitStatus msg;
uint16_t circuit_id = 0; if(uavcan_equipment_power_CircuitStatus_decode(transfer, &msg)) {
canardDecodeScalar(transfer, (uint32_t)0, 16, false, (void *)&circuit_id); return; // decode error
canardDecodeScalar(transfer, (uint32_t)16, 16, true, (void *)&tmp_float); }
float voltage = canardConvertFloat16ToNativeFloat(tmp_float);
canardDecodeScalar(transfer, (uint32_t)32, 16, true, (void *)&tmp_float);
float current = canardConvertFloat16ToNativeFloat(tmp_float);
uint8_t error_flags = 0;
canardDecodeScalar(transfer, (uint32_t)48, 8, false, (void *)&error_flags);
// Search for the circuit or free spot // Search for the circuit or free spot
uint8_t circuit_idx = POWER_UAVCAN_CIRCUITS_MAX; uint8_t circuit_idx = POWER_UAVCAN_CIRCUITS_MAX;
for (uint8_t i = 0; i < POWER_UAVCAN_CIRCUITS_MAX; i++) { for (uint8_t i = 0; i < POWER_UAVCAN_CIRCUITS_MAX; i++) {
if (circuits[i].set && circuits[i].node_id == transfer->source_node_id && circuits[i].circuit_id == circuit_id) { if (circuits[i].set && circuits[i].node_id == transfer->source_node_id && circuits[i].status.circuit_id == msg.circuit_id) {
circuit_idx = i; circuit_idx = i;
break; break;
} }
@@ -238,21 +172,18 @@ static void power_uavcan_circuit_cb(struct uavcan_iface_t *iface __attribute__((
// Set the circuit info // Set the circuit info
circuits[circuit_idx].set = true; circuits[circuit_idx].set = true;
circuits[circuit_idx].node_id = transfer->source_node_id; circuits[circuit_idx].node_id = transfer->source_node_id;
circuits[circuit_idx].circuit_id = circuit_id; circuits[circuit_idx].status = msg;
circuits[circuit_idx].voltage = voltage;
circuits[circuit_idx].current = current;
circuits[circuit_idx].error_flags = error_flags;
// Sum the 'battery' circuit currents // Sum the 'battery' circuit currents
float current_sum = 0; float current_sum = 0;
for (uint8_t i = 0; i < POWER_UAVCAN_CIRCUITS_MAX; i++) { for (uint8_t i = 0; i < POWER_UAVCAN_CIRCUITS_MAX; i++) {
if (circuits[i].set && circuits[i].is_battery) { if (circuits[i].set && circuits[i].is_battery) {
current_sum += circuits[i].current; current_sum += circuits[i].status.current;
} }
} }
electrical.current = current_sum; electrical.current = current_sum;
if (voltage > 0 && circuits[circuit_idx].is_battery) { if (msg.voltage > 0 && circuits[circuit_idx].is_battery) {
electrical.vsupply = voltage; electrical.vsupply = msg.voltage;
} }
} }
@@ -262,7 +193,7 @@ void power_uavcan_init(void)
for (uint8_t i = 0; i < sizeof(battery_circuits) / sizeof(struct uavcan_circuit_battery_t); i++) { for (uint8_t i = 0; i < sizeof(battery_circuits) / sizeof(struct uavcan_circuit_battery_t); i++) {
circuits[i].set = true; circuits[i].set = true;
circuits[i].node_id = battery_circuits[i].node_id; circuits[i].node_id = battery_circuits[i].node_id;
circuits[i].circuit_id = battery_circuits[i].circuit_id; circuits[i].status.circuit_id = battery_circuits[i].circuit_id;
circuits[i].is_battery = true; circuits[i].is_battery = true;
} }
@@ -26,21 +26,11 @@
#include "range_sensor_uavcan.h" #include "range_sensor_uavcan.h"
#include "uavcan/uavcan.h" #include "uavcan/uavcan.h"
#include "core/abi.h" #include "core/abi.h"
#include "uavcan.equipment.range_sensor.Measurement.h"
/* uavcan EQUIPMENT_RANGE_SENSOR_MEASUREMENT message definition */
#define UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_ID 1050
#define UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_SIGNATURE (0x68FFFE70FC771952ULL)
#define UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_MAX_SIZE ((120 + 7)/8)
/* Local structure */
struct range_sensor_uavcan_t {
float range;
uint8_t reading_type;
};
/* Local variables */ /* Local variables */
static struct range_sensor_uavcan_t range_sensor_uavcan = {0}; static struct uavcan_equipment_range_sensor_Measurement range_sensor_uavcan = {0};
static uavcan_event range_sensor_uavcan_ev; static uavcan_event range_sensor_uavcan_ev;
#if PERIODIC_TELEMETRY #if PERIODIC_TELEMETRY
@@ -58,21 +48,9 @@ static void range_sensor_uavcan_send_lidar(struct transport_tx *trans, struct li
#endif #endif
static void range_sensor_uavcan_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) { static void range_sensor_uavcan_cb(struct uavcan_iface_t *iface __attribute__((unused)), CanardRxTransfer *transfer) {
uint16_t tmp_float = 0; if(uavcan_equipment_range_sensor_Measurement_decode(transfer, &range_sensor_uavcan)) {
return; // decode error
/* Decode the message */ }
//canardDecodeScalar(transfer, (uint32_t)0, 56, false, (void*)&dest->usec);
//canardDecodeScalar(transfer, (uint32_t)56, 8, false, (void*)&dest->sensor_id);
//canardDecodeScalar(transfer, (uint32_t)64, 5, true, (void*)(dest->fixed_axis_roll_pitch_yaw + 0));
//canardDecodeScalar(transfer, (uint32_t)69, 5, true, (void*)(dest->fixed_axis_roll_pitch_yaw + 1));
//canardDecodeScalar(transfer, (uint32_t)74, 5, true, (void*)(dest->fixed_axis_roll_pitch_yaw + 2));
//canardDecodeScalar(transfer, (uint32_t)79, 1, false, (void*)&dest->orientation_defined);
//canardDecodeScalar(transfer, (uint32_t)80, 16, false, (void*)&tmp_float);
//float fov = canardConvertFloat16ToNativeFloat(tmp_float);
//canardDecodeScalar(transfer, (uint32_t)96, 5, false, (void*)&dest->sensor_type);
canardDecodeScalar(transfer, (uint32_t)101, 3, false, (void*)&range_sensor_uavcan.reading_type);
canardDecodeScalar(transfer, (uint32_t)104, 16, false, (void*)&tmp_float);
range_sensor_uavcan.range = canardConvertFloat16ToNativeFloat(tmp_float);
// Send the range over ABI // Send the range over ABI
if(!isnan(range_sensor_uavcan.range)) { if(!isnan(range_sensor_uavcan.range)) {
+8 -2
View File
@@ -35,7 +35,7 @@ include $(PAPARAZZI_SRC)/conf/Makefile.arm-embedded-toolchain
MY_PYTHON := $(shell echo `which python3`) MY_PYTHON := $(shell echo `which python3`)
MY_MAVLINKTOOLS := $(shell $(MY_PYTHON) -c 'import imp; import future' 2>&1) MY_MAVLINKTOOLS := $(shell $(MY_PYTHON) -c 'import imp; import future' 2>&1)
all: libopencm3 luftboot chibios fatfs libsbp TRICAL hacl-c key_generator rustlink ecl matrix mavlink all: libopencm3 luftboot chibios fatfs libsbp TRICAL hacl-c key_generator rustlink ecl matrix mavlink dronecan
# update (and init if needed) all submodules # update (and init if needed) all submodules
update_submodules: update_submodules:
@@ -112,6 +112,9 @@ opencv_bebop: opencv_bebop.update opencv_bebop.build
opencv_bebop.build: opencv_bebop.build:
$(Q)$(MAKE) -C opencv_bebop $(Q)$(MAKE) -C opencv_bebop
dronecan:
$(Q)$(MAKE) -C dronecan
clean: clean:
$(Q)if [ -f libopencm3/Makefile ]; then \ $(Q)if [ -f libopencm3/Makefile ]; then \
$(MAKE) -C $(EXT_DIR)/libopencm3 clean; \ $(MAKE) -C $(EXT_DIR)/libopencm3 clean; \
@@ -126,4 +129,7 @@ clean_opencv_bebop:
fi fi
.NOTPARALLEL: libopencm3 luftboot .NOTPARALLEL: libopencm3 luftboot
.PHONY: all clean update_submodules libopencm3 luftboot chibios fatfs luftboot_flash libopencm3.build luftboot.build mavlink.build libsbp pprzlink pprzlink.build opencv_bebop opencv_bebop.build clean_opencv_bebop TRICAL .PHONY: all clean update_submodules libopencm3 luftboot \
chibios fatfs luftboot_flash libopencm3.build luftboot.build \
mavlink.build libsbp pprzlink pprzlink.build opencv_bebop \
opencv_bebop.build clean_opencv_bebop TRICAL dronecan
+67
View File
@@ -0,0 +1,67 @@
# Hey Emacs, this is a -*- makefile -*-
#
# Copyright (C) 2012 The Paparazzi Team
#
# 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, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# The default is to produce a quiet echo of compilation commands
# Launch with "make Q=''" to get full echo
Q=@
PAPARAZZI_SRC=../../..
DRONECAN_DIR=$(PAPARAZZI_SRC)/sw/ext/dronecan
DSDL_DIR := $(DRONECAN_DIR)/DSDL
all: libcanard DSDL dronecan_dsdlc pydronecan
libcanard: libcanard.sync libcanard.update
DSDL : DSDL.sync DSDL.update
dronecan_dsdlc : dronecan_dsdlc.sync dronecan_dsdlc.update dronecan_dsdlc.build
pydronecan : pydronecan.sync pydronecan.update
dronecan_dsdlc.build:
$(eval DSDL_ROOTS_PART := $(sort $(dir $(wildcard $(DSDL_DIR)/*/))))
$(eval DSDL_ROOTS := $(filter-out $(DRONECAN_DIR)/DSDL/tests/ $(DRONECAN_DIR)/DSDL/,$(DSDL_ROOTS_PART)))
@echo Generating dsdl code from $(DSDL_ROOTS) to $(PAPARAZZI_SRC)/var/include/DSDLcode
$(Q) python $(DRONECAN_DIR)/dronecan_dsdlc/dronecan_dsdlc.py -O $(PAPARAZZI_SRC)/var/include/DSDLcode $(DSDL_ROOTS)
@echo Done
# update (and init if needed) a specific submodule
%.update:
$(Q)if [ -d $(PAPARAZZI_SRC)/.git ]; then \
cd $(PAPARAZZI_SRC) && git submodule update --init --recursive sw/ext/dronecan/$*; \
fi
# sync a specific submodule
%.sync:
$(Q)if [ -d $(PAPARAZZI_SRC)/.git ]; then \
cd $(PAPARAZZI_SRC) && git submodule sync --recursive sw/ext/dronecan/$*; \
fi
clean:
$(Q)rm -r $(PAPARAZZI_SRC)/var/include/DSDLcode
.PHONY: all clean pydronecan dronecan dronecan_dsdlc.build DSDL libcanard