mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-05 11:30:34 +08:00
Merge branch 'master' into offboard2
This commit is contained in:
@@ -47,8 +47,8 @@
|
||||
#include <mathlib/mathlib.h>
|
||||
#include <controllib/blocks.hpp>
|
||||
#include <controllib/block/BlockParam.hpp>
|
||||
#include <controllib/uorb/UOrbSubscription.hpp>
|
||||
#include <controllib/uorb/UOrbPublication.hpp>
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/Publication.hpp>
|
||||
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
@@ -138,13 +138,13 @@ protected:
|
||||
math::Matrix<3,3> C_nb; /**< direction cosine matrix from body to nav frame */
|
||||
math::Quaternion q; /**< quaternion from body to nav frame */
|
||||
// subscriptions
|
||||
control::UOrbSubscription<sensor_combined_s> _sensors; /**< sensors sub. */
|
||||
control::UOrbSubscription<vehicle_gps_position_s> _gps; /**< gps sub. */
|
||||
control::UOrbSubscription<parameter_update_s> _param_update; /**< parameter update sub. */
|
||||
uORB::Subscription<sensor_combined_s> _sensors; /**< sensors sub. */
|
||||
uORB::Subscription<vehicle_gps_position_s> _gps; /**< gps sub. */
|
||||
uORB::Subscription<parameter_update_s> _param_update; /**< parameter update sub. */
|
||||
// publications
|
||||
control::UOrbPublication<vehicle_global_position_s> _pos; /**< position pub. */
|
||||
control::UOrbPublication<vehicle_local_position_s> _localPos; /**< local position pub. */
|
||||
control::UOrbPublication<vehicle_attitude_s> _att; /**< attitude pub. */
|
||||
uORB::Publication<vehicle_global_position_s> _pos; /**< position pub. */
|
||||
uORB::Publication<vehicle_local_position_s> _localPos; /**< local position pub. */
|
||||
uORB::Publication<vehicle_attitude_s> _att; /**< attitude pub. */
|
||||
// time stamps
|
||||
uint64_t _pubTimeStamp; /**< output data publication time stamp */
|
||||
uint64_t _predictTimeStamp; /**< prediction time stamp */
|
||||
|
||||
@@ -277,7 +277,6 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
// XXX write this out to perf regs
|
||||
|
||||
/* keep track of sensor updates */
|
||||
uint32_t sensor_last_count[3] = {0, 0, 0};
|
||||
uint64_t sensor_last_timestamp[3] = {0, 0, 0};
|
||||
|
||||
struct attitude_estimator_ekf_params ekf_params;
|
||||
@@ -380,9 +379,8 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
uint8_t update_vect[3] = {0, 0, 0};
|
||||
|
||||
/* Fill in gyro measurements */
|
||||
if (sensor_last_count[0] != raw.gyro_counter) {
|
||||
if (sensor_last_timestamp[0] != raw.timestamp) {
|
||||
update_vect[0] = 1;
|
||||
sensor_last_count[0] = raw.gyro_counter;
|
||||
sensor_update_hz[0] = 1e6f / (raw.timestamp - sensor_last_timestamp[0]);
|
||||
sensor_last_timestamp[0] = raw.timestamp;
|
||||
}
|
||||
@@ -392,11 +390,10 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
z_k[2] = raw.gyro_rad_s[2] - gyro_offsets[2];
|
||||
|
||||
/* update accelerometer measurements */
|
||||
if (sensor_last_count[1] != raw.accelerometer_counter) {
|
||||
if (sensor_last_timestamp[1] != raw.accelerometer_timestamp) {
|
||||
update_vect[1] = 1;
|
||||
sensor_last_count[1] = raw.accelerometer_counter;
|
||||
sensor_update_hz[1] = 1e6f / (raw.timestamp - sensor_last_timestamp[1]);
|
||||
sensor_last_timestamp[1] = raw.timestamp;
|
||||
sensor_last_timestamp[1] = raw.accelerometer_timestamp;
|
||||
}
|
||||
|
||||
hrt_abstime vel_t = 0;
|
||||
@@ -445,11 +442,10 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
z_k[5] = raw.accelerometer_m_s2[2] - acc(2);
|
||||
|
||||
/* update magnetometer measurements */
|
||||
if (sensor_last_count[2] != raw.magnetometer_counter) {
|
||||
if (sensor_last_timestamp[2] != raw.magnetometer_timestamp) {
|
||||
update_vect[2] = 1;
|
||||
sensor_last_count[2] = raw.magnetometer_counter;
|
||||
sensor_update_hz[2] = 1e6f / (raw.timestamp - sensor_last_timestamp[2]);
|
||||
sensor_last_timestamp[2] = raw.timestamp;
|
||||
sensor_last_timestamp[2] = raw.magnetometer_timestamp;
|
||||
}
|
||||
|
||||
z_k[6] = raw.magnetometer_ga[0];
|
||||
@@ -477,6 +473,9 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
dt = 0.005f;
|
||||
parameters_update(&ekf_param_handles, &ekf_params);
|
||||
|
||||
/* update mag declination rotation matrix */
|
||||
R_decl.from_euler(0.0f, 0.0f, ekf_params.mag_decl);
|
||||
|
||||
x_aposteriori_k[0] = z_k[0];
|
||||
x_aposteriori_k[1] = z_k[1];
|
||||
x_aposteriori_k[2] = z_k[2];
|
||||
|
||||
@@ -445,7 +445,6 @@ int attitude_estimator_so3_thread_main(int argc, char *argv[])
|
||||
// XXX write this out to perf regs
|
||||
|
||||
/* keep track of sensor updates */
|
||||
uint32_t sensor_last_count[3] = {0, 0, 0};
|
||||
uint64_t sensor_last_timestamp[3] = {0, 0, 0};
|
||||
|
||||
struct attitude_estimator_so3_params so3_comp_params;
|
||||
@@ -526,9 +525,8 @@ int attitude_estimator_so3_thread_main(int argc, char *argv[])
|
||||
uint8_t update_vect[3] = {0, 0, 0};
|
||||
|
||||
/* Fill in gyro measurements */
|
||||
if (sensor_last_count[0] != raw.gyro_counter) {
|
||||
if (sensor_last_timestamp[0] != raw.timestamp) {
|
||||
update_vect[0] = 1;
|
||||
sensor_last_count[0] = raw.gyro_counter;
|
||||
sensor_update_hz[0] = 1e6f / (raw.timestamp - sensor_last_timestamp[0]);
|
||||
sensor_last_timestamp[0] = raw.timestamp;
|
||||
}
|
||||
@@ -538,11 +536,10 @@ int attitude_estimator_so3_thread_main(int argc, char *argv[])
|
||||
gyro[2] = raw.gyro_rad_s[2] - gyro_offsets[2];
|
||||
|
||||
/* update accelerometer measurements */
|
||||
if (sensor_last_count[1] != raw.accelerometer_counter) {
|
||||
if (sensor_last_timestamp[1] != raw.accelerometer_timestamp) {
|
||||
update_vect[1] = 1;
|
||||
sensor_last_count[1] = raw.accelerometer_counter;
|
||||
sensor_update_hz[1] = 1e6f / (raw.timestamp - sensor_last_timestamp[1]);
|
||||
sensor_last_timestamp[1] = raw.timestamp;
|
||||
sensor_last_timestamp[1] = raw.accelerometer_timestamp;
|
||||
}
|
||||
|
||||
acc[0] = raw.accelerometer_m_s2[0];
|
||||
@@ -550,11 +547,10 @@ int attitude_estimator_so3_thread_main(int argc, char *argv[])
|
||||
acc[2] = raw.accelerometer_m_s2[2];
|
||||
|
||||
/* update magnetometer measurements */
|
||||
if (sensor_last_count[2] != raw.magnetometer_counter) {
|
||||
if (sensor_last_timestamp[2] != raw.magnetometer_timestamp) {
|
||||
update_vect[2] = 1;
|
||||
sensor_last_count[2] = raw.magnetometer_counter;
|
||||
sensor_update_hz[2] = 1e6f / (raw.timestamp - sensor_last_timestamp[2]);
|
||||
sensor_last_timestamp[2] = raw.timestamp;
|
||||
sensor_last_timestamp[2] = raw.magnetometer_timestamp;
|
||||
}
|
||||
|
||||
mag[0] = raw.magnetometer_ga[0];
|
||||
|
||||
@@ -311,7 +311,7 @@ int do_accel_calibration_measurements(int mavlink_fd, float accel_offs[3], float
|
||||
(double)accel_ref[orient][2]);
|
||||
|
||||
data_collected[orient] = true;
|
||||
tune_neutral();
|
||||
tune_neutral(true);
|
||||
}
|
||||
|
||||
close(sensor_combined_sub);
|
||||
|
||||
@@ -142,7 +142,7 @@ int do_airspeed_calibration(int mavlink_fd)
|
||||
}
|
||||
|
||||
mavlink_log_info(mavlink_fd, CAL_DONE_MSG, sensor_name);
|
||||
tune_neutral();
|
||||
tune_neutral(true);
|
||||
close(diff_pres_sub);
|
||||
return OK;
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ extern struct system_load_s system_load;
|
||||
|
||||
#define POSITION_TIMEOUT 1000000 /**< consider the local or global position estimate invalid after 1s */
|
||||
#define RC_TIMEOUT 100000
|
||||
#define RC_TIMEOUT_HIL 500000
|
||||
#define OFFBOARD_TIMEOUT 200000
|
||||
#define DIFFPRESS_TIMEOUT 2000000
|
||||
|
||||
@@ -616,7 +617,6 @@ int commander_thread_main(int argc, char *argv[])
|
||||
/* not yet initialized */
|
||||
commander_initialized = false;
|
||||
|
||||
bool battery_tune_played = false;
|
||||
bool arm_tune_played = false;
|
||||
|
||||
/* set parameters */
|
||||
@@ -909,7 +909,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
orb_copy(ORB_ID(safety), safety_sub, &safety);
|
||||
|
||||
/* disarm if safety is now on and still armed */
|
||||
if (safety.safety_switch_available && !safety.safety_off && armed.armed) {
|
||||
if (status.hil_state == HIL_STATE_OFF && safety.safety_switch_available && !safety.safety_off && armed.armed) {
|
||||
arming_state_t new_arming_state = (status.arming_state == ARMING_STATE_ARMED ? ARMING_STATE_STANDBY : ARMING_STATE_STANDBY_ERROR);
|
||||
if (TRANSITION_CHANGED == arming_state_transition(&status, &safety, new_arming_state, &armed)) {
|
||||
mavlink_log_info(mavlink_fd, "[cmd] DISARMED by safety switch");
|
||||
@@ -969,7 +969,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
orb_copy(ORB_ID(battery_status), battery_sub, &battery);
|
||||
|
||||
/* only consider battery voltage if system has been running 2s and battery voltage is valid */
|
||||
if (hrt_absolute_time() > start_time + 2000000 && battery.voltage_filtered_v > 0.0f) {
|
||||
if (status.hil_state == HIL_STATE_OFF && hrt_absolute_time() > start_time + 2000000 && battery.voltage_filtered_v > 0.0f) {
|
||||
status.battery_voltage = battery.voltage_filtered_v;
|
||||
status.battery_current = battery.current_a;
|
||||
status.condition_battery_voltage_valid = true;
|
||||
@@ -1032,14 +1032,12 @@ int commander_thread_main(int argc, char *argv[])
|
||||
mavlink_log_critical(mavlink_fd, "#audio: WARNING: LOW BATTERY");
|
||||
status.battery_warning = VEHICLE_BATTERY_WARNING_LOW;
|
||||
status_changed = true;
|
||||
battery_tune_played = false;
|
||||
|
||||
} else if (status.condition_battery_voltage_valid && status.battery_remaining < 0.1f && !critical_battery_voltage_actions_done && low_battery_voltage_actions_done) {
|
||||
/* critical battery voltage, this is rather an emergency, change state machine */
|
||||
critical_battery_voltage_actions_done = true;
|
||||
mavlink_log_critical(mavlink_fd, "#audio: EMERGENCY: CRITICAL BATTERY");
|
||||
status.battery_warning = VEHICLE_BATTERY_WARNING_CRITICAL;
|
||||
battery_tune_played = false;
|
||||
|
||||
if (armed.armed) {
|
||||
arming_state_transition(&status, &safety, ARMING_STATE_ARMED_ERROR, &armed);
|
||||
@@ -1113,12 +1111,20 @@ int commander_thread_main(int argc, char *argv[])
|
||||
|
||||
/* mark home position as set */
|
||||
status.condition_home_position_valid = true;
|
||||
tune_positive();
|
||||
tune_positive(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX workaround:
|
||||
* Prevent RC loss in HIL when sensors.cpp is only publishing sp_man at a low rate (e.g. 30Hz)
|
||||
* which can trigger RC loss if the computer/simulator lags.
|
||||
*/
|
||||
uint64_t rc_timeout = status.hil_state == HIL_STATE_ON ? RC_TIMEOUT_HIL : RC_TIMEOUT;
|
||||
|
||||
/* start RC input check */
|
||||
if (!status.rc_input_blocked && sp_man.timestamp != 0 && hrt_absolute_time() < sp_man.timestamp + RC_TIMEOUT) {
|
||||
if (!status.rc_input_blocked && sp_man.timestamp != 0 && hrt_absolute_time() < sp_man.timestamp + rc_timeout) {
|
||||
/* handle the case where RC signal was regained */
|
||||
if (!status.rc_signal_found_once) {
|
||||
status.rc_signal_found_once = true;
|
||||
@@ -1208,8 +1214,9 @@ int commander_thread_main(int argc, char *argv[])
|
||||
/* evaluate the main state machine according to mode switches */
|
||||
res = set_main_state_rc(&status);
|
||||
|
||||
/* play tune on mode change only if armed, blink LED always */
|
||||
if (res == TRANSITION_CHANGED) {
|
||||
tune_positive();
|
||||
tune_positive(armed.armed);
|
||||
|
||||
} else if (res == TRANSITION_DENIED) {
|
||||
/* DENIED here indicates bug in the commander */
|
||||
@@ -1309,7 +1316,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
/* flight termination in manual mode if assisted switch is on easy position */
|
||||
if (!status.is_rotary_wing && parachute_enabled && armed.armed && status.main_state == MAIN_STATE_MANUAL && sp_man.assisted_switch > STICK_ON_OFF_LIMIT) {
|
||||
if (TRANSITION_CHANGED == failsafe_state_transition(&status, FAILSAFE_STATE_TERMINATION)) {
|
||||
tune_positive();
|
||||
tune_positive(armed.armed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,26 +1371,23 @@ int commander_thread_main(int argc, char *argv[])
|
||||
/* play arming and battery warning tunes */
|
||||
if (!arm_tune_played && armed.armed && (!safety.safety_switch_available || (safety.safety_switch_available && safety.safety_off))) {
|
||||
/* play tune when armed */
|
||||
if (tune_arm() == OK)
|
||||
arm_tune_played = true;
|
||||
|
||||
} else if (status.battery_warning == VEHICLE_BATTERY_WARNING_LOW) {
|
||||
/* play tune on battery warning */
|
||||
if (tune_low_bat() == OK)
|
||||
battery_tune_played = true;
|
||||
set_tune(TONE_ARMING_WARNING_TUNE);
|
||||
arm_tune_played = true;
|
||||
|
||||
} else if (status.battery_warning == VEHICLE_BATTERY_WARNING_CRITICAL) {
|
||||
/* play tune on battery critical */
|
||||
if (tune_critical_bat() == OK)
|
||||
battery_tune_played = true;
|
||||
set_tune(TONE_BATTERY_WARNING_FAST_TUNE);
|
||||
|
||||
} else if (battery_tune_played) {
|
||||
tune_stop();
|
||||
battery_tune_played = false;
|
||||
} else if (status.battery_warning == VEHICLE_BATTERY_WARNING_LOW || status.failsafe_state != FAILSAFE_STATE_NORMAL) {
|
||||
/* play tune on battery warning or failsafe */
|
||||
set_tune(TONE_BATTERY_WARNING_SLOW_TUNE);
|
||||
|
||||
} else {
|
||||
set_tune(TONE_STOP_TUNE);
|
||||
}
|
||||
|
||||
/* reset arm_tune_played when disarmed */
|
||||
if (status.arming_state != ARMING_STATE_ARMED || (safety.safety_switch_available && !safety.safety_off)) {
|
||||
if (!armed.armed || (safety.safety_switch_available && !safety.safety_off)) {
|
||||
arm_tune_played = false;
|
||||
}
|
||||
|
||||
@@ -1478,11 +1482,8 @@ control_status_leds(vehicle_status_s *status, const actuator_armed_s *actuator_a
|
||||
|
||||
if (set_normal_color) {
|
||||
/* set color */
|
||||
if (status->battery_warning != VEHICLE_BATTERY_WARNING_NONE) {
|
||||
if (status->battery_warning == VEHICLE_BATTERY_WARNING_LOW) {
|
||||
rgbled_set_color(RGBLED_COLOR_AMBER);
|
||||
}
|
||||
|
||||
if (status->battery_warning == VEHICLE_BATTERY_WARNING_LOW || status->failsafe_state != FAILSAFE_STATE_NORMAL) {
|
||||
rgbled_set_color(RGBLED_COLOR_AMBER);
|
||||
/* VEHICLE_BATTERY_WARNING_CRITICAL handled as ARMING_STATE_ARMED_ERROR / ARMING_STATE_STANDBY_ERROR */
|
||||
|
||||
} else {
|
||||
@@ -1802,15 +1803,9 @@ print_reject_mode(struct vehicle_status_s *status, const char *msg)
|
||||
sprintf(s, "#audio: REJECT %s", msg);
|
||||
mavlink_log_critical(mavlink_fd, s);
|
||||
|
||||
// only buzz if armed, because else we're driving people nuts indoors
|
||||
// they really need to look at the leds as well.
|
||||
if (status->arming_state == ARMING_STATE_ARMED) {
|
||||
tune_negative();
|
||||
} else {
|
||||
|
||||
// Always show the led indication
|
||||
led_negative();
|
||||
}
|
||||
/* only buzz if armed, because else we're driving people nuts indoors
|
||||
they really need to look at the leds as well. */
|
||||
tune_negative(armed.armed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1824,7 +1819,7 @@ print_reject_arm(const char *msg)
|
||||
char s[80];
|
||||
sprintf(s, "#audio: %s", msg);
|
||||
mavlink_log_critical(mavlink_fd, s);
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1832,27 +1827,27 @@ void answer_command(struct vehicle_command_s &cmd, enum VEHICLE_CMD_RESULT resul
|
||||
{
|
||||
switch (result) {
|
||||
case VEHICLE_CMD_RESULT_ACCEPTED:
|
||||
tune_positive();
|
||||
tune_positive(true);
|
||||
break;
|
||||
|
||||
case VEHICLE_CMD_RESULT_DENIED:
|
||||
mavlink_log_critical(mavlink_fd, "#audio: command denied: %u", cmd.command);
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
break;
|
||||
|
||||
case VEHICLE_CMD_RESULT_FAILED:
|
||||
mavlink_log_critical(mavlink_fd, "#audio: command failed: %u", cmd.command);
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
break;
|
||||
|
||||
case VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED:
|
||||
mavlink_log_critical(mavlink_fd, "#audio: command temporarily rejected: %u", cmd.command);
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
break;
|
||||
|
||||
case VEHICLE_CMD_RESULT_UNSUPPORTED:
|
||||
mavlink_log_critical(mavlink_fd, "#audio: command unsupported: %u", cmd.command);
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1992,9 +1987,9 @@ void *commander_low_prio_loop(void *arg)
|
||||
}
|
||||
|
||||
if (calib_ret == OK)
|
||||
tune_positive();
|
||||
tune_positive(true);
|
||||
else
|
||||
tune_negative();
|
||||
tune_negative(true);
|
||||
|
||||
arming_state_transition(&status, &safety, ARMING_STATE_STANDBY, &armed);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
@@ -81,11 +82,22 @@ bool is_rotary_wing(const struct vehicle_status_s *current_status)
|
||||
|| (current_status->system_type == VEHICLE_TYPE_COAXIAL);
|
||||
}
|
||||
|
||||
static int buzzer;
|
||||
static hrt_abstime blink_msg_end;
|
||||
static int buzzer = -1;
|
||||
static hrt_abstime blink_msg_end = 0; // end time for currently blinking LED message, 0 if no blink message
|
||||
static hrt_abstime tune_end = 0; // end time of currently played tune, 0 for repeating tunes or silence
|
||||
static int tune_current = TONE_STOP_TUNE; // currently playing tune, can be interrupted after tune_end
|
||||
static unsigned int tune_durations[TONE_NUMBER_OF_TUNES];
|
||||
|
||||
int buzzer_init()
|
||||
{
|
||||
tune_end = 0;
|
||||
tune_current = 0;
|
||||
memset(tune_durations, 0, sizeof(tune_durations));
|
||||
tune_durations[TONE_NOTIFY_POSITIVE_TUNE] = 800000;
|
||||
tune_durations[TONE_NOTIFY_NEGATIVE_TUNE] = 900000;
|
||||
tune_durations[TONE_NOTIFY_NEUTRAL_TUNE] = 500000;
|
||||
tune_durations[TONE_ARMING_WARNING_TUNE] = 3000000;
|
||||
|
||||
buzzer = open(TONEALARM_DEVICE_PATH, O_WRONLY);
|
||||
|
||||
if (buzzer < 0) {
|
||||
@@ -101,58 +113,60 @@ void buzzer_deinit()
|
||||
close(buzzer);
|
||||
}
|
||||
|
||||
void tune_error()
|
||||
{
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_ERROR_TUNE);
|
||||
void set_tune(int tune) {
|
||||
unsigned int new_tune_duration = tune_durations[tune];
|
||||
/* don't interrupt currently playing non-repeating tune by repeating */
|
||||
if (tune_end == 0 || new_tune_duration != 0 || hrt_absolute_time() > tune_end) {
|
||||
/* allow interrupting current non-repeating tune by the same tune */
|
||||
if (tune != tune_current || new_tune_duration != 0) {
|
||||
ioctl(buzzer, TONE_SET_ALARM, tune);
|
||||
}
|
||||
tune_current = tune;
|
||||
if (new_tune_duration != 0) {
|
||||
tune_end = hrt_absolute_time() + new_tune_duration;
|
||||
} else {
|
||||
tune_end = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tune_positive()
|
||||
/**
|
||||
* Blink green LED and play positive tune (if use_buzzer == true).
|
||||
*/
|
||||
void tune_positive(bool use_buzzer)
|
||||
{
|
||||
blink_msg_end = hrt_absolute_time() + BLINK_MSG_TIME;
|
||||
rgbled_set_color(RGBLED_COLOR_GREEN);
|
||||
rgbled_set_mode(RGBLED_MODE_BLINK_FAST);
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_NOTIFY_POSITIVE_TUNE);
|
||||
if (use_buzzer) {
|
||||
set_tune(TONE_NOTIFY_POSITIVE_TUNE);
|
||||
}
|
||||
}
|
||||
|
||||
void tune_neutral()
|
||||
/**
|
||||
* Blink white LED and play neutral tune (if use_buzzer == true).
|
||||
*/
|
||||
void tune_neutral(bool use_buzzer)
|
||||
{
|
||||
blink_msg_end = hrt_absolute_time() + BLINK_MSG_TIME;
|
||||
rgbled_set_color(RGBLED_COLOR_WHITE);
|
||||
rgbled_set_mode(RGBLED_MODE_BLINK_FAST);
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_NOTIFY_NEUTRAL_TUNE);
|
||||
if (use_buzzer) {
|
||||
set_tune(TONE_NOTIFY_NEUTRAL_TUNE);
|
||||
}
|
||||
}
|
||||
|
||||
void tune_negative()
|
||||
{
|
||||
led_negative();
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_NOTIFY_NEGATIVE_TUNE);
|
||||
}
|
||||
|
||||
void led_negative()
|
||||
/**
|
||||
* Blink red LED and play negative tune (if use_buzzer == true).
|
||||
*/
|
||||
void tune_negative(bool use_buzzer)
|
||||
{
|
||||
blink_msg_end = hrt_absolute_time() + BLINK_MSG_TIME;
|
||||
rgbled_set_color(RGBLED_COLOR_RED);
|
||||
rgbled_set_mode(RGBLED_MODE_BLINK_FAST);
|
||||
}
|
||||
|
||||
int tune_arm()
|
||||
{
|
||||
return ioctl(buzzer, TONE_SET_ALARM, TONE_ARMING_WARNING_TUNE);
|
||||
}
|
||||
|
||||
int tune_low_bat()
|
||||
{
|
||||
return ioctl(buzzer, TONE_SET_ALARM, TONE_BATTERY_WARNING_SLOW_TUNE);
|
||||
}
|
||||
|
||||
int tune_critical_bat()
|
||||
{
|
||||
return ioctl(buzzer, TONE_SET_ALARM, TONE_BATTERY_WARNING_FAST_TUNE);
|
||||
}
|
||||
|
||||
void tune_stop()
|
||||
{
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_STOP_TUNE);
|
||||
if (use_buzzer) {
|
||||
set_tune(TONE_NOTIFY_NEGATIVE_TUNE);
|
||||
}
|
||||
}
|
||||
|
||||
int blink_msg_state()
|
||||
@@ -161,6 +175,7 @@ int blink_msg_state()
|
||||
return 0;
|
||||
|
||||
} else if (hrt_absolute_time() > blink_msg_end) {
|
||||
blink_msg_end = 0;
|
||||
return 2;
|
||||
|
||||
} else {
|
||||
@@ -168,8 +183,8 @@ int blink_msg_state()
|
||||
}
|
||||
}
|
||||
|
||||
static int leds;
|
||||
static int rgbleds;
|
||||
static int leds = -1;
|
||||
static int rgbleds = -1;
|
||||
|
||||
int led_init()
|
||||
{
|
||||
|
||||
@@ -54,16 +54,10 @@ bool is_rotary_wing(const struct vehicle_status_s *current_status);
|
||||
int buzzer_init(void);
|
||||
void buzzer_deinit(void);
|
||||
|
||||
void tune_error(void);
|
||||
void tune_positive(void);
|
||||
void tune_neutral(void);
|
||||
void tune_negative(void);
|
||||
int tune_arm(void);
|
||||
int tune_low_bat(void);
|
||||
int tune_critical_bat(void);
|
||||
void tune_stop(void);
|
||||
|
||||
void led_negative();
|
||||
void set_tune(int tune);
|
||||
void tune_positive(bool use_buzzer);
|
||||
void tune_neutral(bool use_buzzer);
|
||||
void tune_negative(bool use_buzzer);
|
||||
|
||||
int blink_msg_state();
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef PX4_CUSTOM_MODE_H_
|
||||
#define PX4_CUSTOM_MODE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum PX4_CUSTOM_MAIN_MODE {
|
||||
PX4_CUSTOM_MAIN_MODE_MANUAL = 1,
|
||||
PX4_CUSTOM_MAIN_MODE_SEATBELT,
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
@@ -321,10 +322,7 @@ int hil_state_transition(hil_state_t new_state, int status_pub, struct vehicle_s
|
||||
bool valid_transition = false;
|
||||
int ret = ERROR;
|
||||
|
||||
warnx("Current state: %d, requested state: %d", current_status->hil_state, new_state);
|
||||
|
||||
if (current_status->hil_state == new_state) {
|
||||
warnx("Hil state not changed");
|
||||
valid_transition = true;
|
||||
|
||||
} else {
|
||||
@@ -352,23 +350,60 @@ int hil_state_transition(hil_state_t new_state, int status_pub, struct vehicle_s
|
||||
|
||||
/* list directory */
|
||||
DIR *d;
|
||||
struct dirent *direntry;
|
||||
d = opendir("/dev");
|
||||
if (d) {
|
||||
|
||||
struct dirent *direntry;
|
||||
char devname[24];
|
||||
|
||||
while ((direntry = readdir(d)) != NULL) {
|
||||
|
||||
int sensfd = ::open(direntry->d_name, 0);
|
||||
int block_ret = ::ioctl(sensfd, DEVIOCSPUBBLOCK, 0);
|
||||
/* skip serial ports */
|
||||
if (!strncmp("tty", direntry->d_name, 3)) {
|
||||
continue;
|
||||
}
|
||||
/* skip mtd devices */
|
||||
if (!strncmp("mtd", direntry->d_name, 3)) {
|
||||
continue;
|
||||
}
|
||||
/* skip ram devices */
|
||||
if (!strncmp("ram", direntry->d_name, 3)) {
|
||||
continue;
|
||||
}
|
||||
/* skip MMC devices */
|
||||
if (!strncmp("mmc", direntry->d_name, 3)) {
|
||||
continue;
|
||||
}
|
||||
/* skip mavlink */
|
||||
if (!strcmp("mavlink", direntry->d_name)) {
|
||||
continue;
|
||||
}
|
||||
/* skip console */
|
||||
if (!strcmp("console", direntry->d_name)) {
|
||||
continue;
|
||||
}
|
||||
/* skip null */
|
||||
if (!strcmp("null", direntry->d_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(devname, sizeof(devname), "/dev/%s", direntry->d_name);
|
||||
|
||||
int sensfd = ::open(devname, 0);
|
||||
|
||||
if (sensfd < 0) {
|
||||
warn("failed opening device %s", devname);
|
||||
continue;
|
||||
}
|
||||
|
||||
int block_ret = ::ioctl(sensfd, DEVIOCSPUBBLOCK, 1);
|
||||
close(sensfd);
|
||||
|
||||
printf("Disabling %s\n: %s", direntry->d_name, (!block_ret) ? "OK" : "FAIL");
|
||||
printf("Disabling %s: %s\n", devname, (block_ret == OK) ? "OK" : "ERROR");
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
warnx("directory listing ok (FS mounted and readable)");
|
||||
|
||||
} else {
|
||||
/* failed opening dir */
|
||||
warnx("FAILED LISTING DEVICE ROOT DIRECTORY");
|
||||
|
||||
@@ -41,10 +41,11 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/Publication.hpp>
|
||||
|
||||
#include "Block.hpp"
|
||||
#include "BlockParam.hpp"
|
||||
#include "../uorb/UOrbSubscription.hpp"
|
||||
#include "../uorb/UOrbPublication.hpp"
|
||||
|
||||
namespace control
|
||||
{
|
||||
@@ -100,7 +101,7 @@ void Block::updateParams()
|
||||
|
||||
void Block::updateSubscriptions()
|
||||
{
|
||||
UOrbSubscriptionBase *sub = getSubscriptions().getHead();
|
||||
uORB::SubscriptionBase *sub = getSubscriptions().getHead();
|
||||
int count = 0;
|
||||
|
||||
while (sub != NULL) {
|
||||
@@ -118,7 +119,7 @@ void Block::updateSubscriptions()
|
||||
|
||||
void Block::updatePublications()
|
||||
{
|
||||
UOrbPublicationBase *pub = getPublications().getHead();
|
||||
uORB::PublicationBase *pub = getPublications().getHead();
|
||||
int count = 0;
|
||||
|
||||
while (pub != NULL) {
|
||||
|
||||
@@ -42,7 +42,13 @@
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "List.hpp"
|
||||
#include <containers/List.hpp>
|
||||
|
||||
// forward declaration
|
||||
namespace uORB {
|
||||
class SubscriptionBase;
|
||||
class PublicationBase;
|
||||
}
|
||||
|
||||
namespace control
|
||||
{
|
||||
@@ -55,8 +61,6 @@ static const uint8_t blockNameLengthMax = 80;
|
||||
|
||||
// forward declaration
|
||||
class BlockParamBase;
|
||||
class UOrbSubscriptionBase;
|
||||
class UOrbPublicationBase;
|
||||
class SuperBlock;
|
||||
|
||||
/**
|
||||
@@ -79,15 +83,15 @@ public:
|
||||
protected:
|
||||
// accessors
|
||||
SuperBlock *getParent() { return _parent; }
|
||||
List<UOrbSubscriptionBase *> & getSubscriptions() { return _subscriptions; }
|
||||
List<UOrbPublicationBase *> & getPublications() { return _publications; }
|
||||
List<uORB::SubscriptionBase *> & getSubscriptions() { return _subscriptions; }
|
||||
List<uORB::PublicationBase *> & getPublications() { return _publications; }
|
||||
List<BlockParamBase *> & getParams() { return _params; }
|
||||
// attributes
|
||||
const char *_name;
|
||||
SuperBlock *_parent;
|
||||
float _dt;
|
||||
List<UOrbSubscriptionBase *> _subscriptions;
|
||||
List<UOrbPublicationBase *> _publications;
|
||||
List<uORB::SubscriptionBase *> _subscriptions;
|
||||
List<uORB::PublicationBase *> _publications;
|
||||
List<BlockParamBase *> _params;
|
||||
};
|
||||
|
||||
|
||||
@@ -76,4 +76,29 @@ BlockParamBase::BlockParamBase(Block *parent, const char *name, bool parent_pref
|
||||
printf("error finding param: %s\n", fullname);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
BlockParam<T>::BlockParam(Block *block, const char *name,
|
||||
bool parent_prefix) :
|
||||
BlockParamBase(block, name, parent_prefix),
|
||||
_val() {
|
||||
update();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T BlockParam<T>::get() { return _val; }
|
||||
|
||||
template <class T>
|
||||
void BlockParam<T>::set(T val) { _val = val; }
|
||||
|
||||
template <class T>
|
||||
void BlockParam<T>::update() {
|
||||
if (_handle != PARAM_INVALID) param_get(_handle, &_val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BlockParam<T>::~BlockParam() {};
|
||||
|
||||
template class __EXPORT BlockParam<float>;
|
||||
template class __EXPORT BlockParam<int>;
|
||||
|
||||
} // namespace control
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
#include "Block.hpp"
|
||||
#include "List.hpp"
|
||||
#include <containers/List.hpp>
|
||||
|
||||
namespace control
|
||||
{
|
||||
@@ -70,38 +70,21 @@ protected:
|
||||
* Parameters that are tied to blocks for updating and nameing.
|
||||
*/
|
||||
|
||||
class __EXPORT BlockParamFloat : public BlockParamBase
|
||||
template <class T>
|
||||
class BlockParam : public BlockParamBase
|
||||
{
|
||||
public:
|
||||
BlockParamFloat(Block *block, const char *name, bool parent_prefix=true) :
|
||||
BlockParamBase(block, name, parent_prefix),
|
||||
_val() {
|
||||
update();
|
||||
}
|
||||
float get() { return _val; }
|
||||
void set(float val) { _val = val; }
|
||||
void update() {
|
||||
if (_handle != PARAM_INVALID) param_get(_handle, &_val);
|
||||
}
|
||||
BlockParam(Block *block, const char *name,
|
||||
bool parent_prefix=true);
|
||||
T get();
|
||||
void set(T val);
|
||||
void update();
|
||||
virtual ~BlockParam();
|
||||
protected:
|
||||
float _val;
|
||||
T _val;
|
||||
};
|
||||
|
||||
class __EXPORT BlockParamInt : public BlockParamBase
|
||||
{
|
||||
public:
|
||||
BlockParamInt(Block *block, const char *name, bool parent_prefix=true) :
|
||||
BlockParamBase(block, name, parent_prefix),
|
||||
_val() {
|
||||
update();
|
||||
}
|
||||
int get() { return _val; }
|
||||
void set(int val) { _val = val; }
|
||||
void update() {
|
||||
if (_handle != PARAM_INVALID) param_get(_handle, &_val);
|
||||
}
|
||||
protected:
|
||||
int _val;
|
||||
};
|
||||
typedef BlockParam<float> BlockParamFloat;
|
||||
typedef BlockParam<int> BlockParamInt;
|
||||
|
||||
} // namespace control
|
||||
|
||||
@@ -37,7 +37,5 @@
|
||||
SRCS = test_params.c \
|
||||
block/Block.cpp \
|
||||
block/BlockParam.cpp \
|
||||
uorb/UOrbPublication.cpp \
|
||||
uorb/UOrbSubscription.cpp \
|
||||
uorb/blocks.cpp \
|
||||
blocks.cpp
|
||||
|
||||
@@ -62,8 +62,8 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "../blocks.hpp"
|
||||
#include "UOrbSubscription.hpp"
|
||||
#include "UOrbPublication.hpp"
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/Publication.hpp>
|
||||
|
||||
namespace control
|
||||
{
|
||||
@@ -94,16 +94,16 @@ class __EXPORT BlockUorbEnabledAutopilot : public SuperBlock
|
||||
{
|
||||
protected:
|
||||
// subscriptions
|
||||
UOrbSubscription<vehicle_attitude_s> _att;
|
||||
UOrbSubscription<vehicle_attitude_setpoint_s> _attCmd;
|
||||
UOrbSubscription<vehicle_rates_setpoint_s> _ratesCmd;
|
||||
UOrbSubscription<vehicle_global_position_s> _pos;
|
||||
UOrbSubscription<position_setpoint_triplet_s> _missionCmd;
|
||||
UOrbSubscription<manual_control_setpoint_s> _manual;
|
||||
UOrbSubscription<vehicle_status_s> _status;
|
||||
UOrbSubscription<parameter_update_s> _param_update;
|
||||
uORB::Subscription<vehicle_attitude_s> _att;
|
||||
uORB::Subscription<vehicle_attitude_setpoint_s> _attCmd;
|
||||
uORB::Subscription<vehicle_rates_setpoint_s> _ratesCmd;
|
||||
uORB::Subscription<vehicle_global_position_s> _pos;
|
||||
uORB::Subscription<position_setpoint_triplet_s> _missionCmd;
|
||||
uORB::Subscription<manual_control_setpoint_s> _manual;
|
||||
uORB::Subscription<vehicle_status_s> _status;
|
||||
uORB::Subscription<parameter_update_s> _param_update;
|
||||
// publications
|
||||
UOrbPublication<actuator_controls_s> _actuators;
|
||||
uORB::Publication<actuator_controls_s> _actuators;
|
||||
public:
|
||||
BlockUorbEnabledAutopilot(SuperBlock *parent, const char *name);
|
||||
virtual ~BlockUorbEnabledAutopilot();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier
|
||||
* Jean Cyr
|
||||
* Author: Jean Cyr
|
||||
* Lorenz Meier
|
||||
* Julian Oes
|
||||
* Thomas Gubler
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -40,16 +42,8 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include "dataman.h"
|
||||
@@ -175,8 +169,10 @@ create_work_item(void)
|
||||
|
||||
/* Try to reuse item from free item queue */
|
||||
lock_queue(&g_free_q);
|
||||
|
||||
if ((item = (work_q_item_t *)sq_remfirst(&(g_free_q.q))))
|
||||
g_free_q.size--;
|
||||
|
||||
unlock_queue(&g_free_q);
|
||||
|
||||
/* If we there weren't any free items then obtain memory for a new one */
|
||||
@@ -289,11 +285,11 @@ _write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const v
|
||||
offset = calculate_offset(item, index);
|
||||
|
||||
/* If item type or index out of range, return error */
|
||||
if (offset < 0)
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
/* Make sure caller has not given us more data than we can handle */
|
||||
if (count > DM_MAX_DATA_SIZE)
|
||||
if (count > DM_MAX_DATA_SIZE)
|
||||
return -1;
|
||||
|
||||
/* Write out the data, prefixed with length and persistence level */
|
||||
@@ -339,6 +335,7 @@ _read(dm_item_t item, unsigned char index, void *buf, size_t count)
|
||||
|
||||
/* Read the prefix and data */
|
||||
len = -1;
|
||||
|
||||
if (lseek(g_task_fd, offset, SEEK_SET) == offset)
|
||||
len = read(g_task_fd, buffer, count + DM_SECTOR_HDR_SIZE);
|
||||
|
||||
@@ -492,7 +489,7 @@ dm_write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const
|
||||
return -1;
|
||||
|
||||
/* get a work item and queue up a write request */
|
||||
if ((work = create_work_item()) == NULL)
|
||||
if ((work = create_work_item()) == NULL)
|
||||
return -1;
|
||||
|
||||
work->func = dm_write_func;
|
||||
@@ -599,17 +596,20 @@ task_main(int argc, char *argv[])
|
||||
|
||||
/* Open or create the data manager file */
|
||||
g_task_fd = open(k_data_manager_device_path, O_RDWR | O_CREAT | O_BINARY);
|
||||
|
||||
if (g_task_fd < 0) {
|
||||
warnx("Could not open data manager file %s", k_data_manager_device_path);
|
||||
sem_post(&g_init_sema); /* Don't want to hang startup */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(g_task_fd, max_offset, SEEK_SET) != max_offset) {
|
||||
close(g_task_fd);
|
||||
warnx("Could not seek data manager file %s", k_data_manager_device_path);
|
||||
sem_post(&g_init_sema); /* Don't want to hang startup */
|
||||
return -1;
|
||||
}
|
||||
|
||||
fsync(g_task_fd);
|
||||
|
||||
/* We use two file descriptors, one for the caller context and one for the worker thread */
|
||||
@@ -767,10 +767,10 @@ dataman_main(int argc, char *argv[])
|
||||
stop();
|
||||
else if (!strcmp(argv[1], "status"))
|
||||
status();
|
||||
else if (!strcmp(argv[1], "poweronrestart"))
|
||||
dm_restart(DM_INIT_REASON_POWER_ON);
|
||||
else if (!strcmp(argv[1], "inflightrestart"))
|
||||
dm_restart(DM_INIT_REASON_IN_FLIGHT);
|
||||
else if (!strcmp(argv[1], "poweronrestart"))
|
||||
dm_restart(DM_INIT_REASON_POWER_ON);
|
||||
else if (!strcmp(argv[1], "inflightrestart"))
|
||||
dm_restart(DM_INIT_REASON_IN_FLIGHT);
|
||||
else
|
||||
usage();
|
||||
|
||||
|
||||
@@ -38,5 +38,3 @@
|
||||
MODULE_COMMAND = dataman
|
||||
|
||||
SRCS = dataman.c
|
||||
|
||||
INCLUDE_DIRS += $(MAVLINK_SRC)/include/mavlink
|
||||
|
||||
@@ -175,14 +175,14 @@ void BlockMultiModeBacksideAutopilot::update()
|
||||
// the min/max velocity
|
||||
float v = _vLimit.update(sqrtf(
|
||||
_pos.vel_n * _pos.vel_n +
|
||||
_pos.vy * _pos.vy +
|
||||
_pos.vel_e * _pos.vel_e +
|
||||
_pos.vel_d * _pos.vel_d));
|
||||
|
||||
// limit velocity command between min/max velocity
|
||||
float vCmd = _vLimit.update(_vCmd.get());
|
||||
|
||||
// altitude hold
|
||||
float dThrottle = _h2Thr.update(_missionCmd.current.altitude - _pos.alt);
|
||||
float dThrottle = _h2Thr.update(_missionCmd.current.alt - _pos.alt);
|
||||
|
||||
// heading hold
|
||||
float psiError = _wrap_pi(_guide.getPsiCmd() - _att.yaw);
|
||||
@@ -237,7 +237,7 @@ void BlockMultiModeBacksideAutopilot::update()
|
||||
// the min/max velocity
|
||||
float v = _vLimit.update(sqrtf(
|
||||
_pos.vel_n * _pos.vel_n +
|
||||
_pos.vy * _pos.vy +
|
||||
_pos.vel_e * _pos.vel_e +
|
||||
_pos.vel_d * _pos.vel_d));
|
||||
|
||||
// pitch channel -> rate of climb
|
||||
|
||||
@@ -108,14 +108,14 @@ private:
|
||||
bool _task_should_exit; /**< if true, sensor task should exit */
|
||||
int _control_task; /**< task handle for sensor task */
|
||||
|
||||
int _att_sub; /**< vehicle attitude subscription */
|
||||
int _accel_sub; /**< accelerometer subscription */
|
||||
int _att_sub; /**< vehicle attitude subscription */
|
||||
int _accel_sub; /**< accelerometer subscription */
|
||||
int _att_sp_sub; /**< vehicle attitude setpoint */
|
||||
int _attitude_sub; /**< raw rc channels data subscription */
|
||||
int _airspeed_sub; /**< airspeed subscription */
|
||||
int _vcontrol_mode_sub; /**< vehicle status subscription */
|
||||
int _params_sub; /**< notification of parameter updates */
|
||||
int _manual_sub; /**< notification of manual control updates */
|
||||
int _params_sub; /**< notification of parameter updates */
|
||||
int _manual_sub; /**< notification of manual control updates */
|
||||
int _global_pos_sub; /**< global position subscription */
|
||||
|
||||
orb_advert_t _rate_sp_pub; /**< rate setpoint publication */
|
||||
@@ -123,20 +123,19 @@ private:
|
||||
orb_advert_t _actuators_0_pub; /**< actuator control group 0 setpoint */
|
||||
orb_advert_t _actuators_1_pub; /**< actuator control group 1 setpoint (Airframe) */
|
||||
|
||||
struct vehicle_attitude_s _att; /**< vehicle attitude */
|
||||
struct accel_report _accel; /**< body frame accelerations */
|
||||
struct vehicle_attitude_s _att; /**< vehicle attitude */
|
||||
struct accel_report _accel; /**< body frame accelerations */
|
||||
struct vehicle_attitude_setpoint_s _att_sp; /**< vehicle attitude setpoint */
|
||||
struct manual_control_setpoint_s _manual; /**< r/c channel data */
|
||||
struct airspeed_s _airspeed; /**< airspeed */
|
||||
struct vehicle_control_mode_s _vcontrol_mode; /**< vehicle control mode */
|
||||
struct airspeed_s _airspeed; /**< airspeed */
|
||||
struct vehicle_control_mode_s _vcontrol_mode; /**< vehicle control mode */
|
||||
struct actuator_controls_s _actuators; /**< actuator control inputs */
|
||||
struct actuator_controls_s _actuators_airframe; /**< actuator control inputs */
|
||||
struct vehicle_global_position_s _global_pos; /**< global position */
|
||||
struct actuator_controls_s _actuators_airframe; /**< actuator control inputs */
|
||||
struct vehicle_global_position_s _global_pos; /**< global position */
|
||||
|
||||
perf_counter_t _loop_perf; /**< loop performance counter */
|
||||
|
||||
bool _setpoint_valid; /**< flag if the position control setpoint is valid */
|
||||
bool _airspeed_valid; /**< flag if the airspeed measurement is valid */
|
||||
|
||||
struct {
|
||||
float tconst;
|
||||
@@ -166,6 +165,15 @@ private:
|
||||
float airspeed_min;
|
||||
float airspeed_trim;
|
||||
float airspeed_max;
|
||||
|
||||
float trim_roll;
|
||||
float trim_pitch;
|
||||
float trim_yaw;
|
||||
float rollsp_offset_deg; /**< Roll Setpoint Offset in deg */
|
||||
float pitchsp_offset_deg; /**< Pitch Setpoint Offset in deg */
|
||||
float rollsp_offset_rad; /**< Roll Setpoint Offset in rad */
|
||||
float pitchsp_offset_rad; /**< Pitch Setpoint Offset in rad */
|
||||
|
||||
} _parameters; /**< local copies of interesting parameters */
|
||||
|
||||
struct {
|
||||
@@ -197,6 +205,12 @@ private:
|
||||
param_t airspeed_min;
|
||||
param_t airspeed_trim;
|
||||
param_t airspeed_max;
|
||||
|
||||
param_t trim_roll;
|
||||
param_t trim_pitch;
|
||||
param_t trim_yaw;
|
||||
param_t rollsp_offset_deg;
|
||||
param_t pitchsp_offset_deg;
|
||||
} _parameter_handles; /**< handles for interesting parameters */
|
||||
|
||||
|
||||
@@ -230,7 +244,7 @@ private:
|
||||
/**
|
||||
* Check for airspeed updates.
|
||||
*/
|
||||
bool vehicle_airspeed_poll();
|
||||
void vehicle_airspeed_poll();
|
||||
|
||||
/**
|
||||
* Check for accel updates.
|
||||
@@ -293,19 +307,18 @@ FixedwingAttitudeControl::FixedwingAttitudeControl() :
|
||||
/* performance counters */
|
||||
_loop_perf(perf_alloc(PC_ELAPSED, "fw att control")),
|
||||
/* states */
|
||||
_setpoint_valid(false),
|
||||
_airspeed_valid(false)
|
||||
_setpoint_valid(false)
|
||||
{
|
||||
/* safely initialize structs */
|
||||
_att = {0};
|
||||
_accel = {0};
|
||||
_att_sp = {0};
|
||||
_manual = {0};
|
||||
_airspeed = {0};
|
||||
_vcontrol_mode = {0};
|
||||
_actuators = {0};
|
||||
_actuators_airframe = {0};
|
||||
_global_pos = {0};
|
||||
_att = {};
|
||||
_accel = {};
|
||||
_att_sp = {};
|
||||
_manual = {};
|
||||
_airspeed = {};
|
||||
_vcontrol_mode = {};
|
||||
_actuators = {};
|
||||
_actuators_airframe = {};
|
||||
_global_pos = {};
|
||||
|
||||
|
||||
_parameter_handles.tconst = param_find("FW_ATT_TC");
|
||||
@@ -335,6 +348,12 @@ FixedwingAttitudeControl::FixedwingAttitudeControl() :
|
||||
|
||||
_parameter_handles.y_coordinated_min_speed = param_find("FW_YCO_VMIN");
|
||||
|
||||
_parameter_handles.trim_roll = param_find("TRIM_ROLL");
|
||||
_parameter_handles.trim_pitch = param_find("TRIM_PITCH");
|
||||
_parameter_handles.trim_yaw = param_find("TRIM_YAW");
|
||||
_parameter_handles.rollsp_offset_deg = param_find("FW_RSP_OFF");
|
||||
_parameter_handles.pitchsp_offset_deg = param_find("FW_PSP_OFF");
|
||||
|
||||
/* fetch initial parameter values */
|
||||
parameters_update();
|
||||
}
|
||||
@@ -395,6 +414,15 @@ FixedwingAttitudeControl::parameters_update()
|
||||
param_get(_parameter_handles.airspeed_trim, &(_parameters.airspeed_trim));
|
||||
param_get(_parameter_handles.airspeed_max, &(_parameters.airspeed_max));
|
||||
|
||||
param_get(_parameter_handles.trim_roll, &(_parameters.trim_roll));
|
||||
param_get(_parameter_handles.trim_pitch, &(_parameters.trim_pitch));
|
||||
param_get(_parameter_handles.trim_yaw, &(_parameters.trim_yaw));
|
||||
param_get(_parameter_handles.rollsp_offset_deg, &(_parameters.rollsp_offset_deg));
|
||||
param_get(_parameter_handles.pitchsp_offset_deg, &(_parameters.pitchsp_offset_deg));
|
||||
_parameters.rollsp_offset_rad = math::radians(_parameters.rollsp_offset_deg);
|
||||
_parameters.pitchsp_offset_rad = math::radians(_parameters.pitchsp_offset_deg);
|
||||
|
||||
|
||||
/* pitch control parameters */
|
||||
_pitch_ctrl.set_time_constant(_parameters.tconst);
|
||||
_pitch_ctrl.set_k_p(_parameters.p_p);
|
||||
@@ -452,7 +480,7 @@ FixedwingAttitudeControl::vehicle_manual_poll()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
FixedwingAttitudeControl::vehicle_airspeed_poll()
|
||||
{
|
||||
/* check if there is a new position */
|
||||
@@ -462,10 +490,7 @@ FixedwingAttitudeControl::vehicle_airspeed_poll()
|
||||
if (airspeed_updated) {
|
||||
orb_copy(ORB_ID(airspeed), _airspeed_sub, &_airspeed);
|
||||
// warnx("airspeed poll: ind: %.4f, true: %.4f", _airspeed.indicated_airspeed_m_s, _airspeed.true_airspeed_m_s);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -539,7 +564,7 @@ FixedwingAttitudeControl::task_main()
|
||||
parameters_update();
|
||||
|
||||
/* get an initial update for all sensor and status data */
|
||||
(void)vehicle_airspeed_poll();
|
||||
vehicle_airspeed_poll();
|
||||
vehicle_setpoint_poll();
|
||||
vehicle_accel_poll();
|
||||
vehicle_control_mode_poll();
|
||||
@@ -596,7 +621,7 @@ FixedwingAttitudeControl::task_main()
|
||||
/* load local copies */
|
||||
orb_copy(ORB_ID(vehicle_attitude), _att_sub, &_att);
|
||||
|
||||
_airspeed_valid = vehicle_airspeed_poll();
|
||||
vehicle_airspeed_poll();
|
||||
|
||||
vehicle_setpoint_poll();
|
||||
|
||||
@@ -636,9 +661,9 @@ FixedwingAttitudeControl::task_main()
|
||||
float airspeed;
|
||||
|
||||
/* if airspeed is smaller than min, the sensor is not giving good readings */
|
||||
if (!_airspeed_valid ||
|
||||
(_airspeed.indicated_airspeed_m_s < 0.5f * _parameters.airspeed_min) ||
|
||||
!isfinite(_airspeed.indicated_airspeed_m_s)) {
|
||||
if ((_airspeed.indicated_airspeed_m_s < 0.5f * _parameters.airspeed_min) ||
|
||||
!isfinite(_airspeed.indicated_airspeed_m_s) ||
|
||||
hrt_elapsed_time(&_airspeed.timestamp) > 1e6) {
|
||||
airspeed = _parameters.airspeed_trim;
|
||||
|
||||
} else {
|
||||
@@ -648,13 +673,13 @@ FixedwingAttitudeControl::task_main()
|
||||
float airspeed_scaling = _parameters.airspeed_trim / airspeed;
|
||||
//warnx("aspd scale: %6.2f act scale: %6.2f", airspeed_scaling, actuator_scaling);
|
||||
|
||||
float roll_sp = 0.0f;
|
||||
float pitch_sp = 0.0f;
|
||||
float roll_sp = _parameters.rollsp_offset_rad;
|
||||
float pitch_sp = _parameters.pitchsp_offset_rad;
|
||||
float throttle_sp = 0.0f;
|
||||
|
||||
if (_vcontrol_mode.flag_control_velocity_enabled || _vcontrol_mode.flag_control_position_enabled) {
|
||||
roll_sp = _att_sp.roll_body;
|
||||
pitch_sp = _att_sp.pitch_body;
|
||||
roll_sp = _att_sp.roll_body + _parameters.rollsp_offset_rad;
|
||||
pitch_sp = _att_sp.pitch_body + _parameters.pitchsp_offset_rad;
|
||||
throttle_sp = _att_sp.thrust;
|
||||
|
||||
/* reset integrals where needed */
|
||||
@@ -670,9 +695,13 @@ FixedwingAttitudeControl::task_main()
|
||||
* With this mapping the stick angle is a 1:1 representation of
|
||||
* the commanded attitude. If more than 45 degrees are desired,
|
||||
* a scaling parameter can be applied to the remote.
|
||||
*
|
||||
* The trim gets subtracted here from the manual setpoint to get
|
||||
* the intended attitude setpoint. Later, after the rate control step the
|
||||
* trim is added again to the control signal.
|
||||
*/
|
||||
roll_sp = _manual.roll * 0.75f;
|
||||
pitch_sp = _manual.pitch * 0.75f;
|
||||
roll_sp = (_manual.roll - _parameters.trim_roll) * 0.75f + _parameters.rollsp_offset_rad;
|
||||
pitch_sp = (_manual.pitch - _parameters.trim_pitch) * 0.75f + _parameters.pitchsp_offset_rad;
|
||||
throttle_sp = _manual.throttle;
|
||||
_actuators.control[4] = _manual.flaps;
|
||||
|
||||
@@ -685,7 +714,7 @@ FixedwingAttitudeControl::task_main()
|
||||
att_sp.timestamp = hrt_absolute_time();
|
||||
att_sp.roll_body = roll_sp;
|
||||
att_sp.pitch_body = pitch_sp;
|
||||
att_sp.yaw_body = 0.0f;
|
||||
att_sp.yaw_body = 0.0f - _parameters.trim_yaw;
|
||||
att_sp.thrust = throttle_sp;
|
||||
|
||||
/* lazily publish the setpoint only once available */
|
||||
@@ -719,12 +748,12 @@ FixedwingAttitudeControl::task_main()
|
||||
speed_body_u, speed_body_v, speed_body_w,
|
||||
_roll_ctrl.get_desired_rate(), _pitch_ctrl.get_desired_rate()); //runs last, because is depending on output of roll and pitch attitude
|
||||
|
||||
/* Run attitude RATE controllers which need the desired attitudes from above */
|
||||
/* Run attitude RATE controllers which need the desired attitudes from above, add trim */
|
||||
float roll_u = _roll_ctrl.control_bodyrate(_att.pitch,
|
||||
_att.rollspeed, _att.yawspeed,
|
||||
_yaw_ctrl.get_desired_rate(),
|
||||
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
|
||||
_actuators.control[0] = (isfinite(roll_u)) ? roll_u : 0.0f;
|
||||
_actuators.control[0] = (isfinite(roll_u)) ? roll_u + _parameters.trim_roll : _parameters.trim_roll;
|
||||
if (!isfinite(roll_u)) {
|
||||
warnx("roll_u %.4f", roll_u);
|
||||
}
|
||||
@@ -733,7 +762,7 @@ FixedwingAttitudeControl::task_main()
|
||||
_att.pitchspeed, _att.yawspeed,
|
||||
_yaw_ctrl.get_desired_rate(),
|
||||
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
|
||||
_actuators.control[1] = (isfinite(pitch_u)) ? pitch_u : 0.0f;
|
||||
_actuators.control[1] = (isfinite(pitch_u)) ? pitch_u + _parameters.trim_pitch : _parameters.trim_pitch;
|
||||
if (!isfinite(pitch_u)) {
|
||||
warnx("pitch_u %.4f, _yaw_ctrl.get_desired_rate() %.4f, airspeed %.4f, airspeed_scaling %.4f, roll_sp %.4f, pitch_sp %.4f, _roll_ctrl.get_desired_rate() %.4f, _pitch_ctrl.get_desired_rate() %.4f att_sp.roll_body %.4f",
|
||||
pitch_u, _yaw_ctrl.get_desired_rate(), airspeed, airspeed_scaling, roll_sp, pitch_sp, _roll_ctrl.get_desired_rate(), _pitch_ctrl.get_desired_rate(), _att_sp.roll_body);
|
||||
@@ -743,7 +772,7 @@ FixedwingAttitudeControl::task_main()
|
||||
_att.pitchspeed, _att.yawspeed,
|
||||
_pitch_ctrl.get_desired_rate(),
|
||||
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
|
||||
_actuators.control[2] = (isfinite(yaw_u)) ? yaw_u : 0.0f;
|
||||
_actuators.control[2] = (isfinite(yaw_u)) ? yaw_u + _parameters.trim_yaw : _parameters.trim_yaw;
|
||||
if (!isfinite(yaw_u)) {
|
||||
warnx("yaw_u %.4f", yaw_u);
|
||||
}
|
||||
@@ -757,10 +786,6 @@ FixedwingAttitudeControl::task_main()
|
||||
warnx("Non-finite setpoint roll_sp: %.4f, pitch_sp %.4f", roll_sp, pitch_sp);
|
||||
}
|
||||
|
||||
// warnx("aspd: %s: %6.2f, aspd scaling: %6.2f, controls: %5.2f %5.2f %5.2f %5.2f", (_airspeed_valid) ? "valid" : "unknown",
|
||||
// airspeed, airspeed_scaling, _actuators.control[0], _actuators.control[1],
|
||||
// _actuators.control[2], _actuators.control[3]);
|
||||
|
||||
/*
|
||||
* Lazily publish the rate setpoint (for analysis, the actuators are published below)
|
||||
* only once available
|
||||
|
||||
@@ -176,3 +176,13 @@ PARAM_DEFINE_FLOAT(FW_AIRSPD_TRIM, 20.0f);
|
||||
// @Description If the airspeed is above this value the TECS controller will try to decrease airspeed more aggressively
|
||||
// @Range 0.0 to 30
|
||||
PARAM_DEFINE_FLOAT(FW_AIRSPD_MAX, 50.0f);
|
||||
|
||||
// @DisplayName Roll Setpoint Offset
|
||||
// @Description An airframe specific offset of the roll setpoint in degrees, the value is added to the roll setpoint and should correspond to the typical cruise speed of the airframe
|
||||
// @Range -90.0 to 90.0
|
||||
PARAM_DEFINE_FLOAT(FW_RSP_OFF, 0.0f);
|
||||
|
||||
// @DisplayName Pitch Setpoint Offset
|
||||
// @Description An airframe specific offset of the pitch setpoint in degrees, the value is added to the pitch setpoint and should correspond to the typical cruise speed of the airframe
|
||||
// @Range -90.0 to 90.0
|
||||
PARAM_DEFINE_FLOAT(FW_PSP_OFF, 0.0f);
|
||||
|
||||
@@ -130,23 +130,23 @@ private:
|
||||
int _att_sub; /**< vehicle attitude subscription */
|
||||
int _attitude_sub; /**< raw rc channels data subscription */
|
||||
int _airspeed_sub; /**< airspeed subscription */
|
||||
int _control_mode_sub; /**< vehicle status subscription */
|
||||
int _control_mode_sub; /**< vehicle status subscription */
|
||||
int _params_sub; /**< notification of parameter updates */
|
||||
int _manual_control_sub; /**< notification of manual control updates */
|
||||
int _sensor_combined_sub; /**< for body frame accelerations */
|
||||
int _sensor_combined_sub; /**< for body frame accelerations */
|
||||
|
||||
orb_advert_t _attitude_sp_pub; /**< attitude setpoint */
|
||||
orb_advert_t _nav_capabilities_pub; /**< navigation capabilities publication */
|
||||
|
||||
struct vehicle_attitude_s _att; /**< vehicle attitude */
|
||||
struct vehicle_attitude_setpoint_s _att_sp; /**< vehicle attitude setpoint */
|
||||
struct navigation_capabilities_s _nav_capabilities; /**< navigation capabilities */
|
||||
struct manual_control_setpoint_s _manual; /**< r/c channel data */
|
||||
struct airspeed_s _airspeed; /**< airspeed */
|
||||
struct vehicle_control_mode_s _control_mode; /**< vehicle status */
|
||||
struct vehicle_global_position_s _global_pos; /**< global vehicle position */
|
||||
struct position_setpoint_triplet_s _pos_sp_triplet; /**< triplet of mission items */
|
||||
struct sensor_combined_s _sensor_combined; /**< for body frame accelerations */
|
||||
struct vehicle_attitude_s _att; /**< vehicle attitude */
|
||||
struct vehicle_attitude_setpoint_s _att_sp; /**< vehicle attitude setpoint */
|
||||
struct navigation_capabilities_s _nav_capabilities; /**< navigation capabilities */
|
||||
struct manual_control_setpoint_s _manual; /**< r/c channel data */
|
||||
struct airspeed_s _airspeed; /**< airspeed */
|
||||
struct vehicle_control_mode_s _control_mode; /**< vehicle status */
|
||||
struct vehicle_global_position_s _global_pos; /**< global vehicle position */
|
||||
struct position_setpoint_triplet_s _pos_sp_triplet; /**< triplet of mission items */
|
||||
struct sensor_combined_s _sensor_combined; /**< for body frame accelerations */
|
||||
|
||||
perf_counter_t _loop_perf; /**< loop performance counter */
|
||||
|
||||
@@ -154,13 +154,13 @@ private:
|
||||
|
||||
/** manual control states */
|
||||
float _seatbelt_hold_heading; /**< heading the system should hold in seatbelt mode */
|
||||
float _loiter_hold_lat;
|
||||
float _loiter_hold_lon;
|
||||
double _loiter_hold_lat;
|
||||
double _loiter_hold_lon;
|
||||
float _loiter_hold_alt;
|
||||
bool _loiter_hold;
|
||||
|
||||
float _launch_lat;
|
||||
float _launch_lon;
|
||||
double _launch_lat;
|
||||
double _launch_lon;
|
||||
float _launch_alt;
|
||||
bool _launch_valid;
|
||||
|
||||
@@ -176,6 +176,8 @@ private:
|
||||
bool launch_detected;
|
||||
bool usePreTakeoffThrust;
|
||||
|
||||
bool last_manual; ///< true if the last iteration was in manual mode (used to determine when a reset is needed)
|
||||
|
||||
/* Landingslope object */
|
||||
Landingslope landingslope;
|
||||
|
||||
@@ -184,7 +186,7 @@ private:
|
||||
float target_bearing;
|
||||
|
||||
/* Launch detection */
|
||||
LaunchDetector launchDetector;
|
||||
launchdetection::LaunchDetector launchDetector;
|
||||
|
||||
/* throttle and airspeed states */
|
||||
float _airspeed_error; ///< airspeed error to setpoint in m/s
|
||||
@@ -192,7 +194,7 @@ private:
|
||||
uint64_t _airspeed_last_valid; ///< last time airspeed was valid. Used to detect sensor failures
|
||||
float _groundspeed_undershoot; ///< ground speed error to min. speed in m/s
|
||||
bool _global_pos_valid; ///< global position is valid
|
||||
math::Matrix<3, 3> _R_nb; ///< current attitude
|
||||
math::Matrix<3, 3> _R_nb; ///< current attitude
|
||||
|
||||
ECL_L1_Pos_Controller _l1_control;
|
||||
TECS _tecs;
|
||||
@@ -233,7 +235,6 @@ private:
|
||||
float speedrate_p;
|
||||
|
||||
float land_slope_angle;
|
||||
float land_slope_length;
|
||||
float land_H1_virt;
|
||||
float land_flare_alt_relative;
|
||||
float land_thrust_lim_alt_relative;
|
||||
@@ -278,7 +279,6 @@ private:
|
||||
param_t speedrate_p;
|
||||
|
||||
param_t land_slope_angle;
|
||||
param_t land_slope_length;
|
||||
param_t land_H1_virt;
|
||||
param_t land_flare_alt_relative;
|
||||
param_t land_thrust_lim_alt_relative;
|
||||
@@ -346,6 +346,16 @@ private:
|
||||
* Main sensor collection task.
|
||||
*/
|
||||
void task_main() __attribute__((noreturn));
|
||||
|
||||
/*
|
||||
* Reset takeoff state
|
||||
*/
|
||||
void reset_takeoff_state();
|
||||
|
||||
/*
|
||||
* Reset landing state
|
||||
*/
|
||||
void reset_landing_state();
|
||||
};
|
||||
|
||||
namespace l1_control
|
||||
@@ -362,6 +372,7 @@ FixedwingPositionControl *g_control;
|
||||
|
||||
FixedwingPositionControl::FixedwingPositionControl() :
|
||||
|
||||
_mavlink_fd(-1),
|
||||
_task_should_exit(false),
|
||||
_control_task(-1),
|
||||
|
||||
@@ -380,38 +391,34 @@ FixedwingPositionControl::FixedwingPositionControl() :
|
||||
|
||||
/* performance counters */
|
||||
_loop_perf(perf_alloc(PC_ELAPSED, "fw l1 control")),
|
||||
|
||||
/* states */
|
||||
_setpoint_valid(false),
|
||||
_loiter_hold(false),
|
||||
_airspeed_error(0.0f),
|
||||
_airspeed_valid(false),
|
||||
_groundspeed_undershoot(0.0f),
|
||||
_global_pos_valid(false),
|
||||
land_noreturn_horizontal(false),
|
||||
land_noreturn_vertical(false),
|
||||
land_stayonground(false),
|
||||
land_motor_lim(false),
|
||||
land_onslope(false),
|
||||
flare_curve_alt_last(0.0f),
|
||||
_mavlink_fd(-1),
|
||||
launchDetector(),
|
||||
launch_detected(false),
|
||||
usePreTakeoffThrust(false)
|
||||
last_manual(false),
|
||||
usePreTakeoffThrust(false),
|
||||
flare_curve_alt_last(0.0f),
|
||||
launchDetector(),
|
||||
_airspeed_error(0.0f),
|
||||
_airspeed_valid(false),
|
||||
_groundspeed_undershoot(0.0f),
|
||||
_global_pos_valid(false),
|
||||
_att(),
|
||||
_att_sp(),
|
||||
_nav_capabilities(),
|
||||
_manual(),
|
||||
_airspeed(),
|
||||
_control_mode(),
|
||||
_global_pos(),
|
||||
_pos_sp_triplet(),
|
||||
_sensor_combined()
|
||||
{
|
||||
/* safely initialize structs */
|
||||
vehicle_attitude_s _att = {0};
|
||||
vehicle_attitude_setpoint_s _att_sp = {0};
|
||||
navigation_capabilities_s _nav_capabilities = {0};
|
||||
manual_control_setpoint_s _manual = {0};
|
||||
airspeed_s _airspeed = {0};
|
||||
vehicle_control_mode_s _control_mode = {0};
|
||||
vehicle_global_position_s _global_pos = {0};
|
||||
position_setpoint_triplet_s _pos_sp_triplet = {0};
|
||||
sensor_combined_s _sensor_combined = {0};
|
||||
|
||||
|
||||
|
||||
|
||||
_nav_capabilities.turn_distance = 0.0f;
|
||||
|
||||
_parameter_handles.l1_period = param_find("FW_L1_PERIOD");
|
||||
@@ -431,7 +438,6 @@ FixedwingPositionControl::FixedwingPositionControl() :
|
||||
_parameter_handles.throttle_land_max = param_find("FW_THR_LND_MAX");
|
||||
|
||||
_parameter_handles.land_slope_angle = param_find("FW_LND_ANG");
|
||||
_parameter_handles.land_slope_length = param_find("FW_LND_SLLR");
|
||||
_parameter_handles.land_H1_virt = param_find("FW_LND_HVIRT");
|
||||
_parameter_handles.land_flare_alt_relative = param_find("FW_LND_FLALT");
|
||||
_parameter_handles.land_thrust_lim_alt_relative = param_find("FW_LND_TLALT");
|
||||
@@ -520,7 +526,6 @@ FixedwingPositionControl::parameters_update()
|
||||
param_get(_parameter_handles.speedrate_p, &(_parameters.speedrate_p));
|
||||
|
||||
param_get(_parameter_handles.land_slope_angle, &(_parameters.land_slope_angle));
|
||||
param_get(_parameter_handles.land_slope_length, &(_parameters.land_slope_length));
|
||||
param_get(_parameter_handles.land_H1_virt, &(_parameters.land_H1_virt));
|
||||
param_get(_parameter_handles.land_flare_alt_relative, &(_parameters.land_flare_alt_relative));
|
||||
param_get(_parameter_handles.land_thrust_lim_alt_relative, &(_parameters.land_thrust_lim_alt_relative));
|
||||
@@ -587,8 +592,8 @@ FixedwingPositionControl::vehicle_control_mode_poll()
|
||||
orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode);
|
||||
|
||||
if (!was_armed && _control_mode.flag_armed) {
|
||||
_launch_lat = _global_pos.lat / 1e7f;
|
||||
_launch_lon = _global_pos.lon / 1e7f;
|
||||
_launch_lat = _global_pos.lat;
|
||||
_launch_lon = _global_pos.lon;
|
||||
_launch_alt = _global_pos.alt;
|
||||
_launch_valid = true;
|
||||
}
|
||||
@@ -703,7 +708,7 @@ void
|
||||
FixedwingPositionControl::calculate_gndspeed_undershoot(const math::Vector<2> ¤t_position, const math::Vector<2> &ground_speed, const struct position_setpoint_triplet_s &pos_sp_triplet)
|
||||
{
|
||||
|
||||
if (_global_pos_valid) {
|
||||
if (_global_pos_valid && !(pos_sp_triplet.current.type == SETPOINT_TYPE_LOITER)) {
|
||||
|
||||
/* rotate ground speed vector with current attitude */
|
||||
math::Vector<2> yaw_vector(_R_nb(0, 0), _R_nb(1, 0));
|
||||
@@ -889,8 +894,10 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
float airspeed_land = 1.3f * _parameters.airspeed_min;
|
||||
float airspeed_approach = 1.3f * _parameters.airspeed_min;
|
||||
|
||||
float L_wp_distance = get_distance_to_next_waypoint(prev_wp(0), prev_wp(1), curr_wp(0), curr_wp(1)) * _parameters.land_slope_length;
|
||||
/* Calculate distance (to landing waypoint) and altitude of last ordinary waypoint L */
|
||||
float L_wp_distance = get_distance_to_next_waypoint(prev_wp(0), prev_wp(1), curr_wp(0), curr_wp(1));
|
||||
float L_altitude = landingslope.getLandingSlopeAbsoluteAltitude(L_wp_distance, _pos_sp_triplet.current.alt);
|
||||
|
||||
float bearing_airplane_currwp = get_bearing_to_next_waypoint(current_position(0), current_position(1), curr_wp(0), curr_wp(1));
|
||||
float landing_slope_alt_desired = landingslope.getLandingSlopeAbsoluteAltitudeSave(wp_distance, bearing_lastwp_currwp, bearing_airplane_currwp, _pos_sp_triplet.current.alt);
|
||||
|
||||
@@ -916,7 +923,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
float flare_curve_alt = landingslope.getFlareCurveAltitudeSave(wp_distance, bearing_lastwp_currwp, bearing_airplane_currwp, _pos_sp_triplet.current.alt);
|
||||
|
||||
/* avoid climbout */
|
||||
if (flare_curve_alt_last < flare_curve_alt && land_noreturn_vertical || land_stayonground)
|
||||
if ((flare_curve_alt_last < flare_curve_alt && land_noreturn_vertical) || land_stayonground)
|
||||
{
|
||||
flare_curve_alt = pos_sp_triplet.current.alt;
|
||||
land_stayonground = true;
|
||||
@@ -935,38 +942,24 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
//warnx("Landing: flare, _global_pos.alt %.1f, flare_curve_alt %.1f, flare_curve_alt_last %.1f, flare_length %.1f, wp_distance %.1f", _global_pos.alt, flare_curve_alt, flare_curve_alt_last, flare_length, wp_distance);
|
||||
|
||||
flare_curve_alt_last = flare_curve_alt;
|
||||
|
||||
} else if (wp_distance < L_wp_distance) {
|
||||
|
||||
/* minimize speed to approach speed, stay on landing slope */
|
||||
_tecs.update_pitch_throttle(_R_nb, _att.pitch, _global_pos.alt, landing_slope_alt_desired, calculate_target_airspeed(airspeed_approach),
|
||||
_airspeed.indicated_airspeed_m_s, eas2tas,
|
||||
false, flare_pitch_angle_rad,
|
||||
_parameters.throttle_min, _parameters.throttle_max, _parameters.throttle_cruise,
|
||||
math::radians(_parameters.pitch_limit_min), math::radians(_parameters.pitch_limit_max));
|
||||
//warnx("Landing: stay on slope, alt_desired: %.1f (wp_distance: %.1f), calculate_target_airspeed(airspeed_land) %.1f, horizontal_slope_displacement %.1f, d1 %.1f, flare_length %.1f", landing_slope_alt_desired, wp_distance, calculate_target_airspeed(airspeed_land), horizontal_slope_displacement, d1, flare_length);
|
||||
|
||||
if (!land_onslope) {
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "#audio: Landing, on slope");
|
||||
land_onslope = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* intersect glide slope:
|
||||
* if current position is higher or within 10m of slope follow the glide slope
|
||||
* if current position is below slope -10m continue on maximum of previous wp altitude or L_altitude until the intersection with the slope
|
||||
* */
|
||||
* minimize speed to approach speed
|
||||
* if current position is higher or within 10m of slope follow the glide slope
|
||||
* if current position is below slope -10m continue on maximum of previous wp altitude or L_altitude until the intersection with the slope
|
||||
* */
|
||||
float altitude_desired = _global_pos.alt;
|
||||
if (_global_pos.alt > landing_slope_alt_desired - 10.0f) {
|
||||
/* stay on slope */
|
||||
altitude_desired = landing_slope_alt_desired;
|
||||
//warnx("Landing: before L, stay on landing slope, alt_desired: %.1f (wp_distance: %.1f, L_wp_distance %.1f), calculate_target_airspeed(airspeed_land) %.1f, horizontal_slope_displacement %.1f", altitude_desired, wp_distance, L_wp_distance, calculate_target_airspeed(airspeed_land), horizontal_slope_displacement);
|
||||
if (!land_onslope) {
|
||||
mavlink_log_info(_mavlink_fd, "#audio: Landing, on slope");
|
||||
land_onslope = true;
|
||||
}
|
||||
} else {
|
||||
/* continue horizontally */
|
||||
altitude_desired = math::max(_global_pos.alt, L_altitude);
|
||||
//warnx("Landing: before L,continue at: %.4f, (landing_slope_alt_desired %.4f, wp_distance: %.4f, L_altitude: %.4f L_wp_distance: %.4f)", altitude_desired, landing_slope_alt_desired, wp_distance, L_altitude, L_wp_distance);
|
||||
}
|
||||
|
||||
_tecs.update_pitch_throttle(_R_nb, _att.pitch, _global_pos.alt, altitude_desired, calculate_target_airspeed(airspeed_approach),
|
||||
@@ -996,6 +989,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
} else {
|
||||
/* no takeoff detection --> fly */
|
||||
launch_detected = true;
|
||||
warnx("launchdetection off");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,19 +1036,14 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
// mission is active
|
||||
_loiter_hold = false;
|
||||
|
||||
/* reset land state */
|
||||
/* reset landing state */
|
||||
if (pos_sp_triplet.current.type != SETPOINT_TYPE_LAND) {
|
||||
land_noreturn_horizontal = false;
|
||||
land_noreturn_vertical = false;
|
||||
land_stayonground = false;
|
||||
land_motor_lim = false;
|
||||
land_onslope = false;
|
||||
reset_landing_state();
|
||||
}
|
||||
|
||||
/* reset takeoff/launch state */
|
||||
if (pos_sp_triplet.current.type != SETPOINT_TYPE_TAKEOFF) {
|
||||
launch_detected = false;
|
||||
usePreTakeoffThrust = false;
|
||||
reset_takeoff_state();
|
||||
}
|
||||
|
||||
if (was_circle_mode && !_l1_control.circle_mode()) {
|
||||
@@ -1074,13 +1063,15 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
_seatbelt_hold_heading = _att.yaw + _manual.yaw;
|
||||
}
|
||||
|
||||
/* climb out control */
|
||||
bool climb_out = false;
|
||||
//XXX not used
|
||||
|
||||
/* user wants to climb out */
|
||||
if (_manual.pitch > 0.3f && _manual.throttle > 0.8f) {
|
||||
climb_out = true;
|
||||
}
|
||||
/* climb out control */
|
||||
// bool climb_out = false;
|
||||
//
|
||||
// /* user wants to climb out */
|
||||
// if (_manual.pitch > 0.3f && _manual.throttle > 0.8f) {
|
||||
// climb_out = true;
|
||||
// }
|
||||
|
||||
/* if in seatbelt mode, set airspeed based on manual control */
|
||||
|
||||
@@ -1149,6 +1140,12 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
|
||||
/* no flight mode applies, do not publish an attitude setpoint */
|
||||
setpoint = false;
|
||||
|
||||
/* reset landing and takeoff state */
|
||||
if (!last_manual) {
|
||||
reset_landing_state();
|
||||
reset_takeoff_state();
|
||||
}
|
||||
}
|
||||
|
||||
if (usePreTakeoffThrust) {
|
||||
@@ -1159,6 +1156,12 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
}
|
||||
_att_sp.pitch_body = _tecs.get_pitch_demand();
|
||||
|
||||
if (_control_mode.flag_control_position_enabled) {
|
||||
last_manual = false;
|
||||
} else {
|
||||
last_manual = true;
|
||||
}
|
||||
|
||||
|
||||
return setpoint;
|
||||
}
|
||||
@@ -1287,7 +1290,7 @@ FixedwingPositionControl::task_main()
|
||||
float turn_distance = _l1_control.switch_distance(100.0f);
|
||||
|
||||
/* lazily publish navigation capabilities */
|
||||
if (turn_distance != _nav_capabilities.turn_distance && turn_distance > 0) {
|
||||
if (fabsf(turn_distance - _nav_capabilities.turn_distance) > FLT_EPSILON && turn_distance > 0) {
|
||||
|
||||
/* set new turn distance */
|
||||
_nav_capabilities.turn_distance = turn_distance;
|
||||
@@ -1309,6 +1312,22 @@ FixedwingPositionControl::task_main()
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void FixedwingPositionControl::reset_takeoff_state()
|
||||
{
|
||||
launch_detected = false;
|
||||
usePreTakeoffThrust = false;
|
||||
launchDetector.reset();
|
||||
}
|
||||
|
||||
void FixedwingPositionControl::reset_landing_state()
|
||||
{
|
||||
land_noreturn_horizontal = false;
|
||||
land_noreturn_vertical = false;
|
||||
land_stayonground = false;
|
||||
land_motor_lim = false;
|
||||
land_onslope = false;
|
||||
}
|
||||
|
||||
int
|
||||
FixedwingPositionControl::start()
|
||||
{
|
||||
|
||||
@@ -245,7 +245,7 @@ PARAM_DEFINE_FLOAT(FW_T_INTEG_GAIN, 0.1f);
|
||||
/**
|
||||
* Maximum vertical acceleration
|
||||
*
|
||||
* This is the maximum vertical acceleration (in metres/second^2)
|
||||
* This is the maximum vertical acceleration (in metres/second square)
|
||||
* either up or down that the controller will use to correct speed
|
||||
* or height errors. The default value of 7 m/s/s (equivalent to +- 0.7 g)
|
||||
* allows for reasonably aggressive pitch changes if required to recover
|
||||
@@ -348,13 +348,6 @@ PARAM_DEFINE_FLOAT(FW_T_SRATE_P, 0.05f);
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_LND_ANG, 5.0f);
|
||||
|
||||
/**
|
||||
* Landing slope length
|
||||
*
|
||||
* @group L1 Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_LND_SLLR, 0.9f);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
#include <systemlib/err.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/actuator_armed.h>
|
||||
#include <poll.h>
|
||||
#include <drivers/drv_gpio.h>
|
||||
#include <modules/px4iofirmware/protocol.h>
|
||||
@@ -63,8 +62,6 @@ struct gpio_led_s {
|
||||
int pin;
|
||||
struct vehicle_status_s status;
|
||||
int vehicle_status_sub;
|
||||
struct actuator_armed_s armed;
|
||||
int actuator_armed_sub;
|
||||
bool led_state;
|
||||
int counter;
|
||||
};
|
||||
@@ -81,6 +78,7 @@ void gpio_led_cycle(FAR void *arg);
|
||||
int gpio_led_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
|
||||
errx(1, "usage: gpio_led {start|stop} [-p <1|2|a1|a2|r1|r2>]\n"
|
||||
"\t-p\tUse pin:\n"
|
||||
"\t\t1\tPX4FMU GPIO_EXT1 (default)\n"
|
||||
@@ -88,7 +86,14 @@ int gpio_led_main(int argc, char *argv[])
|
||||
"\t\ta1\tPX4IO ACC1\n"
|
||||
"\t\ta2\tPX4IO ACC2\n"
|
||||
"\t\tr1\tPX4IO RELAY1\n"
|
||||
"\t\tr2\tPX4IO RELAY2");
|
||||
"\t\tr2\tPX4IO RELAY2"
|
||||
);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
|
||||
errx(1, "usage: gpio_led {start|stop} [-p <n>]\n"
|
||||
"\t-p <n>\tUse specified AUX OUT pin number (default: 1)"
|
||||
);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
@@ -98,37 +103,70 @@ int gpio_led_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
bool use_io = false;
|
||||
int pin = GPIO_EXT_1;
|
||||
|
||||
/* by default use GPIO_EXT_1 on FMUv1 and GPIO_SERVO_1 on FMUv2 */
|
||||
int pin = 1;
|
||||
|
||||
/* pin name to display */
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
|
||||
char *pin_name = "PX4FMU GPIO_EXT1";
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
|
||||
char pin_name[] = "AUX OUT 1";
|
||||
#endif
|
||||
|
||||
if (argc > 2) {
|
||||
if (!strcmp(argv[2], "-p")) {
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
|
||||
|
||||
if (!strcmp(argv[3], "1")) {
|
||||
use_io = false;
|
||||
pin = GPIO_EXT_1;
|
||||
pin_name = "PX4FMU GPIO_EXT1";
|
||||
|
||||
} else if (!strcmp(argv[3], "2")) {
|
||||
use_io = false;
|
||||
pin = GPIO_EXT_2;
|
||||
pin_name = "PX4FMU GPIO_EXT2";
|
||||
|
||||
} else if (!strcmp(argv[3], "a1")) {
|
||||
use_io = true;
|
||||
pin = PX4IO_P_SETUP_RELAYS_ACC1;
|
||||
pin_name = "PX4IO ACC1";
|
||||
|
||||
} else if (!strcmp(argv[3], "a2")) {
|
||||
use_io = true;
|
||||
pin = PX4IO_P_SETUP_RELAYS_ACC2;
|
||||
pin_name = "PX4IO ACC2";
|
||||
|
||||
} else if (!strcmp(argv[3], "r1")) {
|
||||
use_io = true;
|
||||
pin = PX4IO_P_SETUP_RELAYS_POWER1;
|
||||
pin_name = "PX4IO RELAY1";
|
||||
|
||||
} else if (!strcmp(argv[3], "r2")) {
|
||||
use_io = true;
|
||||
pin = PX4IO_P_SETUP_RELAYS_POWER2;
|
||||
pin_name = "PX4IO RELAY2";
|
||||
|
||||
} else {
|
||||
errx(1, "unsupported pin: %s", argv[3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
|
||||
unsigned int n = strtoul(argv[3], NULL, 10);
|
||||
|
||||
if (n >= 1 && n <= 6) {
|
||||
use_io = false;
|
||||
pin = 1 << (n - 1);
|
||||
snprintf(pin_name, sizeof(pin_name), "AUX OUT %d", n);
|
||||
|
||||
} else {
|
||||
errx(1, "unsupported pin: %s", argv[3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,21 +180,6 @@ int gpio_led_main(int argc, char *argv[])
|
||||
|
||||
} else {
|
||||
gpio_led_started = true;
|
||||
char pin_name[24];
|
||||
|
||||
if (use_io) {
|
||||
if (pin & (PX4IO_P_SETUP_RELAYS_ACC1 | PX4IO_P_SETUP_RELAYS_ACC2)) {
|
||||
sprintf(pin_name, "PX4IO ACC%i", (pin >> 3));
|
||||
|
||||
} else {
|
||||
sprintf(pin_name, "PX4IO RELAY%i", pin);
|
||||
}
|
||||
|
||||
} else {
|
||||
sprintf(pin_name, "PX4FMU GPIO_EXT%i", pin);
|
||||
|
||||
}
|
||||
|
||||
warnx("start, using pin: %s", pin_name);
|
||||
}
|
||||
|
||||
@@ -186,6 +209,7 @@ void gpio_led_start(FAR void *arg)
|
||||
|
||||
if (priv->use_io) {
|
||||
gpio_dev = PX4IO_DEVICE_PATH;
|
||||
|
||||
} else {
|
||||
gpio_dev = PX4FMU_DEVICE_PATH;
|
||||
}
|
||||
@@ -204,8 +228,10 @@ void gpio_led_start(FAR void *arg)
|
||||
/* px4fmu only, px4io doesn't support GPIO_SET_OUTPUT and will ignore */
|
||||
ioctl(priv->gpio_fd, GPIO_SET_OUTPUT, priv->pin);
|
||||
|
||||
/* subscribe to vehicle status topic */
|
||||
/* initialize vehicle status structure */
|
||||
memset(&priv->status, 0, sizeof(priv->status));
|
||||
|
||||
/* subscribe to vehicle status topic */
|
||||
priv->vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
|
||||
/* add worker to queue */
|
||||
@@ -224,38 +250,33 @@ void gpio_led_cycle(FAR void *arg)
|
||||
FAR struct gpio_led_s *priv = (FAR struct gpio_led_s *)arg;
|
||||
|
||||
/* check for status updates*/
|
||||
bool status_updated;
|
||||
orb_check(priv->vehicle_status_sub, &status_updated);
|
||||
bool updated;
|
||||
orb_check(priv->vehicle_status_sub, &updated);
|
||||
|
||||
if (status_updated)
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(vehicle_status), priv->vehicle_status_sub, &priv->status);
|
||||
|
||||
orb_check(priv->vehicle_status_sub, &status_updated);
|
||||
|
||||
if (status_updated)
|
||||
orb_copy(ORB_ID(actuator_armed), priv->actuator_armed_sub, &priv->armed);
|
||||
}
|
||||
|
||||
/* select pattern for current status */
|
||||
int pattern = 0;
|
||||
|
||||
if (priv->armed.armed) {
|
||||
if (priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE) {
|
||||
if (priv->status.arming_state == ARMING_STATE_ARMED_ERROR) {
|
||||
pattern = 0x2A; // *_*_*_ fast blink (armed, error)
|
||||
|
||||
} else if (priv->status.arming_state == ARMING_STATE_ARMED) {
|
||||
if (priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE && priv->status.failsafe_state == FAILSAFE_STATE_NORMAL) {
|
||||
pattern = 0x3f; // ****** solid (armed)
|
||||
|
||||
} else {
|
||||
pattern = 0x2A; // *_*_*_ fast blink (armed, battery warning)
|
||||
pattern = 0x3e; // *****_ slow blink (armed, battery low or failsafe)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (priv->armed.ready_to_arm) {
|
||||
pattern = 0x00; // ______ off (disarmed, preflight check)
|
||||
} else if (priv->status.arming_state == ARMING_STATE_STANDBY) {
|
||||
pattern = 0x38; // ***___ slow blink (disarmed, ready)
|
||||
|
||||
} else if (priv->armed.ready_to_arm && priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE) {
|
||||
pattern = 0x38; // ***___ slow blink (disarmed, ready)
|
||||
} else if (priv->status.arming_state == ARMING_STATE_STANDBY_ERROR) {
|
||||
pattern = 0x28; // *_*___ slow double blink (disarmed, error)
|
||||
|
||||
} else {
|
||||
pattern = 0x28; // *_*___ slow double blink (disarmed, not good to arm)
|
||||
}
|
||||
}
|
||||
|
||||
/* blink pattern */
|
||||
@@ -266,6 +287,7 @@ void gpio_led_cycle(FAR void *arg)
|
||||
|
||||
if (led_state_new) {
|
||||
ioctl(priv->gpio_fd, GPIO_SET, priv->pin);
|
||||
|
||||
} else {
|
||||
ioctl(priv->gpio_fd, GPIO_CLEAR, priv->pin);
|
||||
}
|
||||
@@ -273,8 +295,9 @@ void gpio_led_cycle(FAR void *arg)
|
||||
|
||||
priv->counter++;
|
||||
|
||||
if (priv->counter > 5)
|
||||
if (priv->counter > 5) {
|
||||
priv->counter = 0;
|
||||
}
|
||||
|
||||
/* repeat cycle at 5 Hz */
|
||||
if (gpio_led_started) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -34,46 +33,18 @@
|
||||
|
||||
/**
|
||||
* @file mavlink.c
|
||||
* MAVLink 1.0 protocol implementation.
|
||||
* Adapter functions expected by the protocol library
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
#include <string.h>
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <unistd.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <mavlink/mavlink_log.h>
|
||||
#include <commander/px4_custom_mode.h>
|
||||
|
||||
#include "waypoints.h"
|
||||
#include "orb_topics.h"
|
||||
#include "mavlink_hil.h"
|
||||
#include "util.h"
|
||||
#include "waypoints.h"
|
||||
#include "mavlink_parameters.h"
|
||||
|
||||
#include <uORB/topics/mission_result.h>
|
||||
|
||||
/* define MAVLink specific parameters */
|
||||
/**
|
||||
@@ -92,22 +63,6 @@ PARAM_DEFINE_INT32(MAV_COMP_ID, 50);
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MAV_TYPE, MAV_TYPE_FIXED_WING);
|
||||
|
||||
__EXPORT int mavlink_main(int argc, char *argv[]);
|
||||
|
||||
static int mavlink_thread_main(int argc, char *argv[]);
|
||||
|
||||
/* thread state */
|
||||
volatile bool thread_should_exit = false;
|
||||
static volatile bool thread_running = false;
|
||||
static int mavlink_task;
|
||||
|
||||
/* pthreads */
|
||||
static pthread_t receive_thread;
|
||||
static pthread_t uorb_receive_thread;
|
||||
|
||||
/* terminate MAVLink on user request - disabled by default */
|
||||
static bool mavlink_link_termination_allowed = false;
|
||||
|
||||
mavlink_system_t mavlink_system = {
|
||||
100,
|
||||
50,
|
||||
@@ -117,365 +72,6 @@ mavlink_system_t mavlink_system = {
|
||||
0
|
||||
}; // System ID, 1-255, Component/Subsystem ID, 1-255
|
||||
|
||||
/* XXX not widely used */
|
||||
uint8_t chan = MAVLINK_COMM_0;
|
||||
|
||||
/* XXX probably should be in a header... */
|
||||
extern pthread_t receive_start(int uart);
|
||||
|
||||
/* Allocate storage space for waypoints */
|
||||
static mavlink_wpm_storage wpm_s;
|
||||
mavlink_wpm_storage *wpm = &wpm_s;
|
||||
|
||||
bool mavlink_hil_enabled = false;
|
||||
|
||||
/* protocol interface */
|
||||
static int uart;
|
||||
static int baudrate;
|
||||
bool gcs_link = true;
|
||||
|
||||
/* interface mode */
|
||||
static enum {
|
||||
MAVLINK_INTERFACE_MODE_OFFBOARD,
|
||||
MAVLINK_INTERFACE_MODE_ONBOARD
|
||||
} mavlink_link_mode = MAVLINK_INTERFACE_MODE_OFFBOARD;
|
||||
|
||||
static struct mavlink_logbuffer lb;
|
||||
|
||||
static void mavlink_update_system(void);
|
||||
static int mavlink_open_uart(int baudrate, const char *uart_name, struct termios *uart_config_original, bool *is_usb);
|
||||
static void usage(void);
|
||||
int set_mavlink_interval_limit(struct mavlink_subscriptions *subs, int mavlink_msg_id, int min_interval);
|
||||
|
||||
|
||||
|
||||
int
|
||||
set_hil_on_off(bool hil_enabled)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
/* Enable HIL */
|
||||
if (hil_enabled && !mavlink_hil_enabled) {
|
||||
|
||||
mavlink_hil_enabled = true;
|
||||
|
||||
/* ramp up some HIL-related subscriptions */
|
||||
unsigned hil_rate_interval;
|
||||
|
||||
if (baudrate < 19200) {
|
||||
/* 10 Hz */
|
||||
hil_rate_interval = 100;
|
||||
|
||||
} else if (baudrate < 38400) {
|
||||
/* 10 Hz */
|
||||
hil_rate_interval = 100;
|
||||
|
||||
} else if (baudrate < 115200) {
|
||||
/* 20 Hz */
|
||||
hil_rate_interval = 50;
|
||||
|
||||
} else {
|
||||
/* 200 Hz */
|
||||
hil_rate_interval = 5;
|
||||
}
|
||||
|
||||
orb_set_interval(mavlink_subs.spa_sub, hil_rate_interval);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, hil_rate_interval);
|
||||
}
|
||||
|
||||
if (!hil_enabled && mavlink_hil_enabled) {
|
||||
mavlink_hil_enabled = false;
|
||||
orb_set_interval(mavlink_subs.spa_sub, 200);
|
||||
|
||||
} else {
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
get_mavlink_mode_and_state(uint8_t *mavlink_state, uint8_t *mavlink_base_mode, uint32_t *mavlink_custom_mode)
|
||||
{
|
||||
/* reset MAVLink mode bitfield */
|
||||
*mavlink_base_mode = 0;
|
||||
*mavlink_custom_mode = 0;
|
||||
|
||||
/**
|
||||
* Set mode flags
|
||||
**/
|
||||
|
||||
/* HIL */
|
||||
if (v_status.hil_state == HIL_STATE_ON) {
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_HIL_ENABLED;
|
||||
}
|
||||
|
||||
/* arming state */
|
||||
if (armed.armed) {
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_SAFETY_ARMED;
|
||||
}
|
||||
|
||||
/* main state */
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_CUSTOM_MODE_ENABLED;
|
||||
union px4_custom_mode custom_mode;
|
||||
custom_mode.data = 0;
|
||||
if (pos_sp_triplet.nav_state == NAV_STATE_NONE) {
|
||||
/* use main state when navigator is not active */
|
||||
if (v_status.main_state == MAIN_STATE_MANUAL) {
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED | (v_status.is_rotary_wing ? MAV_MODE_FLAG_STABILIZE_ENABLED : 0);
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_MANUAL;
|
||||
} else if (v_status.main_state == MAIN_STATE_SEATBELT) {
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED | MAV_MODE_FLAG_STABILIZE_ENABLED;
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_SEATBELT;
|
||||
} else if (v_status.main_state == MAIN_STATE_EASY) {
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED | MAV_MODE_FLAG_STABILIZE_ENABLED | MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_EASY;
|
||||
} else if (v_status.main_state == MAIN_STATE_AUTO) {
|
||||
/* this must not happen */
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_AUTO_ENABLED | MAV_MODE_FLAG_STABILIZE_ENABLED | MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_AUTO;
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_READY;
|
||||
} else if (v_status.main_state == MAIN_STATE_OFFBOARD) {
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_OFFBOARD;
|
||||
}
|
||||
} else {
|
||||
/* use navigation state when navigator is active */
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_AUTO_ENABLED | MAV_MODE_FLAG_STABILIZE_ENABLED | MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
custom_mode.main_mode = PX4_CUSTOM_MAIN_MODE_AUTO;
|
||||
if (pos_sp_triplet.nav_state == NAV_STATE_READY) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_READY;
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_LOITER) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_LOITER;
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_MISSION) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_MISSION;
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_RTL) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_RTL;
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_LAND) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_LAND;
|
||||
}
|
||||
}
|
||||
*mavlink_custom_mode = custom_mode.data;
|
||||
|
||||
/**
|
||||
* Set mavlink state
|
||||
**/
|
||||
|
||||
/* set calibration state */
|
||||
if (v_status.arming_state == ARMING_STATE_INIT
|
||||
|| v_status.arming_state == ARMING_STATE_IN_AIR_RESTORE
|
||||
|| v_status.arming_state == ARMING_STATE_STANDBY_ERROR) { // TODO review
|
||||
*mavlink_state = MAV_STATE_UNINIT;
|
||||
} else if (v_status.arming_state == ARMING_STATE_ARMED) {
|
||||
*mavlink_state = MAV_STATE_ACTIVE;
|
||||
} else if (v_status.arming_state == ARMING_STATE_ARMED_ERROR) {
|
||||
*mavlink_state = MAV_STATE_CRITICAL;
|
||||
} else if (v_status.arming_state == ARMING_STATE_STANDBY) {
|
||||
*mavlink_state = MAV_STATE_STANDBY;
|
||||
} else if (v_status.arming_state == ARMING_STATE_REBOOT) {
|
||||
*mavlink_state = MAV_STATE_POWEROFF;
|
||||
} else {
|
||||
warnx("Unknown mavlink state");
|
||||
*mavlink_state = MAV_STATE_CRITICAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int set_mavlink_interval_limit(struct mavlink_subscriptions *subs, int mavlink_msg_id, int min_interval)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
switch (mavlink_msg_id) {
|
||||
case MAVLINK_MSG_ID_SCALED_IMU:
|
||||
/* sensor sub triggers scaled IMU */
|
||||
orb_set_interval(subs->sensor_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_HIGHRES_IMU:
|
||||
/* sensor sub triggers highres IMU */
|
||||
orb_set_interval(subs->sensor_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_RAW_IMU:
|
||||
/* sensor sub triggers RAW IMU */
|
||||
orb_set_interval(subs->sensor_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_ATTITUDE:
|
||||
/* attitude sub triggers attitude */
|
||||
orb_set_interval(subs->att_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_SERVO_OUTPUT_RAW:
|
||||
/* actuator_outputs triggers this message */
|
||||
orb_set_interval(subs->act_0_sub, min_interval);
|
||||
orb_set_interval(subs->act_1_sub, min_interval);
|
||||
orb_set_interval(subs->act_2_sub, min_interval);
|
||||
orb_set_interval(subs->act_3_sub, min_interval);
|
||||
orb_set_interval(subs->actuators_sub, min_interval);
|
||||
orb_set_interval(subs->actuators_effective_sub, min_interval);
|
||||
orb_set_interval(subs->spa_sub, min_interval);
|
||||
orb_set_interval(mavlink_subs.rates_setpoint_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_MANUAL_CONTROL:
|
||||
/* manual_control_setpoint triggers this message */
|
||||
orb_set_interval(subs->man_control_sp_sub, min_interval);
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_NAMED_VALUE_FLOAT:
|
||||
orb_set_interval(subs->debug_key_value, min_interval);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* not found */
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* MAVLink text message logger
|
||||
****************************************************************************/
|
||||
|
||||
static int mavlink_dev_ioctl(struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
static const struct file_operations mavlink_fops = {
|
||||
.ioctl = mavlink_dev_ioctl
|
||||
};
|
||||
|
||||
static int
|
||||
mavlink_dev_ioctl(struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
static unsigned int total_counter = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case (int)MAVLINK_IOC_SEND_TEXT_INFO:
|
||||
case (int)MAVLINK_IOC_SEND_TEXT_CRITICAL:
|
||||
case (int)MAVLINK_IOC_SEND_TEXT_EMERGENCY: {
|
||||
const char *txt = (const char *)arg;
|
||||
struct mavlink_logmessage msg;
|
||||
strncpy(msg.text, txt, sizeof(msg.text));
|
||||
mavlink_logbuffer_write(&lb, &msg);
|
||||
total_counter++;
|
||||
return OK;
|
||||
}
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAVLINK_OFFBOARD_CONTROL_FLAG_ARMED 0x10
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int mavlink_open_uart(int baud, const char *uart_name, struct termios *uart_config_original, bool *is_usb)
|
||||
{
|
||||
/* process baud rate */
|
||||
int speed;
|
||||
|
||||
switch (baud) {
|
||||
case 0: speed = B0; break;
|
||||
|
||||
case 50: speed = B50; break;
|
||||
|
||||
case 75: speed = B75; break;
|
||||
|
||||
case 110: speed = B110; break;
|
||||
|
||||
case 134: speed = B134; break;
|
||||
|
||||
case 150: speed = B150; break;
|
||||
|
||||
case 200: speed = B200; break;
|
||||
|
||||
case 300: speed = B300; break;
|
||||
|
||||
case 600: speed = B600; break;
|
||||
|
||||
case 1200: speed = B1200; break;
|
||||
|
||||
case 1800: speed = B1800; break;
|
||||
|
||||
case 2400: speed = B2400; break;
|
||||
|
||||
case 4800: speed = B4800; break;
|
||||
|
||||
case 9600: speed = B9600; break;
|
||||
|
||||
case 19200: speed = B19200; break;
|
||||
|
||||
case 38400: speed = B38400; break;
|
||||
|
||||
case 57600: speed = B57600; break;
|
||||
|
||||
case 115200: speed = B115200; break;
|
||||
|
||||
case 230400: speed = B230400; break;
|
||||
|
||||
case 460800: speed = B460800; break;
|
||||
|
||||
case 921600: speed = B921600; break;
|
||||
|
||||
default:
|
||||
warnx("ERROR: Unsupported baudrate: %d\n\tsupported examples:\n\n\t9600\n19200\n38400\n57600\n115200\n230400\n460800\n921600\n\n", baud);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* open uart */
|
||||
warnx("UART is %s, baudrate is %d\n", uart_name, baud);
|
||||
uart = open(uart_name, O_RDWR | O_NOCTTY);
|
||||
|
||||
/* Try to set baud rate */
|
||||
struct termios uart_config;
|
||||
int termios_state;
|
||||
*is_usb = false;
|
||||
|
||||
/* Back up the original uart configuration to restore it after exit */
|
||||
if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) {
|
||||
warnx("ERROR get termios config %s: %d\n", uart_name, termios_state);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill the struct for the new configuration */
|
||||
tcgetattr(uart, &uart_config);
|
||||
|
||||
/* Clear ONLCR flag (which appends a CR for every LF) */
|
||||
uart_config.c_oflag &= ~ONLCR;
|
||||
|
||||
/* USB serial is indicated by /dev/ttyACM0*/
|
||||
if (strcmp(uart_name, "/dev/ttyACM0") != OK && strcmp(uart_name, "/dev/ttyACM1") != OK) {
|
||||
|
||||
/* Set baud rate */
|
||||
if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) {
|
||||
warnx("ERROR setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) {
|
||||
warnx("ERROR setting baudrate / termios config for %s (tcsetattr)\n", uart_name);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uart;
|
||||
}
|
||||
|
||||
void
|
||||
mavlink_send_uart_bytes(mavlink_channel_t channel, const uint8_t *ch, int length)
|
||||
{
|
||||
write(uart, ch, (size_t)(sizeof(uint8_t) * length));
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to give access to the channel status for each channel
|
||||
*/
|
||||
@@ -493,362 +89,3 @@ extern mavlink_message_t *mavlink_get_channel_buffer(uint8_t channel)
|
||||
static mavlink_message_t m_mavlink_buffer[MAVLINK_COMM_NUM_BUFFERS];
|
||||
return &m_mavlink_buffer[channel];
|
||||
}
|
||||
|
||||
void mavlink_update_system(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
static param_t param_system_id;
|
||||
static param_t param_component_id;
|
||||
static param_t param_system_type;
|
||||
|
||||
if (!initialized) {
|
||||
param_system_id = param_find("MAV_SYS_ID");
|
||||
param_component_id = param_find("MAV_COMP_ID");
|
||||
param_system_type = param_find("MAV_TYPE");
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/* update system and component id */
|
||||
int32_t system_id;
|
||||
param_get(param_system_id, &system_id);
|
||||
|
||||
if (system_id > 0 && system_id < 255) {
|
||||
mavlink_system.sysid = system_id;
|
||||
}
|
||||
|
||||
int32_t component_id;
|
||||
param_get(param_component_id, &component_id);
|
||||
|
||||
if (component_id > 0 && component_id < 255) {
|
||||
mavlink_system.compid = component_id;
|
||||
}
|
||||
|
||||
int32_t system_type;
|
||||
param_get(param_system_type, &system_type);
|
||||
|
||||
if (system_type >= 0 && system_type < MAV_TYPE_ENUM_END) {
|
||||
mavlink_system.type = system_type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MAVLink Protocol main function.
|
||||
*/
|
||||
int mavlink_thread_main(int argc, char *argv[])
|
||||
{
|
||||
/* initialize mavlink text message buffering */
|
||||
mavlink_logbuffer_init(&lb, 10);
|
||||
|
||||
int ch;
|
||||
char *device_name = "/dev/ttyS1";
|
||||
baudrate = 57600;
|
||||
|
||||
/* work around some stupidity in task_create's argv handling */
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:d:eo")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
baudrate = strtoul(optarg, NULL, 10);
|
||||
|
||||
if (baudrate < 9600 || baudrate > 921600)
|
||||
errx(1, "invalid baud rate '%s'", optarg);
|
||||
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
device_name = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
mavlink_link_termination_allowed = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
mavlink_link_mode = MAVLINK_INTERFACE_MODE_ONBOARD;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct termios uart_config_original;
|
||||
|
||||
bool usb_uart;
|
||||
|
||||
/* print welcome text */
|
||||
warnx("MAVLink v1.0 serial interface starting...");
|
||||
|
||||
/* inform about mode */
|
||||
warnx((mavlink_link_mode == MAVLINK_INTERFACE_MODE_ONBOARD) ? "ONBOARD MODE" : "DOWNLINK MODE");
|
||||
|
||||
/* Flush stdout in case MAVLink is about to take it over */
|
||||
fflush(stdout);
|
||||
|
||||
/* default values for arguments */
|
||||
uart = mavlink_open_uart(baudrate, device_name, &uart_config_original, &usb_uart);
|
||||
|
||||
if (uart < 0)
|
||||
err(1, "could not open %s", device_name);
|
||||
|
||||
/* create the device node that's used for sending text log messages, etc. */
|
||||
register_driver(MAVLINK_LOG_DEVICE, &mavlink_fops, 0666, NULL);
|
||||
|
||||
/* Initialize system properties */
|
||||
mavlink_update_system();
|
||||
|
||||
/* start the MAVLink receiver */
|
||||
receive_thread = receive_start(uart);
|
||||
|
||||
/* start the ORB receiver */
|
||||
uorb_receive_thread = uorb_receive_start();
|
||||
|
||||
/* initialize waypoint manager */
|
||||
mavlink_wpm_init(wpm);
|
||||
|
||||
/* all subscriptions are now active, set up initial guess about rate limits */
|
||||
if (baudrate >= 230400) {
|
||||
/* 200 Hz / 5 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_HIGHRES_IMU, 20);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_RAW_IMU, 20);
|
||||
/* 50 Hz / 20 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_ATTITUDE, 30);
|
||||
/* 20 Hz / 50 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, 10);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, 50);
|
||||
/* 10 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_GPS_RAW_INT, 100);
|
||||
/* 10 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_MANUAL_CONTROL, 100);
|
||||
|
||||
} else if (baudrate >= 115200) {
|
||||
/* 20 Hz / 50 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_HIGHRES_IMU, 50);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_RAW_IMU, 50);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_ATTITUDE, 50);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, 50);
|
||||
/* 5 Hz / 200 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, 200);
|
||||
/* 5 Hz / 200 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_GPS_RAW_INT, 200);
|
||||
/* 2 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_MANUAL_CONTROL, 500);
|
||||
|
||||
} else if (baudrate >= 57600) {
|
||||
/* 10 Hz / 100 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_RAW_IMU, 300);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_HIGHRES_IMU, 300);
|
||||
/* 10 Hz / 100 ms ATTITUDE */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_ATTITUDE, 200);
|
||||
/* 5 Hz / 200 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, 200);
|
||||
/* 5 Hz / 200 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, 500);
|
||||
/* 2 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_MANUAL_CONTROL, 500);
|
||||
/* 2 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_GPS_RAW_INT, 500);
|
||||
|
||||
} else {
|
||||
/* very low baud rate, limit to 1 Hz / 1000 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_RAW_IMU, 1000);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_ATTITUDE, 1000);
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_HIGHRES_IMU, 1000);
|
||||
/* 1 Hz / 1000 ms */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_NAMED_VALUE_FLOAT, 1000);
|
||||
/* 0.5 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, 2000);
|
||||
/* 0.1 Hz */
|
||||
set_mavlink_interval_limit(&mavlink_subs, MAVLINK_MSG_ID_MANUAL_CONTROL, 10000);
|
||||
}
|
||||
|
||||
int mission_result_sub = orb_subscribe(ORB_ID(mission_result));
|
||||
struct mission_result_s mission_result;
|
||||
memset(&mission_result, 0, sizeof(mission_result));
|
||||
|
||||
thread_running = true;
|
||||
|
||||
/* arm counter to go off immediately */
|
||||
unsigned lowspeed_counter = 10;
|
||||
|
||||
while (!thread_should_exit) {
|
||||
|
||||
/* 1 Hz */
|
||||
if (lowspeed_counter == 10) {
|
||||
mavlink_update_system();
|
||||
|
||||
/* translate the current system state to mavlink state and mode */
|
||||
uint8_t mavlink_state = 0;
|
||||
uint8_t mavlink_base_mode = 0;
|
||||
uint32_t mavlink_custom_mode = 0;
|
||||
get_mavlink_mode_and_state(&mavlink_state, &mavlink_base_mode, &mavlink_custom_mode);
|
||||
|
||||
/* send heartbeat */
|
||||
mavlink_msg_heartbeat_send(chan, mavlink_system.type, MAV_AUTOPILOT_PX4, mavlink_base_mode, mavlink_custom_mode, mavlink_state);
|
||||
|
||||
/* switch HIL mode if required */
|
||||
if (v_status.hil_state == HIL_STATE_ON)
|
||||
set_hil_on_off(true);
|
||||
else if (v_status.hil_state == HIL_STATE_OFF)
|
||||
set_hil_on_off(false);
|
||||
|
||||
/* send status (values already copied in the section above) */
|
||||
mavlink_msg_sys_status_send(chan,
|
||||
v_status.onboard_control_sensors_present,
|
||||
v_status.onboard_control_sensors_enabled,
|
||||
v_status.onboard_control_sensors_health,
|
||||
v_status.load * 1000.0f,
|
||||
v_status.battery_voltage * 1000.0f,
|
||||
v_status.battery_current * 100.0f,
|
||||
v_status.battery_remaining * 100.0f,
|
||||
v_status.drop_rate_comm,
|
||||
v_status.errors_comm,
|
||||
v_status.errors_count1,
|
||||
v_status.errors_count2,
|
||||
v_status.errors_count3,
|
||||
v_status.errors_count4);
|
||||
lowspeed_counter = 0;
|
||||
}
|
||||
|
||||
lowspeed_counter++;
|
||||
|
||||
bool updated;
|
||||
orb_check(mission_result_sub, &updated);
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(mission_result), mission_result_sub, &mission_result);
|
||||
|
||||
if (mission_result.mission_reached) {
|
||||
mavlink_wpm_send_waypoint_reached((uint16_t)mission_result.mission_index);
|
||||
}
|
||||
}
|
||||
|
||||
mavlink_waypoint_eventloop(hrt_absolute_time());
|
||||
|
||||
/* sleep quarter the time */
|
||||
usleep(25000);
|
||||
|
||||
/* check if waypoint has been reached against the last positions */
|
||||
mavlink_waypoint_eventloop(hrt_absolute_time());
|
||||
|
||||
/* sleep quarter the time */
|
||||
usleep(25000);
|
||||
|
||||
/* send parameters at 20 Hz (if queued for sending) */
|
||||
mavlink_pm_queued_send();
|
||||
mavlink_waypoint_eventloop(hrt_absolute_time());
|
||||
|
||||
/* sleep quarter the time */
|
||||
usleep(25000);
|
||||
|
||||
mavlink_waypoint_eventloop(hrt_absolute_time());
|
||||
|
||||
if (baudrate > 57600) {
|
||||
mavlink_pm_queued_send();
|
||||
}
|
||||
|
||||
/* sleep 10 ms */
|
||||
usleep(10000);
|
||||
|
||||
/* send one string at 10 Hz */
|
||||
if (!mavlink_logbuffer_is_empty(&lb)) {
|
||||
struct mavlink_logmessage msg;
|
||||
int lb_ret = mavlink_logbuffer_read(&lb, &msg);
|
||||
|
||||
if (lb_ret == OK) {
|
||||
mavlink_missionlib_send_gcs_string(msg.text);
|
||||
}
|
||||
}
|
||||
|
||||
/* sleep 15 ms */
|
||||
usleep(15000);
|
||||
}
|
||||
|
||||
/* wait for threads to complete */
|
||||
pthread_join(receive_thread, NULL);
|
||||
pthread_join(uorb_receive_thread, NULL);
|
||||
|
||||
/* Reset the UART flags to original state */
|
||||
tcsetattr(uart, TCSANOW, &uart_config_original);
|
||||
|
||||
/* destroy log buffer */
|
||||
//mavlink_logbuffer_destroy(&lb);
|
||||
|
||||
thread_running = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: mavlink start [-d <devicename>] [-b <baud rate>]\n"
|
||||
" mavlink stop\n"
|
||||
" mavlink status\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int mavlink_main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argc < 2) {
|
||||
warnx("missing command");
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
/* this is not an error */
|
||||
if (thread_running)
|
||||
errx(0, "mavlink already running");
|
||||
|
||||
thread_should_exit = false;
|
||||
mavlink_task = task_spawn_cmd("mavlink",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
2048,
|
||||
mavlink_thread_main,
|
||||
(const char **)argv);
|
||||
|
||||
while (!thread_running) {
|
||||
usleep(200);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
|
||||
/* this is not an error */
|
||||
if (!thread_running)
|
||||
errx(0, "mavlink already stopped");
|
||||
|
||||
thread_should_exit = true;
|
||||
|
||||
while (thread_running) {
|
||||
usleep(200000);
|
||||
warnx(".");
|
||||
}
|
||||
|
||||
warnx("terminated.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
errx(0, "running");
|
||||
|
||||
} else {
|
||||
errx(1, "not running");
|
||||
}
|
||||
}
|
||||
|
||||
warnx("unrecognized command");
|
||||
usage();
|
||||
/* not getting here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -43,6 +42,8 @@
|
||||
#ifndef MAVLINK_BRIDGE_HEADER_H
|
||||
#define MAVLINK_BRIDGE_HEADER_H
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define MAVLINK_USE_CONVENIENCE_FUNCTIONS
|
||||
|
||||
/* use efficient approach, see mavlink_helpers.h */
|
||||
@@ -73,11 +74,13 @@ extern mavlink_system_t mavlink_system;
|
||||
* @param chan MAVLink channel to use, usually MAVLINK_COMM_0 = UART0
|
||||
* @param ch Character to send
|
||||
*/
|
||||
extern void mavlink_send_uart_bytes(mavlink_channel_t chan, const uint8_t *ch, int length);
|
||||
void mavlink_send_uart_bytes(mavlink_channel_t chan, const uint8_t *ch, int length);
|
||||
|
||||
extern mavlink_status_t *mavlink_get_channel_status(uint8_t chan);
|
||||
extern mavlink_message_t *mavlink_get_channel_buffer(uint8_t chan);
|
||||
|
||||
#include <v1.0/common/mavlink.h>
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* MAVLINK_BRIDGE_HEADER_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,325 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_main.h
|
||||
* MAVLink 1.0 protocol interface definition.
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <pthread.h>
|
||||
#include <mavlink/mavlink_log.h>
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/mission.h>
|
||||
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include "mavlink_orb_subscription.h"
|
||||
#include "mavlink_stream.h"
|
||||
#include "mavlink_messages.h"
|
||||
|
||||
// FIXME XXX - TO BE MOVED TO XML
|
||||
enum MAVLINK_WPM_STATES {
|
||||
MAVLINK_WPM_STATE_IDLE = 0,
|
||||
MAVLINK_WPM_STATE_SENDLIST,
|
||||
MAVLINK_WPM_STATE_SENDLIST_SENDWPS,
|
||||
MAVLINK_WPM_STATE_GETLIST,
|
||||
MAVLINK_WPM_STATE_GETLIST_GETWPS,
|
||||
MAVLINK_WPM_STATE_GETLIST_GOTALL,
|
||||
MAVLINK_WPM_STATE_ENUM_END
|
||||
};
|
||||
|
||||
enum MAVLINK_WPM_CODES {
|
||||
MAVLINK_WPM_CODE_OK = 0,
|
||||
MAVLINK_WPM_CODE_ERR_WAYPOINT_ACTION_NOT_SUPPORTED,
|
||||
MAVLINK_WPM_CODE_ERR_WAYPOINT_FRAME_NOT_SUPPORTED,
|
||||
MAVLINK_WPM_CODE_ERR_WAYPOINT_OUT_OF_BOUNDS,
|
||||
MAVLINK_WPM_CODE_ERR_WAYPOINT_MAX_NUMBER_EXCEEDED,
|
||||
MAVLINK_WPM_CODE_ENUM_END
|
||||
};
|
||||
|
||||
|
||||
#define MAVLINK_WPM_MAX_WP_COUNT 255
|
||||
#define MAVLINK_WPM_PROTOCOL_TIMEOUT_DEFAULT 5000000 ///< Protocol communication timeout in useconds
|
||||
#define MAVLINK_WPM_SETPOINT_DELAY_DEFAULT 1000000 ///< When to send a new setpoint
|
||||
#define MAVLINK_WPM_PROTOCOL_DELAY_DEFAULT 40000
|
||||
|
||||
|
||||
struct mavlink_wpm_storage {
|
||||
uint16_t size;
|
||||
uint16_t max_size;
|
||||
enum MAVLINK_WPM_STATES current_state;
|
||||
int16_t current_wp_id; ///< Waypoint in current transmission
|
||||
uint16_t current_count;
|
||||
uint8_t current_partner_sysid;
|
||||
uint8_t current_partner_compid;
|
||||
uint64_t timestamp_lastaction;
|
||||
uint64_t timestamp_last_send_setpoint;
|
||||
uint32_t timeout;
|
||||
int current_dataman_id;
|
||||
};
|
||||
|
||||
|
||||
class Mavlink
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Mavlink();
|
||||
|
||||
/**
|
||||
* Destructor, also kills the mavlinks task.
|
||||
*/
|
||||
~Mavlink();
|
||||
|
||||
/**
|
||||
* Start the mavlink task.
|
||||
*
|
||||
* @return OK on success.
|
||||
*/
|
||||
static int start(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Display the mavlink status.
|
||||
*/
|
||||
void status();
|
||||
|
||||
static int stream(int argc, char *argv[]);
|
||||
|
||||
static int instance_count();
|
||||
|
||||
static Mavlink *new_instance();
|
||||
|
||||
static Mavlink *get_instance(unsigned instance);
|
||||
|
||||
static Mavlink *get_instance_for_device(const char *device_name);
|
||||
|
||||
static int destroy_all_instances();
|
||||
|
||||
static bool instance_exists(const char *device_name, Mavlink *self);
|
||||
|
||||
static int get_uart_fd(unsigned index);
|
||||
|
||||
int get_uart_fd();
|
||||
|
||||
const char *_device_name;
|
||||
|
||||
enum MAVLINK_MODE {
|
||||
MAVLINK_MODE_NORMAL = 0,
|
||||
MAVLINK_MODE_CUSTOM,
|
||||
MAVLINK_MODE_CAMERA
|
||||
};
|
||||
|
||||
void set_mode(enum MAVLINK_MODE);
|
||||
enum MAVLINK_MODE get_mode() { return _mode; }
|
||||
|
||||
bool get_hil_enabled() { return _hil_enabled; };
|
||||
|
||||
bool get_flow_control_enabled() { return _flow_control_enabled; }
|
||||
|
||||
/**
|
||||
* Handle waypoint related messages.
|
||||
*/
|
||||
void mavlink_wpm_message_handler(const mavlink_message_t *msg);
|
||||
|
||||
static int start_helper(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Handle parameter related messages.
|
||||
*/
|
||||
void mavlink_pm_message_handler(const mavlink_channel_t chan, const mavlink_message_t *msg);
|
||||
|
||||
void get_mavlink_mode_and_state(struct vehicle_status_s *status, struct position_setpoint_triplet_s *pos_sp_triplet, uint8_t *mavlink_state, uint8_t *mavlink_base_mode, uint32_t *mavlink_custom_mode);
|
||||
|
||||
/**
|
||||
* Enable / disable Hardware in the Loop simulation mode.
|
||||
*
|
||||
* @param hil_enabled The new HIL enable/disable state.
|
||||
* @return OK if the HIL state changed, ERROR if the
|
||||
* requested change could not be made or was
|
||||
* redundant.
|
||||
*/
|
||||
int set_hil_enabled(bool hil_enabled);
|
||||
|
||||
MavlinkOrbSubscription *add_orb_subscription(const orb_id_t topic);
|
||||
|
||||
int get_instance_id();
|
||||
|
||||
/**
|
||||
* Enable / disable hardware flow control.
|
||||
*
|
||||
* @param enabled True if hardware flow control should be enabled
|
||||
*/
|
||||
int enable_flow_control(bool enabled);
|
||||
|
||||
mavlink_channel_t get_channel();
|
||||
|
||||
bool _task_should_exit; /**< if true, mavlink task should exit */
|
||||
|
||||
protected:
|
||||
Mavlink *next;
|
||||
|
||||
private:
|
||||
int _instance_id;
|
||||
|
||||
int _mavlink_fd;
|
||||
bool _task_running;
|
||||
|
||||
perf_counter_t _loop_perf; /**< loop performance counter */
|
||||
|
||||
/* states */
|
||||
bool _hil_enabled; /**< Hardware In the Loop mode */
|
||||
bool _is_usb_uart; /**< Port is USB */
|
||||
|
||||
unsigned _main_loop_delay; /**< mainloop delay, depends on data rate */
|
||||
|
||||
MavlinkOrbSubscription *_subscriptions;
|
||||
MavlinkStream *_streams;
|
||||
|
||||
orb_advert_t _mission_pub;
|
||||
struct mission_s mission;
|
||||
uint8_t missionlib_msg_buf[MAVLINK_MAX_PACKET_LEN];
|
||||
MAVLINK_MODE _mode;
|
||||
|
||||
uint8_t _mavlink_wpm_comp_id;
|
||||
mavlink_channel_t _channel;
|
||||
|
||||
struct mavlink_logbuffer _logbuffer;
|
||||
unsigned int _total_counter;
|
||||
|
||||
pthread_t _receive_thread;
|
||||
|
||||
/* Allocate storage space for waypoints */
|
||||
mavlink_wpm_storage _wpm_s;
|
||||
mavlink_wpm_storage *_wpm;
|
||||
|
||||
bool _verbose;
|
||||
int _uart_fd;
|
||||
int _baudrate;
|
||||
int _datarate;
|
||||
|
||||
/**
|
||||
* If the queue index is not at 0, the queue sending
|
||||
* logic will send parameters from the current index
|
||||
* to len - 1, the end of the param list.
|
||||
*/
|
||||
unsigned int _mavlink_param_queue_index;
|
||||
|
||||
bool mavlink_link_termination_allowed;
|
||||
|
||||
char *_subscribe_to_stream;
|
||||
float _subscribe_to_stream_rate;
|
||||
|
||||
bool _flow_control_enabled;
|
||||
|
||||
/**
|
||||
* Send one parameter.
|
||||
*
|
||||
* @param param The parameter id to send.
|
||||
* @return zero on success, nonzero on failure.
|
||||
*/
|
||||
int mavlink_pm_send_param(param_t param);
|
||||
|
||||
/**
|
||||
* Send one parameter identified by index.
|
||||
*
|
||||
* @param index The index of the parameter to send.
|
||||
* @return zero on success, nonzero else.
|
||||
*/
|
||||
int mavlink_pm_send_param_for_index(uint16_t index);
|
||||
|
||||
/**
|
||||
* Send one parameter identified by name.
|
||||
*
|
||||
* @param name The index of the parameter to send.
|
||||
* @return zero on success, nonzero else.
|
||||
*/
|
||||
int mavlink_pm_send_param_for_name(const char *name);
|
||||
|
||||
/**
|
||||
* Send a queue of parameters, one parameter per function call.
|
||||
*
|
||||
* @return zero on success, nonzero on failure
|
||||
*/
|
||||
int mavlink_pm_queued_send(void);
|
||||
|
||||
/**
|
||||
* Start sending the parameter queue.
|
||||
*
|
||||
* This function will not directly send parameters, but instead
|
||||
* activate the sending of one parameter on each call of
|
||||
* mavlink_pm_queued_send().
|
||||
* @see mavlink_pm_queued_send()
|
||||
*/
|
||||
void mavlink_pm_start_queued_send();
|
||||
|
||||
void mavlink_update_system();
|
||||
|
||||
void mavlink_waypoint_eventloop(uint64_t now);
|
||||
void mavlink_wpm_send_waypoint_reached(uint16_t seq);
|
||||
void mavlink_wpm_send_waypoint_request(uint8_t sysid, uint8_t compid, uint16_t seq);
|
||||
void mavlink_wpm_send_waypoint(uint8_t sysid, uint8_t compid, uint16_t seq);
|
||||
void mavlink_wpm_send_waypoint_count(uint8_t sysid, uint8_t compid, uint16_t count);
|
||||
void mavlink_wpm_send_waypoint_current(uint16_t seq);
|
||||
void mavlink_wpm_send_waypoint_ack(uint8_t sysid, uint8_t compid, uint8_t type);
|
||||
void mavlink_wpm_init(mavlink_wpm_storage *state);
|
||||
int map_mission_item_to_mavlink_mission_item(const struct mission_item_s *mission_item, mavlink_mission_item_t *mavlink_mission_item);
|
||||
int map_mavlink_mission_item_to_mission_item(const mavlink_mission_item_t *mavlink_mission_item, struct mission_item_s *mission_item);
|
||||
void publish_mission();
|
||||
|
||||
void mavlink_missionlib_send_message(mavlink_message_t *msg);
|
||||
int mavlink_missionlib_send_gcs_string(const char *string);
|
||||
|
||||
int mavlink_open_uart(int baudrate, const char *uart_name, struct termios *uart_config_original, bool *is_usb);
|
||||
|
||||
int configure_stream(const char *stream_name, const float rate);
|
||||
void configure_stream_threadsafe(const char *stream_name, const float rate);
|
||||
|
||||
static int mavlink_dev_ioctl(struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* Main mavlink task.
|
||||
*/
|
||||
int task_main(int argc, char *argv[]);
|
||||
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
+9
-12
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -32,20 +32,17 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file UOrbSubscription.cpp
|
||||
* @file mavlink_messages.h
|
||||
* MAVLink 1.0 message formatters definition.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include "UOrbSubscription.hpp"
|
||||
#ifndef MAVLINK_MESSAGES_H_
|
||||
#define MAVLINK_MESSAGES_H_
|
||||
|
||||
namespace control
|
||||
{
|
||||
#include "mavlink_stream.h"
|
||||
|
||||
bool __EXPORT UOrbSubscriptionBase::updated()
|
||||
{
|
||||
bool isUpdated = false;
|
||||
orb_check(_handle, &isUpdated);
|
||||
return isUpdated;
|
||||
}
|
||||
extern MavlinkStream *streams_list[];
|
||||
|
||||
} // namespace control
|
||||
#endif /* MAVLINK_MESSAGES_H_ */
|
||||
@@ -0,0 +1,113 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_orb_subscription.cpp
|
||||
* uORB subscription implementation.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mavlink_orb_subscription.h"
|
||||
|
||||
MavlinkOrbSubscription::MavlinkOrbSubscription(const orb_id_t topic) :
|
||||
_fd(orb_subscribe(_topic)),
|
||||
_published(false),
|
||||
_topic(topic),
|
||||
_last_check(0),
|
||||
next(nullptr)
|
||||
{
|
||||
_data = malloc(topic->o_size);
|
||||
memset(_data, 0, topic->o_size);
|
||||
}
|
||||
|
||||
MavlinkOrbSubscription::~MavlinkOrbSubscription()
|
||||
{
|
||||
close(_fd);
|
||||
free(_data);
|
||||
}
|
||||
|
||||
const orb_id_t
|
||||
MavlinkOrbSubscription::get_topic()
|
||||
{
|
||||
return _topic;
|
||||
}
|
||||
|
||||
void *
|
||||
MavlinkOrbSubscription::get_data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
bool
|
||||
MavlinkOrbSubscription::update(const hrt_abstime t)
|
||||
{
|
||||
if (_last_check == t) {
|
||||
/* already checked right now, return result of the check */
|
||||
return _updated;
|
||||
|
||||
} else {
|
||||
_last_check = t;
|
||||
orb_check(_fd, &_updated);
|
||||
|
||||
if (_updated) {
|
||||
orb_copy(_topic, _fd, _data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MavlinkOrbSubscription::is_published()
|
||||
{
|
||||
if (_published) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool updated;
|
||||
orb_check(_fd, &updated);
|
||||
|
||||
if (updated) {
|
||||
_published = true;
|
||||
}
|
||||
|
||||
return _published;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_orb_subscription.h
|
||||
* uORB subscription definition.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#ifndef MAVLINK_ORB_SUBSCRIPTION_H_
|
||||
#define MAVLINK_ORB_SUBSCRIPTION_H_
|
||||
|
||||
#include <systemlib/uthash/utlist.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
|
||||
|
||||
class MavlinkOrbSubscription
|
||||
{
|
||||
public:
|
||||
MavlinkOrbSubscription *next; /*< pointer to next subscription in list */
|
||||
|
||||
MavlinkOrbSubscription(const orb_id_t topic);
|
||||
~MavlinkOrbSubscription();
|
||||
|
||||
bool update(const hrt_abstime t);
|
||||
|
||||
/**
|
||||
* Check if the topic has been published.
|
||||
*
|
||||
* This call will return true if the topic was ever published.
|
||||
* @return true if the topic has been published at least once.
|
||||
*/
|
||||
bool is_published();
|
||||
void *get_data();
|
||||
const orb_id_t get_topic();
|
||||
|
||||
private:
|
||||
const orb_id_t _topic; /*< topic metadata */
|
||||
int _fd; /*< subscription handle */
|
||||
bool _published; /*< topic was ever published */
|
||||
void *_data; /*< pointer to data buffer */
|
||||
hrt_abstime _last_check; /*< time of last check */
|
||||
bool _updated; /*< updated on last check */
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAVLINK_ORB_SUBSCRIPTION_H_ */
|
||||
@@ -1,230 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_parameters.c
|
||||
* MAVLink parameter protocol implementation (BSD-relicensed).
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include "mavlink_parameters.h"
|
||||
#include <uORB/uORB.h>
|
||||
#include "math.h" /* isinf / isnan checks */
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
extern mavlink_system_t mavlink_system;
|
||||
|
||||
extern int mavlink_missionlib_send_message(mavlink_message_t *msg);
|
||||
extern int mavlink_missionlib_send_gcs_string(const char *string);
|
||||
|
||||
/**
|
||||
* If the queue index is not at 0, the queue sending
|
||||
* logic will send parameters from the current index
|
||||
* to len - 1, the end of the param list.
|
||||
*/
|
||||
static unsigned int mavlink_param_queue_index = 0;
|
||||
|
||||
/**
|
||||
* Callback for param interface.
|
||||
*/
|
||||
void mavlink_pm_callback(void *arg, param_t param);
|
||||
|
||||
void mavlink_pm_callback(void *arg, param_t param)
|
||||
{
|
||||
mavlink_pm_send_param(param);
|
||||
usleep(*(unsigned int *)arg);
|
||||
}
|
||||
|
||||
void mavlink_pm_send_all_params(unsigned int delay)
|
||||
{
|
||||
unsigned int dbuf = delay;
|
||||
param_foreach(&mavlink_pm_callback, &dbuf, false);
|
||||
}
|
||||
|
||||
int mavlink_pm_queued_send()
|
||||
{
|
||||
if (mavlink_param_queue_index < param_count()) {
|
||||
mavlink_pm_send_param(param_for_index(mavlink_param_queue_index));
|
||||
mavlink_param_queue_index++;
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void mavlink_pm_start_queued_send()
|
||||
{
|
||||
mavlink_param_queue_index = 0;
|
||||
}
|
||||
|
||||
int mavlink_pm_send_param_for_index(uint16_t index)
|
||||
{
|
||||
return mavlink_pm_send_param(param_for_index(index));
|
||||
}
|
||||
|
||||
int mavlink_pm_send_param_for_name(const char *name)
|
||||
{
|
||||
return mavlink_pm_send_param(param_find(name));
|
||||
}
|
||||
|
||||
int mavlink_pm_send_param(param_t param)
|
||||
{
|
||||
if (param == PARAM_INVALID) return 1;
|
||||
|
||||
/* buffers for param transmission */
|
||||
static char name_buf[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN];
|
||||
float val_buf;
|
||||
static mavlink_message_t tx_msg;
|
||||
|
||||
/* query parameter type */
|
||||
param_type_t type = param_type(param);
|
||||
/* copy parameter name */
|
||||
strncpy((char *)name_buf, param_name(param), MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
|
||||
|
||||
/*
|
||||
* Map onboard parameter type to MAVLink type,
|
||||
* endianess matches (both little endian)
|
||||
*/
|
||||
uint8_t mavlink_type;
|
||||
|
||||
if (type == PARAM_TYPE_INT32) {
|
||||
mavlink_type = MAVLINK_TYPE_INT32_T;
|
||||
|
||||
} else if (type == PARAM_TYPE_FLOAT) {
|
||||
mavlink_type = MAVLINK_TYPE_FLOAT;
|
||||
|
||||
} else {
|
||||
mavlink_type = MAVLINK_TYPE_FLOAT;
|
||||
}
|
||||
|
||||
/*
|
||||
* get param value, since MAVLink encodes float and int params in the same
|
||||
* space during transmission, copy param onto float val_buf
|
||||
*/
|
||||
|
||||
int ret;
|
||||
|
||||
if ((ret = param_get(param, &val_buf)) != OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
mavlink_msg_param_value_pack_chan(mavlink_system.sysid,
|
||||
mavlink_system.compid,
|
||||
MAVLINK_COMM_0,
|
||||
&tx_msg,
|
||||
name_buf,
|
||||
val_buf,
|
||||
mavlink_type,
|
||||
param_count(),
|
||||
param_get_index(param));
|
||||
ret = mavlink_missionlib_send_message(&tx_msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mavlink_pm_message_handler(const mavlink_channel_t chan, const mavlink_message_t *msg)
|
||||
{
|
||||
switch (msg->msgid) {
|
||||
case MAVLINK_MSG_ID_PARAM_REQUEST_LIST: {
|
||||
/* Start sending parameters */
|
||||
mavlink_pm_start_queued_send();
|
||||
mavlink_missionlib_send_gcs_string("[mavlink pm] sending list");
|
||||
} break;
|
||||
|
||||
case MAVLINK_MSG_ID_PARAM_SET: {
|
||||
|
||||
/* Handle parameter setting */
|
||||
|
||||
if (msg->msgid == MAVLINK_MSG_ID_PARAM_SET) {
|
||||
mavlink_param_set_t mavlink_param_set;
|
||||
mavlink_msg_param_set_decode(msg, &mavlink_param_set);
|
||||
|
||||
if (mavlink_param_set.target_system == mavlink_system.sysid && ((mavlink_param_set.target_component == mavlink_system.compid) || (mavlink_param_set.target_component == MAV_COMP_ID_ALL))) {
|
||||
/* local name buffer to enforce null-terminated string */
|
||||
char name[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN + 1];
|
||||
strncpy(name, mavlink_param_set.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
|
||||
/* enforce null termination */
|
||||
name[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN] = '\0';
|
||||
/* attempt to find parameter, set and send it */
|
||||
param_t param = param_find(name);
|
||||
|
||||
if (param == PARAM_INVALID) {
|
||||
char buf[MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN];
|
||||
sprintf(buf, "[mavlink pm] unknown: %s", name);
|
||||
mavlink_missionlib_send_gcs_string(buf);
|
||||
|
||||
} else {
|
||||
/* set and send parameter */
|
||||
param_set(param, &(mavlink_param_set.param_value));
|
||||
mavlink_pm_send_param(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case MAVLINK_MSG_ID_PARAM_REQUEST_READ: {
|
||||
mavlink_param_request_read_t mavlink_param_request_read;
|
||||
mavlink_msg_param_request_read_decode(msg, &mavlink_param_request_read);
|
||||
|
||||
if (mavlink_param_request_read.target_system == mavlink_system.sysid && ((mavlink_param_request_read.target_component == mavlink_system.compid) || (mavlink_param_request_read.target_component == MAV_COMP_ID_ALL))) {
|
||||
/* when no index is given, loop through string ids and compare them */
|
||||
if (mavlink_param_request_read.param_index == -1) {
|
||||
/* local name buffer to enforce null-terminated string */
|
||||
char name[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN + 1];
|
||||
strncpy(name, mavlink_param_request_read.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
|
||||
/* enforce null termination */
|
||||
name[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN] = '\0';
|
||||
/* attempt to find parameter and send it */
|
||||
mavlink_pm_send_param_for_name(name);
|
||||
|
||||
} else {
|
||||
/* when index is >= 0, send this parameter again */
|
||||
mavlink_pm_send_param_for_index(mavlink_param_request_read.param_index);
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_parameters.h
|
||||
* MAVLink parameter protocol definitions (BSD-relicensed).
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
/* This assumes you have the mavlink headers on your include path
|
||||
or in the same folder as this source file */
|
||||
|
||||
|
||||
#include <v1.0/mavlink_types.h>
|
||||
#include <stdbool.h>
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
/**
|
||||
* Handle parameter related messages.
|
||||
*/
|
||||
void mavlink_pm_message_handler(const mavlink_channel_t chan, const mavlink_message_t *msg);
|
||||
|
||||
/**
|
||||
* Send all parameters at once.
|
||||
*
|
||||
* This function blocks until all parameters have been sent.
|
||||
* it delays each parameter by the passed amount of microseconds.
|
||||
*
|
||||
* @param delay The delay in us between sending all parameters.
|
||||
*/
|
||||
void mavlink_pm_send_all_params(unsigned int delay);
|
||||
|
||||
/**
|
||||
* Send one parameter.
|
||||
*
|
||||
* @param param The parameter id to send.
|
||||
* @return zero on success, nonzero on failure.
|
||||
*/
|
||||
int mavlink_pm_send_param(param_t param);
|
||||
|
||||
/**
|
||||
* Send one parameter identified by index.
|
||||
*
|
||||
* @param index The index of the parameter to send.
|
||||
* @return zero on success, nonzero else.
|
||||
*/
|
||||
int mavlink_pm_send_param_for_index(uint16_t index);
|
||||
|
||||
/**
|
||||
* Send one parameter identified by name.
|
||||
*
|
||||
* @param name The index of the parameter to send.
|
||||
* @return zero on success, nonzero else.
|
||||
*/
|
||||
int mavlink_pm_send_param_for_name(const char *name);
|
||||
|
||||
/**
|
||||
* Send a queue of parameters, one parameter per function call.
|
||||
*
|
||||
* @return zero on success, nonzero on failure
|
||||
*/
|
||||
int mavlink_pm_queued_send(void);
|
||||
|
||||
/**
|
||||
* Start sending the parameter queue.
|
||||
*
|
||||
* This function will not directly send parameters, but instead
|
||||
* activate the sending of one parameter on each call of
|
||||
* mavlink_pm_queued_send().
|
||||
* @see mavlink_pm_queued_send()
|
||||
*/
|
||||
void mavlink_pm_start_queued_send(void);
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -33,20 +32,41 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_hil.h
|
||||
* Hardware-in-the-loop simulation support.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern bool mavlink_hil_enabled;
|
||||
|
||||
/**
|
||||
* Enable / disable Hardware in the Loop simulation mode.
|
||||
* @file mavlink_rate_limiter.cpp
|
||||
* Message rate limiter implementation.
|
||||
*
|
||||
* @param hil_enabled The new HIL enable/disable state.
|
||||
* @return OK if the HIL state changed, ERROR if the
|
||||
* requested change could not be made or was
|
||||
* redundant.
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
extern int set_hil_on_off(bool hil_enabled);
|
||||
|
||||
#include "mavlink_rate_limiter.h"
|
||||
|
||||
MavlinkRateLimiter::MavlinkRateLimiter() : _last_sent(0), _interval(1000000)
|
||||
{
|
||||
}
|
||||
|
||||
MavlinkRateLimiter::MavlinkRateLimiter(unsigned int interval) : _last_sent(0), _interval(interval)
|
||||
{
|
||||
}
|
||||
|
||||
MavlinkRateLimiter::~MavlinkRateLimiter()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MavlinkRateLimiter::set_interval(unsigned int interval)
|
||||
{
|
||||
_interval = interval;
|
||||
}
|
||||
|
||||
bool
|
||||
MavlinkRateLimiter::check(hrt_abstime t)
|
||||
{
|
||||
uint64_t dt = t - _last_sent;
|
||||
|
||||
if (dt > 0 && dt >= _interval) {
|
||||
_last_sent = (t / _interval) * _interval;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
+21
-30
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -32,40 +32,31 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Node.h
|
||||
* @file mavlink_rate_limiter.h
|
||||
* Message rate limiter definition.
|
||||
*
|
||||
* A node of a linked list.
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef MAVLINK_RATE_LIMITER_H_
|
||||
#define MAVLINK_RATE_LIMITER_H_
|
||||
|
||||
template<class T>
|
||||
class __EXPORT ListNode
|
||||
{
|
||||
public:
|
||||
ListNode() : _sibling(NULL) {
|
||||
}
|
||||
void setSibling(T sibling) { _sibling = sibling; }
|
||||
T getSibling() { return _sibling; }
|
||||
T get() {
|
||||
return _sibling;
|
||||
}
|
||||
protected:
|
||||
T _sibling;
|
||||
};
|
||||
#include <drivers/drv_hrt.h>
|
||||
|
||||
template<class T>
|
||||
class __EXPORT List
|
||||
|
||||
class MavlinkRateLimiter
|
||||
{
|
||||
public:
|
||||
List() : _head() {
|
||||
}
|
||||
void add(T newNode) {
|
||||
newNode->setSibling(getHead());
|
||||
setHead(newNode);
|
||||
}
|
||||
T getHead() { return _head; }
|
||||
private:
|
||||
void setHead(T &head) { _head = head; }
|
||||
T _head;
|
||||
hrt_abstime _last_sent;
|
||||
hrt_abstime _interval;
|
||||
|
||||
public:
|
||||
MavlinkRateLimiter();
|
||||
MavlinkRateLimiter(unsigned int interval);
|
||||
~MavlinkRateLimiter();
|
||||
void set_interval(unsigned int interval);
|
||||
bool check(hrt_abstime t);
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAVLINK_RATE_LIMITER_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -33,12 +32,15 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file orb_topics.h
|
||||
* Common sets of topics subscribed to or published by the MAVLink driver,
|
||||
* and structures maintained by those subscriptions.
|
||||
* @file mavlink_orb_listener.h
|
||||
* MAVLink 1.0 uORB listener definition
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/sensor_combined.h>
|
||||
#include <uORB/topics/rc_channels.h>
|
||||
@@ -55,7 +57,6 @@
|
||||
#include <uORB/topics/vehicle_vicon_position.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/optical_flow.h>
|
||||
#include <uORB/topics/actuator_outputs.h>
|
||||
#include <uORB/topics/actuator_controls_effective.h>
|
||||
@@ -66,59 +67,80 @@
|
||||
#include <uORB/topics/debug_key_value.h>
|
||||
#include <uORB/topics/airspeed.h>
|
||||
#include <uORB/topics/battery_status.h>
|
||||
#include <drivers/drv_rc_input.h>
|
||||
#include <uORB/topics/navigation_capabilities.h>
|
||||
|
||||
struct mavlink_subscriptions {
|
||||
int sensor_sub;
|
||||
int att_sub;
|
||||
int global_pos_sub;
|
||||
int act_0_sub;
|
||||
int act_1_sub;
|
||||
int act_2_sub;
|
||||
int act_3_sub;
|
||||
int gps_sub;
|
||||
int man_control_sp_sub;
|
||||
int safety_sub;
|
||||
int actuators_sub;
|
||||
int armed_sub;
|
||||
int actuators_effective_sub;
|
||||
int local_pos_sub;
|
||||
int spa_sub;
|
||||
int spl_sub;
|
||||
int triplet_sub;
|
||||
int debug_key_value;
|
||||
int input_rc_sub;
|
||||
int optical_flow;
|
||||
int rates_setpoint_sub;
|
||||
int home_sub;
|
||||
int airspeed_sub;
|
||||
int navigation_capabilities_sub;
|
||||
int position_setpoint_triplet_sub;
|
||||
class Mavlink;
|
||||
|
||||
class MavlinkReceiver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MavlinkReceiver(Mavlink *parent);
|
||||
|
||||
/**
|
||||
* Destructor, also kills the mavlinks task.
|
||||
*/
|
||||
~MavlinkReceiver();
|
||||
|
||||
/**
|
||||
* Start the mavlink task.
|
||||
*
|
||||
* @return OK on success.
|
||||
*/
|
||||
int start();
|
||||
|
||||
/**
|
||||
* Display the mavlink status.
|
||||
*/
|
||||
void print_status();
|
||||
|
||||
static pthread_t receive_start(Mavlink *parent);
|
||||
|
||||
static void *start_helper(void *context);
|
||||
|
||||
private:
|
||||
perf_counter_t _loop_perf; /**< loop performance counter */
|
||||
|
||||
Mavlink *_mavlink;
|
||||
|
||||
void handle_message(mavlink_message_t *msg);
|
||||
void handle_message_command_long(mavlink_message_t *msg);
|
||||
void handle_message_optical_flow(mavlink_message_t *msg);
|
||||
void handle_message_set_mode(mavlink_message_t *msg);
|
||||
void handle_message_vicon_position_estimate(mavlink_message_t *msg);
|
||||
void handle_message_quad_swarm_roll_pitch_yaw_thrust(mavlink_message_t *msg);
|
||||
void handle_message_radio_status(mavlink_message_t *msg);
|
||||
void handle_message_manual_control(mavlink_message_t *msg);
|
||||
void handle_message_hil_sensor(mavlink_message_t *msg);
|
||||
void handle_message_hil_gps(mavlink_message_t *msg);
|
||||
void handle_message_hil_state_quaternion(mavlink_message_t *msg);
|
||||
|
||||
void *receive_thread(void *arg);
|
||||
|
||||
mavlink_status_t status;
|
||||
struct vehicle_local_position_s hil_local_pos;
|
||||
int _manual_sub;
|
||||
orb_advert_t _global_pos_pub;
|
||||
orb_advert_t _local_pos_pub;
|
||||
orb_advert_t _attitude_pub;
|
||||
orb_advert_t _gps_pub;
|
||||
orb_advert_t _sensors_pub;
|
||||
orb_advert_t _gyro_pub;
|
||||
orb_advert_t _accel_pub;
|
||||
orb_advert_t _mag_pub;
|
||||
orb_advert_t _baro_pub;
|
||||
orb_advert_t _airspeed_pub;
|
||||
orb_advert_t _battery_pub;
|
||||
orb_advert_t _cmd_pub;
|
||||
orb_advert_t _flow_pub;
|
||||
orb_advert_t _offboard_control_sp_pub;
|
||||
orb_advert_t _vicon_position_pub;
|
||||
orb_advert_t _telemetry_status_pub;
|
||||
orb_advert_t _rc_pub;
|
||||
orb_advert_t _manual_pub;
|
||||
int _hil_frames;
|
||||
uint64_t _old_timestamp;
|
||||
bool _hil_local_proj_inited;
|
||||
float _hil_local_alt0;
|
||||
};
|
||||
|
||||
extern struct mavlink_subscriptions mavlink_subs;
|
||||
|
||||
/** Global position */
|
||||
extern struct vehicle_global_position_s global_pos;
|
||||
|
||||
/** Local position */
|
||||
extern struct vehicle_local_position_s local_pos;
|
||||
|
||||
/** navigation capabilities */
|
||||
extern struct navigation_capabilities_s nav_cap;
|
||||
|
||||
/** Vehicle status */
|
||||
extern struct vehicle_status_s v_status;
|
||||
|
||||
/** Position setpoint triplet */
|
||||
extern struct position_setpoint_triplet_s pos_sp_triplet;
|
||||
|
||||
/** RC channels */
|
||||
extern struct rc_channels_s rc;
|
||||
|
||||
/** Actuator armed state */
|
||||
extern struct actuator_armed_s armed;
|
||||
|
||||
/** Worker thread starter */
|
||||
extern pthread_t uorb_receive_start(void);
|
||||
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_stream.cpp
|
||||
* Mavlink messages stream implementation.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mavlink_stream.h"
|
||||
#include "mavlink_main.h"
|
||||
|
||||
MavlinkStream::MavlinkStream() : _interval(1000000), _last_sent(0), _channel(MAVLINK_COMM_0), next(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
MavlinkStream::~MavlinkStream()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set messages interval in ms
|
||||
*/
|
||||
void
|
||||
MavlinkStream::set_interval(const unsigned int interval)
|
||||
{
|
||||
_interval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mavlink channel
|
||||
*/
|
||||
void
|
||||
MavlinkStream::set_channel(mavlink_channel_t channel)
|
||||
{
|
||||
_channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update subscriptions and send message if necessary
|
||||
*/
|
||||
int
|
||||
MavlinkStream::update(const hrt_abstime t)
|
||||
{
|
||||
uint64_t dt = t - _last_sent;
|
||||
|
||||
if (dt > 0 && dt >= _interval) {
|
||||
/* interval expired, send message */
|
||||
send(t);
|
||||
_last_sent = (t / _interval) * _interval;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -33,23 +32,45 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file util.h
|
||||
* Utility and helper functions and data.
|
||||
* @file mavlink_stream.cpp
|
||||
* Mavlink messages stream definition.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef MAVLINK_STREAM_H_
|
||||
#define MAVLINK_STREAM_H_
|
||||
|
||||
#include "orb_topics.h"
|
||||
#include <drivers/drv_hrt.h>
|
||||
|
||||
/** MAVLink communications channel */
|
||||
extern uint8_t chan;
|
||||
class Mavlink;
|
||||
class MavlinkStream;
|
||||
|
||||
/** Shutdown marker */
|
||||
extern volatile bool thread_should_exit;
|
||||
#include "mavlink_main.h"
|
||||
|
||||
/**
|
||||
* Translate the custom state into standard mavlink modes and state.
|
||||
*/
|
||||
extern void
|
||||
get_mavlink_mode_and_state(const struct vehicle_control_mode_s *control_mode, const struct actuator_armed_s *armed,
|
||||
uint8_t *mavlink_state, uint8_t *mavlink_mode);
|
||||
class MavlinkStream
|
||||
{
|
||||
private:
|
||||
hrt_abstime _last_sent;
|
||||
|
||||
protected:
|
||||
mavlink_channel_t _channel;
|
||||
unsigned int _interval;
|
||||
|
||||
virtual void send(const hrt_abstime t) = 0;
|
||||
|
||||
public:
|
||||
MavlinkStream *next;
|
||||
|
||||
MavlinkStream();
|
||||
~MavlinkStream();
|
||||
void set_interval(const unsigned int interval);
|
||||
void set_channel(mavlink_channel_t channel);
|
||||
int update(const hrt_abstime t);
|
||||
virtual MavlinkStream *new_instance() = 0;
|
||||
virtual void subscribe(Mavlink *mavlink) = 0;
|
||||
virtual const char *get_name() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAVLINK_STREAM_H_ */
|
||||
@@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2012-2013 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
@@ -36,10 +36,12 @@
|
||||
#
|
||||
|
||||
MODULE_COMMAND = mavlink
|
||||
SRCS += mavlink.c \
|
||||
mavlink_parameters.c \
|
||||
mavlink_receiver.cpp \
|
||||
orb_listener.c \
|
||||
waypoints.c
|
||||
SRCS += mavlink_main.cpp \
|
||||
mavlink.c \
|
||||
mavlink_receiver.cpp \
|
||||
mavlink_orb_subscription.cpp \
|
||||
mavlink_messages.cpp \
|
||||
mavlink_stream.cpp \
|
||||
mavlink_rate_limiter.cpp
|
||||
|
||||
INCLUDE_DIRS += $(MAVLINK_SRC)/include/mavlink
|
||||
|
||||
@@ -1,848 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file orb_listener.c
|
||||
* Monitors ORB topics and sends update messages as appropriate.
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
// XXX trim includes
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
#include <lib/geo/geo.h>
|
||||
|
||||
#include <mavlink/mavlink_log.h>
|
||||
|
||||
#include "waypoints.h"
|
||||
#include "orb_topics.h"
|
||||
#include "mavlink_hil.h"
|
||||
#include "util.h"
|
||||
|
||||
extern bool gcs_link;
|
||||
|
||||
struct vehicle_global_position_s global_pos;
|
||||
struct vehicle_local_position_s local_pos;
|
||||
struct home_position_s home;
|
||||
struct navigation_capabilities_s nav_cap;
|
||||
struct vehicle_status_s v_status;
|
||||
struct position_setpoint_triplet_s pos_sp_triplet;
|
||||
struct rc_channels_s rc;
|
||||
struct rc_input_values rc_raw;
|
||||
struct actuator_armed_s armed;
|
||||
struct actuator_controls_s actuators_0;
|
||||
struct vehicle_attitude_s att;
|
||||
struct airspeed_s airspeed;
|
||||
|
||||
struct mavlink_subscriptions mavlink_subs;
|
||||
|
||||
static int status_sub;
|
||||
static int rc_sub;
|
||||
|
||||
static unsigned int sensors_raw_counter;
|
||||
static unsigned int attitude_counter;
|
||||
static unsigned int gps_counter;
|
||||
|
||||
/*
|
||||
* Last sensor loop time
|
||||
* some outputs are better timestamped
|
||||
* with this "global" reference.
|
||||
*/
|
||||
static uint64_t last_sensor_timestamp;
|
||||
|
||||
static hrt_abstime last_sent_vfr = 0;
|
||||
|
||||
static void *uorb_receive_thread(void *arg);
|
||||
|
||||
struct listener {
|
||||
void (*callback)(const struct listener *l);
|
||||
int *subp;
|
||||
uintptr_t arg;
|
||||
};
|
||||
|
||||
uint16_t cm_uint16_from_m_float(float m);
|
||||
|
||||
static void l_sensor_combined(const struct listener *l);
|
||||
static void l_vehicle_attitude(const struct listener *l);
|
||||
static void l_vehicle_gps_position(const struct listener *l);
|
||||
static void l_vehicle_status(const struct listener *l);
|
||||
static void l_rc_channels(const struct listener *l);
|
||||
static void l_input_rc(const struct listener *l);
|
||||
static void l_global_position(const struct listener *l);
|
||||
static void l_local_position(const struct listener *l);
|
||||
static void l_global_position_setpoint(const struct listener *l);
|
||||
static void l_local_position_setpoint(const struct listener *l);
|
||||
static void l_attitude_setpoint(const struct listener *l);
|
||||
static void l_actuator_outputs(const struct listener *l);
|
||||
static void l_actuator_armed(const struct listener *l);
|
||||
static void l_manual_control_setpoint(const struct listener *l);
|
||||
static void l_vehicle_attitude_controls(const struct listener *l);
|
||||
static void l_debug_key_value(const struct listener *l);
|
||||
static void l_optical_flow(const struct listener *l);
|
||||
static void l_vehicle_rates_setpoint(const struct listener *l);
|
||||
static void l_home(const struct listener *l);
|
||||
static void l_airspeed(const struct listener *l);
|
||||
static void l_nav_cap(const struct listener *l);
|
||||
|
||||
static const struct listener listeners[] = {
|
||||
{l_sensor_combined, &mavlink_subs.sensor_sub, 0},
|
||||
{l_vehicle_attitude, &mavlink_subs.att_sub, 0},
|
||||
{l_vehicle_gps_position, &mavlink_subs.gps_sub, 0},
|
||||
{l_vehicle_status, &status_sub, 0},
|
||||
{l_rc_channels, &rc_sub, 0},
|
||||
{l_input_rc, &mavlink_subs.input_rc_sub, 0},
|
||||
{l_global_position, &mavlink_subs.global_pos_sub, 0},
|
||||
{l_local_position, &mavlink_subs.local_pos_sub, 0},
|
||||
{l_global_position_setpoint, &mavlink_subs.triplet_sub, 0},
|
||||
{l_local_position_setpoint, &mavlink_subs.spl_sub, 0},
|
||||
{l_attitude_setpoint, &mavlink_subs.spa_sub, 0},
|
||||
{l_actuator_outputs, &mavlink_subs.act_0_sub, 0},
|
||||
{l_actuator_outputs, &mavlink_subs.act_1_sub, 1},
|
||||
{l_actuator_outputs, &mavlink_subs.act_2_sub, 2},
|
||||
{l_actuator_outputs, &mavlink_subs.act_3_sub, 3},
|
||||
{l_actuator_armed, &mavlink_subs.armed_sub, 0},
|
||||
{l_manual_control_setpoint, &mavlink_subs.man_control_sp_sub, 0},
|
||||
{l_vehicle_attitude_controls, &mavlink_subs.actuators_sub, 0},
|
||||
{l_debug_key_value, &mavlink_subs.debug_key_value, 0},
|
||||
{l_optical_flow, &mavlink_subs.optical_flow, 0},
|
||||
{l_vehicle_rates_setpoint, &mavlink_subs.rates_setpoint_sub, 0},
|
||||
{l_home, &mavlink_subs.home_sub, 0},
|
||||
{l_airspeed, &mavlink_subs.airspeed_sub, 0},
|
||||
{l_nav_cap, &mavlink_subs.navigation_capabilities_sub, 0},
|
||||
};
|
||||
|
||||
static const unsigned n_listeners = sizeof(listeners) / sizeof(listeners[0]);
|
||||
|
||||
uint16_t
|
||||
cm_uint16_from_m_float(float m)
|
||||
{
|
||||
if (m < 0.0f) {
|
||||
return 0;
|
||||
|
||||
} else if (m > 655.35f) {
|
||||
return 65535;
|
||||
}
|
||||
|
||||
return (uint16_t)(m * 100.0f);
|
||||
}
|
||||
|
||||
void
|
||||
l_sensor_combined(const struct listener *l)
|
||||
{
|
||||
struct sensor_combined_s raw;
|
||||
|
||||
/* copy sensors raw data into local buffer */
|
||||
orb_copy(ORB_ID(sensor_combined), mavlink_subs.sensor_sub, &raw);
|
||||
|
||||
last_sensor_timestamp = raw.timestamp;
|
||||
|
||||
/* mark individual fields as changed */
|
||||
uint16_t fields_updated = 0;
|
||||
static unsigned accel_counter = 0;
|
||||
static unsigned gyro_counter = 0;
|
||||
static unsigned mag_counter = 0;
|
||||
static unsigned baro_counter = 0;
|
||||
|
||||
if (accel_counter != raw.accelerometer_counter) {
|
||||
/* mark first three dimensions as changed */
|
||||
fields_updated |= (1 << 0) | (1 << 1) | (1 << 2);
|
||||
accel_counter = raw.accelerometer_counter;
|
||||
}
|
||||
|
||||
if (gyro_counter != raw.gyro_counter) {
|
||||
/* mark second group dimensions as changed */
|
||||
fields_updated |= (1 << 3) | (1 << 4) | (1 << 5);
|
||||
gyro_counter = raw.gyro_counter;
|
||||
}
|
||||
|
||||
if (mag_counter != raw.magnetometer_counter) {
|
||||
/* mark third group dimensions as changed */
|
||||
fields_updated |= (1 << 6) | (1 << 7) | (1 << 8);
|
||||
mag_counter = raw.magnetometer_counter;
|
||||
}
|
||||
|
||||
if (baro_counter != raw.baro_counter) {
|
||||
/* mark last group dimensions as changed */
|
||||
fields_updated |= (1 << 9) | (1 << 11) | (1 << 12);
|
||||
baro_counter = raw.baro_counter;
|
||||
}
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_highres_imu_send(MAVLINK_COMM_0, last_sensor_timestamp,
|
||||
raw.accelerometer_m_s2[0], raw.accelerometer_m_s2[1],
|
||||
raw.accelerometer_m_s2[2], raw.gyro_rad_s[0],
|
||||
raw.gyro_rad_s[1], raw.gyro_rad_s[2],
|
||||
raw.magnetometer_ga[0],
|
||||
raw.magnetometer_ga[1], raw.magnetometer_ga[2],
|
||||
raw.baro_pres_mbar, raw.differential_pressure_pa,
|
||||
raw.baro_alt_meter, raw.baro_temp_celcius,
|
||||
fields_updated);
|
||||
|
||||
sensors_raw_counter++;
|
||||
}
|
||||
|
||||
void
|
||||
l_vehicle_attitude(const struct listener *l)
|
||||
{
|
||||
/* copy attitude data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_attitude), mavlink_subs.att_sub, &att);
|
||||
|
||||
if (gcs_link) {
|
||||
/* send sensor values */
|
||||
mavlink_msg_attitude_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
att.roll,
|
||||
att.pitch,
|
||||
att.yaw,
|
||||
att.rollspeed,
|
||||
att.pitchspeed,
|
||||
att.yawspeed);
|
||||
|
||||
/* limit VFR message rate to 10Hz */
|
||||
hrt_abstime t = hrt_absolute_time();
|
||||
if (t >= last_sent_vfr + 100000) {
|
||||
last_sent_vfr = t;
|
||||
float groundspeed = sqrtf(global_pos.vel_n * global_pos.vel_n + global_pos.vel_e * global_pos.vel_e);
|
||||
uint16_t heading = _wrap_2pi(att.yaw) * M_RAD_TO_DEG_F;
|
||||
float throttle = armed.armed ? actuators_0.control[3] * 100.0f : 0.0f;
|
||||
mavlink_msg_vfr_hud_send(MAVLINK_COMM_0, airspeed.true_airspeed_m_s, groundspeed, heading, throttle, global_pos.alt, -global_pos.vel_d);
|
||||
}
|
||||
|
||||
/* send quaternion values if it exists */
|
||||
if(att.q_valid) {
|
||||
mavlink_msg_attitude_quaternion_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
att.q[0],
|
||||
att.q[1],
|
||||
att.q[2],
|
||||
att.q[3],
|
||||
att.rollspeed,
|
||||
att.pitchspeed,
|
||||
att.yawspeed);
|
||||
}
|
||||
}
|
||||
|
||||
attitude_counter++;
|
||||
}
|
||||
|
||||
void
|
||||
l_vehicle_gps_position(const struct listener *l)
|
||||
{
|
||||
struct vehicle_gps_position_s gps;
|
||||
|
||||
/* copy gps data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_gps_position), mavlink_subs.gps_sub, &gps);
|
||||
|
||||
/* GPS COG is 0..2PI in degrees * 1e2 */
|
||||
float cog_deg = _wrap_2pi(gps.cog_rad) * M_RAD_TO_DEG_F;
|
||||
|
||||
/* GPS position */
|
||||
mavlink_msg_gps_raw_int_send(MAVLINK_COMM_0,
|
||||
gps.timestamp_position,
|
||||
gps.fix_type,
|
||||
gps.lat,
|
||||
gps.lon,
|
||||
gps.alt,
|
||||
cm_uint16_from_m_float(gps.eph_m),
|
||||
cm_uint16_from_m_float(gps.epv_m),
|
||||
gps.vel_m_s * 1e2f, // from m/s to cm/s
|
||||
cog_deg * 1e2f, // from deg to deg * 100
|
||||
gps.satellites_visible);
|
||||
|
||||
/* update SAT info every 10 seconds */
|
||||
if (gps.satellite_info_available && (gps_counter % 50 == 0)) {
|
||||
mavlink_msg_gps_status_send(MAVLINK_COMM_0,
|
||||
gps.satellites_visible,
|
||||
gps.satellite_prn,
|
||||
gps.satellite_used,
|
||||
gps.satellite_elevation,
|
||||
gps.satellite_azimuth,
|
||||
gps.satellite_snr);
|
||||
}
|
||||
|
||||
gps_counter++;
|
||||
}
|
||||
|
||||
void
|
||||
l_vehicle_status(const struct listener *l)
|
||||
{
|
||||
/* immediately communicate state changes back to user */
|
||||
orb_copy(ORB_ID(vehicle_status), status_sub, &v_status);
|
||||
orb_copy(ORB_ID(actuator_armed), mavlink_subs.armed_sub, &armed);
|
||||
orb_copy(ORB_ID(position_setpoint_triplet), mavlink_subs.position_setpoint_triplet_sub, &pos_sp_triplet);
|
||||
|
||||
/* enable or disable HIL */
|
||||
if (v_status.hil_state == HIL_STATE_ON)
|
||||
set_hil_on_off(true);
|
||||
else if (v_status.hil_state == HIL_STATE_OFF)
|
||||
set_hil_on_off(false);
|
||||
|
||||
/* translate the current syste state to mavlink state and mode */
|
||||
uint8_t mavlink_state = 0;
|
||||
uint8_t mavlink_base_mode = 0;
|
||||
uint32_t mavlink_custom_mode = 0;
|
||||
get_mavlink_mode_and_state(&mavlink_state, &mavlink_base_mode, &mavlink_custom_mode);
|
||||
|
||||
/* send heartbeat */
|
||||
mavlink_msg_heartbeat_send(chan,
|
||||
mavlink_system.type,
|
||||
MAV_AUTOPILOT_PX4,
|
||||
mavlink_base_mode,
|
||||
mavlink_custom_mode,
|
||||
mavlink_state);
|
||||
}
|
||||
|
||||
void
|
||||
l_rc_channels(const struct listener *l)
|
||||
{
|
||||
/* copy rc channels into local buffer */
|
||||
orb_copy(ORB_ID(rc_channels), rc_sub, &rc);
|
||||
// XXX Add RC channels scaled message here
|
||||
}
|
||||
|
||||
void
|
||||
l_input_rc(const struct listener *l)
|
||||
{
|
||||
/* copy rc channels into local buffer */
|
||||
orb_copy(ORB_ID(input_rc), mavlink_subs.input_rc_sub, &rc_raw);
|
||||
|
||||
if (gcs_link) {
|
||||
|
||||
const unsigned port_width = 8;
|
||||
|
||||
for (unsigned i = 0; (i * port_width) < rc_raw.channel_count; i++) {
|
||||
/* Channels are sent in MAVLink main loop at a fixed interval */
|
||||
mavlink_msg_rc_channels_raw_send(chan,
|
||||
rc_raw.timestamp_publication / 1000,
|
||||
i,
|
||||
(rc_raw.channel_count > (i * port_width) + 0) ? rc_raw.values[(i * port_width) + 0] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 1) ? rc_raw.values[(i * port_width) + 1] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 2) ? rc_raw.values[(i * port_width) + 2] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 3) ? rc_raw.values[(i * port_width) + 3] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 4) ? rc_raw.values[(i * port_width) + 4] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 5) ? rc_raw.values[(i * port_width) + 5] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 6) ? rc_raw.values[(i * port_width) + 6] : UINT16_MAX,
|
||||
(rc_raw.channel_count > (i * port_width) + 7) ? rc_raw.values[(i * port_width) + 7] : UINT16_MAX,
|
||||
rc_raw.rssi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
l_global_position(const struct listener *l)
|
||||
{
|
||||
/* copy global position data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_global_position), mavlink_subs.global_pos_sub, &global_pos);
|
||||
|
||||
mavlink_msg_global_position_int_send(MAVLINK_COMM_0,
|
||||
global_pos.timestamp / 1000,
|
||||
global_pos.lat * 1e7,
|
||||
global_pos.lon * 1e7,
|
||||
global_pos.alt * 1000.0f,
|
||||
(global_pos.alt - home.alt) * 1000.0f,
|
||||
global_pos.vel_n * 100.0f,
|
||||
global_pos.vel_e * 100.0f,
|
||||
global_pos.vel_d * 100.0f,
|
||||
_wrap_2pi(global_pos.yaw) * M_RAD_TO_DEG_F * 100.0f);
|
||||
}
|
||||
|
||||
void
|
||||
l_local_position(const struct listener *l)
|
||||
{
|
||||
/* copy local position data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_local_position), mavlink_subs.local_pos_sub, &local_pos);
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_local_position_ned_send(MAVLINK_COMM_0,
|
||||
local_pos.timestamp / 1000,
|
||||
local_pos.x,
|
||||
local_pos.y,
|
||||
local_pos.z,
|
||||
local_pos.vx,
|
||||
local_pos.vy,
|
||||
local_pos.vz);
|
||||
}
|
||||
|
||||
void
|
||||
l_global_position_setpoint(const struct listener *l)
|
||||
{
|
||||
struct position_setpoint_triplet_s triplet;
|
||||
orb_copy(ORB_ID(position_setpoint_triplet), mavlink_subs.triplet_sub, &triplet);
|
||||
|
||||
if (!triplet.current.valid)
|
||||
return;
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_global_position_setpoint_int_send(MAVLINK_COMM_0,
|
||||
MAV_FRAME_GLOBAL,
|
||||
(int32_t)(triplet.current.lat * 1e7d),
|
||||
(int32_t)(triplet.current.lon * 1e7d),
|
||||
(int32_t)(triplet.current.alt * 1e3f),
|
||||
(int16_t)(triplet.current.yaw * M_RAD_TO_DEG_F * 1e2f));
|
||||
}
|
||||
|
||||
void
|
||||
l_local_position_setpoint(const struct listener *l)
|
||||
{
|
||||
struct vehicle_local_position_setpoint_s local_sp;
|
||||
|
||||
/* copy local position data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_local_position_setpoint), mavlink_subs.spl_sub, &local_sp);
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_local_position_setpoint_send(MAVLINK_COMM_0,
|
||||
MAV_FRAME_LOCAL_NED,
|
||||
local_sp.x,
|
||||
local_sp.y,
|
||||
local_sp.z,
|
||||
local_sp.yaw);
|
||||
}
|
||||
|
||||
void
|
||||
l_attitude_setpoint(const struct listener *l)
|
||||
{
|
||||
struct vehicle_attitude_setpoint_s att_sp;
|
||||
|
||||
/* copy local position data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_attitude_setpoint), mavlink_subs.spa_sub, &att_sp);
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_roll_pitch_yaw_thrust_setpoint_send(MAVLINK_COMM_0,
|
||||
att_sp.timestamp / 1000,
|
||||
att_sp.roll_body,
|
||||
att_sp.pitch_body,
|
||||
att_sp.yaw_body,
|
||||
att_sp.thrust);
|
||||
}
|
||||
|
||||
void
|
||||
l_vehicle_rates_setpoint(const struct listener *l)
|
||||
{
|
||||
struct vehicle_rates_setpoint_s rates_sp;
|
||||
|
||||
/* copy local position data into local buffer */
|
||||
orb_copy(ORB_ID(vehicle_rates_setpoint), mavlink_subs.rates_setpoint_sub, &rates_sp);
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_roll_pitch_yaw_rates_thrust_setpoint_send(MAVLINK_COMM_0,
|
||||
rates_sp.timestamp / 1000,
|
||||
rates_sp.roll,
|
||||
rates_sp.pitch,
|
||||
rates_sp.yaw,
|
||||
rates_sp.thrust);
|
||||
}
|
||||
|
||||
void
|
||||
l_actuator_outputs(const struct listener *l)
|
||||
{
|
||||
struct actuator_outputs_s act_outputs;
|
||||
|
||||
orb_id_t ids[] = {
|
||||
ORB_ID(actuator_outputs_0),
|
||||
ORB_ID(actuator_outputs_1),
|
||||
ORB_ID(actuator_outputs_2),
|
||||
ORB_ID(actuator_outputs_3)
|
||||
};
|
||||
|
||||
/* copy actuator data into local buffer */
|
||||
orb_copy(ids[l->arg], *l->subp, &act_outputs);
|
||||
|
||||
if (gcs_link) {
|
||||
mavlink_msg_servo_output_raw_send(MAVLINK_COMM_0, last_sensor_timestamp / 1000,
|
||||
l->arg /* port number - needs GCS support */,
|
||||
/* QGC has port number support already */
|
||||
act_outputs.output[0],
|
||||
act_outputs.output[1],
|
||||
act_outputs.output[2],
|
||||
act_outputs.output[3],
|
||||
act_outputs.output[4],
|
||||
act_outputs.output[5],
|
||||
act_outputs.output[6],
|
||||
act_outputs.output[7]);
|
||||
|
||||
/* only send in HIL mode and only send first group for HIL */
|
||||
if (mavlink_hil_enabled && armed.armed && ids[l->arg] == ORB_ID(actuator_outputs_0)) {
|
||||
|
||||
/* translate the current syste state to mavlink state and mode */
|
||||
uint8_t mavlink_state = 0;
|
||||
uint8_t mavlink_base_mode = 0;
|
||||
uint32_t mavlink_custom_mode = 0;
|
||||
get_mavlink_mode_and_state(&mavlink_state, &mavlink_base_mode, &mavlink_custom_mode);
|
||||
|
||||
/* HIL message as per MAVLink spec */
|
||||
|
||||
/* scale / assign outputs depending on system type */
|
||||
|
||||
if (mavlink_system.type == MAV_TYPE_QUADROTOR) {
|
||||
mavlink_msg_hil_controls_send(chan,
|
||||
hrt_absolute_time(),
|
||||
((act_outputs.output[0] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[1] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[2] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[3] - 900.0f) / 600.0f) / 2.0f,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
mavlink_base_mode,
|
||||
0);
|
||||
|
||||
} else if (mavlink_system.type == MAV_TYPE_HEXAROTOR) {
|
||||
mavlink_msg_hil_controls_send(chan,
|
||||
hrt_absolute_time(),
|
||||
((act_outputs.output[0] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[1] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[2] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[3] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[4] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[5] - 900.0f) / 600.0f) / 2.0f,
|
||||
-1,
|
||||
-1,
|
||||
mavlink_base_mode,
|
||||
0);
|
||||
|
||||
} else if (mavlink_system.type == MAV_TYPE_OCTOROTOR) {
|
||||
mavlink_msg_hil_controls_send(chan,
|
||||
hrt_absolute_time(),
|
||||
((act_outputs.output[0] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[1] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[2] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[3] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[4] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[5] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[6] - 900.0f) / 600.0f) / 2.0f,
|
||||
((act_outputs.output[7] - 900.0f) / 600.0f) / 2.0f,
|
||||
mavlink_base_mode,
|
||||
0);
|
||||
|
||||
} else {
|
||||
mavlink_msg_hil_controls_send(chan,
|
||||
hrt_absolute_time(),
|
||||
(act_outputs.output[0] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[1] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[2] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[3] - 1000.0f) / 1000.0f,
|
||||
(act_outputs.output[4] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[5] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[6] - 1500.0f) / 500.0f,
|
||||
(act_outputs.output[7] - 1500.0f) / 500.0f,
|
||||
mavlink_base_mode,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
l_actuator_armed(const struct listener *l)
|
||||
{
|
||||
orb_copy(ORB_ID(actuator_armed), mavlink_subs.armed_sub, &armed);
|
||||
}
|
||||
|
||||
void
|
||||
l_manual_control_setpoint(const struct listener *l)
|
||||
{
|
||||
struct manual_control_setpoint_s man_control;
|
||||
|
||||
/* copy manual control data into local buffer */
|
||||
orb_copy(ORB_ID(manual_control_setpoint), mavlink_subs.man_control_sp_sub, &man_control);
|
||||
|
||||
if (gcs_link)
|
||||
mavlink_msg_manual_control_send(MAVLINK_COMM_0,
|
||||
mavlink_system.sysid,
|
||||
man_control.roll * 1000,
|
||||
man_control.pitch * 1000,
|
||||
man_control.yaw * 1000,
|
||||
man_control.throttle * 1000,
|
||||
0);
|
||||
}
|
||||
|
||||
void
|
||||
l_vehicle_attitude_controls(const struct listener *l)
|
||||
{
|
||||
orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, mavlink_subs.actuators_sub, &actuators_0);
|
||||
|
||||
if (gcs_link) {
|
||||
/* send, add spaces so that string buffer is at least 10 chars long */
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
"ctrl0 ",
|
||||
actuators_0.control[0]);
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
"ctrl1 ",
|
||||
actuators_0.control[1]);
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
"ctrl2 ",
|
||||
actuators_0.control[2]);
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
"ctrl3 ",
|
||||
actuators_0.control[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
l_debug_key_value(const struct listener *l)
|
||||
{
|
||||
struct debug_key_value_s debug;
|
||||
|
||||
orb_copy(ORB_ID(debug_key_value), mavlink_subs.debug_key_value, &debug);
|
||||
|
||||
/* Enforce null termination */
|
||||
debug.key[sizeof(debug.key) - 1] = '\0';
|
||||
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
last_sensor_timestamp / 1000,
|
||||
debug.key,
|
||||
debug.value);
|
||||
}
|
||||
|
||||
void
|
||||
l_optical_flow(const struct listener *l)
|
||||
{
|
||||
struct optical_flow_s flow;
|
||||
|
||||
orb_copy(ORB_ID(optical_flow), mavlink_subs.optical_flow, &flow);
|
||||
|
||||
mavlink_msg_optical_flow_send(MAVLINK_COMM_0, flow.timestamp, flow.sensor_id, flow.flow_raw_x, flow.flow_raw_y,
|
||||
flow.flow_comp_x_m, flow.flow_comp_y_m, flow.quality, flow.ground_distance_m);
|
||||
}
|
||||
|
||||
void
|
||||
l_home(const struct listener *l)
|
||||
{
|
||||
orb_copy(ORB_ID(home_position), mavlink_subs.home_sub, &home);
|
||||
|
||||
mavlink_msg_gps_global_origin_send(MAVLINK_COMM_0, (int32_t)(home.lat*1e7d), (int32_t)(home.lon*1e7d), (int32_t)(home.alt)*1e3f);
|
||||
}
|
||||
|
||||
void
|
||||
l_airspeed(const struct listener *l)
|
||||
{
|
||||
orb_copy(ORB_ID(airspeed), mavlink_subs.airspeed_sub, &airspeed);
|
||||
}
|
||||
|
||||
void
|
||||
l_nav_cap(const struct listener *l)
|
||||
{
|
||||
|
||||
orb_copy(ORB_ID(navigation_capabilities), mavlink_subs.navigation_capabilities_sub, &nav_cap);
|
||||
|
||||
mavlink_msg_named_value_float_send(MAVLINK_COMM_0,
|
||||
hrt_absolute_time() / 1000,
|
||||
"turn dist",
|
||||
nav_cap.turn_distance);
|
||||
|
||||
}
|
||||
|
||||
static void *
|
||||
uorb_receive_thread(void *arg)
|
||||
{
|
||||
/* Set thread name */
|
||||
prctl(PR_SET_NAME, "mavlink_orb_rcv", getpid());
|
||||
|
||||
/*
|
||||
* set up poll to block for new data,
|
||||
* wait for a maximum of 1000 ms (1 second)
|
||||
*/
|
||||
const int timeout = 1000;
|
||||
|
||||
/*
|
||||
* Initialise listener array.
|
||||
*
|
||||
* Might want to invoke each listener once to set initial state.
|
||||
*/
|
||||
struct pollfd fds[n_listeners];
|
||||
|
||||
for (unsigned i = 0; i < n_listeners; i++) {
|
||||
fds[i].fd = *listeners[i].subp;
|
||||
fds[i].events = POLLIN;
|
||||
|
||||
/* Invoke callback to set initial state */
|
||||
//listeners[i].callback(&listener[i]);
|
||||
}
|
||||
|
||||
while (!thread_should_exit) {
|
||||
|
||||
int poll_ret = poll(fds, n_listeners, timeout);
|
||||
|
||||
/* handle the poll result */
|
||||
if (poll_ret == 0) {
|
||||
/* silent */
|
||||
|
||||
} else if (poll_ret < 0) {
|
||||
mavlink_missionlib_send_gcs_string("[mavlink] ERROR reading uORB data");
|
||||
|
||||
} else {
|
||||
|
||||
for (unsigned i = 0; i < n_listeners; i++) {
|
||||
if (fds[i].revents & POLLIN)
|
||||
listeners[i].callback(&listeners[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pthread_t
|
||||
uorb_receive_start(void)
|
||||
{
|
||||
/* --- SENSORS RAW VALUE --- */
|
||||
mavlink_subs.sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
|
||||
/* rate limit set externally based on interface speed, set a basic default here */
|
||||
orb_set_interval(mavlink_subs.sensor_sub, 200); /* 5Hz updates */
|
||||
|
||||
/* --- ATTITUDE VALUE --- */
|
||||
mavlink_subs.att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
/* rate limit set externally based on interface speed, set a basic default here */
|
||||
orb_set_interval(mavlink_subs.att_sub, 200); /* 5Hz updates */
|
||||
|
||||
/* --- GPS VALUE --- */
|
||||
mavlink_subs.gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
|
||||
orb_set_interval(mavlink_subs.gps_sub, 200); /* 5Hz updates */
|
||||
|
||||
/* --- HOME POSITION --- */
|
||||
mavlink_subs.home_sub = orb_subscribe(ORB_ID(home_position));
|
||||
orb_set_interval(mavlink_subs.home_sub, 1000); /* 1Hz updates */
|
||||
|
||||
/* --- SYSTEM STATE --- */
|
||||
status_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
orb_set_interval(status_sub, 300); /* max 3.33 Hz updates */
|
||||
|
||||
/* --- POSITION SETPOINT TRIPLET --- */
|
||||
mavlink_subs.position_setpoint_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
|
||||
orb_set_interval(mavlink_subs.position_setpoint_triplet_sub, 0); /* not polled, don't limit */
|
||||
|
||||
/* --- RC CHANNELS VALUE --- */
|
||||
rc_sub = orb_subscribe(ORB_ID(rc_channels));
|
||||
orb_set_interval(rc_sub, 100); /* 10Hz updates */
|
||||
|
||||
/* --- RC RAW VALUE --- */
|
||||
mavlink_subs.input_rc_sub = orb_subscribe(ORB_ID(input_rc));
|
||||
orb_set_interval(mavlink_subs.input_rc_sub, 100);
|
||||
|
||||
/* --- GLOBAL POS VALUE --- */
|
||||
mavlink_subs.global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
|
||||
orb_set_interval(mavlink_subs.global_pos_sub, 100); /* 10 Hz active updates */
|
||||
|
||||
/* --- LOCAL POS VALUE --- */
|
||||
mavlink_subs.local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
|
||||
orb_set_interval(mavlink_subs.local_pos_sub, 1000); /* 1Hz active updates */
|
||||
|
||||
/* --- GLOBAL SETPOINT VALUE --- */
|
||||
mavlink_subs.triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
|
||||
orb_set_interval(mavlink_subs.triplet_sub, 2000); /* 0.5 Hz updates */
|
||||
|
||||
/* --- LOCAL SETPOINT VALUE --- */
|
||||
mavlink_subs.spl_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
|
||||
orb_set_interval(mavlink_subs.spl_sub, 2000); /* 0.5 Hz updates */
|
||||
|
||||
/* --- ATTITUDE SETPOINT VALUE --- */
|
||||
mavlink_subs.spa_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
|
||||
orb_set_interval(mavlink_subs.spa_sub, 2000); /* 0.5 Hz updates */
|
||||
|
||||
/* --- RATES SETPOINT VALUE --- */
|
||||
mavlink_subs.rates_setpoint_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
|
||||
orb_set_interval(mavlink_subs.rates_setpoint_sub, 2000); /* 0.5 Hz updates */
|
||||
|
||||
/* --- ACTUATOR OUTPUTS --- */
|
||||
mavlink_subs.act_0_sub = orb_subscribe(ORB_ID(actuator_outputs_0));
|
||||
mavlink_subs.act_1_sub = orb_subscribe(ORB_ID(actuator_outputs_1));
|
||||
mavlink_subs.act_2_sub = orb_subscribe(ORB_ID(actuator_outputs_2));
|
||||
mavlink_subs.act_3_sub = orb_subscribe(ORB_ID(actuator_outputs_3));
|
||||
/* rate limits set externally based on interface speed, set a basic default here */
|
||||
orb_set_interval(mavlink_subs.act_0_sub, 100); /* 10Hz updates */
|
||||
orb_set_interval(mavlink_subs.act_1_sub, 100); /* 10Hz updates */
|
||||
orb_set_interval(mavlink_subs.act_2_sub, 100); /* 10Hz updates */
|
||||
orb_set_interval(mavlink_subs.act_3_sub, 100); /* 10Hz updates */
|
||||
|
||||
/* --- ACTUATOR ARMED VALUE --- */
|
||||
mavlink_subs.armed_sub = orb_subscribe(ORB_ID(actuator_armed));
|
||||
orb_set_interval(mavlink_subs.armed_sub, 100); /* 10Hz updates */
|
||||
|
||||
/* --- MAPPED MANUAL CONTROL INPUTS --- */
|
||||
mavlink_subs.man_control_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
|
||||
/* rate limits set externally based on interface speed, set a basic default here */
|
||||
orb_set_interval(mavlink_subs.man_control_sp_sub, 100); /* 10Hz updates */
|
||||
|
||||
/* --- ACTUATOR CONTROL VALUE --- */
|
||||
mavlink_subs.actuators_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
|
||||
orb_set_interval(mavlink_subs.actuators_sub, 100); /* 10Hz updates */
|
||||
|
||||
/* --- DEBUG VALUE OUTPUT --- */
|
||||
mavlink_subs.debug_key_value = orb_subscribe(ORB_ID(debug_key_value));
|
||||
orb_set_interval(mavlink_subs.debug_key_value, 100); /* 10Hz updates */
|
||||
|
||||
/* --- FLOW SENSOR --- */
|
||||
mavlink_subs.optical_flow = orb_subscribe(ORB_ID(optical_flow));
|
||||
orb_set_interval(mavlink_subs.optical_flow, 200); /* 5Hz updates */
|
||||
|
||||
/* --- AIRSPEED --- */
|
||||
mavlink_subs.airspeed_sub = orb_subscribe(ORB_ID(airspeed));
|
||||
orb_set_interval(mavlink_subs.airspeed_sub, 200); /* 5Hz updates */
|
||||
|
||||
/* --- NAVIGATION CAPABILITIES --- */
|
||||
mavlink_subs.navigation_capabilities_sub = orb_subscribe(ORB_ID(navigation_capabilities));
|
||||
orb_set_interval(mavlink_subs.navigation_capabilities_sub, 500); /* 2Hz updates */
|
||||
nav_cap.turn_distance = 0.0f;
|
||||
|
||||
/* start the listener loop */
|
||||
pthread_attr_t uorb_attr;
|
||||
pthread_attr_init(&uorb_attr);
|
||||
|
||||
/* Set stack size, needs less than 2k */
|
||||
pthread_attr_setstacksize(&uorb_attr, 2048);
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, &uorb_attr, uorb_receive_thread, NULL);
|
||||
|
||||
pthread_attr_destroy(&uorb_attr);
|
||||
return thread;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
@@ -1,730 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Petri Tanskanen <petri.tanskanen@inf.ethz.ch>
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file waypoints.c
|
||||
* MAVLink waypoint protocol implementation (BSD-relicensed).
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include "waypoints.h"
|
||||
#include "util.h"
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/mission.h>
|
||||
#include <geo/geo.h>
|
||||
#include <dataman/dataman.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <systemlib/err.h>
|
||||
|
||||
bool verbose = true;
|
||||
|
||||
orb_advert_t mission_pub = -1;
|
||||
struct mission_s mission;
|
||||
|
||||
uint8_t mavlink_wpm_comp_id = MAV_COMP_ID_MISSIONPLANNER;
|
||||
|
||||
void
|
||||
mavlink_missionlib_send_message(mavlink_message_t *msg)
|
||||
{
|
||||
uint16_t len = mavlink_msg_to_send_buffer(missionlib_msg_buf, msg);
|
||||
|
||||
mavlink_send_uart_bytes(chan, missionlib_msg_buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
mavlink_missionlib_send_gcs_string(const char *string)
|
||||
{
|
||||
const int len = MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN;
|
||||
mavlink_statustext_t statustext;
|
||||
int i = 0;
|
||||
|
||||
while (i < len - 1) {
|
||||
statustext.text[i] = string[i];
|
||||
|
||||
if (string[i] == '\0')
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > 1) {
|
||||
/* Enforce null termination */
|
||||
statustext.text[i] = '\0';
|
||||
mavlink_message_t msg;
|
||||
|
||||
mavlink_msg_statustext_encode(mavlink_system.sysid, mavlink_system.compid, &msg, &statustext);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void publish_mission()
|
||||
{
|
||||
/* Initialize mission publication if necessary */
|
||||
if (mission_pub < 0) {
|
||||
mission_pub = orb_advertise(ORB_ID(mission), &mission);
|
||||
|
||||
} else {
|
||||
orb_publish(ORB_ID(mission), mission_pub, &mission);
|
||||
}
|
||||
}
|
||||
|
||||
int map_mavlink_mission_item_to_mission_item(const mavlink_mission_item_t *mavlink_mission_item, struct mission_item_s *mission_item)
|
||||
{
|
||||
/* only support global waypoints for now */
|
||||
switch (mavlink_mission_item->frame) {
|
||||
case MAV_FRAME_GLOBAL:
|
||||
mission_item->lat = (double)mavlink_mission_item->x;
|
||||
mission_item->lon = (double)mavlink_mission_item->y;
|
||||
mission_item->altitude = mavlink_mission_item->z;
|
||||
mission_item->altitude_is_relative = false;
|
||||
break;
|
||||
|
||||
case MAV_FRAME_GLOBAL_RELATIVE_ALT:
|
||||
mission_item->lat = (double)mavlink_mission_item->x;
|
||||
mission_item->lon = (double)mavlink_mission_item->y;
|
||||
mission_item->altitude = mavlink_mission_item->z;
|
||||
mission_item->altitude_is_relative = true;
|
||||
break;
|
||||
|
||||
case MAV_FRAME_LOCAL_NED:
|
||||
case MAV_FRAME_LOCAL_ENU:
|
||||
return MAV_MISSION_UNSUPPORTED_FRAME;
|
||||
case MAV_FRAME_MISSION:
|
||||
default:
|
||||
return MAV_MISSION_ERROR;
|
||||
}
|
||||
|
||||
switch (mavlink_mission_item->command) {
|
||||
case MAV_CMD_NAV_TAKEOFF:
|
||||
mission_item->pitch_min = mavlink_mission_item->param2;
|
||||
break;
|
||||
default:
|
||||
mission_item->acceptance_radius = mavlink_mission_item->param2;
|
||||
break;
|
||||
}
|
||||
|
||||
mission_item->yaw = _wrap_pi(mavlink_mission_item->param4*M_DEG_TO_RAD_F);
|
||||
mission_item->loiter_radius = fabsf(mavlink_mission_item->param3);
|
||||
mission_item->loiter_direction = (mavlink_mission_item->param3 > 0) ? 1 : -1; /* 1 if positive CW, -1 if negative CCW */
|
||||
mission_item->nav_cmd = mavlink_mission_item->command;
|
||||
|
||||
mission_item->time_inside = mavlink_mission_item->param1;
|
||||
mission_item->autocontinue = mavlink_mission_item->autocontinue;
|
||||
// mission_item->index = mavlink_mission_item->seq;
|
||||
mission_item->origin = ORIGIN_MAVLINK;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int map_mission_item_to_mavlink_mission_item(const struct mission_item_s *mission_item, mavlink_mission_item_t *mavlink_mission_item)
|
||||
{
|
||||
if (mission_item->altitude_is_relative) {
|
||||
mavlink_mission_item->frame = MAV_FRAME_GLOBAL;
|
||||
} else {
|
||||
mavlink_mission_item->frame = MAV_FRAME_GLOBAL_RELATIVE_ALT;
|
||||
}
|
||||
|
||||
switch (mission_item->nav_cmd) {
|
||||
case NAV_CMD_TAKEOFF:
|
||||
mavlink_mission_item->param2 = mission_item->pitch_min;
|
||||
break;
|
||||
default:
|
||||
mavlink_mission_item->param2 = mission_item->acceptance_radius;
|
||||
break;
|
||||
}
|
||||
|
||||
mavlink_mission_item->x = (float)mission_item->lat;
|
||||
mavlink_mission_item->y = (float)mission_item->lon;
|
||||
mavlink_mission_item->z = mission_item->altitude;
|
||||
|
||||
mavlink_mission_item->param4 = mission_item->yaw*M_RAD_TO_DEG_F;
|
||||
mavlink_mission_item->param3 = mission_item->loiter_radius*(float)mission_item->loiter_direction;
|
||||
mavlink_mission_item->command = mission_item->nav_cmd;
|
||||
mavlink_mission_item->param1 = mission_item->time_inside;
|
||||
mavlink_mission_item->autocontinue = mission_item->autocontinue;
|
||||
// mavlink_mission_item->seq = mission_item->index;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void mavlink_wpm_init(mavlink_wpm_storage *state)
|
||||
{
|
||||
state->size = 0;
|
||||
state->max_size = MAVLINK_WPM_MAX_WP_COUNT;
|
||||
state->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
state->current_partner_sysid = 0;
|
||||
state->current_partner_compid = 0;
|
||||
state->timestamp_lastaction = 0;
|
||||
state->timestamp_last_send_setpoint = 0;
|
||||
state->timeout = MAVLINK_WPM_PROTOCOL_TIMEOUT_DEFAULT;
|
||||
state->current_dataman_id = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Sends an waypoint ack message
|
||||
*/
|
||||
void mavlink_wpm_send_waypoint_ack(uint8_t sysid, uint8_t compid, uint8_t type)
|
||||
{
|
||||
mavlink_message_t msg;
|
||||
mavlink_mission_ack_t wpa;
|
||||
|
||||
wpa.target_system = sysid;
|
||||
wpa.target_component = compid;
|
||||
wpa.type = type;
|
||||
|
||||
mavlink_msg_mission_ack_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpa);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Sent waypoint ack (%u) to ID %u", wpa.type, wpa.target_system);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Broadcasts the new target waypoint and directs the MAV to fly there
|
||||
*
|
||||
* This function broadcasts its new active waypoint sequence number and
|
||||
* sends a message to the controller, advising it to fly to the coordinates
|
||||
* of the waypoint with a given orientation
|
||||
*
|
||||
* @param seq The waypoint sequence number the MAV should fly to.
|
||||
*/
|
||||
void mavlink_wpm_send_waypoint_current(uint16_t seq)
|
||||
{
|
||||
if (seq < wpm->size) {
|
||||
mavlink_message_t msg;
|
||||
mavlink_mission_current_t wpc;
|
||||
|
||||
wpc.seq = seq;
|
||||
|
||||
mavlink_msg_mission_current_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpc);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Broadcasted new current waypoint %u", wpc.seq);
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("ERROR: wp index out of bounds");
|
||||
if (verbose) warnx("ERROR: index out of bounds");
|
||||
}
|
||||
}
|
||||
|
||||
void mavlink_wpm_send_waypoint_count(uint8_t sysid, uint8_t compid, uint16_t count)
|
||||
{
|
||||
mavlink_message_t msg;
|
||||
mavlink_mission_count_t wpc;
|
||||
|
||||
wpc.target_system = sysid;
|
||||
wpc.target_component = compid;
|
||||
wpc.count = mission.count;
|
||||
|
||||
mavlink_msg_mission_count_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpc);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Sent waypoint count (%u) to ID %u", wpc.count, wpc.target_system);
|
||||
}
|
||||
|
||||
void mavlink_wpm_send_waypoint(uint8_t sysid, uint8_t compid, uint16_t seq)
|
||||
{
|
||||
|
||||
struct mission_item_s mission_item;
|
||||
ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
dm_item_t dm_current;
|
||||
|
||||
if (wpm->current_dataman_id == 0) {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||
} else {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||
}
|
||||
|
||||
if (dm_read(dm_current, seq, &mission_item, len) == len) {
|
||||
|
||||
/* create mission_item_s from mavlink_mission_item_t */
|
||||
mavlink_mission_item_t wp;
|
||||
map_mission_item_to_mavlink_mission_item(&mission_item, &wp);
|
||||
|
||||
mavlink_message_t msg;
|
||||
wp.target_system = sysid;
|
||||
wp.target_component = compid;
|
||||
wp.seq = seq;
|
||||
mavlink_msg_mission_item_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wp);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Sent waypoint %u to ID %u", wp.seq, wp.target_system);
|
||||
} else {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ERROR);
|
||||
if (verbose) warnx("ERROR: could not read WP%u", seq);
|
||||
}
|
||||
}
|
||||
|
||||
void mavlink_wpm_send_waypoint_request(uint8_t sysid, uint8_t compid, uint16_t seq)
|
||||
{
|
||||
if (seq < wpm->max_size) {
|
||||
mavlink_message_t msg;
|
||||
mavlink_mission_request_t wpr;
|
||||
wpr.target_system = sysid;
|
||||
wpr.target_component = compid;
|
||||
wpr.seq = seq;
|
||||
mavlink_msg_mission_request_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wpr);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Sent waypoint request %u to ID %u", wpr.seq, wpr.target_system);
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("ERROR: Waypoint index exceeds list capacity");
|
||||
if (verbose) warnx("ERROR: Waypoint index exceeds list capacity");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief emits a message that a waypoint reached
|
||||
*
|
||||
* This function broadcasts a message that a waypoint is reached.
|
||||
*
|
||||
* @param seq The waypoint sequence number the MAV has reached.
|
||||
*/
|
||||
void mavlink_wpm_send_waypoint_reached(uint16_t seq)
|
||||
{
|
||||
mavlink_message_t msg;
|
||||
mavlink_mission_item_reached_t wp_reached;
|
||||
|
||||
wp_reached.seq = seq;
|
||||
|
||||
mavlink_msg_mission_item_reached_encode(mavlink_system.sysid, mavlink_wpm_comp_id, &msg, &wp_reached);
|
||||
mavlink_missionlib_send_message(&msg);
|
||||
|
||||
if (verbose) warnx("Sent waypoint %u reached message", wp_reached.seq);
|
||||
}
|
||||
|
||||
|
||||
void mavlink_waypoint_eventloop(uint64_t now)
|
||||
{
|
||||
/* check for timed-out operations */
|
||||
if (now - wpm->timestamp_lastaction > wpm->timeout && wpm->current_state != MAVLINK_WPM_STATE_IDLE) {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("Operation timeout");
|
||||
|
||||
if (verbose) warnx("Last operation (state=%u) timed out, changing state to MAVLINK_WPM_STATE_IDLE", wpm->current_state);
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
wpm->current_partner_sysid = 0;
|
||||
wpm->current_partner_compid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mavlink_wpm_message_handler(const mavlink_message_t *msg)
|
||||
{
|
||||
uint64_t now = hrt_absolute_time();
|
||||
|
||||
switch (msg->msgid) {
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_ACK: {
|
||||
mavlink_mission_ack_t wpa;
|
||||
mavlink_msg_mission_ack_decode(msg, &wpa);
|
||||
|
||||
if ((msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid) && (wpa.target_system == mavlink_system.sysid /*&& wpa.target_component == mavlink_wpm_comp_id*/)) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST || wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS) {
|
||||
if (wpm->current_wp_id == wpm->size - 1) {
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
wpm->current_wp_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: curr partner id mismatch");
|
||||
if (verbose) warnx("REJ. WP CMD: curr partner id mismatch");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_SET_CURRENT: {
|
||||
mavlink_mission_set_current_t wpc;
|
||||
mavlink_msg_mission_set_current_decode(msg, &wpc);
|
||||
|
||||
if (wpc.target_system == mavlink_system.sysid /*&& wpc.target_component == mavlink_wpm_comp_id*/) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) {
|
||||
if (wpc.seq < wpm->size) {
|
||||
|
||||
mission.current_index = wpc.seq;
|
||||
publish_mission();
|
||||
|
||||
mavlink_wpm_send_waypoint_current(wpc.seq);
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("IGN WP CURR CMD: Not in list");
|
||||
if (verbose) warnx("IGN WP CURR CMD: Not in list");
|
||||
}
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("IGN WP CURR CMD: Busy");
|
||||
if (verbose) warnx("IGN WP CURR CMD: Busy");
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch");
|
||||
if (verbose) warnx("REJ. WP CMD: target id mismatch");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_REQUEST_LIST: {
|
||||
mavlink_mission_request_list_t wprl;
|
||||
mavlink_msg_mission_request_list_decode(msg, &wprl);
|
||||
|
||||
if (wprl.target_system == mavlink_system.sysid /*&& wprl.target_component == mavlink_wpm_comp_id*/) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_IDLE || wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) {
|
||||
if (wpm->size > 0) {
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_SENDLIST;
|
||||
wpm->current_wp_id = 0;
|
||||
wpm->current_partner_sysid = msg->sysid;
|
||||
wpm->current_partner_compid = msg->compid;
|
||||
|
||||
} else {
|
||||
if (verbose) warnx("No waypoints send");
|
||||
}
|
||||
|
||||
wpm->current_count = wpm->size;
|
||||
mavlink_wpm_send_waypoint_count(msg->sysid, msg->compid, wpm->current_count);
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("IGN REQUEST LIST: Busy");
|
||||
if (verbose) warnx("IGN REQUEST LIST: Busy");
|
||||
}
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. REQUEST LIST: target id mismatch");
|
||||
if (verbose) warnx("REJ. REQUEST LIST: target id mismatch");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_REQUEST: {
|
||||
mavlink_mission_request_t wpr;
|
||||
mavlink_msg_mission_request_decode(msg, &wpr);
|
||||
|
||||
if (msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid && wpr.target_system == mavlink_system.sysid /*&& wpr.target_component == mavlink_wpm_comp_id*/) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
if (wpr.seq >= wpm->size) {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: Req. WP not in list");
|
||||
if (verbose) warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because the requested waypoint ID (%u) was out of bounds.", wpr.seq);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that we are in the correct state and that the first request has id 0
|
||||
* and the following requests have either the last id (re-send last waypoint) or last_id+1 (next waypoint)
|
||||
*/
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST) {
|
||||
|
||||
if (wpr.seq == 0) {
|
||||
if (verbose) warnx("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u from %u changing state to MAVLINK_WPM_STATE_SENDLIST_SENDWPS", wpr.seq, msg->sysid);
|
||||
wpm->current_state = MAVLINK_WPM_STATE_SENDLIST_SENDWPS;
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: First id != 0");
|
||||
if (verbose) warnx("REJ. WP CMD: First id != 0");
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (wpm->current_state == MAVLINK_WPM_STATE_SENDLIST_SENDWPS) {
|
||||
|
||||
if (wpr.seq == wpm->current_wp_id) {
|
||||
|
||||
if (verbose) warnx("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u (again) from %u staying in state MAVLINK_WPM_STATE_SENDLIST_SENDWPS", wpr.seq, msg->sysid);
|
||||
|
||||
} else if (wpr.seq == wpm->current_wp_id + 1) {
|
||||
|
||||
if (verbose) warnx("Got MAVLINK_MSG_ID_MISSION_ITEM_REQUEST of waypoint %u from %u staying in state MAVLINK_WPM_STATE_SENDLIST_SENDWPS", wpr.seq, msg->sysid);
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: Req. WP was unexpected");
|
||||
if (verbose) warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because the requested waypoint ID (%u) was not the expected (%u or %u).", wpr.seq, wpm->current_wp_id, wpm->current_wp_id + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy");
|
||||
if (verbose) warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST because i'm doing something else already (state=%i).", wpm->current_state);
|
||||
break;
|
||||
}
|
||||
|
||||
wpm->current_wp_id = wpr.seq;
|
||||
wpm->current_state = MAVLINK_WPM_STATE_SENDLIST_SENDWPS;
|
||||
|
||||
if (wpr.seq < wpm->size) {
|
||||
|
||||
mavlink_wpm_send_waypoint(wpm->current_partner_sysid, wpm->current_partner_compid,wpm->current_wp_id);
|
||||
|
||||
} else {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ERROR);
|
||||
if (verbose) warnx("ERROR: Waypoint %u out of bounds", wpr.seq);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//we we're target but already communicating with someone else
|
||||
if ((wpr.target_system == mavlink_system.sysid /*&& wpr.target_component == mavlink_wpm_comp_id*/) && !(msg->sysid == wpm->current_partner_sysid && msg->compid == wpm->current_partner_compid)) {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy");
|
||||
if (verbose) warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM_REQUEST from ID %u because i'm already talking to ID %u.", msg->sysid, wpm->current_partner_sysid);
|
||||
|
||||
} else {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch");
|
||||
if (verbose) warnx("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_COUNT: {
|
||||
mavlink_mission_count_t wpc;
|
||||
mavlink_msg_mission_count_decode(msg, &wpc);
|
||||
|
||||
if (wpc.target_system == mavlink_system.sysid/* && wpc.target_component == mavlink_wpm_comp_id*/) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) {
|
||||
|
||||
if (wpc.count > NUM_MISSIONS_SUPPORTED) {
|
||||
if (verbose) warnx("Too many waypoints: %d, supported: %d", wpc.count, NUM_MISSIONS_SUPPORTED);
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_NO_SPACE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wpc.count == 0) {
|
||||
mavlink_missionlib_send_gcs_string("COUNT 0");
|
||||
if (verbose) warnx("got waypoint count of 0, clearing waypoint list and staying in state MAVLINK_WPM_STATE_IDLE");
|
||||
break;
|
||||
}
|
||||
|
||||
if (verbose) warnx("Got MAVLINK_MSG_ID_MISSION_ITEM_COUNT (%u) from %u changing state to MAVLINK_WPM_STATE_GETLIST", wpc.count, msg->sysid);
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_GETLIST;
|
||||
wpm->current_wp_id = 0;
|
||||
wpm->current_partner_sysid = msg->sysid;
|
||||
wpm->current_partner_compid = msg->compid;
|
||||
wpm->current_count = wpc.count;
|
||||
|
||||
mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id);
|
||||
|
||||
} else if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST) {
|
||||
|
||||
if (wpm->current_wp_id == 0) {
|
||||
mavlink_missionlib_send_gcs_string("WP CMD OK AGAIN");
|
||||
if (verbose) warnx("Got MAVLINK_MSG_ID_MISSION_ITEM_COUNT (%u) again from %u", wpc.count, msg->sysid);
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: Busy");
|
||||
if (verbose) warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM_COUNT because i'm already receiving waypoint %u.", wpm->current_wp_id);
|
||||
}
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("IGN MISSION_COUNT CMD: Busy");
|
||||
if (verbose) warnx("IGN MISSION_COUNT CMD: Busy");
|
||||
}
|
||||
} else {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP COUNT CMD: target id mismatch");
|
||||
if (verbose) warnx("IGNORED WAYPOINT COUNT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_ITEM: {
|
||||
mavlink_mission_item_t wp;
|
||||
mavlink_msg_mission_item_decode(msg, &wp);
|
||||
|
||||
if (wp.target_system == mavlink_system.sysid && wp.target_component == mavlink_wpm_comp_id) {
|
||||
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
/*
|
||||
* ensure that we are in the correct state and that the first waypoint has id 0
|
||||
* and the following waypoints have the correct ids
|
||||
*/
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST) {
|
||||
|
||||
if (wp.seq != 0) {
|
||||
mavlink_missionlib_send_gcs_string("Ignored MISSION_ITEM WP not 0");
|
||||
warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the first waypoint ID (%u) was not 0.", wp.seq);
|
||||
break;
|
||||
}
|
||||
} else if (wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS) {
|
||||
|
||||
if (wp.seq >= wpm->current_count) {
|
||||
mavlink_missionlib_send_gcs_string("Ignored MISSION_ITEM WP out of bounds");
|
||||
warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the waypoint ID (%u) was out of bounds.", wp.seq);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wp.seq != wpm->current_wp_id) {
|
||||
warnx("Ignored MAVLINK_MSG_ID_MISSION_ITEM because the waypoint ID (%u) was not the expected %u.", wp.seq, wpm->current_wp_id);
|
||||
mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_GETLIST_GETWPS;
|
||||
|
||||
struct mission_item_s mission_item;
|
||||
|
||||
int ret = map_mavlink_mission_item_to_mission_item(&wp, &mission_item);
|
||||
|
||||
if (ret != OK) {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, ret);
|
||||
wpm->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
dm_item_t dm_next;
|
||||
|
||||
if (wpm->current_dataman_id == 0) {
|
||||
dm_next = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||
mission.dataman_id = 1;
|
||||
} else {
|
||||
dm_next = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||
mission.dataman_id = 0;
|
||||
}
|
||||
|
||||
if (dm_write(dm_next, wp.seq, DM_PERSIST_IN_FLIGHT_RESET, &mission_item, len) != len) {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ERROR);
|
||||
wpm->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wp.current) {
|
||||
mission.current_index = wp.seq;
|
||||
}
|
||||
|
||||
wpm->current_wp_id = wp.seq + 1;
|
||||
|
||||
if (wpm->current_wp_id == wpm->current_count && wpm->current_state == MAVLINK_WPM_STATE_GETLIST_GETWPS) {
|
||||
|
||||
if (verbose) warnx("Got all %u waypoints, changing state to MAVLINK_WPM_STATE_IDLE", wpm->current_count);
|
||||
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ACCEPTED);
|
||||
|
||||
mission.count = wpm->current_count;
|
||||
|
||||
publish_mission();
|
||||
|
||||
wpm->current_dataman_id = mission.dataman_id;
|
||||
wpm->size = wpm->current_count;
|
||||
|
||||
wpm->current_state = MAVLINK_WPM_STATE_IDLE;
|
||||
|
||||
} else {
|
||||
mavlink_wpm_send_waypoint_request(wpm->current_partner_sysid, wpm->current_partner_compid, wpm->current_wp_id);
|
||||
}
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CMD: target id mismatch");
|
||||
if (verbose) warnx("IGNORED WAYPOINT COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MAVLINK_MSG_ID_MISSION_CLEAR_ALL: {
|
||||
mavlink_mission_clear_all_t wpca;
|
||||
mavlink_msg_mission_clear_all_decode(msg, &wpca);
|
||||
|
||||
if (wpca.target_system == mavlink_system.sysid /*&& wpca.target_component == mavlink_wpm_comp_id */) {
|
||||
|
||||
if (wpm->current_state == MAVLINK_WPM_STATE_IDLE) {
|
||||
wpm->timestamp_lastaction = now;
|
||||
|
||||
wpm->size = 0;
|
||||
|
||||
/* prepare mission topic */
|
||||
mission.dataman_id = -1;
|
||||
mission.count = 0;
|
||||
mission.current_index = -1;
|
||||
publish_mission();
|
||||
|
||||
if (dm_clear(DM_KEY_WAYPOINTS_OFFBOARD_0) == OK && dm_clear(DM_KEY_WAYPOINTS_OFFBOARD_1) == OK) {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ACCEPTED);
|
||||
} else {
|
||||
mavlink_wpm_send_waypoint_ack(wpm->current_partner_sysid, wpm->current_partner_compid, MAV_MISSION_ERROR);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
mavlink_missionlib_send_gcs_string("IGN WP CLEAR CMD: Busy");
|
||||
if (verbose) warnx("IGN WP CLEAR CMD: Busy");
|
||||
}
|
||||
|
||||
|
||||
} else if (wpca.target_system == mavlink_system.sysid /*&& wpca.target_component == mavlink_wpm_comp_id */ && wpm->current_state != MAVLINK_WPM_STATE_IDLE) {
|
||||
|
||||
mavlink_missionlib_send_gcs_string("REJ. WP CLERR CMD: target id mismatch");
|
||||
if (verbose) warnx("IGNORED WAYPOINT CLEAR COMMAND BECAUSE TARGET SYSTEM AND COMPONENT OR COMM PARTNER ID MISMATCH");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
/* other messages might should get caught by mavlink and others */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
* Copyright (c) 2009-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -37,6 +34,11 @@
|
||||
/**
|
||||
* @file waypoints.h
|
||||
* MAVLink waypoint protocol definition (BSD-relicensed).
|
||||
*
|
||||
* @author Petri Tanskanen <petri.tanskanen@inf.ethz.ch>
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef WAYPOINTS_H_
|
||||
@@ -106,7 +108,4 @@ extern void mavlink_missionlib_current_waypoint_changed(uint16_t index, float pa
|
||||
|
||||
static uint8_t missionlib_msg_buf[MAVLINK_MAX_PACKET_LEN];
|
||||
|
||||
void mavlink_missionlib_send_message(mavlink_message_t *msg);
|
||||
int mavlink_missionlib_send_gcs_string(const char *string);
|
||||
|
||||
#endif /* WAYPOINTS_H_ */
|
||||
|
||||
@@ -1,537 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink.c
|
||||
* MAVLink 1.0 protocol implementation.
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
#include <string.h>
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <unistd.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/err.h>
|
||||
|
||||
#include "orb_topics.h"
|
||||
#include "util.h"
|
||||
|
||||
__EXPORT int mavlink_onboard_main(int argc, char *argv[]);
|
||||
|
||||
static int mavlink_thread_main(int argc, char *argv[]);
|
||||
|
||||
/* thread state */
|
||||
volatile bool thread_should_exit = false;
|
||||
static volatile bool thread_running = false;
|
||||
static int mavlink_task;
|
||||
|
||||
/* pthreads */
|
||||
static pthread_t receive_thread;
|
||||
|
||||
/* terminate MAVLink on user request - disabled by default */
|
||||
static bool mavlink_link_termination_allowed = false;
|
||||
|
||||
mavlink_system_t mavlink_system = {
|
||||
100,
|
||||
50,
|
||||
MAV_TYPE_QUADROTOR,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}; // System ID, 1-255, Component/Subsystem ID, 1-255
|
||||
|
||||
/* XXX not widely used */
|
||||
uint8_t chan = MAVLINK_COMM_0;
|
||||
|
||||
/* XXX probably should be in a header... */
|
||||
extern pthread_t receive_start(int uart);
|
||||
|
||||
bool mavlink_hil_enabled = false;
|
||||
|
||||
/* protocol interface */
|
||||
static int uart;
|
||||
static int baudrate;
|
||||
bool gcs_link = true;
|
||||
|
||||
/* interface mode */
|
||||
static enum {
|
||||
MAVLINK_INTERFACE_MODE_OFFBOARD,
|
||||
MAVLINK_INTERFACE_MODE_ONBOARD
|
||||
} mavlink_link_mode = MAVLINK_INTERFACE_MODE_OFFBOARD;
|
||||
|
||||
static void mavlink_update_system(void);
|
||||
static int mavlink_open_uart(int baudrate, const char *uart_name, struct termios *uart_config_original, bool *is_usb);
|
||||
static void usage(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int mavlink_open_uart(int baud, const char *uart_name, struct termios *uart_config_original, bool *is_usb)
|
||||
{
|
||||
/* process baud rate */
|
||||
int speed;
|
||||
|
||||
switch (baud) {
|
||||
case 0: speed = B0; break;
|
||||
|
||||
case 50: speed = B50; break;
|
||||
|
||||
case 75: speed = B75; break;
|
||||
|
||||
case 110: speed = B110; break;
|
||||
|
||||
case 134: speed = B134; break;
|
||||
|
||||
case 150: speed = B150; break;
|
||||
|
||||
case 200: speed = B200; break;
|
||||
|
||||
case 300: speed = B300; break;
|
||||
|
||||
case 600: speed = B600; break;
|
||||
|
||||
case 1200: speed = B1200; break;
|
||||
|
||||
case 1800: speed = B1800; break;
|
||||
|
||||
case 2400: speed = B2400; break;
|
||||
|
||||
case 4800: speed = B4800; break;
|
||||
|
||||
case 9600: speed = B9600; break;
|
||||
|
||||
case 19200: speed = B19200; break;
|
||||
|
||||
case 38400: speed = B38400; break;
|
||||
|
||||
case 57600: speed = B57600; break;
|
||||
|
||||
case 115200: speed = B115200; break;
|
||||
|
||||
case 230400: speed = B230400; break;
|
||||
|
||||
case 460800: speed = B460800; break;
|
||||
|
||||
case 921600: speed = B921600; break;
|
||||
|
||||
default:
|
||||
warnx("ERROR: Unsupported baudrate: %d\n\tsupported examples:\n\n\t9600\n19200\n38400\n57600\n115200\n230400\n460800\n921600", baud);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* open uart */
|
||||
warnx("UART is %s, baudrate is %d", uart_name, baud);
|
||||
uart = open(uart_name, O_RDWR | O_NOCTTY);
|
||||
|
||||
/* Try to set baud rate */
|
||||
struct termios uart_config;
|
||||
int termios_state;
|
||||
*is_usb = false;
|
||||
|
||||
if (strcmp(uart_name, "/dev/ttyACM0") != OK) {
|
||||
/* Back up the original uart configuration to restore it after exit */
|
||||
if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) {
|
||||
warnx("ERROR getting baudrate / termios config for %s: %d", uart_name, termios_state);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill the struct for the new configuration */
|
||||
tcgetattr(uart, &uart_config);
|
||||
|
||||
/* Clear ONLCR flag (which appends a CR for every LF) */
|
||||
uart_config.c_oflag &= ~ONLCR;
|
||||
|
||||
/* Set baud rate */
|
||||
if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) {
|
||||
warnx("ERROR setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)", uart_name, termios_state);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) {
|
||||
warnx("ERROR setting baudrate / termios config for %s (tcsetattr)", uart_name);
|
||||
close(uart);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
*is_usb = true;
|
||||
}
|
||||
|
||||
return uart;
|
||||
}
|
||||
|
||||
void
|
||||
mavlink_send_uart_bytes(mavlink_channel_t channel, uint8_t *ch, int length)
|
||||
{
|
||||
write(uart, ch, (size_t)(sizeof(uint8_t) * length));
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to give access to the channel status for each channel
|
||||
*/
|
||||
mavlink_status_t* mavlink_get_channel_status(uint8_t channel)
|
||||
{
|
||||
static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS];
|
||||
return &m_mavlink_status[channel];
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to give access to the channel buffer for each channel
|
||||
*/
|
||||
mavlink_message_t* mavlink_get_channel_buffer(uint8_t channel)
|
||||
{
|
||||
static mavlink_message_t m_mavlink_buffer[MAVLINK_COMM_NUM_BUFFERS];
|
||||
return &m_mavlink_buffer[channel];
|
||||
}
|
||||
|
||||
void mavlink_update_system(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
param_t param_system_id;
|
||||
param_t param_component_id;
|
||||
param_t param_system_type;
|
||||
|
||||
if (!initialized) {
|
||||
param_system_id = param_find("MAV_SYS_ID");
|
||||
param_component_id = param_find("MAV_COMP_ID");
|
||||
param_system_type = param_find("MAV_TYPE");
|
||||
}
|
||||
|
||||
/* update system and component id */
|
||||
int32_t system_id;
|
||||
param_get(param_system_id, &system_id);
|
||||
if (system_id > 0 && system_id < 255) {
|
||||
mavlink_system.sysid = system_id;
|
||||
}
|
||||
|
||||
int32_t component_id;
|
||||
param_get(param_component_id, &component_id);
|
||||
if (component_id > 0 && component_id < 255) {
|
||||
mavlink_system.compid = component_id;
|
||||
}
|
||||
|
||||
int32_t system_type;
|
||||
param_get(param_system_type, &system_type);
|
||||
if (system_type >= 0 && system_type < MAV_TYPE_ENUM_END) {
|
||||
mavlink_system.type = system_type;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
get_mavlink_mode_and_state(const struct vehicle_control_mode_s *control_mode, const struct actuator_armed_s *armed,
|
||||
uint8_t *mavlink_state, uint8_t *mavlink_mode)
|
||||
{
|
||||
/* reset MAVLink mode bitfield */
|
||||
*mavlink_mode = 0;
|
||||
|
||||
/* set mode flags independent of system state */
|
||||
if (control_mode->flag_control_manual_enabled) {
|
||||
*mavlink_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED;
|
||||
}
|
||||
|
||||
if (control_mode->flag_system_hil_enabled) {
|
||||
*mavlink_mode |= MAV_MODE_FLAG_HIL_ENABLED;
|
||||
}
|
||||
|
||||
/* set arming state */
|
||||
if (armed->armed) {
|
||||
*mavlink_mode |= MAV_MODE_FLAG_SAFETY_ARMED;
|
||||
} else {
|
||||
*mavlink_mode &= ~MAV_MODE_FLAG_SAFETY_ARMED;
|
||||
}
|
||||
|
||||
if (control_mode->flag_control_velocity_enabled) {
|
||||
*mavlink_mode |= MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
} else {
|
||||
*mavlink_mode &= ~MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
}
|
||||
|
||||
// switch (v_status->state_machine) {
|
||||
// case SYSTEM_STATE_PREFLIGHT:
|
||||
// if (v_status->flag_preflight_gyro_calibration ||
|
||||
// v_status->flag_preflight_mag_calibration ||
|
||||
// v_status->flag_preflight_accel_calibration) {
|
||||
// *mavlink_state = MAV_STATE_CALIBRATING;
|
||||
// } else {
|
||||
// *mavlink_state = MAV_STATE_UNINIT;
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_STANDBY:
|
||||
// *mavlink_state = MAV_STATE_STANDBY;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_GROUND_READY:
|
||||
// *mavlink_state = MAV_STATE_ACTIVE;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_MANUAL:
|
||||
// *mavlink_state = MAV_STATE_ACTIVE;
|
||||
// *mavlink_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_STABILIZED:
|
||||
// *mavlink_state = MAV_STATE_ACTIVE;
|
||||
// *mavlink_mode |= MAV_MODE_FLAG_STABILIZE_ENABLED;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_AUTO:
|
||||
// *mavlink_state = MAV_STATE_ACTIVE;
|
||||
// *mavlink_mode |= MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_MISSION_ABORT:
|
||||
// *mavlink_state = MAV_STATE_EMERGENCY;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_EMCY_LANDING:
|
||||
// *mavlink_state = MAV_STATE_EMERGENCY;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_EMCY_CUTOFF:
|
||||
// *mavlink_state = MAV_STATE_EMERGENCY;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_GROUND_ERROR:
|
||||
// *mavlink_state = MAV_STATE_EMERGENCY;
|
||||
// break;
|
||||
//
|
||||
// case SYSTEM_STATE_REBOOT:
|
||||
// *mavlink_state = MAV_STATE_POWEROFF;
|
||||
// break;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* MAVLink Protocol main function.
|
||||
*/
|
||||
int mavlink_thread_main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
char *device_name = "/dev/ttyS1";
|
||||
baudrate = 57600;
|
||||
|
||||
/* XXX this is never written? */
|
||||
struct vehicle_status_s v_status;
|
||||
struct vehicle_control_mode_s control_mode;
|
||||
struct actuator_armed_s armed;
|
||||
|
||||
/* work around some stupidity in task_create's argv handling */
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:d:eo")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
baudrate = strtoul(optarg, NULL, 10);
|
||||
if (baudrate == 0)
|
||||
errx(1, "invalid baud rate '%s'", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
device_name = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
mavlink_link_termination_allowed = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
mavlink_link_mode = MAVLINK_INTERFACE_MODE_ONBOARD;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
struct termios uart_config_original;
|
||||
bool usb_uart;
|
||||
|
||||
/* print welcome text */
|
||||
warnx("MAVLink v1.0 serial interface starting...");
|
||||
|
||||
/* inform about mode */
|
||||
warnx((mavlink_link_mode == MAVLINK_INTERFACE_MODE_ONBOARD) ? "ONBOARD MODE" : "DOWNLINK MODE");
|
||||
|
||||
/* Flush stdout in case MAVLink is about to take it over */
|
||||
fflush(stdout);
|
||||
|
||||
/* default values for arguments */
|
||||
uart = mavlink_open_uart(baudrate, device_name, &uart_config_original, &usb_uart);
|
||||
if (uart < 0)
|
||||
err(1, "could not open %s", device_name);
|
||||
|
||||
/* Initialize system properties */
|
||||
mavlink_update_system();
|
||||
|
||||
/* start the MAVLink receiver */
|
||||
receive_thread = receive_start(uart);
|
||||
|
||||
thread_running = true;
|
||||
|
||||
/* arm counter to go off immediately */
|
||||
unsigned lowspeed_counter = 10;
|
||||
|
||||
while (!thread_should_exit) {
|
||||
|
||||
/* 1 Hz */
|
||||
if (lowspeed_counter == 10) {
|
||||
mavlink_update_system();
|
||||
|
||||
/* translate the current system state to mavlink state and mode */
|
||||
uint8_t mavlink_state = 0;
|
||||
uint8_t mavlink_mode = 0;
|
||||
get_mavlink_mode_and_state(&control_mode, &armed, &mavlink_state, &mavlink_mode);
|
||||
|
||||
/* send heartbeat */
|
||||
// TODO fix navigation state, use control_mode topic
|
||||
mavlink_msg_heartbeat_send(chan, mavlink_system.type, MAV_AUTOPILOT_PX4, mavlink_mode, 0, mavlink_state);
|
||||
|
||||
/* send status (values already copied in the section above) */
|
||||
mavlink_msg_sys_status_send(chan,
|
||||
v_status.onboard_control_sensors_present,
|
||||
v_status.onboard_control_sensors_enabled,
|
||||
v_status.onboard_control_sensors_health,
|
||||
v_status.load * 1000.0f,
|
||||
v_status.battery_voltage * 1000.0f,
|
||||
v_status.battery_current * 1000.0f,
|
||||
v_status.battery_remaining,
|
||||
v_status.drop_rate_comm,
|
||||
v_status.errors_comm,
|
||||
v_status.errors_count1,
|
||||
v_status.errors_count2,
|
||||
v_status.errors_count3,
|
||||
v_status.errors_count4);
|
||||
lowspeed_counter = 0;
|
||||
}
|
||||
lowspeed_counter++;
|
||||
|
||||
/* sleep 1000 ms */
|
||||
usleep(1000000);
|
||||
}
|
||||
|
||||
/* wait for threads to complete */
|
||||
pthread_join(receive_thread, NULL);
|
||||
|
||||
/* Reset the UART flags to original state */
|
||||
if (!usb_uart)
|
||||
tcsetattr(uart, TCSANOW, &uart_config_original);
|
||||
|
||||
thread_running = false;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: mavlink_onboard start [-d <devicename>] [-b <baud rate>]\n"
|
||||
" mavlink_onboard stop\n"
|
||||
" mavlink_onboard status\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int mavlink_onboard_main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argc < 2) {
|
||||
warnx("missing command");
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
/* this is not an error */
|
||||
if (thread_running)
|
||||
errx(0, "already running");
|
||||
|
||||
thread_should_exit = false;
|
||||
mavlink_task = task_spawn_cmd("mavlink_onboard",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_DEFAULT,
|
||||
2048,
|
||||
mavlink_thread_main,
|
||||
(const char**)argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
thread_should_exit = true;
|
||||
while (thread_running) {
|
||||
usleep(200000);
|
||||
}
|
||||
warnx("terminated");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
errx(0, "running");
|
||||
} else {
|
||||
errx(1, "not running");
|
||||
}
|
||||
}
|
||||
|
||||
warnx("unrecognized command");
|
||||
usage();
|
||||
/* not getting here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_bridge_header
|
||||
* MAVLink bridge header for UART access.
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
/* MAVLink adapter header */
|
||||
#ifndef MAVLINK_BRIDGE_HEADER_H
|
||||
#define MAVLINK_BRIDGE_HEADER_H
|
||||
|
||||
#define MAVLINK_USE_CONVENIENCE_FUNCTIONS
|
||||
|
||||
/* use efficient approach, see mavlink_helpers.h */
|
||||
#define MAVLINK_SEND_UART_BYTES mavlink_send_uart_bytes
|
||||
|
||||
#define MAVLINK_GET_CHANNEL_BUFFER mavlink_get_channel_buffer
|
||||
#define MAVLINK_GET_CHANNEL_STATUS mavlink_get_channel_status
|
||||
|
||||
#include <v1.0/mavlink_types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* Struct that stores the communication settings of this system.
|
||||
you can also define / alter these settings elsewhere, as long
|
||||
as they're included BEFORE mavlink.h.
|
||||
So you can set the
|
||||
|
||||
mavlink_system.sysid = 100; // System ID, 1-255
|
||||
mavlink_system.compid = 50; // Component/Subsystem ID, 1-255
|
||||
|
||||
Lines also in your main.c, e.g. by reading these parameter from EEPROM.
|
||||
*/
|
||||
extern mavlink_system_t mavlink_system;
|
||||
|
||||
/**
|
||||
* @brief Send multiple chars (uint8_t) over a comm channel
|
||||
*
|
||||
* @param chan MAVLink channel to use, usually MAVLINK_COMM_0 = UART0
|
||||
* @param ch Character to send
|
||||
*/
|
||||
extern void mavlink_send_uart_bytes(mavlink_channel_t chan, uint8_t *ch, int length);
|
||||
|
||||
mavlink_status_t* mavlink_get_channel_status(uint8_t chan);
|
||||
mavlink_message_t* mavlink_get_channel_buffer(uint8_t chan);
|
||||
|
||||
#include <v1.0/common/mavlink.h>
|
||||
|
||||
#endif /* MAVLINK_BRIDGE_HEADER_H */
|
||||
@@ -1,344 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file mavlink_receiver.c
|
||||
* MAVLink protocol message receive and dispatch
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
/* XXX trim includes */
|
||||
#include <nuttx/config.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
#include <string.h>
|
||||
#include "mavlink_bridge_header.h"
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <unistd.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "orb_topics.h"
|
||||
|
||||
/* XXX should be in a header somewhere */
|
||||
pthread_t receive_start(int uart);
|
||||
|
||||
static void handle_message(mavlink_message_t *msg);
|
||||
static void *receive_thread(void *arg);
|
||||
|
||||
static mavlink_status_t status;
|
||||
static struct vehicle_vicon_position_s vicon_position;
|
||||
static struct vehicle_command_s vcmd;
|
||||
static struct offboard_control_setpoint_s offboard_control_sp;
|
||||
|
||||
struct vehicle_global_position_s hil_global_pos;
|
||||
struct vehicle_attitude_s hil_attitude;
|
||||
orb_advert_t pub_hil_global_pos = -1;
|
||||
orb_advert_t pub_hil_attitude = -1;
|
||||
|
||||
static orb_advert_t cmd_pub = -1;
|
||||
static orb_advert_t flow_pub = -1;
|
||||
|
||||
static orb_advert_t offboard_control_sp_pub = -1;
|
||||
static orb_advert_t vicon_position_pub = -1;
|
||||
|
||||
extern bool gcs_link;
|
||||
|
||||
static void
|
||||
handle_message(mavlink_message_t *msg)
|
||||
{
|
||||
if (msg->msgid == MAVLINK_MSG_ID_COMMAND_LONG) {
|
||||
|
||||
mavlink_command_long_t cmd_mavlink;
|
||||
mavlink_msg_command_long_decode(msg, &cmd_mavlink);
|
||||
|
||||
if (cmd_mavlink.target_system == mavlink_system.sysid && ((cmd_mavlink.target_component == mavlink_system.compid)
|
||||
|| (cmd_mavlink.target_component == MAV_COMP_ID_ALL))) {
|
||||
//check for MAVLINK terminate command
|
||||
if (cmd_mavlink.command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN && ((int)cmd_mavlink.param1) == 3) {
|
||||
/* This is the link shutdown command, terminate mavlink */
|
||||
warnx("terminating...");
|
||||
fflush(stdout);
|
||||
usleep(50000);
|
||||
|
||||
/* terminate other threads and this thread */
|
||||
thread_should_exit = true;
|
||||
|
||||
} else {
|
||||
|
||||
/* Copy the content of mavlink_command_long_t cmd_mavlink into command_t cmd */
|
||||
vcmd.param1 = cmd_mavlink.param1;
|
||||
vcmd.param2 = cmd_mavlink.param2;
|
||||
vcmd.param3 = cmd_mavlink.param3;
|
||||
vcmd.param4 = cmd_mavlink.param4;
|
||||
vcmd.param5 = cmd_mavlink.param5;
|
||||
vcmd.param6 = cmd_mavlink.param6;
|
||||
vcmd.param7 = cmd_mavlink.param7;
|
||||
vcmd.command = cmd_mavlink.command;
|
||||
vcmd.target_system = cmd_mavlink.target_system;
|
||||
vcmd.target_component = cmd_mavlink.target_component;
|
||||
vcmd.source_system = msg->sysid;
|
||||
vcmd.source_component = msg->compid;
|
||||
vcmd.confirmation = cmd_mavlink.confirmation;
|
||||
|
||||
/* check if topic is advertised */
|
||||
if (cmd_pub <= 0) {
|
||||
cmd_pub = orb_advertise(ORB_ID(vehicle_command), &vcmd);
|
||||
}
|
||||
|
||||
/* publish */
|
||||
orb_publish(ORB_ID(vehicle_command), cmd_pub, &vcmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->msgid == MAVLINK_MSG_ID_OPTICAL_FLOW) {
|
||||
mavlink_optical_flow_t flow;
|
||||
mavlink_msg_optical_flow_decode(msg, &flow);
|
||||
|
||||
struct optical_flow_s f;
|
||||
|
||||
f.timestamp = hrt_absolute_time();
|
||||
f.flow_raw_x = flow.flow_x;
|
||||
f.flow_raw_y = flow.flow_y;
|
||||
f.flow_comp_x_m = flow.flow_comp_m_x;
|
||||
f.flow_comp_y_m = flow.flow_comp_m_y;
|
||||
f.ground_distance_m = flow.ground_distance;
|
||||
f.quality = flow.quality;
|
||||
f.sensor_id = flow.sensor_id;
|
||||
|
||||
/* check if topic is advertised */
|
||||
if (flow_pub <= 0) {
|
||||
flow_pub = orb_advertise(ORB_ID(optical_flow), &f);
|
||||
|
||||
} else {
|
||||
/* publish */
|
||||
orb_publish(ORB_ID(optical_flow), flow_pub, &f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (msg->msgid == MAVLINK_MSG_ID_SET_MODE) {
|
||||
/* Set mode on request */
|
||||
mavlink_set_mode_t new_mode;
|
||||
mavlink_msg_set_mode_decode(msg, &new_mode);
|
||||
|
||||
/* Copy the content of mavlink_command_long_t cmd_mavlink into command_t cmd */
|
||||
vcmd.param1 = new_mode.base_mode;
|
||||
vcmd.param2 = new_mode.custom_mode;
|
||||
vcmd.param3 = 0;
|
||||
vcmd.param4 = 0;
|
||||
vcmd.param5 = 0;
|
||||
vcmd.param6 = 0;
|
||||
vcmd.param7 = 0;
|
||||
vcmd.command = MAV_CMD_DO_SET_MODE;
|
||||
vcmd.target_system = new_mode.target_system;
|
||||
vcmd.target_component = MAV_COMP_ID_ALL;
|
||||
vcmd.source_system = msg->sysid;
|
||||
vcmd.source_component = msg->compid;
|
||||
vcmd.confirmation = 1;
|
||||
|
||||
/* check if topic is advertised */
|
||||
if (cmd_pub <= 0) {
|
||||
cmd_pub = orb_advertise(ORB_ID(vehicle_command), &vcmd);
|
||||
|
||||
} else {
|
||||
/* create command */
|
||||
orb_publish(ORB_ID(vehicle_command), cmd_pub, &vcmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Vicon position estimates */
|
||||
if (msg->msgid == MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE) {
|
||||
mavlink_vicon_position_estimate_t pos;
|
||||
mavlink_msg_vicon_position_estimate_decode(msg, &pos);
|
||||
|
||||
vicon_position.x = pos.x;
|
||||
vicon_position.y = pos.y;
|
||||
vicon_position.z = pos.z;
|
||||
|
||||
if (vicon_position_pub <= 0) {
|
||||
vicon_position_pub = orb_advertise(ORB_ID(vehicle_vicon_position), &vicon_position);
|
||||
|
||||
} else {
|
||||
orb_publish(ORB_ID(vehicle_vicon_position), vicon_position_pub, &vicon_position);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle quadrotor motor setpoints */
|
||||
|
||||
if (msg->msgid == MAVLINK_MSG_ID_SET_QUAD_SWARM_ROLL_PITCH_YAW_THRUST) {
|
||||
mavlink_set_quad_swarm_roll_pitch_yaw_thrust_t quad_motors_setpoint;
|
||||
mavlink_msg_set_quad_swarm_roll_pitch_yaw_thrust_decode(msg, &quad_motors_setpoint);
|
||||
|
||||
if (mavlink_system.sysid < 4) {
|
||||
|
||||
/* switch to a receiving link mode */
|
||||
gcs_link = false;
|
||||
|
||||
/*
|
||||
* rate control mode - defined by MAVLink
|
||||
*/
|
||||
|
||||
uint8_t ml_mode = 0;
|
||||
bool ml_armed = false;
|
||||
|
||||
switch (quad_motors_setpoint.mode) {
|
||||
case 0:
|
||||
ml_armed = false;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ml_mode = OFFBOARD_CONTROL_MODE_DIRECT_RATES;
|
||||
ml_armed = true;
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ml_mode = OFFBOARD_CONTROL_MODE_DIRECT_ATTITUDE;
|
||||
ml_armed = true;
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ml_mode = OFFBOARD_CONTROL_MODE_DIRECT_VELOCITY;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ml_mode = OFFBOARD_CONTROL_MODE_DIRECT_POSITION;
|
||||
break;
|
||||
}
|
||||
|
||||
offboard_control_sp.p1 = (float)quad_motors_setpoint.roll[mavlink_system.sysid - 1] / (float)INT16_MAX;
|
||||
offboard_control_sp.p2 = (float)quad_motors_setpoint.pitch[mavlink_system.sysid - 1] / (float)INT16_MAX;
|
||||
offboard_control_sp.p3 = (float)quad_motors_setpoint.yaw[mavlink_system.sysid - 1] / (float)INT16_MAX;
|
||||
offboard_control_sp.p4 = (float)quad_motors_setpoint.thrust[mavlink_system.sysid - 1] / (float)UINT16_MAX;
|
||||
|
||||
if (quad_motors_setpoint.thrust[mavlink_system.sysid - 1] == 0) {
|
||||
ml_armed = false;
|
||||
}
|
||||
|
||||
offboard_control_sp.armed = ml_armed;
|
||||
offboard_control_sp.mode = ml_mode;
|
||||
|
||||
offboard_control_sp.timestamp = hrt_absolute_time();
|
||||
|
||||
/* check if topic has to be advertised */
|
||||
if (offboard_control_sp_pub <= 0) {
|
||||
offboard_control_sp_pub = orb_advertise(ORB_ID(offboard_control_setpoint), &offboard_control_sp);
|
||||
|
||||
} else {
|
||||
/* Publish */
|
||||
orb_publish(ORB_ID(offboard_control_setpoint), offboard_control_sp_pub, &offboard_control_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receive data from UART.
|
||||
*/
|
||||
static void *
|
||||
receive_thread(void *arg)
|
||||
{
|
||||
int uart_fd = *((int *)arg);
|
||||
|
||||
const int timeout = 1000;
|
||||
uint8_t buf[32];
|
||||
|
||||
mavlink_message_t msg;
|
||||
|
||||
prctl(PR_SET_NAME, "mavlink_onboard_rcv", getpid());
|
||||
|
||||
struct pollfd fds[] = { { .fd = uart_fd, .events = POLLIN } };
|
||||
|
||||
ssize_t nread = 0;
|
||||
|
||||
while (!thread_should_exit) {
|
||||
if (poll(fds, 1, timeout) > 0) {
|
||||
if (nread < sizeof(buf)) {
|
||||
/* to avoid reading very small chunks wait for data before reading */
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
/* non-blocking read. read may return negative values */
|
||||
nread = read(uart_fd, buf, sizeof(buf));
|
||||
|
||||
/* if read failed, this loop won't execute */
|
||||
for (ssize_t i = 0; i < nread; i++) {
|
||||
if (mavlink_parse_char(chan, buf[i], &msg, &status)) {
|
||||
/* handle generic messages and commands */
|
||||
handle_message(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pthread_t
|
||||
receive_start(int uart)
|
||||
{
|
||||
pthread_attr_t receiveloop_attr;
|
||||
pthread_attr_init(&receiveloop_attr);
|
||||
|
||||
struct sched_param param;
|
||||
param.sched_priority = SCHED_PRIORITY_MAX - 40;
|
||||
(void)pthread_attr_setschedparam(&receiveloop_attr, ¶m);
|
||||
|
||||
pthread_attr_setstacksize(&receiveloop_attr, 2048);
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, &receiveloop_attr, receive_thread, &uart);
|
||||
return thread;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2012-2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# MAVLink protocol to uORB interface process (XXX hack for onboard use)
|
||||
#
|
||||
|
||||
MODULE_COMMAND = mavlink_onboard
|
||||
SRCS = mavlink.c \
|
||||
mavlink_receiver.c
|
||||
|
||||
INCLUDE_DIRS += $(MAVLINK_SRC)/include/mavlink
|
||||
@@ -1,102 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file orb_topics.h
|
||||
* Common sets of topics subscribed to or published by the MAVLink driver,
|
||||
* and structures maintained by those subscriptions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/sensor_combined.h>
|
||||
#include <uORB/topics/rc_channels.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_gps_position.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/offboard_control_setpoint.h>
|
||||
#include <uORB/topics/vehicle_command.h>
|
||||
#include <uORB/topics/vehicle_local_position_setpoint.h>
|
||||
#include <uORB/topics/vehicle_vicon_position.h>
|
||||
#include <uORB/topics/position_setpoint_triplet.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/optical_flow.h>
|
||||
#include <uORB/topics/actuator_outputs.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/actuator_armed.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <uORB/topics/debug_key_value.h>
|
||||
#include <drivers/drv_rc_input.h>
|
||||
|
||||
struct mavlink_subscriptions {
|
||||
int sensor_sub;
|
||||
int att_sub;
|
||||
int global_pos_sub;
|
||||
int act_0_sub;
|
||||
int act_1_sub;
|
||||
int act_2_sub;
|
||||
int act_3_sub;
|
||||
int gps_sub;
|
||||
int man_control_sp_sub;
|
||||
int safety_sub;
|
||||
int actuators_sub;
|
||||
int local_pos_sub;
|
||||
int spa_sub;
|
||||
int spl_sub;
|
||||
int spg_sub;
|
||||
int debug_key_value;
|
||||
int input_rc_sub;
|
||||
};
|
||||
|
||||
extern struct mavlink_subscriptions mavlink_subs;
|
||||
|
||||
/** Global position */
|
||||
extern struct vehicle_global_position_s global_pos;
|
||||
|
||||
/** Local position */
|
||||
extern struct vehicle_local_position_s local_pos;
|
||||
|
||||
/** Vehicle status */
|
||||
// extern struct vehicle_status_s v_status;
|
||||
|
||||
/** RC channels */
|
||||
extern struct rc_channels_s rc;
|
||||
|
||||
/** Actuator armed state */
|
||||
// extern struct actuator_armed_s armed;
|
||||
|
||||
/** Worker thread starter */
|
||||
extern pthread_t uorb_receive_start(void);
|
||||
@@ -262,8 +262,10 @@ MulticopterAttitudeControl::MulticopterAttitudeControl() :
|
||||
{
|
||||
memset(&_v_att, 0, sizeof(_v_att));
|
||||
memset(&_v_att_sp, 0, sizeof(_v_att_sp));
|
||||
memset(&_v_rates_sp, 0, sizeof(_v_rates_sp));
|
||||
memset(&_manual_control_sp, 0, sizeof(_manual_control_sp));
|
||||
memset(&_v_control_mode, 0, sizeof(_v_control_mode));
|
||||
memset(&_actuators, 0, sizeof(_actuators));
|
||||
memset(&_armed, 0, sizeof(_armed));
|
||||
|
||||
_params.att_p.zero();
|
||||
|
||||
@@ -730,7 +730,6 @@ MulticopterPositionControl::task_main()
|
||||
} else {
|
||||
/* run position & altitude controllers, calculate velocity setpoint */
|
||||
math::Vector<3> pos_err;
|
||||
float err_x, err_y;
|
||||
get_vector_to_next_waypoint_fast(_global_pos.lat, _global_pos.lon, _lat_sp, _lon_sp, &pos_err.data[0], &pos_err.data[1]);
|
||||
pos_err(2) = -(_alt_sp - alt);
|
||||
|
||||
@@ -792,7 +791,6 @@ MulticopterPositionControl::task_main()
|
||||
}
|
||||
|
||||
thrust_int(2) = -i;
|
||||
mavlink_log_info(_mavlink_fd, "[mpc] reset hovering thrust: %.2f", (double)i);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -804,7 +802,6 @@ MulticopterPositionControl::task_main()
|
||||
reset_int_xy = false;
|
||||
thrust_int(0) = 0.0f;
|
||||
thrust_int(1) = 0.0f;
|
||||
mavlink_log_info(_mavlink_fd, "[mpc] reset xy vel integral");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -55,11 +55,13 @@
|
||||
#endif
|
||||
static const int ERROR = -1;
|
||||
|
||||
Geofence::Geofence() : _fence_pub(-1),
|
||||
Geofence::Geofence() :
|
||||
SuperBlock(NULL, "GF"),
|
||||
_fence_pub(-1),
|
||||
_altitude_min(0),
|
||||
_altitude_max(0),
|
||||
_verticesCount(0),
|
||||
param_geofence_on(NULL, "GF_ON", false)
|
||||
param_geofence_on(this, "ON")
|
||||
{
|
||||
/* Load initial params */
|
||||
updateParams();
|
||||
@@ -292,8 +294,3 @@ int Geofence::clearDm()
|
||||
{
|
||||
dm_clear(DM_KEY_FENCE_POINTS);
|
||||
}
|
||||
|
||||
void Geofence::updateParams()
|
||||
{
|
||||
param_geofence_on.update();
|
||||
}
|
||||
|
||||
@@ -41,11 +41,13 @@
|
||||
#define GEOFENCE_H_
|
||||
|
||||
#include <uORB/topics/fence.h>
|
||||
#include <controllib/blocks.hpp>
|
||||
#include <controllib/block/BlockParam.hpp>
|
||||
|
||||
#define GEOFENCE_FILENAME "/fs/microsd/etc/geofence.txt"
|
||||
|
||||
class Geofence {
|
||||
class Geofence : public control::SuperBlock
|
||||
{
|
||||
private:
|
||||
orb_advert_t _fence_pub; /**< publish fence topic */
|
||||
|
||||
@@ -85,8 +87,6 @@ public:
|
||||
int loadFromFile(const char *filename);
|
||||
|
||||
bool isEmpty() {return _verticesCount == 0;}
|
||||
|
||||
void updateParams();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/home_position.h>
|
||||
#include <uORB/topics/position_setpoint_triplet.h>
|
||||
#include <uORB/topics/mission_result.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
@@ -154,17 +153,16 @@ private:
|
||||
int _capabilities_sub; /**< notification of vehicle capabilities updates */
|
||||
int _control_mode_sub; /**< vehicle control mode subscription */
|
||||
|
||||
orb_advert_t _pos_sp_triplet_pub; /**< publish position setpoint triplet */
|
||||
orb_advert_t _pos_sp_triplet_pub; /**< publish position setpoint triplet */
|
||||
orb_advert_t _mission_result_pub; /**< publish mission result topic */
|
||||
|
||||
struct vehicle_status_s _vstatus; /**< vehicle status */
|
||||
struct vehicle_control_mode_s _control_mode; /**< vehicle control mode */
|
||||
struct vehicle_control_mode_s _control_mode; /**< vehicle control mode */
|
||||
struct vehicle_global_position_s _global_pos; /**< global vehicle position */
|
||||
struct home_position_s _home_pos; /**< home position for RTL */
|
||||
struct position_setpoint_triplet_s _pos_sp_triplet; /**< triplet of position setpoints */
|
||||
struct position_setpoint_triplet_s _pos_sp_triplet; /**< triplet of position setpoints */
|
||||
struct mission_result_s _mission_result; /**< mission result for commander/mavlink */
|
||||
struct mission_item_s _mission_item; /**< current mission item */
|
||||
bool _mission_item_valid; /**< current mission item valid */
|
||||
struct mission_item_s _mission_item; /**< current mission item */
|
||||
|
||||
perf_counter_t _loop_perf; /**< loop performance counter */
|
||||
|
||||
@@ -178,21 +176,22 @@ private:
|
||||
|
||||
class Mission _mission;
|
||||
|
||||
bool _global_pos_valid; /**< track changes of global_position.global_valid flag */
|
||||
bool _reset_loiter_pos; /**< if true then loiter position should be set to current position */
|
||||
bool _mission_item_valid; /**< current mission item valid */
|
||||
bool _global_pos_valid; /**< track changes of global_position.global_valid flag */
|
||||
bool _reset_loiter_pos; /**< if true then loiter position should be set to current position */
|
||||
bool _waypoint_position_reached;
|
||||
bool _waypoint_yaw_reached;
|
||||
uint64_t _time_first_inside_orbit;
|
||||
bool _need_takeoff; /**< if need to perform vertical takeoff before going to waypoint (only for MISSION mode and VTOL vehicles) */
|
||||
bool _do_takeoff; /**< vertical takeoff state, current mission item is generated by navigator (only for MISSION mode and VTOL vehicles) */
|
||||
bool _need_takeoff; /**< if need to perform vertical takeoff before going to waypoint (only for MISSION mode and VTOL vehicles) */
|
||||
bool _do_takeoff; /**< vertical takeoff state, current mission item is generated by navigator (only for MISSION mode and VTOL vehicles) */
|
||||
|
||||
MissionFeasibilityChecker missionFeasiblityChecker;
|
||||
|
||||
uint64_t _set_nav_state_timestamp; /**< timestamp of last handled navigation state request */
|
||||
uint64_t _set_nav_state_timestamp; /**< timestamp of last handled navigation state request */
|
||||
|
||||
bool _pos_sp_triplet_updated;
|
||||
|
||||
char *nav_states_str[NAV_STATE_MAX];
|
||||
const char *nav_states_str[NAV_STATE_MAX];
|
||||
|
||||
struct {
|
||||
float min_altitude;
|
||||
@@ -288,9 +287,9 @@ private:
|
||||
static void task_main_trampoline(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Main sensor collection task.
|
||||
* Main task.
|
||||
*/
|
||||
void task_main() __attribute__((noreturn));
|
||||
void task_main();
|
||||
|
||||
void publish_safepoints(unsigned points);
|
||||
|
||||
@@ -321,6 +320,11 @@ private:
|
||||
*/
|
||||
bool onboard_mission_available(unsigned relative_index);
|
||||
|
||||
/**
|
||||
* Reset all "reached" flags.
|
||||
*/
|
||||
void reset_reached();
|
||||
|
||||
/**
|
||||
* Check if current mission item has been reached.
|
||||
*/
|
||||
@@ -382,35 +386,34 @@ Navigator::Navigator() :
|
||||
_global_pos_sub(-1),
|
||||
_home_pos_sub(-1),
|
||||
_vstatus_sub(-1),
|
||||
_control_mode_sub(-1),
|
||||
_params_sub(-1),
|
||||
_offboard_mission_sub(-1),
|
||||
_onboard_mission_sub(-1),
|
||||
_capabilities_sub(-1),
|
||||
_control_mode_sub(-1),
|
||||
|
||||
/* publications */
|
||||
_pos_sp_triplet_pub(-1),
|
||||
_mission_result_pub(-1),
|
||||
|
||||
/* performance counters */
|
||||
_loop_perf(perf_alloc(PC_ELAPSED, "navigator")),
|
||||
|
||||
/* states */
|
||||
_rtl_state(RTL_STATE_NONE),
|
||||
_geofence_violation_warning_sent(false),
|
||||
_fence_valid(false),
|
||||
_inside_fence(true),
|
||||
_mission(),
|
||||
_mission_item_valid(false),
|
||||
_global_pos_valid(false),
|
||||
_reset_loiter_pos(true),
|
||||
_waypoint_position_reached(false),
|
||||
_waypoint_yaw_reached(false),
|
||||
_time_first_inside_orbit(0),
|
||||
_set_nav_state_timestamp(0),
|
||||
_mission_item_valid(false),
|
||||
_need_takeoff(true),
|
||||
_do_takeoff(false),
|
||||
_set_nav_state_timestamp(0),
|
||||
_pos_sp_triplet_updated(false),
|
||||
_geofence_violation_warning_sent(false)
|
||||
/* states */
|
||||
_rtl_state(RTL_STATE_NONE)
|
||||
{
|
||||
_parameter_handles.min_altitude = param_find("NAV_MIN_ALT");
|
||||
_parameter_handles.acceptance_radius = param_find("NAV_ACCEPT_RAD");
|
||||
@@ -422,7 +425,6 @@ Navigator::Navigator() :
|
||||
_parameter_handles.rtl_land_delay = param_find("NAV_RTL_LAND_T");
|
||||
|
||||
memset(&_pos_sp_triplet, 0, sizeof(struct position_setpoint_triplet_s));
|
||||
memset(&_mission_result, 0, sizeof(struct mission_result_s));
|
||||
memset(&_mission_item, 0, sizeof(struct mission_item_s));
|
||||
|
||||
memset(&nav_states_str, 0, sizeof(nav_states_str));
|
||||
@@ -524,13 +526,16 @@ Navigator::offboard_mission_update(bool isrotaryWing)
|
||||
missionFeasiblityChecker.checkMissionFeasible(isrotaryWing, dm_current, (size_t)offboard_mission.count, _geofence);
|
||||
|
||||
_mission.set_offboard_dataman_id(offboard_mission.dataman_id);
|
||||
_mission.set_current_offboard_mission_index(offboard_mission.current_index);
|
||||
|
||||
_mission.set_offboard_mission_count(offboard_mission.count);
|
||||
_mission.set_current_offboard_mission_index(offboard_mission.current_index);
|
||||
|
||||
} else {
|
||||
_mission.set_current_offboard_mission_index(0);
|
||||
_mission.set_offboard_mission_count(0);
|
||||
_mission.set_current_offboard_mission_index(0);
|
||||
}
|
||||
|
||||
_mission.publish_mission_result();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -540,12 +545,12 @@ Navigator::onboard_mission_update()
|
||||
|
||||
if (orb_copy(ORB_ID(mission), _onboard_mission_sub, &onboard_mission) == OK) {
|
||||
|
||||
_mission.set_current_onboard_mission_index(onboard_mission.current_index);
|
||||
_mission.set_onboard_mission_count(onboard_mission.count);
|
||||
_mission.set_current_onboard_mission_index(onboard_mission.current_index);
|
||||
|
||||
} else {
|
||||
_mission.set_current_onboard_mission_index(0);
|
||||
_mission.set_onboard_mission_count(0);
|
||||
_mission.set_current_onboard_mission_index(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +700,7 @@ Navigator::task_main()
|
||||
if (_vstatus.return_switch == RETURN_SWITCH_RETURN) {
|
||||
/* switch to RTL if not already landed after RTL and home position set */
|
||||
if (!(_rtl_state == RTL_STATE_DESCEND &&
|
||||
(myState == NAV_STATE_READY || myState == NAV_STATE_LAND || myState == NAV_STATE_LOITER)) &&
|
||||
(myState == NAV_STATE_LAND || myState == NAV_STATE_LOITER)) &&
|
||||
_vstatus.condition_home_position_valid) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
@@ -741,7 +746,7 @@ Navigator::task_main()
|
||||
|
||||
case NAV_STATE_RTL:
|
||||
if (!(_rtl_state == RTL_STATE_DESCEND &&
|
||||
(myState == NAV_STATE_READY || myState == NAV_STATE_LAND || myState == NAV_STATE_LOITER)) &&
|
||||
(myState == NAV_STATE_LAND || myState == NAV_STATE_LOITER)) &&
|
||||
_vstatus.condition_home_position_valid) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
@@ -749,9 +754,7 @@ Navigator::task_main()
|
||||
break;
|
||||
|
||||
case NAV_STATE_LAND:
|
||||
if (myState != NAV_STATE_READY) {
|
||||
dispatch(EVENT_LAND_REQUESTED);
|
||||
}
|
||||
dispatch(EVENT_LAND_REQUESTED);
|
||||
|
||||
break;
|
||||
|
||||
@@ -853,11 +856,8 @@ Navigator::task_main()
|
||||
|
||||
/* notify user about state changes */
|
||||
if (myState != prevState) {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] nav state: %s", nav_states_str[myState]);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: navigation state: %s", nav_states_str[myState]);
|
||||
prevState = myState;
|
||||
|
||||
/* reset time counter on state changes */
|
||||
_time_first_inside_orbit = 0;
|
||||
}
|
||||
|
||||
perf_end(_loop_perf);
|
||||
@@ -955,7 +955,7 @@ StateTable::Tran const Navigator::myTable[NAV_STATE_MAX][MAX_EVENT] = {
|
||||
/* EVENT_READY_REQUESTED */ {NO_ACTION, NAV_STATE_READY},
|
||||
/* EVENT_LOITER_REQUESTED */ {NO_ACTION, NAV_STATE_READY},
|
||||
/* EVENT_MISSION_REQUESTED */ {ACTION(&Navigator::start_mission), NAV_STATE_MISSION},
|
||||
/* EVENT_RTL_REQUESTED */ {ACTION(&Navigator::start_rtl), NAV_STATE_RTL},
|
||||
/* EVENT_RTL_REQUESTED */ {NO_ACTION, NAV_STATE_READY},
|
||||
/* EVENT_LAND_REQUESTED */ {NO_ACTION, NAV_STATE_READY},
|
||||
/* EVENT_MISSION_CHANGED */ {NO_ACTION, NAV_STATE_READY},
|
||||
/* EVENT_HOME_POSITION_CHANGED */ {NO_ACTION, NAV_STATE_READY},
|
||||
@@ -1009,6 +1009,8 @@ StateTable::Tran const Navigator::myTable[NAV_STATE_MAX][MAX_EVENT] = {
|
||||
void
|
||||
Navigator::start_none()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
_pos_sp_triplet.previous.valid = false;
|
||||
_pos_sp_triplet.current.valid = false;
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
@@ -1024,6 +1026,8 @@ Navigator::start_none()
|
||||
void
|
||||
Navigator::start_ready()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
_pos_sp_triplet.previous.valid = false;
|
||||
_pos_sp_triplet.current.valid = true;
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
@@ -1046,6 +1050,8 @@ Navigator::start_ready()
|
||||
void
|
||||
Navigator::start_loiter()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
_do_takeoff = false;
|
||||
|
||||
/* set loiter position if needed */
|
||||
@@ -1061,11 +1067,11 @@ Navigator::start_loiter()
|
||||
/* use current altitude if above min altitude set by parameter */
|
||||
if (_global_pos.alt < min_alt_amsl && !_vstatus.is_rotary_wing) {
|
||||
_pos_sp_triplet.current.alt = min_alt_amsl;
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] loiter %.1fm higher", (double)(min_alt_amsl - _global_pos.alt));
|
||||
mavlink_log_info(_mavlink_fd, "#audio: loiter %.1fm higher", (double)(min_alt_amsl - _global_pos.alt));
|
||||
|
||||
} else {
|
||||
_pos_sp_triplet.current.alt = _global_pos.alt;
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] loiter at current altitude");
|
||||
mavlink_log_info(_mavlink_fd, "#audio: loiter at current altitude");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1091,6 +1097,8 @@ Navigator::start_mission()
|
||||
void
|
||||
Navigator::set_mission_item()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
/* copy current mission to previous item */
|
||||
memcpy(&_pos_sp_triplet.previous, &_pos_sp_triplet.current, sizeof(position_setpoint_s));
|
||||
|
||||
@@ -1104,8 +1112,7 @@ Navigator::set_mission_item()
|
||||
ret = _mission.get_current_mission_item(&_mission_item, &onboard, &index);
|
||||
|
||||
if (ret == OK) {
|
||||
/* reset time counter for new item */
|
||||
_time_first_inside_orbit = 0;
|
||||
_mission.report_current_offboard_mission_item();
|
||||
|
||||
_mission_item_valid = true;
|
||||
position_setpoint_from_mission_item(&_pos_sp_triplet.current, &_mission_item);
|
||||
@@ -1162,14 +1169,14 @@ Navigator::set_mission_item()
|
||||
}
|
||||
|
||||
if (_do_takeoff) {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] takeoff to %.1fm above home", _pos_sp_triplet.current.alt - _home_pos.alt);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: takeoff to %.1fm above home", (double)(_pos_sp_triplet.current.alt - _home_pos.alt));
|
||||
|
||||
} else {
|
||||
if (onboard) {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] heading to onboard WP %d", index);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: heading to onboard WP %d", index);
|
||||
|
||||
} else {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] heading to offboard WP %d", index);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: heading to offboard WP %d", index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,6 +1231,8 @@ Navigator::start_rtl()
|
||||
void
|
||||
Navigator::start_land()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
/* this state can be requested by commander even if no global position available,
|
||||
* in his case controller must perform landing without position control */
|
||||
_do_takeoff = false;
|
||||
@@ -1255,6 +1264,8 @@ Navigator::start_land()
|
||||
void
|
||||
Navigator::start_land_home()
|
||||
{
|
||||
reset_reached();
|
||||
|
||||
/* land to home position, should be called when hovering above home, from RTL state */
|
||||
_do_takeoff = false;
|
||||
_reset_loiter_pos = true;
|
||||
@@ -1285,8 +1296,7 @@ Navigator::start_land_home()
|
||||
void
|
||||
Navigator::set_rtl_item()
|
||||
{
|
||||
/*reset time counter for new RTL item */
|
||||
_time_first_inside_orbit = 0;
|
||||
reset_reached();
|
||||
|
||||
switch (_rtl_state) {
|
||||
case RTL_STATE_CLIMB: {
|
||||
@@ -1318,7 +1328,7 @@ Navigator::set_rtl_item()
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: climb to %.1fm above home", climb_alt - _home_pos.alt);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: RTL: climb to %.1fm above home", (double)(climb_alt - _home_pos.alt));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1330,7 +1340,14 @@ Navigator::set_rtl_item()
|
||||
_mission_item.lat = _home_pos.lat;
|
||||
_mission_item.lon = _home_pos.lon;
|
||||
// don't change altitude
|
||||
_mission_item.yaw = NAN; // TODO set heading to home
|
||||
if (_pos_sp_triplet.previous.valid) {
|
||||
/* if previous setpoint is valid then use it to calculate heading to home */
|
||||
_mission_item.yaw = get_bearing_to_next_waypoint(_pos_sp_triplet.previous.lat, _pos_sp_triplet.previous.lon, _mission_item.lat, _mission_item.lon);
|
||||
|
||||
} else {
|
||||
/* else use current position */
|
||||
_mission_item.yaw = get_bearing_to_next_waypoint(_global_pos.lat, _global_pos.lon, _mission_item.lat, _mission_item.lon);
|
||||
}
|
||||
_mission_item.loiter_radius = _parameters.loiter_radius;
|
||||
_mission_item.loiter_direction = 1;
|
||||
_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
|
||||
@@ -1344,7 +1361,7 @@ Navigator::set_rtl_item()
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: return at %.1fm above home", _mission_item.altitude - _home_pos.alt);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: RTL: return at %.1fm above home", (double)(_mission_item.altitude - _home_pos.alt));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1362,7 +1379,7 @@ Navigator::set_rtl_item()
|
||||
_mission_item.loiter_direction = 1;
|
||||
_mission_item.nav_cmd = NAV_CMD_WAYPOINT;
|
||||
_mission_item.acceptance_radius = _parameters.acceptance_radius;
|
||||
_mission_item.time_inside = _parameters.rtl_land_delay < 0.0 ? 0.0f : _parameters.rtl_land_delay;
|
||||
_mission_item.time_inside = _parameters.rtl_land_delay < 0.0f ? 0.0f : _parameters.rtl_land_delay;
|
||||
_mission_item.pitch_min = 0.0f;
|
||||
_mission_item.autocontinue = _parameters.rtl_land_delay > -0.001f;
|
||||
_mission_item.origin = ORIGIN_ONBOARD;
|
||||
@@ -1371,12 +1388,12 @@ Navigator::set_rtl_item()
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: descend to %.1fm above home", _mission_item.altitude - _home_pos.alt);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: RTL: descend to %.1fm above home", (double)(_mission_item.altitude - _home_pos.alt));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
mavlink_log_critical(_mavlink_fd, "[navigator] error: unknown RTL state: %d", _rtl_state);
|
||||
mavlink_log_critical(_mavlink_fd, "#audio: [navigator] error: unknown RTL state: %d", _rtl_state);
|
||||
start_loiter();
|
||||
break;
|
||||
}
|
||||
@@ -1388,7 +1405,8 @@ Navigator::set_rtl_item()
|
||||
void
|
||||
Navigator::request_loiter_or_ready()
|
||||
{
|
||||
if (_vstatus.condition_landed) {
|
||||
/* XXX workaround: no landing detector for fixedwing yet */
|
||||
if (_vstatus.condition_landed && _vstatus.is_rotary_wing) {
|
||||
dispatch(EVENT_READY_REQUESTED);
|
||||
|
||||
} else {
|
||||
@@ -1418,17 +1436,28 @@ Navigator::position_setpoint_from_mission_item(position_setpoint_s *sp, mission_
|
||||
sp->lon = _home_pos.lon;
|
||||
sp->alt = _home_pos.alt + _parameters.rtl_alt;
|
||||
|
||||
if (_pos_sp_triplet.previous.valid) {
|
||||
/* if previous setpoint is valid then use it to calculate heading to home */
|
||||
sp->yaw = get_bearing_to_next_waypoint(_pos_sp_triplet.previous.lat, _pos_sp_triplet.previous.lon, sp->lat, sp->lon);
|
||||
|
||||
} else {
|
||||
/* else use current position */
|
||||
sp->yaw = get_bearing_to_next_waypoint(_global_pos.lat, _global_pos.lon, sp->lat, sp->lon);
|
||||
}
|
||||
sp->loiter_radius = _parameters.loiter_radius;
|
||||
sp->loiter_direction = 1;
|
||||
sp->pitch_min = 0.0f;
|
||||
|
||||
} else {
|
||||
sp->lat = item->lat;
|
||||
sp->lon = item->lon;
|
||||
sp->alt = item->altitude_is_relative ? item->altitude + _home_pos.alt : item->altitude;
|
||||
sp->yaw = item->yaw;
|
||||
sp->loiter_radius = item->loiter_radius;
|
||||
sp->loiter_direction = item->loiter_direction;
|
||||
sp->pitch_min = item->pitch_min;
|
||||
}
|
||||
|
||||
sp->yaw = item->yaw;
|
||||
sp->loiter_radius = item->loiter_radius;
|
||||
sp->loiter_direction = item->loiter_direction;
|
||||
sp->pitch_min = item->pitch_min;
|
||||
|
||||
if (item->nav_cmd == NAV_CMD_TAKEOFF) {
|
||||
sp->type = SETPOINT_TYPE_TAKEOFF;
|
||||
|
||||
@@ -1505,7 +1534,7 @@ Navigator::check_mission_item_reached()
|
||||
}
|
||||
}
|
||||
|
||||
if (!_waypoint_yaw_reached) {
|
||||
if (_waypoint_position_reached && !_waypoint_yaw_reached) {
|
||||
if (_vstatus.is_rotary_wing && !_do_takeoff && isfinite(_mission_item.yaw)) {
|
||||
/* check yaw if defined only for rotary wing except takeoff */
|
||||
float yaw_err = _wrap_pi(_mission_item.yaw - _global_pos.yaw);
|
||||
@@ -1525,16 +1554,14 @@ Navigator::check_mission_item_reached()
|
||||
_time_first_inside_orbit = now;
|
||||
|
||||
if (_mission_item.time_inside > 0.01f) {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] waypoint reached, wait for %.1fs", _mission_item.time_inside);
|
||||
mavlink_log_info(_mavlink_fd, "#audio: waypoint reached, wait for %.1fs", (double)_mission_item.time_inside);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the MAV was long enough inside the waypoint orbit */
|
||||
if ((now - _time_first_inside_orbit >= (uint64_t)_mission_item.time_inside * 1e6)
|
||||
|| _mission_item.nav_cmd == NAV_CMD_TAKEOFF) {
|
||||
_time_first_inside_orbit = 0;
|
||||
_waypoint_yaw_reached = false;
|
||||
_waypoint_position_reached = false;
|
||||
reset_reached();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1543,14 +1570,26 @@ Navigator::check_mission_item_reached()
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::reset_reached()
|
||||
{
|
||||
_time_first_inside_orbit = 0;
|
||||
_waypoint_position_reached = false;
|
||||
_waypoint_yaw_reached = false;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::on_mission_item_reached()
|
||||
{
|
||||
if (myState == NAV_STATE_MISSION) {
|
||||
|
||||
_mission.report_mission_item_reached();
|
||||
|
||||
if (_do_takeoff) {
|
||||
/* takeoff completed */
|
||||
_do_takeoff = false;
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] takeoff completed");
|
||||
mavlink_log_info(_mavlink_fd, "#audio: takeoff completed");
|
||||
|
||||
} else {
|
||||
/* advance by one mission item */
|
||||
@@ -1593,6 +1632,7 @@ Navigator::on_mission_item_reached()
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] landing completed");
|
||||
dispatch(EVENT_READY_REQUESTED);
|
||||
}
|
||||
_mission.publish_mission_result();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -36,13 +36,12 @@
|
||||
* Helper class to access missions
|
||||
*/
|
||||
|
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <string.h>
|
||||
// #include <unistd.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dataman/dataman.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/mission_result.h>
|
||||
#include "navigator_mission.h"
|
||||
|
||||
/* oddly, ERROR is not defined for c++ */
|
||||
@@ -60,8 +59,11 @@ Mission::Mission() :
|
||||
_offboard_mission_item_count(0),
|
||||
_onboard_mission_item_count(0),
|
||||
_onboard_mission_allowed(false),
|
||||
_current_mission_type(MISSION_TYPE_NONE)
|
||||
{}
|
||||
_current_mission_type(MISSION_TYPE_NONE),
|
||||
_mission_result_pub(-1)
|
||||
{
|
||||
memset(&_mission_result, 0, sizeof(struct mission_result_s));
|
||||
}
|
||||
|
||||
Mission::~Mission()
|
||||
{
|
||||
@@ -78,8 +80,16 @@ void
|
||||
Mission::set_current_offboard_mission_index(int new_index)
|
||||
{
|
||||
if (new_index != -1) {
|
||||
warnx("specifically set to %d", new_index);
|
||||
_current_offboard_mission_index = (unsigned)new_index;
|
||||
} else {
|
||||
|
||||
/* if less WPs available, reset to first WP */
|
||||
if (_current_offboard_mission_index >= _offboard_mission_item_count) {
|
||||
_current_offboard_mission_index = 0;
|
||||
}
|
||||
}
|
||||
report_current_offboard_mission_item();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -87,7 +97,15 @@ Mission::set_current_onboard_mission_index(int new_index)
|
||||
{
|
||||
if (new_index != -1) {
|
||||
_current_onboard_mission_index = (unsigned)new_index;
|
||||
} else {
|
||||
|
||||
/* if less WPs available, reset to first WP */
|
||||
if (_current_onboard_mission_index >= _onboard_mission_item_count) {
|
||||
_current_onboard_mission_index = 0;
|
||||
}
|
||||
}
|
||||
// TODO: implement this for onboard missions as well
|
||||
// report_current_mission_item();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -266,4 +284,35 @@ Mission::move_to_next()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Mission::report_mission_item_reached()
|
||||
{
|
||||
if (_current_mission_type == MISSION_TYPE_OFFBOARD) {
|
||||
_mission_result.mission_reached = true;
|
||||
_mission_result.mission_index_reached = _current_offboard_mission_index;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Mission::report_current_offboard_mission_item()
|
||||
{
|
||||
_mission_result.index_current_mission = _current_offboard_mission_index;
|
||||
}
|
||||
|
||||
void
|
||||
Mission::publish_mission_result()
|
||||
{
|
||||
/* lazily publish the mission result only once available */
|
||||
if (_mission_result_pub > 0) {
|
||||
/* publish mission result */
|
||||
orb_publish(ORB_ID(mission_result), _mission_result_pub, &_mission_result);
|
||||
|
||||
} else {
|
||||
/* advertise and publish */
|
||||
_mission_result_pub = orb_advertise(ORB_ID(mission_result), &_mission_result);
|
||||
}
|
||||
/* reset reached bool */
|
||||
_mission_result.mission_reached = false;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define NAVIGATOR_MISSION_H
|
||||
|
||||
#include <uORB/topics/mission.h>
|
||||
#include <uORB/topics/mission_result.h>
|
||||
|
||||
|
||||
class __EXPORT Mission
|
||||
@@ -71,7 +72,9 @@ public:
|
||||
|
||||
void move_to_next();
|
||||
|
||||
void add_home_pos(struct mission_item_s *new_mission_item);
|
||||
void report_mission_item_reached();
|
||||
void report_current_offboard_mission_item();
|
||||
void publish_mission_result();
|
||||
|
||||
private:
|
||||
bool current_onboard_mission_available();
|
||||
@@ -92,6 +95,10 @@ private:
|
||||
MISSION_TYPE_ONBOARD,
|
||||
MISSION_TYPE_OFFBOARD,
|
||||
} _current_mission_type;
|
||||
|
||||
int _mission_result_pub;
|
||||
|
||||
struct mission_result_s _mission_result;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -5,27 +5,30 @@
|
||||
* Author: Anton Babushkin <rk3dov@gmail.com>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "inertial_filter.h"
|
||||
|
||||
void inertial_filter_predict(float dt, float x[3])
|
||||
{
|
||||
x[0] += x[1] * dt + x[2] * dt * dt / 2.0f;
|
||||
x[1] += x[2] * dt;
|
||||
if (isfinite(dt)) {
|
||||
x[0] += x[1] * dt + x[2] * dt * dt / 2.0f;
|
||||
x[1] += x[2] * dt;
|
||||
}
|
||||
}
|
||||
|
||||
void inertial_filter_correct(float e, float dt, float x[3], int i, float w)
|
||||
{
|
||||
float ewdt = w * dt;
|
||||
if (ewdt > 1.0f)
|
||||
ewdt = 1.0f; // prevent over-correcting
|
||||
ewdt *= e;
|
||||
x[i] += ewdt;
|
||||
if (isfinite(e) && isfinite(w) && isfinite(dt)) {
|
||||
float ewdt = e * w * dt;
|
||||
x[i] += ewdt;
|
||||
|
||||
if (i == 0) {
|
||||
x[1] += w * ewdt;
|
||||
x[2] += w * w * ewdt / 3.0;
|
||||
if (i == 0) {
|
||||
x[1] += w * ewdt;
|
||||
x[2] += w * w * ewdt / 3.0;
|
||||
|
||||
} else if (i == 1) {
|
||||
x[2] += w * ewdt;
|
||||
} else if (i == 1) {
|
||||
x[2] += w * ewdt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,12 +167,13 @@ void write_debug_log(const char *msg, float dt, float x_est[3], float y_est[3],
|
||||
FILE *f = fopen("/fs/microsd/inav.log", "a");
|
||||
if (f) {
|
||||
char *s = malloc(256);
|
||||
snprintf(s, 256, "%llu %s\n\tdt=%.5f x_est=[%.5f %.5f %.5f] y_est=[%.5f %.5f %.5f] z_est=[%.5f %.5f %.5f]\n", hrt_absolute_time(), msg, dt, x_est[0], x_est[1], x_est[2], y_est[0], y_est[1], y_est[2], z_est[0], z_est[1], z_est[2]);
|
||||
fputs(f, s);
|
||||
snprintf(s, 256, "\tacc_corr=[%.5f %.5f %.5f] gps_pos_corr=[%.5f %.5f %.5f] gps_vel_corr=[%.5f %.5f %.5f] w_xy_gps_p=%.5f w_xy_gps_v=%.5f\n", corr_acc[0], corr_acc[1], corr_acc[2], corr_gps[0][0], corr_gps[1][0], corr_gps[2][0], corr_gps[0][1], corr_gps[1][1], corr_gps[2][1], w_xy_gps_p, w_xy_gps_v);
|
||||
fputs(f, s);
|
||||
unsigned n = snprintf(s, 256, "%llu %s\n\tdt=%.5f x_est=[%.5f %.5f %.5f] y_est=[%.5f %.5f %.5f] z_est=[%.5f %.5f %.5f]\n", hrt_absolute_time(), msg, dt, x_est[0], x_est[1], x_est[2], y_est[0], y_est[1], y_est[2], z_est[0], z_est[1], z_est[2]);
|
||||
fwrite(s, 1, n, f);
|
||||
n = snprintf(s, 256, "\tacc_corr=[%.5f %.5f %.5f] gps_pos_corr=[%.5f %.5f %.5f] gps_vel_corr=[%.5f %.5f %.5f] w_xy_gps_p=%.5f w_xy_gps_v=%.5f\n", corr_acc[0], corr_acc[1], corr_acc[2], corr_gps[0][0], corr_gps[1][0], corr_gps[2][0], corr_gps[0][1], corr_gps[1][1], corr_gps[2][1], w_xy_gps_p, w_xy_gps_v);
|
||||
fwrite(s, 1, n, f);
|
||||
free(s);
|
||||
}
|
||||
fsync(fileno(f));
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
@@ -199,8 +200,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
bool landed = true;
|
||||
hrt_abstime landed_time = 0;
|
||||
|
||||
uint32_t accel_counter = 0;
|
||||
uint32_t baro_counter = 0;
|
||||
hrt_abstime accel_timestamp = 0;
|
||||
hrt_abstime baro_timestamp = 0;
|
||||
|
||||
bool ref_inited = false;
|
||||
hrt_abstime ref_init_start = 0;
|
||||
@@ -309,8 +310,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (fds_init[0].revents & POLLIN) {
|
||||
orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
|
||||
|
||||
if (wait_baro && sensor.baro_counter != baro_counter) {
|
||||
baro_counter = sensor.baro_counter;
|
||||
if (wait_baro && sensor.baro_timestamp != baro_timestamp) {
|
||||
baro_timestamp = sensor.baro_timestamp;
|
||||
|
||||
/* mean calculation over several measurements */
|
||||
if (baro_init_cnt < baro_init_num) {
|
||||
@@ -383,7 +384,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
|
||||
|
||||
if (sensor.accelerometer_counter != accel_counter) {
|
||||
if (sensor.accelerometer_timestamp != accel_timestamp) {
|
||||
if (att.R_valid) {
|
||||
/* correct accel bias */
|
||||
sensor.accelerometer_m_s2[0] -= acc_bias[0];
|
||||
@@ -407,13 +408,13 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
memset(corr_acc, 0, sizeof(corr_acc));
|
||||
}
|
||||
|
||||
accel_counter = sensor.accelerometer_counter;
|
||||
accel_timestamp = sensor.accelerometer_timestamp;
|
||||
accel_updates++;
|
||||
}
|
||||
|
||||
if (sensor.baro_counter != baro_counter) {
|
||||
if (sensor.baro_timestamp != baro_timestamp) {
|
||||
corr_baro = baro_offset - sensor.baro_alt_meter - z_est[0];
|
||||
baro_counter = sensor.baro_counter;
|
||||
baro_timestamp = sensor.baro_timestamp;
|
||||
baro_updates++;
|
||||
}
|
||||
}
|
||||
@@ -622,7 +623,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
float dt = t_prev > 0 ? (t - t_prev) / 1000000.0f : 0.0f;
|
||||
dt = fmaxf(fminf(0.02, dt), 0.005);
|
||||
dt = fmaxf(fminf(0.02, dt), 0.002); // constrain dt from 2 to 20 ms
|
||||
t_prev = t;
|
||||
|
||||
/* use GPS if it's valid and reference position initialized */
|
||||
@@ -708,6 +709,11 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);
|
||||
inertial_filter_correct(corr_acc[2], dt, z_est, 2, params.w_z_acc);
|
||||
|
||||
float x_est_prev[3], y_est_prev[3];
|
||||
|
||||
memcpy(x_est_prev, x_est, sizeof(x_est));
|
||||
memcpy(y_est_prev, y_est, sizeof(y_est));
|
||||
|
||||
if (can_estimate_xy) {
|
||||
/* inertial filter prediction for position */
|
||||
inertial_filter_predict(dt, x_est);
|
||||
@@ -715,7 +721,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
if (!isfinite(x_est[0]) || !isfinite(y_est[0])) {
|
||||
write_debug_log("BAD ESTIMATE AFTER PREDICTION", dt, x_est, y_est, z_est, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
thread_should_exit = true;
|
||||
memcpy(x_est, x_est_prev, sizeof(x_est));
|
||||
memcpy(y_est, y_est_prev, sizeof(y_est));
|
||||
}
|
||||
|
||||
/* inertial filter correction for position */
|
||||
@@ -739,7 +746,11 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
if (!isfinite(x_est[0]) || !isfinite(y_est[0])) {
|
||||
write_debug_log("BAD ESTIMATE AFTER CORRECTION", dt, x_est, y_est, z_est, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
thread_should_exit = true;
|
||||
memcpy(x_est, x_est_prev, sizeof(x_est));
|
||||
memcpy(y_est, y_est_prev, sizeof(y_est));
|
||||
memset(corr_acc, 0, sizeof(corr_acc));
|
||||
memset(corr_gps, 0, sizeof(corr_gps));
|
||||
memset(corr_flow, 0, sizeof(corr_flow));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -162,6 +162,7 @@ dsm_guess_format(bool reset)
|
||||
0xff, /* 8 channels (DX8) */
|
||||
0x1ff, /* 9 channels (DX9, etc.) */
|
||||
0x3ff, /* 10 channels (DX10) */
|
||||
0x1fff, /* 13 channels (DX10t) */
|
||||
0x3fff /* 18 channels (DX10) */
|
||||
};
|
||||
unsigned votes10 = 0;
|
||||
@@ -368,11 +369,25 @@ dsm_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values)
|
||||
if (channel >= *num_values)
|
||||
*num_values = channel + 1;
|
||||
|
||||
/* convert 0-1024 / 0-2048 values to 1000-2000 ppm encoding in a very sloppy fashion */
|
||||
if (dsm_channel_shift == 11)
|
||||
value /= 2;
|
||||
/* convert 0-1024 / 0-2048 values to 1000-2000 ppm encoding. */
|
||||
if (dsm_channel_shift == 10)
|
||||
value *= 2;
|
||||
|
||||
value += 998;
|
||||
/*
|
||||
* Spektrum scaling is special. There are these basic considerations
|
||||
*
|
||||
* * Midpoint is 1520 us
|
||||
* * 100% travel channels are +- 400 us
|
||||
*
|
||||
* We obey the original Spektrum scaling (so a default setup will scale from
|
||||
* 1100 - 1900 us), but we do not obey the weird 1520 us center point
|
||||
* and instead (correctly) center the center around 1500 us. This is in order
|
||||
* to get something useful without requiring the user to calibrate on a digital
|
||||
* link for no reason.
|
||||
*/
|
||||
|
||||
/* scaled integer for decent accuracy while staying efficient */
|
||||
value = ((((int)value - 1024) * 1000) / 1700) + 1500;
|
||||
|
||||
/*
|
||||
* Store the decoded channel into the R/C input buffer, taking into
|
||||
@@ -400,6 +415,15 @@ dsm_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values)
|
||||
values[channel] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Spektrum likes to send junk in higher channel numbers to fill
|
||||
* their packets. We don't know about a 13 channel model in their TX
|
||||
* lines, so if we get a channel count of 13, we'll return 12 (the last
|
||||
* data index that is stable).
|
||||
*/
|
||||
if (*num_values == 13)
|
||||
*num_values = 12;
|
||||
|
||||
if (dsm_channel_shift == 11) {
|
||||
/* Set the 11-bit data indicator */
|
||||
*num_values |= 0x8000;
|
||||
|
||||
@@ -268,7 +268,7 @@ mixer_callback(uintptr_t handle,
|
||||
uint8_t control_index,
|
||||
float &control)
|
||||
{
|
||||
if (control_group > 3)
|
||||
if (control_group >= PX4IO_CONTROL_GROUPS)
|
||||
return -1;
|
||||
|
||||
switch (source) {
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
*/
|
||||
#define PX4IO_SERVO_COUNT 8
|
||||
#define PX4IO_CONTROL_CHANNELS 8
|
||||
#define PX4IO_CONTROL_GROUPS 2
|
||||
#define PX4IO_CONTROL_GROUPS 4
|
||||
#define PX4IO_RC_INPUT_CHANNELS 18
|
||||
#define PX4IO_RC_MAPPED_CONTROL_CHANNELS 8 /**< This is the maximum number of channels mapped/used */
|
||||
|
||||
|
||||
@@ -566,7 +566,7 @@ registers_set_one(uint8_t page, uint8_t offset, uint16_t value)
|
||||
break;
|
||||
|
||||
case PX4IO_P_SETUP_DSM:
|
||||
dsm_bind(value & 0x0f, (value >> 4) & 7);
|
||||
dsm_bind(value & 0x0f, (value >> 4) & 0xF);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Anton Babushkin <anton.babushkin@me.com>
|
||||
* Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -75,8 +74,9 @@ bool logbuffer_write(struct logbuffer_s *lb, void *ptr, int size)
|
||||
// bytes available to write
|
||||
int available = lb->read_ptr - lb->write_ptr - 1;
|
||||
|
||||
if (available < 0)
|
||||
if (available < 0) {
|
||||
available += lb->size;
|
||||
}
|
||||
|
||||
if (size > available) {
|
||||
// buffer overflow
|
||||
|
||||
+432
-566
File diff suppressed because it is too large
Load Diff
@@ -92,6 +92,7 @@ struct log_SENS_s {
|
||||
float baro_alt;
|
||||
float baro_temp;
|
||||
float diff_pres;
|
||||
float diff_pres_filtered;
|
||||
};
|
||||
|
||||
/* --- LPOS - LOCAL POSITION --- */
|
||||
@@ -267,13 +268,13 @@ struct log_DIST_s {
|
||||
/* --- TELE - TELEMETRY STATUS --- */
|
||||
#define LOG_TELE_MSG 22
|
||||
struct log_TELE_s {
|
||||
uint8_t rssi;
|
||||
uint8_t remote_rssi;
|
||||
uint8_t noise;
|
||||
uint8_t remote_noise;
|
||||
uint16_t rxerrors;
|
||||
uint16_t fixed;
|
||||
uint8_t txbuf;
|
||||
uint8_t rssi;
|
||||
uint8_t remote_rssi;
|
||||
uint8_t noise;
|
||||
uint8_t remote_noise;
|
||||
uint16_t rxerrors;
|
||||
uint16_t fixed;
|
||||
uint8_t txbuf;
|
||||
};
|
||||
|
||||
/********** SYSTEM MESSAGES, ID > 0x80 **********/
|
||||
@@ -306,7 +307,7 @@ static const struct log_format_s log_formats[] = {
|
||||
LOG_FORMAT(ATT, "fffffffff", "Roll,Pitch,Yaw,RollRate,PitchRate,YawRate,GX,GY,GZ"),
|
||||
LOG_FORMAT(ATSP, "ffff", "RollSP,PitchSP,YawSP,ThrustSP"),
|
||||
LOG_FORMAT(IMU, "fffffffff", "AccX,AccY,AccZ,GyroX,GyroY,GyroZ,MagX,MagY,MagZ"),
|
||||
LOG_FORMAT(SENS, "ffff", "BaroPres,BaroAlt,BaroTemp,DiffPres"),
|
||||
LOG_FORMAT(SENS, "fffff", "BaroPres,BaroAlt,BaroTemp,DiffPres,DiffPresFilt"),
|
||||
LOG_FORMAT(LPOS, "ffffffLLfBBB", "X,Y,Z,VX,VY,VZ,RefLat,RefLon,RefAlt,XYFlags,ZFlags,Landed"),
|
||||
LOG_FORMAT(LPSP, "ffff", "X,Y,Z,Yaw"),
|
||||
LOG_FORMAT(GPS, "QBffLLfffff", "GPSTime,FixType,EPH,EPV,Lat,Lon,Alt,VelN,VelE,VelD,Cog"),
|
||||
|
||||
@@ -936,7 +936,7 @@ Sensors::accel_poll(struct sensor_combined_s &raw)
|
||||
raw.accelerometer_raw[1] = accel_report.y_raw;
|
||||
raw.accelerometer_raw[2] = accel_report.z_raw;
|
||||
|
||||
raw.accelerometer_counter++;
|
||||
raw.accelerometer_timestamp = accel_report.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +962,7 @@ Sensors::gyro_poll(struct sensor_combined_s &raw)
|
||||
raw.gyro_raw[1] = gyro_report.y_raw;
|
||||
raw.gyro_raw[2] = gyro_report.z_raw;
|
||||
|
||||
raw.gyro_counter++;
|
||||
raw.timestamp = gyro_report.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -992,7 +992,7 @@ Sensors::mag_poll(struct sensor_combined_s &raw)
|
||||
raw.magnetometer_raw[1] = mag_report.y_raw;
|
||||
raw.magnetometer_raw[2] = mag_report.z_raw;
|
||||
|
||||
raw.magnetometer_counter++;
|
||||
raw.magnetometer_timestamp = mag_report.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,7 +1010,7 @@ Sensors::baro_poll(struct sensor_combined_s &raw)
|
||||
raw.baro_alt_meter = _barometer.altitude; // Altitude in meters
|
||||
raw.baro_temp_celcius = _barometer.temperature; // Temperature in degrees celcius
|
||||
|
||||
raw.baro_counter++;
|
||||
raw.baro_timestamp = _barometer.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,10 +1024,12 @@ Sensors::diff_pres_poll(struct sensor_combined_s &raw)
|
||||
orb_copy(ORB_ID(differential_pressure), _diff_pres_sub, &_diff_pres);
|
||||
|
||||
raw.differential_pressure_pa = _diff_pres.differential_pressure_pa;
|
||||
raw.differential_pressure_counter++;
|
||||
raw.differential_pressure_timestamp = _diff_pres.timestamp;
|
||||
raw.differential_pressure_filtered_pa = _diff_pres.differential_pressure_filtered_pa;
|
||||
|
||||
_airspeed.indicated_airspeed_m_s = calc_indicated_airspeed(_diff_pres.differential_pressure_pa);
|
||||
_airspeed.true_airspeed_m_s = calc_true_airspeed(_diff_pres.differential_pressure_pa + raw.baro_pres_mbar * 1e2f,
|
||||
_airspeed.timestamp = _diff_pres.timestamp;
|
||||
_airspeed.indicated_airspeed_m_s = calc_indicated_airspeed(_diff_pres.differential_pressure_filtered_pa);
|
||||
_airspeed.true_airspeed_m_s = calc_true_airspeed(_diff_pres.differential_pressure_filtered_pa + raw.baro_pres_mbar * 1e2f,
|
||||
raw.baro_pres_mbar * 1e2f, raw.baro_temp_celcius - PCB_TEMP_ESTIMATE_DEG);
|
||||
|
||||
/* announce the airspeed if needed, just publish else */
|
||||
@@ -1589,8 +1591,7 @@ Sensors::task_main()
|
||||
/* check parameters for updates */
|
||||
parameter_update_poll();
|
||||
|
||||
/* store the time closest to all measurements (this is bogus, sensor timestamps should be propagated...) */
|
||||
raw.timestamp = hrt_absolute_time();
|
||||
/* the timestamp of the raw struct is updated by the gyro_poll() method */
|
||||
|
||||
/* copy most recent sensor data */
|
||||
gyro_poll(raw);
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#ifndef _SYSTEMLIB_PERF_COUNTER_H
|
||||
#define _SYSTEMLIB_PERF_COUNTER_H value
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Counter types.
|
||||
*/
|
||||
|
||||
@@ -60,3 +60,14 @@ PARAM_DEFINE_INT32(SYS_AUTOSTART, 0);
|
||||
* @group System
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SYS_AUTOCONFIG, 0);
|
||||
|
||||
/**
|
||||
* Set usage of IO board
|
||||
*
|
||||
* Can be used to use a standard startup script but with a FMU only set-up. Set to 0 to force the FMU only set-up.
|
||||
*
|
||||
* @min 0
|
||||
* @max 1
|
||||
* @group System
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SYS_USE_IO, 1);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Publication.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Publication.hpp"
|
||||
#include "topics/vehicle_attitude.h"
|
||||
#include "topics/vehicle_local_position.h"
|
||||
#include "topics/vehicle_global_position.h"
|
||||
#include "topics/debug_key_value.h"
|
||||
#include "topics/actuator_controls.h"
|
||||
#include "topics/vehicle_global_velocity_setpoint.h"
|
||||
#include "topics/vehicle_attitude_setpoint.h"
|
||||
#include "topics/vehicle_rates_setpoint.h"
|
||||
#include "topics/actuator_outputs.h"
|
||||
#include "topics/encoders.h"
|
||||
|
||||
namespace uORB {
|
||||
|
||||
template<class T>
|
||||
Publication<T>::Publication(
|
||||
List<PublicationBase *> * list,
|
||||
const struct orb_metadata *meta) :
|
||||
T(), // initialize data structure to zero
|
||||
PublicationBase(list, meta) {
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Publication<T>::~Publication() {}
|
||||
|
||||
template<class T>
|
||||
void * Publication<T>::getDataVoidPtr() {
|
||||
return (void *)(T *)(this);
|
||||
}
|
||||
|
||||
template class __EXPORT Publication<vehicle_attitude_s>;
|
||||
template class __EXPORT Publication<vehicle_local_position_s>;
|
||||
template class __EXPORT Publication<vehicle_global_position_s>;
|
||||
template class __EXPORT Publication<debug_key_value_s>;
|
||||
template class __EXPORT Publication<actuator_controls_s>;
|
||||
template class __EXPORT Publication<vehicle_global_velocity_setpoint_s>;
|
||||
template class __EXPORT Publication<vehicle_attitude_setpoint_s>;
|
||||
template class __EXPORT Publication<vehicle_rates_setpoint_s>;
|
||||
template class __EXPORT Publication<actuator_outputs_s>;
|
||||
template class __EXPORT Publication<encoders_s>;
|
||||
|
||||
}
|
||||
+15
-22
@@ -32,32 +32,29 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file UOrbPublication.h
|
||||
* @file Publication.h
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include "../block/Block.hpp"
|
||||
#include "../block/List.hpp"
|
||||
#include <containers/List.hpp>
|
||||
|
||||
|
||||
namespace control
|
||||
namespace uORB
|
||||
{
|
||||
|
||||
class Block;
|
||||
|
||||
/**
|
||||
* Base publication warapper class, used in list traversal
|
||||
* of various publications.
|
||||
*/
|
||||
class __EXPORT UOrbPublicationBase : public ListNode<control::UOrbPublicationBase *>
|
||||
class __EXPORT PublicationBase : public ListNode<uORB::PublicationBase *>
|
||||
{
|
||||
public:
|
||||
|
||||
UOrbPublicationBase(
|
||||
List<UOrbPublicationBase *> * list,
|
||||
PublicationBase(
|
||||
List<PublicationBase *> * list,
|
||||
const struct orb_metadata *meta) :
|
||||
_meta(meta),
|
||||
_handle(-1) {
|
||||
@@ -71,7 +68,7 @@ public:
|
||||
}
|
||||
}
|
||||
virtual void *getDataVoidPtr() = 0;
|
||||
virtual ~UOrbPublicationBase() {
|
||||
virtual ~PublicationBase() {
|
||||
orb_unsubscribe(getHandle());
|
||||
}
|
||||
const struct orb_metadata *getMeta() { return _meta; }
|
||||
@@ -83,12 +80,12 @@ protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* UOrb Publication wrapper class
|
||||
* Publication wrapper class
|
||||
*/
|
||||
template<class T>
|
||||
class UOrbPublication :
|
||||
class Publication :
|
||||
public T, // this must be first!
|
||||
public UOrbPublicationBase
|
||||
public PublicationBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -98,13 +95,9 @@ public:
|
||||
* @param meta The uORB metadata (usually from the ORB_ID() macro)
|
||||
* for the topic.
|
||||
*/
|
||||
UOrbPublication(
|
||||
List<UOrbPublicationBase *> * list,
|
||||
const struct orb_metadata *meta) :
|
||||
T(), // initialize data structure to zero
|
||||
UOrbPublicationBase(list, meta) {
|
||||
}
|
||||
virtual ~UOrbPublication() {}
|
||||
Publication(List<PublicationBase *> * list,
|
||||
const struct orb_metadata *meta);
|
||||
virtual ~Publication();
|
||||
/*
|
||||
* XXX
|
||||
* This function gets the T struct, assuming
|
||||
@@ -112,7 +105,7 @@ public:
|
||||
* should use dynamic cast, but doesn't
|
||||
* seem to be available
|
||||
*/
|
||||
void *getDataVoidPtr() { return (void *)(T *)(this); }
|
||||
void *getDataVoidPtr();
|
||||
};
|
||||
|
||||
} // namespace control
|
||||
} // namespace uORB
|
||||
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Subscription.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Subscription.hpp"
|
||||
#include "topics/parameter_update.h"
|
||||
#include "topics/actuator_controls.h"
|
||||
#include "topics/vehicle_gps_position.h"
|
||||
#include "topics/sensor_combined.h"
|
||||
#include "topics/vehicle_attitude.h"
|
||||
#include "topics/vehicle_global_position.h"
|
||||
#include "topics/encoders.h"
|
||||
#include "topics/position_setpoint_triplet.h"
|
||||
#include "topics/vehicle_status.h"
|
||||
#include "topics/manual_control_setpoint.h"
|
||||
#include "topics/vehicle_local_position_setpoint.h"
|
||||
#include "topics/vehicle_local_position.h"
|
||||
#include "topics/vehicle_attitude_setpoint.h"
|
||||
#include "topics/vehicle_rates_setpoint.h"
|
||||
|
||||
namespace uORB
|
||||
{
|
||||
|
||||
bool __EXPORT SubscriptionBase::updated()
|
||||
{
|
||||
bool isUpdated = false;
|
||||
orb_check(_handle, &isUpdated);
|
||||
return isUpdated;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Subscription<T>::Subscription(
|
||||
List<SubscriptionBase *> * list,
|
||||
const struct orb_metadata *meta, unsigned interval) :
|
||||
T(), // initialize data structure to zero
|
||||
SubscriptionBase(list, meta) {
|
||||
setHandle(orb_subscribe(getMeta()));
|
||||
orb_set_interval(getHandle(), interval);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Subscription<T>::~Subscription() {}
|
||||
|
||||
template<class T>
|
||||
void * Subscription<T>::getDataVoidPtr() {
|
||||
return (void *)(T *)(this);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Subscription<T>::getData() {
|
||||
return T(*this);
|
||||
}
|
||||
|
||||
template class __EXPORT Subscription<parameter_update_s>;
|
||||
template class __EXPORT Subscription<actuator_controls_s>;
|
||||
template class __EXPORT Subscription<vehicle_gps_position_s>;
|
||||
template class __EXPORT Subscription<sensor_combined_s>;
|
||||
template class __EXPORT Subscription<vehicle_attitude_s>;
|
||||
template class __EXPORT Subscription<vehicle_global_position_s>;
|
||||
template class __EXPORT Subscription<encoders_s>;
|
||||
template class __EXPORT Subscription<position_setpoint_triplet_s>;
|
||||
template class __EXPORT Subscription<vehicle_status_s>;
|
||||
template class __EXPORT Subscription<manual_control_setpoint_s>;
|
||||
template class __EXPORT Subscription<vehicle_local_position_setpoint_s>;
|
||||
template class __EXPORT Subscription<vehicle_local_position_s>;
|
||||
template class __EXPORT Subscription<vehicle_attitude_setpoint_s>;
|
||||
template class __EXPORT Subscription<vehicle_rates_setpoint_s>;
|
||||
|
||||
} // namespace uORB
|
||||
+18
-27
@@ -32,28 +32,25 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file UOrbSubscription.h
|
||||
* @file Subscription.h
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include "../block/Block.hpp"
|
||||
#include "../block/List.hpp"
|
||||
#include <containers/List.hpp>
|
||||
|
||||
|
||||
namespace control
|
||||
namespace uORB
|
||||
{
|
||||
|
||||
class Block;
|
||||
|
||||
/**
|
||||
* Base subscription warapper class, used in list traversal
|
||||
* of various subscriptions.
|
||||
*/
|
||||
class __EXPORT UOrbSubscriptionBase :
|
||||
public ListNode<control::UOrbSubscriptionBase *>
|
||||
class __EXPORT SubscriptionBase :
|
||||
public ListNode<SubscriptionBase *>
|
||||
{
|
||||
public:
|
||||
// methods
|
||||
@@ -64,8 +61,8 @@ public:
|
||||
* @param meta The uORB metadata (usually from the ORB_ID() macro)
|
||||
* for the topic.
|
||||
*/
|
||||
UOrbSubscriptionBase(
|
||||
List<UOrbSubscriptionBase *> * list,
|
||||
SubscriptionBase(
|
||||
List<SubscriptionBase *> * list,
|
||||
const struct orb_metadata *meta) :
|
||||
_meta(meta),
|
||||
_handle() {
|
||||
@@ -78,7 +75,7 @@ public:
|
||||
}
|
||||
}
|
||||
virtual void *getDataVoidPtr() = 0;
|
||||
virtual ~UOrbSubscriptionBase() {
|
||||
virtual ~SubscriptionBase() {
|
||||
orb_unsubscribe(_handle);
|
||||
}
|
||||
// accessors
|
||||
@@ -93,12 +90,12 @@ protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* UOrb Subscription wrapper class
|
||||
* Subscription wrapper class
|
||||
*/
|
||||
template<class T>
|
||||
class __EXPORT UOrbSubscription :
|
||||
class __EXPORT Subscription :
|
||||
public T, // this must be first!
|
||||
public UOrbSubscriptionBase
|
||||
public SubscriptionBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -109,19 +106,13 @@ public:
|
||||
* for the topic.
|
||||
* @param interval The minimum interval in milliseconds between updates
|
||||
*/
|
||||
UOrbSubscription(
|
||||
List<UOrbSubscriptionBase *> * list,
|
||||
const struct orb_metadata *meta, unsigned interval) :
|
||||
T(), // initialize data structure to zero
|
||||
UOrbSubscriptionBase(list, meta) {
|
||||
setHandle(orb_subscribe(getMeta()));
|
||||
orb_set_interval(getHandle(), interval);
|
||||
}
|
||||
|
||||
Subscription(
|
||||
List<SubscriptionBase *> * list,
|
||||
const struct orb_metadata *meta, unsigned interval);
|
||||
/**
|
||||
* Deconstructor
|
||||
*/
|
||||
virtual ~UOrbSubscription() {}
|
||||
virtual ~Subscription();
|
||||
|
||||
/*
|
||||
* XXX
|
||||
@@ -130,8 +121,8 @@ public:
|
||||
* should use dynamic cast, but doesn't
|
||||
* seem to be available
|
||||
*/
|
||||
void *getDataVoidPtr() { return (void *)(T *)(this); }
|
||||
T getData() { return T(*this); }
|
||||
void *getDataVoidPtr();
|
||||
T getData();
|
||||
};
|
||||
|
||||
} // namespace control
|
||||
} // namespace uORB
|
||||
@@ -41,4 +41,6 @@ MODULE_COMMAND = uorb
|
||||
MODULE_STACKSIZE = 4096
|
||||
|
||||
SRCS = uORB.cpp \
|
||||
objects_common.cpp
|
||||
objects_common.cpp \
|
||||
Publication.cpp \
|
||||
Subscription.cpp
|
||||
|
||||
@@ -190,3 +190,6 @@ ORB_DEFINE(navigation_capabilities, struct navigation_capabilities_s);
|
||||
|
||||
#include "topics/esc_status.h"
|
||||
ORB_DEFINE(esc_status, struct esc_status_s);
|
||||
|
||||
#include "topics/encoders.h"
|
||||
ORB_DEFINE(encoders, struct encoders_s);
|
||||
|
||||
@@ -54,8 +54,9 @@
|
||||
struct differential_pressure_s {
|
||||
uint64_t timestamp; /**< microseconds since system boot, needed to integrate */
|
||||
uint64_t error_count;
|
||||
float differential_pressure_pa; /**< Differential pressure reading */
|
||||
float max_differential_pressure_pa; /**< Maximum differential pressure reading */
|
||||
float differential_pressure_pa; /**< Differential pressure reading */
|
||||
float differential_pressure_filtered_pa; /**< Low pass filtered differential pressure reading */
|
||||
float max_differential_pressure_pa; /**< Maximum differential pressure reading */
|
||||
float voltage; /**< Voltage from analog airspeed sensors (voltage divider already compensated) */
|
||||
float temperature; /**< Temperature provided by sensor */
|
||||
|
||||
|
||||
+29
-2
@@ -32,8 +32,35 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file UOrbPublication.cpp
|
||||
* @file encoders.h
|
||||
*
|
||||
* Encoders topic.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "UOrbPublication.hpp"
|
||||
#ifndef TOPIC_ENCODERS_H
|
||||
#define TOPIC_ENCODERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../uORB.h"
|
||||
|
||||
/**
|
||||
* @addtogroup topics
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NUM_ENCODERS 4
|
||||
|
||||
struct encoders_s {
|
||||
uint64_t timestamp;
|
||||
int64_t counts[NUM_ENCODERS]; // counts of encoder
|
||||
float velocity[NUM_ENCODERS]; // counts of encoder/ second
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
ORB_DECLARE(encoders);
|
||||
|
||||
#endif
|
||||
@@ -54,7 +54,8 @@
|
||||
struct mission_result_s
|
||||
{
|
||||
bool mission_reached; /**< true if mission has been reached */
|
||||
unsigned mission_index; /**< index of the mission which has been reached */
|
||||
unsigned mission_index_reached; /**< index of the mission which has been reached */
|
||||
unsigned index_current_mission; /**< index of the current mission */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,34 +77,35 @@ struct sensor_combined_s {
|
||||
|
||||
/* NOTE: Ordering of fields optimized to align to 32 bit / 4 bytes Change with consideration only */
|
||||
|
||||
uint64_t timestamp; /**< Timestamp in microseconds since boot */
|
||||
uint64_t timestamp; /**< Timestamp in microseconds since boot, from gyro */
|
||||
|
||||
int16_t gyro_raw[3]; /**< Raw sensor values of angular velocity */
|
||||
uint16_t gyro_counter; /**< Number of raw measurments taken */
|
||||
float gyro_rad_s[3]; /**< Angular velocity in radian per seconds */
|
||||
|
||||
|
||||
int16_t accelerometer_raw[3]; /**< Raw acceleration in NED body frame */
|
||||
uint32_t accelerometer_counter; /**< Number of raw acc measurements taken */
|
||||
float accelerometer_m_s2[3]; /**< Acceleration in NED body frame, in m/s^2 */
|
||||
int accelerometer_mode; /**< Accelerometer measurement mode */
|
||||
float accelerometer_range_m_s2; /**< Accelerometer measurement range in m/s^2 */
|
||||
uint64_t accelerometer_timestamp; /**< Accelerometer timestamp */
|
||||
|
||||
int16_t magnetometer_raw[3]; /**< Raw magnetic field in NED body frame */
|
||||
float magnetometer_ga[3]; /**< Magnetic field in NED body frame, in Gauss */
|
||||
int magnetometer_mode; /**< Magnetometer measurement mode */
|
||||
float magnetometer_range_ga; /**< ± measurement range in Gauss */
|
||||
float magnetometer_cuttoff_freq_hz; /**< Internal analog low pass frequency of sensor */
|
||||
uint32_t magnetometer_counter; /**< Number of raw mag measurements taken */
|
||||
|
||||
uint64_t magnetometer_timestamp; /**< Magnetometer timestamp */
|
||||
|
||||
float baro_pres_mbar; /**< Barometric pressure, already temp. comp. */
|
||||
float baro_alt_meter; /**< Altitude, already temp. comp. */
|
||||
float baro_temp_celcius; /**< Temperature in degrees celsius */
|
||||
float adc_voltage_v[4]; /**< ADC voltages of ADC Chan 10/11/12/13 or -1 */
|
||||
float mcu_temp_celcius; /**< Internal temperature measurement of MCU */
|
||||
uint32_t baro_counter; /**< Number of raw baro measurements taken */
|
||||
uint64_t baro_timestamp; /**< Barometer timestamp */
|
||||
|
||||
float differential_pressure_pa; /**< Airspeed sensor differential pressure */
|
||||
uint64_t differential_pressure_timestamp; /**< Last measurement timestamp */
|
||||
float differential_pressure_filtered_pa; /**< Low pass filtered airspeed sensor differential pressure reading */
|
||||
|
||||
float differential_pressure_pa; /**< Airspeed sensor differential pressure */
|
||||
uint32_t differential_pressure_counter; /**< Number of raw differential pressure measurements taken */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ struct vehicle_attitude_s {
|
||||
float rate_offsets[3]; /**< Offsets of the body angular rates from zero */
|
||||
float R[3][3]; /**< Rotation matrix body to world, (Tait-Bryan, NED) */
|
||||
float q[4]; /**< Quaternion (NED) */
|
||||
float g_comp[3]; /**< Compensated gravity vector */
|
||||
float g_comp[3]; /**< Compensated gravity vector */
|
||||
bool R_valid; /**< Rotation matrix valid */
|
||||
bool q_valid; /**< Quaternion valid */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user