mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-17 04:53:34 +08:00
Merge remote-tracking branch 'px4/beta' into beta_mavlink
Conflicts: src/modules/mavlink/mavlink.c src/modules/mavlink/mavlink_receiver.h src/modules/mavlink/orb_listener.c
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* 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
|
||||
@@ -86,6 +86,7 @@ Airspeed::Airspeed(int bus, int address, unsigned conversion_interval) :
|
||||
_collect_phase(false),
|
||||
_diff_pres_offset(0.0f),
|
||||
_airspeed_pub(-1),
|
||||
_class_instance(-1),
|
||||
_conversion_interval(conversion_interval),
|
||||
_sample_perf(perf_alloc(PC_ELAPSED, "airspeed_read")),
|
||||
_comms_errors(perf_alloc(PC_COUNT, "airspeed_comms_errors"))
|
||||
@@ -102,6 +103,9 @@ Airspeed::~Airspeed()
|
||||
/* make sure we are truly inactive */
|
||||
stop();
|
||||
|
||||
if (_class_instance != -1)
|
||||
unregister_class_devname(AIRSPEED_DEVICE_PATH, _class_instance);
|
||||
|
||||
/* free any existing reports */
|
||||
if (_reports != nullptr)
|
||||
delete _reports;
|
||||
@@ -126,13 +130,23 @@ Airspeed::init()
|
||||
if (_reports == nullptr)
|
||||
goto out;
|
||||
|
||||
/* get a publish handle on the airspeed topic */
|
||||
differential_pressure_s zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &zero_report);
|
||||
/* register alternate interfaces if we have to */
|
||||
_class_instance = register_class_devname(AIRSPEED_DEVICE_PATH);
|
||||
|
||||
if (_airspeed_pub < 0)
|
||||
warnx("failed to create airspeed sensor object. Did you start uOrb?");
|
||||
/* publication init */
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct differential_pressure_s arp;
|
||||
measure();
|
||||
_reports->get(&arp);
|
||||
|
||||
/* measurement will have generated a report, publish */
|
||||
_airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &arp);
|
||||
|
||||
if (_airspeed_pub < 0)
|
||||
warnx("failed to create airspeed sensor object. uORB started?");
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
/* sensor is ok, but we don't really know if it is within range */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* 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
|
||||
@@ -127,6 +127,8 @@ protected:
|
||||
|
||||
orb_advert_t _airspeed_pub;
|
||||
|
||||
int _class_instance;
|
||||
|
||||
unsigned _conversion_interval;
|
||||
|
||||
perf_counter_t _sample_perf;
|
||||
|
||||
@@ -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
|
||||
@@ -153,6 +153,7 @@ private:
|
||||
float _accel_range_scale;
|
||||
float _accel_range_m_s2;
|
||||
orb_advert_t _accel_topic;
|
||||
int _class_instance;
|
||||
|
||||
unsigned _current_lowpass;
|
||||
unsigned _current_range;
|
||||
@@ -238,6 +239,7 @@ BMA180::BMA180(int bus, spi_dev_e device) :
|
||||
_accel_range_scale(0.0f),
|
||||
_accel_range_m_s2(0.0f),
|
||||
_accel_topic(-1),
|
||||
_class_instance(-1),
|
||||
_current_lowpass(0),
|
||||
_current_range(0),
|
||||
_sample_perf(perf_alloc(PC_ELAPSED, "bma180_read"))
|
||||
@@ -282,11 +284,6 @@ BMA180::init()
|
||||
if (_reports == nullptr)
|
||||
goto out;
|
||||
|
||||
/* advertise sensor topic */
|
||||
struct accel_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &zero_report);
|
||||
|
||||
/* perform soft reset (p48) */
|
||||
write_reg(ADDR_RESET, SOFT_RESET);
|
||||
|
||||
@@ -322,6 +319,19 @@ BMA180::init()
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
_class_instance = register_class_devname(ACCEL_DEVICE_PATH);
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
measure();
|
||||
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
struct accel_report arp;
|
||||
_reports->get(&arp);
|
||||
|
||||
/* measurement will have generated a report, publish */
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &arp);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -723,7 +733,8 @@ BMA180::measure()
|
||||
poll_notify(POLLIN);
|
||||
|
||||
/* publish for subscribers */
|
||||
orb_publish(ORB_ID(sensor_accel), _accel_topic, &report);
|
||||
if (_accel_topic > 0 && !(_pub_blocked))
|
||||
orb_publish(ORB_ID(sensor_accel), _accel_topic, &report);
|
||||
|
||||
/* stop the perf counter */
|
||||
perf_end(_sample_perf);
|
||||
|
||||
@@ -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
|
||||
@@ -38,6 +38,7 @@
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
#include "drivers/drv_device.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <arch/irq.h>
|
||||
@@ -93,6 +94,7 @@ CDev::CDev(const char *name,
|
||||
Device(name, irq),
|
||||
// public
|
||||
// protected
|
||||
_pub_blocked(false),
|
||||
// private
|
||||
_devname(devname),
|
||||
_registered(false),
|
||||
@@ -256,6 +258,14 @@ CDev::ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
case DIOC_GETPRIV:
|
||||
*(void **)(uintptr_t)arg = (void *)this;
|
||||
return OK;
|
||||
break;
|
||||
case DEVIOCSPUBBLOCK:
|
||||
_pub_blocked = (arg != 0);
|
||||
return OK;
|
||||
break;
|
||||
case DEVIOCGPUBBLOCK:
|
||||
return _pub_blocked;
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -415,6 +415,8 @@ protected:
|
||||
*/
|
||||
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance);
|
||||
|
||||
bool _pub_blocked; /**< true if publishing should be blocked */
|
||||
|
||||
private:
|
||||
static const unsigned _max_pollwaiters = 8;
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 drv_device.h
|
||||
*
|
||||
* Generic device / sensor interface.
|
||||
*/
|
||||
|
||||
#ifndef _DRV_DEVICE_H
|
||||
#define _DRV_DEVICE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "drv_sensor.h"
|
||||
#include "drv_orb_dev.h"
|
||||
|
||||
/*
|
||||
* ioctl() definitions
|
||||
*/
|
||||
|
||||
#define _DEVICEIOCBASE (0x100)
|
||||
#define _DEVICEIOC(_n) (_IOC(_DEVICEIOCBASE, _n))
|
||||
|
||||
/** ask device to stop publishing */
|
||||
#define DEVIOCSPUBBLOCK _DEVICEIOC(0)
|
||||
|
||||
/** check publication block status */
|
||||
#define DEVIOCGPUBBLOCK _DEVICEIOC(1)
|
||||
|
||||
#endif /* _DRV_DEVICE_H */
|
||||
@@ -193,6 +193,20 @@ ORB_DECLARE(output_pwm);
|
||||
* split between servos and GPIO */
|
||||
#define PWM_SERVO_SET_COUNT _IOC(_PWM_SERVO_BASE, 20)
|
||||
|
||||
/** set the lockdown override flag to enable outputs in HIL */
|
||||
#define PWM_SERVO_SET_DISABLE_LOCKDOWN _IOC(_PWM_SERVO_BASE, 21)
|
||||
|
||||
/** get the lockdown override flag to enable outputs in HIL */
|
||||
#define PWM_SERVO_GET_DISABLE_LOCKDOWN _IOC(_PWM_SERVO_BASE, 22)
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* WARNING WARNING WARNING! DO NOT EXCEED 31 IN IOC INDICES HERE!
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/** set a single servo to a specific value */
|
||||
#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -62,6 +62,11 @@
|
||||
*/
|
||||
#define RC_INPUT_MAX_CHANNELS 18
|
||||
|
||||
/**
|
||||
* Maximum RSSI value
|
||||
*/
|
||||
#define RC_INPUT_RSSI_MAX 255
|
||||
|
||||
/**
|
||||
* Input signal type, value is a control position from zero to 100
|
||||
* percent.
|
||||
@@ -83,8 +88,11 @@ enum RC_INPUT_SOURCE {
|
||||
* on the board involved.
|
||||
*/
|
||||
struct rc_input_values {
|
||||
/** decoding time */
|
||||
uint64_t timestamp;
|
||||
/** publication time */
|
||||
uint64_t timestamp_publication;
|
||||
|
||||
/** last valid reception time */
|
||||
uint64_t timestamp_last_signal;
|
||||
|
||||
/** number of channels actually being seen */
|
||||
uint32_t channel_count;
|
||||
@@ -92,6 +100,40 @@ struct rc_input_values {
|
||||
/** receive signal strength indicator (RSSI): < 0: Undefined, 0: no signal, 255: full reception */
|
||||
int32_t rssi;
|
||||
|
||||
/**
|
||||
* explicit failsafe flag: true on TX failure or TX out of range , false otherwise.
|
||||
* Only the true state is reliable, as there are some (PPM) receivers on the market going
|
||||
* into failsafe without telling us explicitly.
|
||||
* */
|
||||
bool rc_failsafe;
|
||||
|
||||
/**
|
||||
* RC receiver connection status: True,if no frame has arrived in the expected time, false otherwise.
|
||||
* True usally means that the receiver has been disconnected, but can also indicate a radio link loss on "stupid" systems.
|
||||
* Will remain false, if a RX with failsafe option continues to transmit frames after a link loss.
|
||||
* */
|
||||
bool rc_lost;
|
||||
|
||||
/**
|
||||
* Number of lost RC frames.
|
||||
* Note: intended purpose: observe the radio link quality if RSSI is not available
|
||||
* This value must not be used to trigger any failsafe-alike funtionality.
|
||||
* */
|
||||
uint16_t rc_lost_frame_count;
|
||||
|
||||
/**
|
||||
* Number of total RC frames.
|
||||
* Note: intended purpose: observe the radio link quality if RSSI is not available
|
||||
* This value must not be used to trigger any failsafe-alike funtionality.
|
||||
* */
|
||||
uint16_t rc_total_frame_count;
|
||||
|
||||
/**
|
||||
* Length of a single PPM frame.
|
||||
* Zero for non-PPM systems
|
||||
*/
|
||||
uint16_t rc_ppm_frame_length;
|
||||
|
||||
/** Input source */
|
||||
enum RC_INPUT_SOURCE input_source;
|
||||
|
||||
@@ -107,8 +149,12 @@ ORB_DECLARE(input_rc);
|
||||
#define _RC_INPUT_BASE 0x2b00
|
||||
|
||||
/** Fetch R/C input values into (rc_input_values *)arg */
|
||||
|
||||
#define RC_INPUT_GET _IOC(_RC_INPUT_BASE, 0)
|
||||
|
||||
/** Enable RSSI input via ADC */
|
||||
#define RC_INPUT_ENABLE_RSSI_ANALOG _IOC(_RC_INPUT_BASE, 1)
|
||||
|
||||
/** Enable RSSI input via PWM signal */
|
||||
#define RC_INPUT_ENABLE_RSSI_PWM _IOC(_RC_INPUT_BASE, 2)
|
||||
|
||||
#endif /* _DRV_RC_INPUT_H */
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 drv_sbus.h
|
||||
*
|
||||
* Futaba S.BUS / S.BUS 2 compatible interface.
|
||||
*/
|
||||
|
||||
#ifndef _DRV_SBUS_H
|
||||
#define _DRV_SBUS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "drv_orb_dev.h"
|
||||
|
||||
/**
|
||||
* Path for the default S.BUS device
|
||||
*/
|
||||
#define SBUS_DEVICE_PATH "/dev/sbus"
|
||||
|
||||
#define _SBUS_BASE 0x2c00
|
||||
|
||||
/** Enable S.BUS version 1 / 2 output (0 to disable) */
|
||||
#define SBUS_SET_PROTO_VERSION _IOC(_SBUS_BASE, 0)
|
||||
|
||||
#endif /* _DRV_SBUS_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* 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
|
||||
@@ -184,8 +184,10 @@ ETSAirspeed::collect()
|
||||
report.voltage = 0;
|
||||
report.max_differential_pressure_pa = _max_differential_pressure_pa;
|
||||
|
||||
/* announce the airspeed if needed, just publish else */
|
||||
orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
|
||||
if (_airspeed_pub > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
|
||||
}
|
||||
|
||||
new_report(report);
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ void frsky_send_frame2(int uart)
|
||||
float course = 0, lat = 0, lon = 0, speed = 0, alt = 0;
|
||||
char lat_ns = 0, lon_ew = 0;
|
||||
int sec = 0;
|
||||
if (global_pos.valid) {
|
||||
if (global_pos.global_valid) {
|
||||
time_t time_gps = global_pos.time_gps_usec / 1000000;
|
||||
struct tm *tm_gps = gmtime(&time_gps);
|
||||
|
||||
|
||||
+13
-8
@@ -289,11 +289,13 @@ GPS::task_main()
|
||||
|
||||
//no time and satellite information simulated
|
||||
|
||||
if (_report_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_pub, &_report);
|
||||
if (!(_pub_blocked)) {
|
||||
if (_report_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_pub, &_report);
|
||||
|
||||
} else {
|
||||
_report_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report);
|
||||
} else {
|
||||
_report_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report);
|
||||
}
|
||||
}
|
||||
|
||||
usleep(2e5);
|
||||
@@ -330,11 +332,14 @@ GPS::task_main()
|
||||
while (_Helper->receive(TIMEOUT_5HZ) > 0 && !_task_should_exit) {
|
||||
// lock();
|
||||
/* opportunistic publishing - else invalid data would end up on the bus */
|
||||
if (_report_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_pub, &_report);
|
||||
|
||||
} else {
|
||||
_report_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report);
|
||||
if (!(_pub_blocked)) {
|
||||
if (_report_pub > 0) {
|
||||
orb_publish(ORB_ID(vehicle_gps_position), _report_pub, &_report);
|
||||
|
||||
} else {
|
||||
_report_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report);
|
||||
}
|
||||
}
|
||||
|
||||
last_rate_count++;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.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
|
||||
@@ -41,6 +39,9 @@
|
||||
|
||||
/**
|
||||
* @file gps_helper.cpp
|
||||
*
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*/
|
||||
|
||||
float
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.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
|
||||
@@ -35,6 +33,8 @@
|
||||
|
||||
/**
|
||||
* @file gps_helper.h
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef GPS_HELPER_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
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* 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
|
||||
@@ -33,7 +31,12 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file mkt.cpp */
|
||||
/**
|
||||
* @file mtk.cpp
|
||||
*
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* 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
|
||||
@@ -33,7 +31,12 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file mtk.h */
|
||||
/**
|
||||
* @file mtk.cpp
|
||||
*
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef MTK_H_
|
||||
#define MTK_H_
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* Anton Babushkin <anton.babushkin@me.com>
|
||||
* 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
|
||||
@@ -40,8 +37,13 @@
|
||||
* U-Blox protocol implementation. Following u-blox 6/7 Receiver Description
|
||||
* including Prototol Specification.
|
||||
*
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*
|
||||
* @see http://www.u-blox.com/images/downloads/Product_Docs/u-blox6_ReceiverDescriptionProtocolSpec_%28GPS.G6-SW-10018%29.pdf
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
|
||||
+12
-5
@@ -1,9 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* Anton Babushkin <anton.babushkin@me.com>
|
||||
* 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
|
||||
@@ -34,7 +31,17 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file U-Blox protocol definitions */
|
||||
/**
|
||||
* @file ubx.h
|
||||
*
|
||||
* U-Blox protocol definition. Following u-blox 6/7 Receiver Description
|
||||
* including Prototol Specification.
|
||||
*
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UBX_H_
|
||||
#define UBX_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
|
||||
@@ -381,16 +381,6 @@ HMC5883::init()
|
||||
reset();
|
||||
|
||||
_class_instance = register_class_devname(MAG_DEVICE_PATH);
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
/* get a publish handle on the mag topic if we are
|
||||
* the primary mag */
|
||||
struct mag_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_mag_topic = orb_advertise(ORB_ID(sensor_mag), &zero_report);
|
||||
|
||||
if (_mag_topic < 0)
|
||||
debug("failed to create sensor_mag object");
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
/* sensor is ok, but not calibrated */
|
||||
@@ -867,9 +857,17 @@ HMC5883::collect()
|
||||
/* z remains z */
|
||||
new_report.z = ((report.z * _range_scale) - _scale.z_offset) * _scale.z_scale;
|
||||
|
||||
if (_mag_topic != -1) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY && !(_pub_blocked)) {
|
||||
|
||||
if (_mag_topic != -1) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);
|
||||
} else {
|
||||
_mag_topic = orb_advertise(ORB_ID(sensor_mag), &new_report);
|
||||
|
||||
if (_mag_topic < 0)
|
||||
debug("failed to create sensor_mag publication");
|
||||
}
|
||||
}
|
||||
|
||||
/* post a report to the ring */
|
||||
@@ -1140,10 +1138,12 @@ int HMC5883::check_calibration()
|
||||
SUBSYSTEM_TYPE_MAG};
|
||||
static orb_advert_t pub = -1;
|
||||
|
||||
if (pub > 0) {
|
||||
orb_publish(ORB_ID(subsystem_info), pub, &info);
|
||||
} else {
|
||||
pub = orb_advertise(ORB_ID(subsystem_info), &info);
|
||||
if (!(_pub_blocked)) {
|
||||
if (pub > 0) {
|
||||
orb_publish(ORB_ID(subsystem_info), pub, &info);
|
||||
} else {
|
||||
pub = orb_advertise(ORB_ID(subsystem_info), &info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -379,15 +379,24 @@ L3GD20::init()
|
||||
goto out;
|
||||
|
||||
_class_instance = register_class_devname(GYRO_DEVICE_PATH);
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
/* advertise sensor topic */
|
||||
struct gyro_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_gyro_topic = orb_advertise(ORB_ID(sensor_gyro), &zero_report);
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
measure();
|
||||
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct gyro_report grp;
|
||||
_reports->get(&grp);
|
||||
|
||||
_gyro_topic = orb_advertise(ORB_ID(sensor_gyro), &grp);
|
||||
|
||||
if (_gyro_topic < 0)
|
||||
debug("failed to create sensor_gyro publication");
|
||||
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
out:
|
||||
return ret;
|
||||
@@ -894,8 +903,10 @@ L3GD20::measure()
|
||||
poll_notify(POLLIN);
|
||||
|
||||
/* publish for subscribers */
|
||||
if (_gyro_topic > 0)
|
||||
if (_gyro_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_gyro), _gyro_topic, &report);
|
||||
}
|
||||
|
||||
_read++;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* 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
|
||||
@@ -277,15 +277,15 @@ private:
|
||||
unsigned _mag_samplerate;
|
||||
|
||||
orb_advert_t _accel_topic;
|
||||
int _class_instance;
|
||||
int _accel_class_instance;
|
||||
|
||||
unsigned _accel_read;
|
||||
unsigned _mag_read;
|
||||
|
||||
perf_counter_t _accel_sample_perf;
|
||||
perf_counter_t _mag_sample_perf;
|
||||
perf_counter_t _reg7_resets;
|
||||
perf_counter_t _reg1_resets;
|
||||
perf_counter_t _reg7_resets;
|
||||
perf_counter_t _extreme_values;
|
||||
perf_counter_t _accel_reschedules;
|
||||
|
||||
@@ -295,8 +295,8 @@ private:
|
||||
|
||||
// expceted values of reg1 and reg7 to catch in-flight
|
||||
// brownouts of the sensor
|
||||
uint8_t _reg7_expected;
|
||||
uint8_t _reg1_expected;
|
||||
uint8_t _reg7_expected;
|
||||
|
||||
// accel logging
|
||||
int _accel_log_fd;
|
||||
@@ -500,7 +500,7 @@ LSM303D::LSM303D(int bus, const char* path, spi_dev_e device) :
|
||||
_mag_range_scale(0.0f),
|
||||
_mag_samplerate(0),
|
||||
_accel_topic(-1),
|
||||
_class_instance(-1),
|
||||
_accel_class_instance(-1),
|
||||
_accel_read(0),
|
||||
_mag_read(0),
|
||||
_accel_sample_perf(perf_alloc(PC_ELAPSED, "lsm303d_accel_read")),
|
||||
@@ -551,8 +551,8 @@ LSM303D::~LSM303D()
|
||||
if (_mag_reports != nullptr)
|
||||
delete _mag_reports;
|
||||
|
||||
if (_class_instance != -1)
|
||||
unregister_class_devname(ACCEL_DEVICE_PATH, _class_instance);
|
||||
if (_accel_class_instance != -1)
|
||||
unregister_class_devname(ACCEL_DEVICE_PATH, _accel_class_instance);
|
||||
|
||||
delete _mag;
|
||||
|
||||
@@ -562,13 +562,13 @@ LSM303D::~LSM303D()
|
||||
perf_free(_reg1_resets);
|
||||
perf_free(_reg7_resets);
|
||||
perf_free(_extreme_values);
|
||||
perf_free(_accel_reschedules);
|
||||
}
|
||||
|
||||
int
|
||||
LSM303D::init()
|
||||
{
|
||||
int ret = ERROR;
|
||||
int mag_ret;
|
||||
|
||||
/* do SPI init (and probe) first */
|
||||
if (SPI::init() != OK) {
|
||||
@@ -597,13 +597,37 @@ LSM303D::init()
|
||||
goto out;
|
||||
}
|
||||
|
||||
_class_instance = register_class_devname(ACCEL_DEVICE_PATH);
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
// we are the primary accel device, so advertise to
|
||||
// the ORB
|
||||
struct accel_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &zero_report);
|
||||
/* fill report structures */
|
||||
measure();
|
||||
|
||||
if (_mag->_mag_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct mag_report mrp;
|
||||
_mag_reports->get(&mrp);
|
||||
|
||||
/* measurement will have generated a report, publish */
|
||||
_mag->_mag_topic = orb_advertise(ORB_ID(sensor_mag), &mrp);
|
||||
|
||||
if (_mag->_mag_topic < 0)
|
||||
debug("failed to create sensor_mag publication");
|
||||
|
||||
}
|
||||
|
||||
_accel_class_instance = register_class_devname(ACCEL_DEVICE_PATH);
|
||||
|
||||
if (_accel_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct accel_report arp;
|
||||
_accel_reports->get(&arp);
|
||||
|
||||
/* measurement will have generated a report, publish */
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &arp);
|
||||
|
||||
if (_accel_topic < 0)
|
||||
debug("failed to create sensor_accel publication");
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -727,7 +751,7 @@ LSM303D::check_extremes(const accel_report *arb)
|
||||
_last_log_us = now;
|
||||
::dprintf(_accel_log_fd, "ARB %llu %.3f %.3f %.3f %d %d %d boot_ok=%u\r\n",
|
||||
(unsigned long long)arb->timestamp,
|
||||
arb->x, arb->y, arb->z,
|
||||
(double)arb->x, (double)arb->y, (double)arb->z,
|
||||
(int)arb->x_raw,
|
||||
(int)arb->y_raw,
|
||||
(int)arb->z_raw,
|
||||
@@ -1517,8 +1541,8 @@ LSM303D::measure()
|
||||
/* notify anyone waiting for data */
|
||||
poll_notify(POLLIN);
|
||||
|
||||
if (_accel_topic != -1) {
|
||||
/* publish for subscribers */
|
||||
if (_accel_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_accel), _accel_topic, &accel_report);
|
||||
}
|
||||
|
||||
@@ -1591,8 +1615,8 @@ LSM303D::mag_measure()
|
||||
/* notify anyone waiting for data */
|
||||
poll_notify(POLLIN);
|
||||
|
||||
if (_mag->_mag_topic != -1) {
|
||||
/* publish for subscribers */
|
||||
if (_mag->_mag_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_mag), _mag->_mag_topic, &mag_report);
|
||||
}
|
||||
|
||||
@@ -1707,13 +1731,6 @@ LSM303D_mag::init()
|
||||
goto out;
|
||||
|
||||
_mag_class_instance = register_class_devname(MAG_DEVICE_PATH);
|
||||
if (_mag_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
// we are the primary mag device, so advertise to
|
||||
// the ORB
|
||||
struct mag_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_mag_topic = orb_advertise(ORB_ID(sensor_mag), &zero_report);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
|
||||
* 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
|
||||
@@ -208,8 +208,10 @@ MEASAirspeed::collect()
|
||||
report.voltage = 0;
|
||||
report.max_differential_pressure_pa = _max_differential_pressure_pa;
|
||||
|
||||
/* announce the airspeed if needed, just publish else */
|
||||
orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
|
||||
if (_airspeed_pub > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
|
||||
}
|
||||
|
||||
new_report(report);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
|
||||
* Copyright (C) 2012-2014 PX4 Development Team. All rights reserved.
|
||||
* Author: Marco Bauer <marco@wtns.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -65,7 +65,6 @@
|
||||
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_pwm_output.h>
|
||||
#include <drivers/drv_gpio.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <drivers/drv_rc_input.h>
|
||||
|
||||
@@ -93,16 +92,12 @@
|
||||
#define MOTOR_SPINUP_COUNTER 30
|
||||
#define ESC_UORB_PUBLISH_DELAY 500000
|
||||
|
||||
|
||||
|
||||
|
||||
class MK : public device::I2C
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
MODE_NONE,
|
||||
MODE_2PWM,
|
||||
MODE_4PWM,
|
||||
MODE_6PWM,
|
||||
};
|
||||
|
||||
enum MappingMode {
|
||||
MAPPING_MK = 0,
|
||||
MAPPING_PX4,
|
||||
@@ -120,8 +115,7 @@ public:
|
||||
virtual int init(unsigned motors);
|
||||
virtual ssize_t write(file *filp, const char *buffer, size_t len);
|
||||
|
||||
int set_mode(Mode mode);
|
||||
int set_pwm_rate(unsigned rate);
|
||||
int set_update_rate(unsigned rate);
|
||||
int set_motor_count(unsigned count);
|
||||
int set_motor_test(bool motortest);
|
||||
int set_overrideSecurityChecks(bool overrideSecurityChecks);
|
||||
@@ -133,7 +127,6 @@ private:
|
||||
static const unsigned _max_actuators = MAX_MOTORS;
|
||||
static const bool showDebug = false;
|
||||
|
||||
Mode _mode;
|
||||
int _update_rate;
|
||||
int _current_update_rate;
|
||||
int _task;
|
||||
@@ -180,33 +173,15 @@ private:
|
||||
static const GPIOConfig _gpio_tab[];
|
||||
static const unsigned _ngpio;
|
||||
|
||||
void gpio_reset(void);
|
||||
void gpio_set_function(uint32_t gpios, int function);
|
||||
void gpio_write(uint32_t gpios, int function);
|
||||
uint32_t gpio_read(void);
|
||||
int gpio_ioctl(file *filp, int cmd, unsigned long arg);
|
||||
int mk_servo_arm(bool status);
|
||||
|
||||
int mk_servo_set(unsigned int chan, short val);
|
||||
int mk_servo_set_value(unsigned int chan, short val);
|
||||
int mk_servo_test(unsigned int chan);
|
||||
short scaling(float val, float inMin, float inMax, float outMin, float outMax);
|
||||
|
||||
|
||||
};
|
||||
|
||||
const MK::GPIOConfig MK::_gpio_tab[] = {
|
||||
{GPIO_GPIO0_INPUT, GPIO_GPIO0_OUTPUT, 0},
|
||||
{GPIO_GPIO1_INPUT, GPIO_GPIO1_OUTPUT, 0},
|
||||
{GPIO_GPIO2_INPUT, GPIO_GPIO2_OUTPUT, GPIO_USART2_CTS_1},
|
||||
{GPIO_GPIO3_INPUT, GPIO_GPIO3_OUTPUT, GPIO_USART2_RTS_1},
|
||||
{GPIO_GPIO4_INPUT, GPIO_GPIO4_OUTPUT, GPIO_USART2_TX_1},
|
||||
{GPIO_GPIO5_INPUT, GPIO_GPIO5_OUTPUT, GPIO_USART2_RX_1},
|
||||
{GPIO_GPIO6_INPUT, GPIO_GPIO6_OUTPUT, GPIO_CAN2_TX_2},
|
||||
{GPIO_GPIO7_INPUT, GPIO_GPIO7_OUTPUT, GPIO_CAN2_RX_2},
|
||||
};
|
||||
|
||||
const unsigned MK::_ngpio = sizeof(MK::_gpio_tab) / sizeof(MK::_gpio_tab[0]);
|
||||
|
||||
|
||||
const int blctrlAddr_quad_plus[] = { 2, 2, -2, -2, 0, 0, 0, 0 }; // Addresstranslator for Quad + configuration
|
||||
const int blctrlAddr_hexa_plus[] = { 0, 2, 2, -2, 1, -3, 0, 0 }; // Addresstranslator for Hexa + configuration
|
||||
@@ -247,8 +222,7 @@ MK *g_mk;
|
||||
|
||||
MK::MK(int bus, const char *_device_path) :
|
||||
I2C("mkblctrl", "/dev/mkblctrl", bus, 0, I2C_BUS_SPEED),
|
||||
_mode(MODE_NONE),
|
||||
_update_rate(50),
|
||||
_update_rate(400),
|
||||
_task(-1),
|
||||
_t_actuators(-1),
|
||||
_t_actuator_armed(-1),
|
||||
@@ -317,26 +291,23 @@ MK::init(unsigned motors)
|
||||
|
||||
usleep(500000);
|
||||
|
||||
if (sizeof(_device) > 0) {
|
||||
ret = register_driver(_device, &fops, 0666, (void *)this);
|
||||
if (sizeof(_device) > 0) {
|
||||
ret = register_driver(_device, &fops, 0666, (void *)this);
|
||||
|
||||
if (ret == OK) {
|
||||
if (ret == OK) {
|
||||
log("creating alternate output device");
|
||||
_primary_pwm_device = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* reset GPIOs */
|
||||
gpio_reset();
|
||||
}
|
||||
|
||||
/* start the IO interface task */
|
||||
_task = task_spawn_cmd("mkblctrl",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
2048,
|
||||
(main_t)&MK::task_main_trampoline,
|
||||
nullptr);
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
2048,
|
||||
(main_t)&MK::task_main_trampoline,
|
||||
nullptr);
|
||||
|
||||
|
||||
if (_task < 0) {
|
||||
@@ -354,43 +325,7 @@ MK::task_main_trampoline(int argc, char *argv[])
|
||||
}
|
||||
|
||||
int
|
||||
MK::set_mode(Mode mode)
|
||||
{
|
||||
/*
|
||||
* Configure for PWM output.
|
||||
*
|
||||
* Note that regardless of the configured mode, the task is always
|
||||
* listening and mixing; the mode just selects which of the channels
|
||||
* are presented on the output pins.
|
||||
*/
|
||||
switch (mode) {
|
||||
case MODE_2PWM:
|
||||
up_pwm_servo_deinit();
|
||||
_update_rate = UPDATE_RATE; /* default output rate */
|
||||
break;
|
||||
|
||||
case MODE_4PWM:
|
||||
up_pwm_servo_deinit();
|
||||
_update_rate = UPDATE_RATE; /* default output rate */
|
||||
break;
|
||||
|
||||
case MODE_NONE:
|
||||
debug("MODE_NONE");
|
||||
/* disable servo outputs and set a very low update rate */
|
||||
up_pwm_servo_deinit();
|
||||
_update_rate = UPDATE_RATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_mode = mode;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
MK::set_pwm_rate(unsigned rate)
|
||||
MK::set_update_rate(unsigned rate)
|
||||
{
|
||||
if ((rate > 500) || (rate < 10))
|
||||
return -EINVAL;
|
||||
@@ -621,11 +556,13 @@ MK::task_main()
|
||||
}
|
||||
}
|
||||
|
||||
if(!_overrideSecurityChecks) {
|
||||
if (!_overrideSecurityChecks) {
|
||||
/* don't go under BLCTRL_MIN_VALUE */
|
||||
|
||||
if (outputs.output[i] < BLCTRL_MIN_VALUE) {
|
||||
outputs.output[i] = BLCTRL_MIN_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* output to BLCtrl's */
|
||||
@@ -675,21 +612,24 @@ MK::task_main()
|
||||
esc.esc[i].esc_current = (uint16_t) Motor[i].Current;
|
||||
esc.esc[i].esc_rpm = (uint16_t) 0;
|
||||
esc.esc[i].esc_setpoint = (float) Motor[i].SetPoint_PX4;
|
||||
|
||||
if (Motor[i].Version == 1) {
|
||||
// BLCtrl 2.0 (11Bit)
|
||||
esc.esc[i].esc_setpoint_raw = (uint16_t) (Motor[i].SetPoint<<3) | Motor[i].SetPointLowerBits;
|
||||
esc.esc[i].esc_setpoint_raw = (uint16_t)(Motor[i].SetPoint << 3) | Motor[i].SetPointLowerBits;
|
||||
|
||||
} else {
|
||||
// BLCtrl < 2.0 (8Bit)
|
||||
esc.esc[i].esc_setpoint_raw = (uint16_t) Motor[i].SetPoint;
|
||||
}
|
||||
|
||||
esc.esc[i].esc_temperature = (uint16_t) Motor[i].Temperature;
|
||||
esc.esc[i].esc_state = (uint16_t) Motor[i].State;
|
||||
esc.esc[i].esc_errorcount = (uint16_t) 0;
|
||||
|
||||
// if motortest is requested - do it...
|
||||
if (_motortest == true) {
|
||||
mk_servo_test(i);
|
||||
}
|
||||
// if motortest is requested - do it...
|
||||
if (_motortest == true) {
|
||||
mk_servo_test(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -728,7 +668,7 @@ MK::mk_servo_arm(bool status)
|
||||
unsigned int
|
||||
MK::mk_check_for_blctrl(unsigned int count, bool showOutput, bool initI2C)
|
||||
{
|
||||
if(initI2C) {
|
||||
if (initI2C) {
|
||||
I2C::init();
|
||||
}
|
||||
|
||||
@@ -781,8 +721,8 @@ MK::mk_check_for_blctrl(unsigned int count, bool showOutput, bool initI2C)
|
||||
fprintf(stderr, "[mkblctrl] blctrl[%i] : found=%i\tversion=%i\tcurrent=%i\tmaxpwm=%i\ttemperature=%i\n", i, Motor[i].State, Motor[i].Version, Motor[i].Current, Motor[i].MaxPWM, Motor[i].Temperature);
|
||||
}
|
||||
|
||||
|
||||
if(!_overrideSecurityChecks) {
|
||||
|
||||
if (!_overrideSecurityChecks) {
|
||||
if (foundMotorCount != 4 && foundMotorCount != 6 && foundMotorCount != 8) {
|
||||
_task_should_exit = true;
|
||||
}
|
||||
@@ -811,8 +751,8 @@ MK::mk_servo_set(unsigned int chan, short val)
|
||||
tmpVal = 0;
|
||||
}
|
||||
|
||||
Motor[chan].SetPoint = (uint8_t)(tmpVal>>3)&0xff;
|
||||
Motor[chan].SetPointLowerBits = ((uint8_t)tmpVal%8)&0x07;
|
||||
Motor[chan].SetPoint = (uint8_t)(tmpVal >> 3) & 0xff;
|
||||
Motor[chan].SetPointLowerBits = ((uint8_t)tmpVal % 8) & 0x07;
|
||||
|
||||
if (_armed == false) {
|
||||
Motor[chan].SetPoint = 0;
|
||||
@@ -1019,28 +959,6 @@ MK::ioctl(file *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// XXX disabled, confusing users
|
||||
|
||||
/* try it as a GPIO ioctl first */
|
||||
ret = gpio_ioctl(filp, cmd, arg);
|
||||
|
||||
if (ret != -ENOTTY)
|
||||
return ret;
|
||||
|
||||
/* if we are in valid PWM mode, try it as a PWM ioctl as well */
|
||||
/*
|
||||
switch (_mode) {
|
||||
case MODE_2PWM:
|
||||
case MODE_4PWM:
|
||||
case MODE_6PWM:
|
||||
ret = pwm_ioctl(filp, cmd, arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("not in a PWM mode");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
ret = pwm_ioctl(filp, cmd, arg);
|
||||
|
||||
/* if nobody wants it, let CDev have it */
|
||||
@@ -1075,6 +993,10 @@ MK::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
ret = OK;
|
||||
break;
|
||||
|
||||
case PWM_SERVO_GET_UPDATE_RATE:
|
||||
*(uint32_t *)arg = _update_rate;
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SET_SELECT_UPDATE_RATE:
|
||||
ret = OK;
|
||||
break;
|
||||
@@ -1084,6 +1006,7 @@ MK::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
if (arg < 2150) {
|
||||
Motor[cmd - PWM_SERVO_SET(0)].RawPwmValue = (unsigned short)arg;
|
||||
mk_servo_set(cmd - PWM_SERVO_SET(0), scaling(arg, 1010, 2100, 0, 2047));
|
||||
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
@@ -1198,139 +1121,10 @@ MK::write(file *filp, const char *buffer, size_t len)
|
||||
return count * 2;
|
||||
}
|
||||
|
||||
void
|
||||
MK::gpio_reset(void)
|
||||
{
|
||||
/*
|
||||
* Setup default GPIO config - all pins as GPIOs, GPIO driver chip
|
||||
* to input mode.
|
||||
*/
|
||||
for (unsigned i = 0; i < _ngpio; i++)
|
||||
stm32_configgpio(_gpio_tab[i].input);
|
||||
|
||||
stm32_gpiowrite(GPIO_GPIO_DIR, 0);
|
||||
stm32_configgpio(GPIO_GPIO_DIR);
|
||||
}
|
||||
|
||||
void
|
||||
MK::gpio_set_function(uint32_t gpios, int function)
|
||||
{
|
||||
/*
|
||||
* GPIOs 0 and 1 must have the same direction as they are buffered
|
||||
* by a shared 2-port driver. Any attempt to set either sets both.
|
||||
*/
|
||||
if (gpios & 3) {
|
||||
gpios |= 3;
|
||||
|
||||
/* flip the buffer to output mode if required */
|
||||
if (GPIO_SET_OUTPUT == function)
|
||||
stm32_gpiowrite(GPIO_GPIO_DIR, 1);
|
||||
}
|
||||
|
||||
/* configure selected GPIOs as required */
|
||||
for (unsigned i = 0; i < _ngpio; i++) {
|
||||
if (gpios & (1 << i)) {
|
||||
switch (function) {
|
||||
case GPIO_SET_INPUT:
|
||||
stm32_configgpio(_gpio_tab[i].input);
|
||||
break;
|
||||
|
||||
case GPIO_SET_OUTPUT:
|
||||
stm32_configgpio(_gpio_tab[i].output);
|
||||
break;
|
||||
|
||||
case GPIO_SET_ALT_1:
|
||||
if (_gpio_tab[i].alt != 0)
|
||||
stm32_configgpio(_gpio_tab[i].alt);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* flip buffer to input mode if required */
|
||||
if ((GPIO_SET_INPUT == function) && (gpios & 3))
|
||||
stm32_gpiowrite(GPIO_GPIO_DIR, 0);
|
||||
}
|
||||
|
||||
void
|
||||
MK::gpio_write(uint32_t gpios, int function)
|
||||
{
|
||||
int value = (function == GPIO_SET) ? 1 : 0;
|
||||
|
||||
for (unsigned i = 0; i < _ngpio; i++)
|
||||
if (gpios & (1 << i))
|
||||
stm32_gpiowrite(_gpio_tab[i].output, value);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MK::gpio_read(void)
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
|
||||
for (unsigned i = 0; i < _ngpio; i++)
|
||||
if (stm32_gpioread(_gpio_tab[i].input))
|
||||
bits |= (1 << i);
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
int
|
||||
MK::gpio_ioctl(struct file *filp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
lock();
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case GPIO_RESET:
|
||||
gpio_reset();
|
||||
break;
|
||||
|
||||
case GPIO_SET_OUTPUT:
|
||||
case GPIO_SET_INPUT:
|
||||
case GPIO_SET_ALT_1:
|
||||
gpio_set_function(arg, cmd);
|
||||
break;
|
||||
|
||||
case GPIO_SET_ALT_2:
|
||||
case GPIO_SET_ALT_3:
|
||||
case GPIO_SET_ALT_4:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
||||
case GPIO_SET:
|
||||
case GPIO_CLEAR:
|
||||
gpio_write(arg, cmd);
|
||||
break;
|
||||
|
||||
case GPIO_GET:
|
||||
*(uint32_t *)arg = gpio_read();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum PortMode {
|
||||
PORT_MODE_UNSET = 0,
|
||||
PORT_FULL_GPIO,
|
||||
PORT_FULL_SERIAL,
|
||||
PORT_FULL_PWM,
|
||||
PORT_GPIO_AND_SERIAL,
|
||||
PORT_PWM_AND_SERIAL,
|
||||
PORT_PWM_AND_GPIO,
|
||||
};
|
||||
|
||||
enum MappingMode {
|
||||
MAPPING_MK = 0,
|
||||
MAPPING_PX4,
|
||||
@@ -1341,20 +1135,11 @@ enum FrameType {
|
||||
FRAME_X,
|
||||
};
|
||||
|
||||
PortMode g_port_mode;
|
||||
|
||||
int
|
||||
mk_new_mode(PortMode new_mode, int update_rate, int motorcount, bool motortest, int px4mode, int frametype, bool overrideSecurityChecks)
|
||||
mk_new_mode(int update_rate, int motorcount, bool motortest, int px4mode, int frametype, bool overrideSecurityChecks)
|
||||
{
|
||||
uint32_t gpio_bits;
|
||||
int shouldStop = 0;
|
||||
MK::Mode servo_mode;
|
||||
|
||||
/* reset to all-inputs */
|
||||
g_mk->ioctl(0, GPIO_RESET, 0);
|
||||
|
||||
gpio_bits = 0;
|
||||
servo_mode = MK::MODE_NONE;
|
||||
|
||||
/* native PX4 addressing) */
|
||||
g_mk->set_px4mode(px4mode);
|
||||
@@ -1368,7 +1153,6 @@ mk_new_mode(PortMode new_mode, int update_rate, int motorcount, bool motortest,
|
||||
/* ovveride security checks if enabled */
|
||||
g_mk->set_overrideSecurityChecks(overrideSecurityChecks);
|
||||
|
||||
|
||||
/* count used motors */
|
||||
do {
|
||||
if (g_mk->mk_check_for_blctrl(8, false, false) != 0) {
|
||||
@@ -1383,86 +1167,54 @@ mk_new_mode(PortMode new_mode, int update_rate, int motorcount, bool motortest,
|
||||
|
||||
g_mk->set_motor_count(g_mk->mk_check_for_blctrl(8, true, false));
|
||||
|
||||
/* (re)set the PWM output mode */
|
||||
g_mk->set_mode(servo_mode);
|
||||
|
||||
|
||||
if ((servo_mode != MK::MODE_NONE) && (update_rate != 0))
|
||||
g_mk->set_pwm_rate(update_rate);
|
||||
g_mk->set_update_rate(update_rate);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
mk_start(unsigned bus, unsigned motors, char *device_path)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
if (g_mk == nullptr) {
|
||||
|
||||
g_mk = new MK(bus, device_path);
|
||||
|
||||
if (g_mk == nullptr) {
|
||||
ret = -ENOMEM;
|
||||
|
||||
} else {
|
||||
ret = g_mk->init(motors);
|
||||
|
||||
if (ret != OK) {
|
||||
delete g_mk;
|
||||
g_mk = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mk_check_for_i2c_esc_bus(char *device_path, int motors)
|
||||
mk_start(unsigned motors, char *device_path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (g_mk == nullptr) {
|
||||
// try i2c3 first
|
||||
g_mk = new MK(3, device_path);
|
||||
|
||||
g_mk = new MK(3, device_path);
|
||||
if (!g_mk)
|
||||
return -ENOMEM;
|
||||
|
||||
if (g_mk == nullptr) {
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
ret = g_mk->mk_check_for_blctrl(8, false, true);
|
||||
delete g_mk;
|
||||
g_mk = nullptr;
|
||||
|
||||
if (ret > 0) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
g_mk = new MK(1, device_path);
|
||||
|
||||
if (g_mk == nullptr) {
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
ret = g_mk->mk_check_for_blctrl(8, false, true);
|
||||
delete g_mk;
|
||||
g_mk = nullptr;
|
||||
|
||||
if (ret > 0) {
|
||||
return 1;
|
||||
}
|
||||
if (OK == g_mk->init(motors)) {
|
||||
warnx("[mkblctrl] scanning i2c3...\n");
|
||||
ret = g_mk->mk_check_for_blctrl(8, false, true);
|
||||
|
||||
if (ret > 0) {
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
delete g_mk;
|
||||
g_mk = nullptr;
|
||||
|
||||
// fallback to bus 1
|
||||
g_mk = new MK(1, device_path);
|
||||
|
||||
if (!g_mk)
|
||||
return -ENOMEM;
|
||||
|
||||
if (OK == g_mk->init(motors)) {
|
||||
warnx("[mkblctrl] scanning i2c1...\n");
|
||||
ret = g_mk->mk_check_for_blctrl(8, false, true);
|
||||
|
||||
if (ret > 0) {
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
delete g_mk;
|
||||
g_mk = nullptr;
|
||||
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
@@ -1472,10 +1224,8 @@ extern "C" __EXPORT int mkblctrl_main(int argc, char *argv[]);
|
||||
int
|
||||
mkblctrl_main(int argc, char *argv[])
|
||||
{
|
||||
PortMode port_mode = PORT_FULL_PWM;
|
||||
int pwm_update_rate_in_hz = UPDATE_RATE;
|
||||
int motorcount = 8;
|
||||
int bus = -1;
|
||||
int px4mode = MAPPING_PX4;
|
||||
int frametype = FRAME_PLUS; // + plus is default
|
||||
bool motortest = false;
|
||||
@@ -1489,18 +1239,6 @@ mkblctrl_main(int argc, char *argv[])
|
||||
*/
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
/* look for the optional i2c bus parameter */
|
||||
if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--bus") == 0) {
|
||||
if (argc > i + 1) {
|
||||
bus = atoi(argv[i + 1]);
|
||||
newMode = true;
|
||||
|
||||
} else {
|
||||
errx(1, "missing argument for i2c bus (-b)");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* look for the optional frame parameter */
|
||||
if (strcmp(argv[i], "-mkmode") == 0 || strcmp(argv[i], "--mkmode") == 0) {
|
||||
if (argc > i + 1) {
|
||||
@@ -1560,51 +1298,43 @@ mkblctrl_main(int argc, char *argv[])
|
||||
fprintf(stderr, "mkblctrl: help:\n");
|
||||
fprintf(stderr, " [-mkmode {+/x}] [-b i2c_bus_number] [-d devicename] [--override-security-checks] [-h / --help]\n\n");
|
||||
fprintf(stderr, "\t -mkmode {+/x} \t\t Type of frame, if Mikrokopter motor order is used.\n");
|
||||
fprintf(stderr, "\t -b {i2c_bus_number} \t\t Set the i2c bus where the ESCs are connected to (default autoscan).\n");
|
||||
fprintf(stderr, "\t -d {devicepath & name}\t\t Create alternate pwm device.\n");
|
||||
fprintf(stderr, "\t --override-security-checks \t\t Disable all security checks (arming and number of ESCs). Used to test single Motors etc. (DANGER !!!)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Motortest:\n");
|
||||
fprintf(stderr, "First you have to start mkblctrl, the you can enter Motortest Mode with:\n");
|
||||
fprintf(stderr, "mkblctrl -t\n");
|
||||
fprintf(stderr, "This will spin up once every motor in order of motoraddress. (DANGER !!!)\n");
|
||||
fprintf(stderr, "This will spin up once every motor in order of motoraddress. (DANGER !!!)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (!motortest) {
|
||||
if (g_mk == nullptr) {
|
||||
if (bus == -1) {
|
||||
bus = mk_check_for_i2c_esc_bus(devicepath, motorcount);
|
||||
}
|
||||
if (g_mk == nullptr) {
|
||||
if (mk_start(motorcount, devicepath) != OK) {
|
||||
errx(1, "failed to start the MK-BLCtrl driver");
|
||||
}
|
||||
|
||||
if (bus != -1) {
|
||||
if (mk_start(bus, motorcount, devicepath) != OK) {
|
||||
errx(1, "failed to start the MK-BLCtrl driver");
|
||||
}
|
||||
} else {
|
||||
errx(1, "failed to start the MK-BLCtrl driver (cannot find i2c esc's)");
|
||||
}
|
||||
/* parameter set ? */
|
||||
if (newMode) {
|
||||
/* switch parameter */
|
||||
return mk_new_mode(pwm_update_rate_in_hz, motorcount, motortest, px4mode, frametype, overrideSecurityChecks);
|
||||
}
|
||||
|
||||
/* parameter set ? */
|
||||
if (newMode) {
|
||||
/* switch parameter */
|
||||
return mk_new_mode(port_mode, pwm_update_rate_in_hz, motorcount, motortest, px4mode, frametype, overrideSecurityChecks);
|
||||
}
|
||||
exit(0);
|
||||
|
||||
exit(0);
|
||||
} else {
|
||||
errx(1, "MK-BLCtrl driver already running");
|
||||
}
|
||||
} else {
|
||||
errx(1, "MK-BLCtrl driver already running");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (g_mk == nullptr) {
|
||||
errx(1, "MK-BLCtrl driver not running. You have to start it first.");
|
||||
} else {
|
||||
if (g_mk == nullptr) {
|
||||
errx(1, "MK-BLCtrl driver not running. You have to start it first.");
|
||||
|
||||
} else {
|
||||
g_mk->set_motor_test(motortest);
|
||||
exit(0);
|
||||
} else {
|
||||
g_mk->set_motor_test(motortest);
|
||||
exit(0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -443,7 +443,6 @@ int
|
||||
MPU6000::init()
|
||||
{
|
||||
int ret;
|
||||
int gyro_ret;
|
||||
|
||||
/* do SPI init (and probe) first */
|
||||
ret = SPI::init();
|
||||
@@ -488,16 +487,36 @@ MPU6000::init()
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fetch an initial set of measurements for advertisement */
|
||||
_accel_class_instance = register_class_devname(ACCEL_DEVICE_PATH);
|
||||
|
||||
measure();
|
||||
|
||||
_accel_class_instance = register_class_devname(ACCEL_DEVICE_PATH);
|
||||
if (_accel_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
/* advertise accel topic */
|
||||
accel_report ar;
|
||||
_accel_reports->get(&ar);
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &ar);
|
||||
}
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct accel_report arp;
|
||||
_accel_reports->get(&arp);
|
||||
|
||||
/* measurement will have generated a report, publish */
|
||||
_accel_topic = orb_advertise(ORB_ID(sensor_accel), &arp);
|
||||
|
||||
if (_accel_topic < 0)
|
||||
debug("failed to create sensor_accel publication");
|
||||
|
||||
}
|
||||
|
||||
if (_gyro->_gyro_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
/* advertise sensor topic, measure manually to initialize valid report */
|
||||
struct gyro_report grp;
|
||||
_gyro_reports->get(&grp);
|
||||
|
||||
_gyro->_gyro_topic = orb_advertise(ORB_ID(sensor_gyro), &grp);
|
||||
|
||||
if (_gyro->_gyro_topic < 0)
|
||||
debug("failed to create sensor_gyro publication");
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -1307,10 +1326,13 @@ MPU6000::measure()
|
||||
poll_notify(POLLIN);
|
||||
_gyro->parent_poll_notify();
|
||||
|
||||
if (_accel_topic != -1) {
|
||||
if (_accel_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_accel), _accel_topic, &arb);
|
||||
}
|
||||
if (_gyro->_gyro_topic != -1) {
|
||||
|
||||
if (_gyro->_gyro_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_gyro), _gyro->_gyro_topic, &grb);
|
||||
}
|
||||
|
||||
@@ -1356,11 +1378,6 @@ MPU6000_gyro::init()
|
||||
}
|
||||
|
||||
_gyro_class_instance = register_class_devname(GYRO_DEVICE_PATH);
|
||||
if (_gyro_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
gyro_report gr;
|
||||
memset(&gr, 0, sizeof(gr));
|
||||
_gyro_topic = orb_advertise(ORB_ID(sensor_gyro), &gr);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
@@ -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
|
||||
@@ -90,6 +90,7 @@ static const int ERROR = -1;
|
||||
/* internal conversion time: 9.17 ms, so should not be read at rates higher than 100 Hz */
|
||||
#define MS5611_CONVERSION_INTERVAL 10000 /* microseconds */
|
||||
#define MS5611_MEASUREMENT_RATIO 3 /* pressure measurements per temperature measurement */
|
||||
#define MS5611_BARO_DEVICE_PATH "/dev/ms5611"
|
||||
|
||||
class MS5611 : public device::CDev
|
||||
{
|
||||
@@ -132,6 +133,8 @@ protected:
|
||||
|
||||
orb_advert_t _baro_topic;
|
||||
|
||||
int _class_instance;
|
||||
|
||||
perf_counter_t _sample_perf;
|
||||
perf_counter_t _measure_perf;
|
||||
perf_counter_t _comms_errors;
|
||||
@@ -192,7 +195,7 @@ protected:
|
||||
extern "C" __EXPORT int ms5611_main(int argc, char *argv[]);
|
||||
|
||||
MS5611::MS5611(device::Device *interface, ms5611::prom_u &prom_buf) :
|
||||
CDev("MS5611", BARO_DEVICE_PATH),
|
||||
CDev("MS5611", MS5611_BARO_DEVICE_PATH),
|
||||
_interface(interface),
|
||||
_prom(prom_buf.s),
|
||||
_measure_ticks(0),
|
||||
@@ -204,6 +207,7 @@ MS5611::MS5611(device::Device *interface, ms5611::prom_u &prom_buf) :
|
||||
_SENS(0),
|
||||
_msl_pressure(101325),
|
||||
_baro_topic(-1),
|
||||
_class_instance(-1),
|
||||
_sample_perf(perf_alloc(PC_ELAPSED, "ms5611_read")),
|
||||
_measure_perf(perf_alloc(PC_ELAPSED, "ms5611_measure")),
|
||||
_comms_errors(perf_alloc(PC_COUNT, "ms5611_comms_errors")),
|
||||
@@ -218,6 +222,9 @@ MS5611::~MS5611()
|
||||
/* make sure we are truly inactive */
|
||||
stop_cycle();
|
||||
|
||||
if (_class_instance != -1)
|
||||
unregister_class_devname(MS5611_BARO_DEVICE_PATH, _class_instance);
|
||||
|
||||
/* free any existing reports */
|
||||
if (_reports != nullptr)
|
||||
delete _reports;
|
||||
@@ -251,18 +258,57 @@ MS5611::init()
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get a publish handle on the baro topic */
|
||||
struct baro_report zero_report;
|
||||
memset(&zero_report, 0, sizeof(zero_report));
|
||||
_baro_topic = orb_advertise(ORB_ID(sensor_baro), &zero_report);
|
||||
/* register alternate interfaces if we have to */
|
||||
_class_instance = register_class_devname(BARO_DEVICE_PATH);
|
||||
|
||||
if (_baro_topic < 0) {
|
||||
debug("failed to create sensor_baro object");
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
struct baro_report brp;
|
||||
/* do a first measurement cycle to populate reports with valid data */
|
||||
_measure_phase = 0;
|
||||
_reports->flush();
|
||||
|
||||
/* this do..while is goto without goto */
|
||||
do {
|
||||
/* do temperature first */
|
||||
if (OK != measure()) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(MS5611_CONVERSION_INTERVAL);
|
||||
|
||||
if (OK != collect()) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* now do a pressure measurement */
|
||||
if (OK != measure()) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(MS5611_CONVERSION_INTERVAL);
|
||||
|
||||
if (OK != collect()) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* state machine will have generated a report, copy it out */
|
||||
_reports->get(&brp);
|
||||
|
||||
ret = OK;
|
||||
|
||||
if (_class_instance == CLASS_DEVICE_PRIMARY) {
|
||||
|
||||
_baro_topic = orb_advertise(ORB_ID(sensor_baro), &brp);
|
||||
|
||||
if (_baro_topic < 0)
|
||||
debug("failed to create sensor_baro publication");
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
ret = OK;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -670,7 +716,10 @@ MS5611::collect()
|
||||
report.altitude = (((pow((p / p1), (-(a * R) / g))) * T1) - T1) / a;
|
||||
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_baro), _baro_topic, &report);
|
||||
if (_baro_topic > 0 && !(_pub_blocked)) {
|
||||
/* publish it */
|
||||
orb_publish(ORB_ID(sensor_baro), _baro_topic, &report);
|
||||
}
|
||||
|
||||
if (_reports->force(&report)) {
|
||||
perf_count(_buffer_overflows);
|
||||
@@ -812,7 +861,7 @@ start()
|
||||
goto fail;
|
||||
|
||||
/* set the poll rate to default, starts automatic data collection */
|
||||
fd = open(BARO_DEVICE_PATH, O_RDONLY);
|
||||
fd = open(MS5611_BARO_DEVICE_PATH, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
warnx("can't open baro device");
|
||||
goto fail;
|
||||
@@ -846,10 +895,10 @@ test()
|
||||
ssize_t sz;
|
||||
int ret;
|
||||
|
||||
int fd = open(BARO_DEVICE_PATH, O_RDONLY);
|
||||
int fd = open(MS5611_BARO_DEVICE_PATH, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
err(1, "%s open failed (try 'ms5611 start' if the driver is not running)", BARO_DEVICE_PATH);
|
||||
err(1, "%s open failed (try 'ms5611 start' if the driver is not running)", MS5611_BARO_DEVICE_PATH);
|
||||
|
||||
/* do a simple demand read */
|
||||
sz = read(fd, &report, sizeof(report));
|
||||
@@ -905,7 +954,7 @@ test()
|
||||
void
|
||||
reset()
|
||||
{
|
||||
int fd = open(BARO_DEVICE_PATH, O_RDONLY);
|
||||
int fd = open(MS5611_BARO_DEVICE_PATH, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
err(1, "failed ");
|
||||
@@ -944,10 +993,10 @@ calibrate(unsigned altitude)
|
||||
float pressure;
|
||||
float p1;
|
||||
|
||||
int fd = open(BARO_DEVICE_PATH, O_RDONLY);
|
||||
int fd = open(MS5611_BARO_DEVICE_PATH, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
err(1, "%s open failed (try 'ms5611 start' if the driver is not running)", BARO_DEVICE_PATH);
|
||||
err(1, "%s open failed (try 'ms5611 start' if the driver is not running)", MS5611_BARO_DEVICE_PATH);
|
||||
|
||||
/* start the sensor polling at max */
|
||||
if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MAX))
|
||||
|
||||
@@ -626,7 +626,7 @@ PX4FMU::task_main()
|
||||
#ifdef HRT_PPM_CHANNEL
|
||||
|
||||
// see if we have new PPM input data
|
||||
if (ppm_last_valid_decode != rc_in.timestamp) {
|
||||
if (ppm_last_valid_decode != rc_in.timestamp_last_signal) {
|
||||
// we have a new PPM frame. Publish it.
|
||||
rc_in.channel_count = ppm_decoded_channels;
|
||||
|
||||
@@ -638,7 +638,15 @@ PX4FMU::task_main()
|
||||
rc_in.values[i] = ppm_buffer[i];
|
||||
}
|
||||
|
||||
rc_in.timestamp = ppm_last_valid_decode;
|
||||
rc_in.timestamp_publication = ppm_last_valid_decode;
|
||||
rc_in.timestamp_last_signal = ppm_last_valid_decode;
|
||||
|
||||
rc_in.rc_ppm_frame_length = ppm_frame_length;
|
||||
rc_in.rssi = RC_INPUT_RSSI_MAX;
|
||||
rc_in.rc_failsafe = false;
|
||||
rc_in.rc_lost = false;
|
||||
rc_in.rc_lost_frame_count = 0;
|
||||
rc_in.rc_total_frame_count = 0;
|
||||
|
||||
/* lazily advertise on first publication */
|
||||
if (to_input_rc == 0) {
|
||||
|
||||
+227
-32
@@ -61,6 +61,7 @@
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_rc_input.h>
|
||||
#include <drivers/drv_pwm_output.h>
|
||||
#include <drivers/drv_sbus.h>
|
||||
#include <drivers/drv_gpio.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <drivers/drv_mixer.h>
|
||||
@@ -238,6 +239,7 @@ private:
|
||||
unsigned _update_interval; ///< Subscription interval limiting send rate
|
||||
bool _rc_handling_disabled; ///< If set, IO does not evaluate, but only forward the RC values
|
||||
unsigned _rc_chan_count; ///< Internal copy of the last seen number of RC channels
|
||||
uint64_t _rc_last_valid; ///< last valid timestamp
|
||||
|
||||
volatile int _task; ///< worker task id
|
||||
volatile bool _task_should_exit; ///< worker terminate flag
|
||||
@@ -274,6 +276,7 @@ private:
|
||||
servorail_status_s _servorail_status; ///< servorail status
|
||||
|
||||
bool _primary_pwm_device; ///< true if we are the default PWM output
|
||||
bool _lockdown_override; ///< allow to override the safety lockdown
|
||||
|
||||
float _battery_amp_per_volt; ///< current sensor amps/volt
|
||||
float _battery_amp_bias; ///< current sensor bias
|
||||
@@ -444,7 +447,7 @@ private:
|
||||
* @param vservo vservo register
|
||||
* @param vrssi vrssi register
|
||||
*/
|
||||
void io_handle_vservo(uint16_t vbatt, uint16_t ibatt);
|
||||
void io_handle_vservo(uint16_t vservo, uint16_t vrssi);
|
||||
|
||||
};
|
||||
|
||||
@@ -467,6 +470,7 @@ PX4IO::PX4IO(device::Device *interface) :
|
||||
_update_interval(0),
|
||||
_rc_handling_disabled(false),
|
||||
_rc_chan_count(0),
|
||||
_rc_last_valid(0),
|
||||
_task(-1),
|
||||
_task_should_exit(false),
|
||||
_mavlink_fd(-1),
|
||||
@@ -490,6 +494,7 @@ PX4IO::PX4IO(device::Device *interface) :
|
||||
_to_servorail(0),
|
||||
_to_safety(0),
|
||||
_primary_pwm_device(false),
|
||||
_lockdown_override(false),
|
||||
_battery_amp_per_volt(90.0f / 5.0f), // this matches the 3DR current sensor
|
||||
_battery_amp_bias(0),
|
||||
_battery_mamphour_total(0),
|
||||
@@ -1047,13 +1052,19 @@ PX4IO::io_set_arming_state()
|
||||
uint16_t set = 0;
|
||||
uint16_t clear = 0;
|
||||
|
||||
if (armed.armed && !armed.lockdown) {
|
||||
if (armed.armed) {
|
||||
set |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
|
||||
|
||||
} else {
|
||||
clear |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
|
||||
}
|
||||
|
||||
if (armed.lockdown && !_lockdown_override) {
|
||||
set |= PX4IO_P_SETUP_ARMING_LOCKDOWN;
|
||||
} else {
|
||||
clear |= PX4IO_P_SETUP_ARMING_LOCKDOWN;
|
||||
}
|
||||
|
||||
if (armed.ready_to_arm) {
|
||||
set |= PX4IO_P_SETUP_ARMING_IO_ARM_OK;
|
||||
|
||||
@@ -1357,7 +1368,10 @@ PX4IO::io_get_status()
|
||||
uint16_t regs[6];
|
||||
int ret;
|
||||
|
||||
/* get STATUS_FLAGS, STATUS_ALARMS, STATUS_VBATT, STATUS_IBATT in that order */
|
||||
/* get
|
||||
* STATUS_FLAGS, STATUS_ALARMS, STATUS_VBATT, STATUS_IBATT,
|
||||
* STATUS_VSERVO, STATUS_VRSSI, STATUS_PRSSI
|
||||
* in that order */
|
||||
ret = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS, ®s[0], sizeof(regs) / sizeof(regs[0]));
|
||||
|
||||
if (ret != OK)
|
||||
@@ -1394,7 +1408,8 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
||||
*
|
||||
* This should be the common case (9 channel R/C control being a reasonable upper bound).
|
||||
*/
|
||||
input_rc.timestamp = hrt_absolute_time();
|
||||
input_rc.timestamp_publication = hrt_absolute_time();
|
||||
|
||||
ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_COUNT, ®s[0], prolog + 9);
|
||||
|
||||
if (ret != OK)
|
||||
@@ -1404,13 +1419,25 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
||||
* Get the channel count any any extra channels. This is no more expensive than reading the
|
||||
* channel count once.
|
||||
*/
|
||||
channel_count = regs[0];
|
||||
channel_count = regs[PX4IO_P_RAW_RC_COUNT];
|
||||
|
||||
if (channel_count != _rc_chan_count)
|
||||
perf_count(_perf_chan_count);
|
||||
|
||||
_rc_chan_count = channel_count;
|
||||
|
||||
input_rc.rc_ppm_frame_length = regs[PX4IO_P_RAW_RC_DATA];
|
||||
input_rc.rssi = regs[PX4IO_P_RAW_RC_NRSSI];
|
||||
input_rc.rc_failsafe = (regs[PX4IO_P_RAW_RC_FLAGS] & PX4IO_P_RAW_RC_FLAGS_FAILSAFE);
|
||||
input_rc.rc_lost_frame_count = regs[PX4IO_P_RAW_LOST_FRAME_COUNT];
|
||||
input_rc.rc_total_frame_count = regs[PX4IO_P_RAW_FRAME_COUNT];
|
||||
|
||||
/* rc_lost has to be set before the call to this function */
|
||||
if (!input_rc.rc_lost && !input_rc.rc_failsafe)
|
||||
_rc_last_valid = input_rc.timestamp_publication;
|
||||
|
||||
input_rc.timestamp_last_signal = _rc_last_valid;
|
||||
|
||||
if (channel_count > 9) {
|
||||
ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_BASE + 9, ®s[prolog + 9], channel_count - 9);
|
||||
|
||||
@@ -1427,13 +1454,12 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
||||
int
|
||||
PX4IO::io_publish_raw_rc()
|
||||
{
|
||||
/* if no raw RC, just don't publish */
|
||||
if (!(_status & PX4IO_P_STATUS_FLAGS_RC_OK))
|
||||
return OK;
|
||||
|
||||
/* fetch values from IO */
|
||||
rc_input_values rc_val;
|
||||
rc_val.timestamp = hrt_absolute_time();
|
||||
|
||||
/* set the RC status flag ORDER MATTERS! */
|
||||
rc_val.rc_lost = !(_status & PX4IO_P_STATUS_FLAGS_RC_OK);
|
||||
|
||||
int ret = io_get_raw_rc_input(rc_val);
|
||||
|
||||
@@ -1452,13 +1478,11 @@ PX4IO::io_publish_raw_rc()
|
||||
|
||||
} else {
|
||||
rc_val.input_source = RC_INPUT_SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* set RSSI */
|
||||
|
||||
if (rc_val.input_source != RC_INPUT_SOURCE_PX4IO_SBUS) {
|
||||
// XXX the correct scaling needs to be validated here
|
||||
rc_val.rssi = (_servorail_status.rssi_v / 3.3f) * UINT8_MAX;
|
||||
/* we do not know the RC input, only publish if RC OK flag is set */
|
||||
/* if no raw RC, just don't publish */
|
||||
if (!(_status & PX4IO_P_STATUS_FLAGS_RC_OK))
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* lazily advertise on first publication */
|
||||
@@ -1767,15 +1791,14 @@ PX4IO::print_status()
|
||||
printf("%u bytes free\n",
|
||||
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FREEMEM));
|
||||
uint16_t flags = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS);
|
||||
printf("status 0x%04x%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
uint16_t io_status_flags = flags;
|
||||
printf("status 0x%04x%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
flags,
|
||||
((flags & PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED) ? " OUTPUTS_ARMED" : ""),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) ? " SAFETY_OFF" : " SAFETY_SAFE"),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) ? " OVERRIDE" : ""),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_RC_OK) ? " RC_OK" : " RC_FAIL"),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_RC_PPM) ? " PPM" : ""),
|
||||
(((flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (!(flags & PX4IO_P_STATUS_FLAGS_RC_DSM11))) ? " DSM10" : ""),
|
||||
(((flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (flags & PX4IO_P_STATUS_FLAGS_RC_DSM11)) ? " DSM11" : ""),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_RC_SBUS) ? " SBUS" : ""),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_FMU_OK) ? " FMU_OK" : " FMU_FAIL"),
|
||||
((flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) ? " RAW_PWM_PASSTHROUGH" : ""),
|
||||
@@ -1834,8 +1857,17 @@ PX4IO::print_status()
|
||||
|
||||
printf("\n");
|
||||
|
||||
if ((flags & PX4IO_P_STATUS_FLAGS_RC_PPM)) {
|
||||
int frame_len = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_RC_DATA);
|
||||
flags = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_FLAGS);
|
||||
printf("R/C flags: 0x%04x%s%s%s%s%s\n", flags,
|
||||
(((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (!(flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11))) ? " DSM10" : ""),
|
||||
(((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11)) ? " DSM11" : ""),
|
||||
((flags & PX4IO_P_RAW_RC_FLAGS_FRAME_DROP) ? " FRAME_DROP" : ""),
|
||||
((flags & PX4IO_P_RAW_RC_FLAGS_FAILSAFE) ? " FAILSAFE" : ""),
|
||||
((flags & PX4IO_P_RAW_RC_FLAGS_MAPPING_OK) ? " MAPPING_OK" : "")
|
||||
);
|
||||
|
||||
if ((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_PPM)) {
|
||||
int frame_len = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_DATA);
|
||||
printf("RC data (PPM frame len) %u us\n", frame_len);
|
||||
|
||||
if ((frame_len - raw_inputs * 2000 - 3000) < 0) {
|
||||
@@ -1861,16 +1893,23 @@ PX4IO::print_status()
|
||||
printf("\n");
|
||||
|
||||
/* setup and state */
|
||||
printf("features 0x%04x\n", io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES));
|
||||
uint16_t features = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES);
|
||||
printf("features 0x%04x%s%s%s%s\n", features,
|
||||
((features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT) ? " S.BUS1_OUT" : ""),
|
||||
((features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT) ? " S.BUS2_OUT" : ""),
|
||||
((features & PX4IO_P_SETUP_FEATURES_PWM_RSSI) ? " RSSI_PWM" : ""),
|
||||
((features & PX4IO_P_SETUP_FEATURES_ADC_RSSI) ? " RSSI_ADC" : "")
|
||||
);
|
||||
uint16_t arming = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING);
|
||||
printf("arming 0x%04x%s%s%s%s%s%s\n",
|
||||
printf("arming 0x%04x%s%s%s%s%s%s%s\n",
|
||||
arming,
|
||||
((arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) ? " FMU_ARMED" : " FMU_DISARMED"),
|
||||
((arming & PX4IO_P_SETUP_ARMING_IO_ARM_OK) ? " IO_ARM_OK" : " IO_ARM_DENIED"),
|
||||
((arming & PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK) ? " MANUAL_OVERRIDE_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM) ? " FAILSAFE_CUSTOM" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) ? " INAIR_RESTART_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE) ? " ALWAYS_PWM_ENABLE" : ""));
|
||||
((arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) ? " FMU_ARMED" : " FMU_DISARMED"),
|
||||
((arming & PX4IO_P_SETUP_ARMING_IO_ARM_OK) ? " IO_ARM_OK" : " IO_ARM_DENIED"),
|
||||
((arming & PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK) ? " MANUAL_OVERRIDE_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM) ? " FAILSAFE_CUSTOM" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) ? " INAIR_RESTART_OK" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE) ? " ALWAYS_PWM_ENABLE" : ""),
|
||||
((arming & PX4IO_P_SETUP_ARMING_LOCKDOWN) ? " LOCKDOWN" : ""));
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
|
||||
printf("rates 0x%04x default %u alt %u relays 0x%04x\n",
|
||||
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES),
|
||||
@@ -2067,6 +2106,14 @@ PX4IO::ioctl(file * /*filep*/, int cmd, unsigned long arg)
|
||||
*(unsigned *)arg = _max_actuators;
|
||||
break;
|
||||
|
||||
case PWM_SERVO_SET_DISABLE_LOCKDOWN:
|
||||
_lockdown_override = arg;
|
||||
break;
|
||||
|
||||
case PWM_SERVO_GET_DISABLE_LOCKDOWN:
|
||||
*(unsigned *)arg = _lockdown_override;
|
||||
break;
|
||||
|
||||
case DSM_BIND_START:
|
||||
io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_DSM, dsm_bind_power_down);
|
||||
usleep(500000);
|
||||
@@ -2283,6 +2330,38 @@ PX4IO::ioctl(file * /*filep*/, int cmd, unsigned long arg)
|
||||
|
||||
break;
|
||||
|
||||
case RC_INPUT_ENABLE_RSSI_ANALOG:
|
||||
|
||||
if (arg) {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_ADC_RSSI);
|
||||
} else {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, PX4IO_P_SETUP_FEATURES_ADC_RSSI, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RC_INPUT_ENABLE_RSSI_PWM:
|
||||
|
||||
if (arg) {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_PWM_RSSI);
|
||||
} else {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, PX4IO_P_SETUP_FEATURES_PWM_RSSI, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SBUS_SET_PROTO_VERSION:
|
||||
|
||||
if (arg == 1) {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_SBUS1_OUT);
|
||||
} else if (arg == 2) {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
|
||||
} else {
|
||||
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | PX4IO_P_SETUP_FEATURES_SBUS2_OUT), 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* not a recognized value */
|
||||
ret = -ENOTTY;
|
||||
@@ -2656,7 +2735,7 @@ monitor(void)
|
||||
/* clear screen */
|
||||
printf("\033[2J");
|
||||
|
||||
unsigned cancels = 3;
|
||||
unsigned cancels = 2;
|
||||
|
||||
for (;;) {
|
||||
pollfd fds[1];
|
||||
@@ -2692,13 +2771,72 @@ void
|
||||
if_test(unsigned mode)
|
||||
{
|
||||
device::Device *interface = get_interface();
|
||||
int result;
|
||||
|
||||
int result = interface->ioctl(1, mode); /* XXX magic numbers */
|
||||
delete interface;
|
||||
if (interface) {
|
||||
result = interface->ioctl(1, mode); /* XXX magic numbers */
|
||||
delete interface;
|
||||
} else {
|
||||
errx(1, "interface not loaded, exiting");
|
||||
}
|
||||
|
||||
errx(0, "test returned %d", result);
|
||||
}
|
||||
|
||||
void
|
||||
lockdown(int argc, char *argv[])
|
||||
{
|
||||
if (g_dev != nullptr) {
|
||||
|
||||
if (argc > 2 && !strcmp(argv[2], "disable")) {
|
||||
|
||||
warnx("WARNING: ACTUATORS WILL BE LIVE IN HIL! PROCEED?");
|
||||
warnx("Press 'y' to enable, any other key to abort.");
|
||||
|
||||
/* check if user wants to abort */
|
||||
char c;
|
||||
|
||||
struct pollfd fds;
|
||||
int ret;
|
||||
hrt_abstime start = hrt_absolute_time();
|
||||
const unsigned long timeout = 5000000;
|
||||
|
||||
while (hrt_elapsed_time(&start) < timeout) {
|
||||
fds.fd = 0; /* stdin */
|
||||
fds.events = POLLIN;
|
||||
ret = poll(&fds, 1, 0);
|
||||
|
||||
if (ret > 0) {
|
||||
|
||||
read(0, &c, 1);
|
||||
|
||||
if (c != 'y') {
|
||||
exit(0);
|
||||
} else if (c == 'y') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
if (hrt_elapsed_time(&start) > timeout)
|
||||
errx(1, "TIMEOUT! ABORTED WITHOUT CHANGES.");
|
||||
|
||||
(void)g_dev->ioctl(0, PWM_SERVO_SET_DISABLE_LOCKDOWN, 1);
|
||||
|
||||
warnx("WARNING: ACTUATORS ARE NOW LIVE IN HIL!");
|
||||
} else {
|
||||
(void)g_dev->ioctl(0, PWM_SERVO_SET_DISABLE_LOCKDOWN, 0);
|
||||
warnx("ACTUATORS ARE NOW SAFE IN HIL.");
|
||||
}
|
||||
|
||||
} else {
|
||||
errx(1, "driver not loaded, exiting");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
int
|
||||
@@ -2932,6 +3070,63 @@ px4io_main(int argc, char *argv[])
|
||||
if (!strcmp(argv[1], "bind"))
|
||||
bind(argc, argv);
|
||||
|
||||
if (!strcmp(argv[1], "lockdown"))
|
||||
lockdown(argc, argv);
|
||||
|
||||
if (!strcmp(argv[1], "sbus1_out")) {
|
||||
/* we can cheat and call the driver directly, as it
|
||||
* doesn't reference filp in ioctl()
|
||||
*/
|
||||
int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 1);
|
||||
|
||||
if (ret != 0) {
|
||||
errx(ret, "S.BUS v1 failed");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "sbus2_out")) {
|
||||
/* we can cheat and call the driver directly, as it
|
||||
* doesn't reference filp in ioctl()
|
||||
*/
|
||||
int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 2);
|
||||
|
||||
if (ret != 0) {
|
||||
errx(ret, "S.BUS v2 failed");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "rssi_analog")) {
|
||||
/* we can cheat and call the driver directly, as it
|
||||
* doesn't reference filp in ioctl()
|
||||
*/
|
||||
int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_ANALOG, 1);
|
||||
|
||||
if (ret != 0) {
|
||||
errx(ret, "RSSI analog failed");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "rssi_pwm")) {
|
||||
/* we can cheat and call the driver directly, as it
|
||||
* doesn't reference filp in ioctl()
|
||||
*/
|
||||
int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_PWM, 1);
|
||||
|
||||
if (ret != 0) {
|
||||
errx(ret, "RSSI PWM failed");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
out:
|
||||
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug',\n 'recovery', 'limit', 'current', 'bind', 'checkcrc', 'forceupdate' or 'update'");
|
||||
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug <level>',\n"
|
||||
"'recovery', 'limit <rate>', 'current', 'bind', 'checkcrc',\n"
|
||||
"'forceupdate', 'update', 'sbus1_out', 'sbus2_out', 'rssi_analog' or 'rssi_pwm'");
|
||||
}
|
||||
|
||||
+53
-28
@@ -72,7 +72,6 @@ __EXPORT void map_projection_init(double lat_0, double lon_0) //lat_0, lon_0 are
|
||||
/* calculate local scale by using the relation of true distance and the distance on plane */ //TODO: this is a quick solution, there are probably easier ways to determine the scale
|
||||
|
||||
/* 1) calculate true distance d on sphere to a point: http://www.movable-type.co.uk/scripts/latlong.html */
|
||||
const double r_earth = 6371000;
|
||||
|
||||
double lat1 = phi_1;
|
||||
double lon1 = lambda_0;
|
||||
@@ -81,7 +80,7 @@ __EXPORT void map_projection_init(double lat_0, double lon_0) //lat_0, lon_0 are
|
||||
double lon2 = lambda_0 + 0.5 / 180 * M_PI;
|
||||
double sin_lat_2 = sin(lat2);
|
||||
double cos_lat_2 = cos(lat2);
|
||||
double d = acos(sin(lat1) * sin_lat_2 + cos(lat1) * cos_lat_2 * cos(lon2 - lon1)) * r_earth;
|
||||
double d = acos(sin(lat1) * sin_lat_2 + cos(lat1) * cos_lat_2 * cos(lon2 - lon1)) * CONSTANTS_RADIUS_OF_EARTH;
|
||||
|
||||
/* 2) calculate distance rho on plane */
|
||||
double k_bar = 0;
|
||||
@@ -188,8 +187,7 @@ __EXPORT float get_distance_to_next_waypoint(double lat_now, double lon_now, dou
|
||||
double a = sin(d_lat / 2.0d) * sin(d_lat / 2.0d) + sin(d_lon / 2.0d) * sin(d_lon / 2.0d) * cos(lat_now_rad) * cos(lat_next_rad);
|
||||
double c = 2.0d * atan2(sqrt(a), sqrt(1.0d - a));
|
||||
|
||||
const double radius_earth = 6371000.0d;
|
||||
return radius_earth * c;
|
||||
return CONSTANTS_RADIUS_OF_EARTH * c;
|
||||
}
|
||||
|
||||
__EXPORT float get_bearing_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next)
|
||||
@@ -210,7 +208,7 @@ __EXPORT float get_bearing_to_next_waypoint(double lat_now, double lon_now, doub
|
||||
return theta;
|
||||
}
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* vx, float* vy)
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e)
|
||||
{
|
||||
double lat_now_rad = lat_now * M_DEG_TO_RAD;
|
||||
double lon_now_rad = lon_now * M_DEG_TO_RAD;
|
||||
@@ -221,11 +219,11 @@ __EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double
|
||||
double d_lon = lon_next_rad - lon_now_rad;
|
||||
|
||||
/* conscious mix of double and float trig function to maximize speed and efficiency */
|
||||
*vy = CONSTANTS_RADIUS_OF_EARTH * sin(d_lon) * cos(lat_next_rad);
|
||||
*vx = CONSTANTS_RADIUS_OF_EARTH * cos(lat_now_rad) * sin(lat_next_rad) - sin(lat_now_rad) * cos(lat_next_rad) * cos(d_lon);
|
||||
*v_n = CONSTANTS_RADIUS_OF_EARTH * (cos(lat_now_rad) * sin(lat_next_rad) - sin(lat_now_rad) * cos(lat_next_rad) * cos(d_lon));
|
||||
*v_e = CONSTANTS_RADIUS_OF_EARTH * sin(d_lon) * cos(lat_next_rad);
|
||||
}
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* vx, float* vy)
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e)
|
||||
{
|
||||
double lat_now_rad = lat_now * M_DEG_TO_RAD;
|
||||
double lon_now_rad = lon_now * M_DEG_TO_RAD;
|
||||
@@ -236,8 +234,17 @@ __EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, d
|
||||
double d_lon = lon_next_rad - lon_now_rad;
|
||||
|
||||
/* conscious mix of double and float trig function to maximize speed and efficiency */
|
||||
*vy = CONSTANTS_RADIUS_OF_EARTH * d_lon;
|
||||
*vx = CONSTANTS_RADIUS_OF_EARTH * cos(lat_now_rad);
|
||||
*v_n = CONSTANTS_RADIUS_OF_EARTH * d_lat;
|
||||
*v_e = CONSTANTS_RADIUS_OF_EARTH * d_lon * cos(lat_now_rad);
|
||||
}
|
||||
|
||||
__EXPORT void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res)
|
||||
{
|
||||
double lat_now_rad = lat_now * M_DEG_TO_RAD;
|
||||
double lon_now_rad = lon_now * M_DEG_TO_RAD;
|
||||
|
||||
*lat_res = (lat_now_rad + v_n / CONSTANTS_RADIUS_OF_EARTH) * M_RAD_TO_DEG;
|
||||
*lon_res = (lon_now_rad + v_e / (CONSTANTS_RADIUS_OF_EARTH * cos(lat_now_rad))) * M_RAD_TO_DEG;
|
||||
}
|
||||
|
||||
// Additional functions - @author Doug Weibel <douglas.weibel@colorado.edu>
|
||||
@@ -429,22 +436,22 @@ __EXPORT float mavlink_wpm_distance_to_point_local(float x_now, float y_now, flo
|
||||
__EXPORT float _wrap_pi(float bearing)
|
||||
{
|
||||
/* value is inf or NaN */
|
||||
if (!isfinite(bearing) || bearing == 0) {
|
||||
if (!isfinite(bearing)) {
|
||||
return bearing;
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
|
||||
while (bearing > M_PI_F && c < 30) {
|
||||
while (bearing > M_PI_F) {
|
||||
bearing -= M_TWOPI_F;
|
||||
c++;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
while (bearing <= -M_PI_F && c < 30) {
|
||||
while (bearing <= -M_PI_F) {
|
||||
bearing += M_TWOPI_F;
|
||||
c++;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -457,12 +464,18 @@ __EXPORT float _wrap_2pi(float bearing)
|
||||
return bearing;
|
||||
}
|
||||
|
||||
while (bearing >= M_TWOPI_F) {
|
||||
bearing = bearing - M_TWOPI_F;
|
||||
int c = 0;
|
||||
while (bearing > M_TWOPI_F) {
|
||||
bearing -= M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
while (bearing < 0.0f) {
|
||||
bearing = bearing + M_TWOPI_F;
|
||||
c = 0;
|
||||
while (bearing <= 0.0f) {
|
||||
bearing += M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -475,12 +488,18 @@ __EXPORT float _wrap_180(float bearing)
|
||||
return bearing;
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
while (bearing > 180.0f) {
|
||||
bearing = bearing - 360.0f;
|
||||
bearing -= 360.0f;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
while (bearing <= -180.0f) {
|
||||
bearing = bearing + 360.0f;
|
||||
c = 0;
|
||||
while (bearing <= -180.0f) {
|
||||
bearing += 360.0f;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -493,12 +512,18 @@ __EXPORT float _wrap_360(float bearing)
|
||||
return bearing;
|
||||
}
|
||||
|
||||
while (bearing >= 360.0f) {
|
||||
bearing = bearing - 360.0f;
|
||||
int c = 0;
|
||||
while (bearing > 360.0f) {
|
||||
bearing -= 360.0f;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
while (bearing < 0.0f) {
|
||||
bearing = bearing + 360.0f;
|
||||
c = 0;
|
||||
while (bearing <= 0.0f) {
|
||||
bearing += 360.0f;
|
||||
if (c++ > 3)
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return bearing;
|
||||
|
||||
+4
-2
@@ -115,9 +115,11 @@ __EXPORT float get_distance_to_next_waypoint(double lat_now, double lon_now, dou
|
||||
*/
|
||||
__EXPORT float get_bearing_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next);
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* vx, float* vy);
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e);
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* vx, float* vy);
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e);
|
||||
|
||||
__EXPORT void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res);
|
||||
|
||||
__EXPORT int get_distance_to_line(struct crosstrack_error_s * crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end);
|
||||
|
||||
|
||||
@@ -83,14 +83,10 @@ bool LaunchDetector::getLaunchDetected()
|
||||
|
||||
void LaunchDetector::updateParams() {
|
||||
|
||||
warnx(" LaunchDetector::updateParams()");
|
||||
launchdetection_on.update();
|
||||
throttlePreTakeoff.update();
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(launchMethods)/sizeof(LaunchMethod); i++) {
|
||||
launchMethods[i]->updateParams();
|
||||
warnx("updating component %d", i);
|
||||
}
|
||||
|
||||
warnx(" LaunchDetector::updateParams() ended");
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ void KalmanNav::updatePublications()
|
||||
// global position publication
|
||||
_pos.timestamp = _pubTimeStamp;
|
||||
_pos.time_gps_usec = _gps.timestamp_position;
|
||||
_pos.valid = true;
|
||||
_pos.global_valid = true;
|
||||
_pos.lat = lat * M_RAD_TO_DEG;
|
||||
_pos.lon = lon * M_RAD_TO_DEG;
|
||||
_pos.alt = float(alt);
|
||||
|
||||
@@ -410,7 +410,7 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
vel(2) = gps.vel_d_m_s;
|
||||
}
|
||||
|
||||
} else if (ekf_params.acc_comp == 2 && global_pos.valid && hrt_absolute_time() < global_pos.timestamp + 500000) {
|
||||
} else if (ekf_params.acc_comp == 2 && global_pos.global_valid && hrt_absolute_time() < global_pos.timestamp + 500000) {
|
||||
vel_valid = true;
|
||||
if (global_pos_updated) {
|
||||
vel_t = global_pos.timestamp;
|
||||
|
||||
@@ -68,7 +68,7 @@ PARAM_DEFINE_FLOAT(ATT_YAW_OFF3, 0.0f);
|
||||
/* magnetic declination, in degrees */
|
||||
PARAM_DEFINE_FLOAT(ATT_MAG_DECL, 0.0f);
|
||||
|
||||
PARAM_DEFINE_INT32(ATT_ACC_COMP, 0);
|
||||
PARAM_DEFINE_INT32(ATT_ACC_COMP, 2);
|
||||
|
||||
int parameters_init(struct attitude_estimator_ekf_param_handles *h)
|
||||
{
|
||||
|
||||
@@ -153,6 +153,11 @@ static bool on_usb_power = false;
|
||||
|
||||
static float takeoff_alt = 5.0f;
|
||||
|
||||
static struct vehicle_status_s status;
|
||||
static struct actuator_armed_s armed;
|
||||
static struct safety_s safety;
|
||||
static struct vehicle_control_mode_s control_mode;
|
||||
|
||||
/* tasks waiting for low prio thread */
|
||||
typedef enum {
|
||||
LOW_PRIO_TASK_NONE = 0,
|
||||
@@ -203,12 +208,19 @@ void check_mode_switches(struct manual_control_setpoint_s *sp_man, struct vehicl
|
||||
|
||||
transition_result_t set_main_state_rc(struct vehicle_status_s *status);
|
||||
|
||||
void print_reject_mode(const char *msg);
|
||||
void set_control_mode();
|
||||
|
||||
void print_reject_mode(struct vehicle_status_s *current_status, const char *msg);
|
||||
|
||||
void print_reject_arm(const char *msg);
|
||||
|
||||
void print_status();
|
||||
|
||||
int arm();
|
||||
int disarm();
|
||||
|
||||
transition_result_t check_navigation_state_machine(struct vehicle_status_s *status, struct vehicle_control_mode_s *control_mode, struct vehicle_local_position_s *local_pos);
|
||||
|
||||
/**
|
||||
* Loop that runs at a lower rate and priority for calibration and parameter tasks.
|
||||
*/
|
||||
@@ -274,6 +286,16 @@ int commander_main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "arm")) {
|
||||
arm();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "disarm")) {
|
||||
disarm();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage("unrecognized command");
|
||||
exit(1);
|
||||
}
|
||||
@@ -340,6 +362,32 @@ void print_status()
|
||||
|
||||
static orb_advert_t status_pub;
|
||||
|
||||
int arm()
|
||||
{
|
||||
int arming_res = arming_state_transition(&status, &safety, ARMING_STATE_ARMED, &armed);
|
||||
|
||||
if (arming_res == TRANSITION_CHANGED) {
|
||||
mavlink_log_info(mavlink_fd, "[cmd] ARMED by commandline");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int disarm()
|
||||
{
|
||||
int arming_res = arming_state_transition(&status, &safety, ARMING_STATE_STANDBY, &armed);
|
||||
|
||||
if (arming_res == TRANSITION_CHANGED) {
|
||||
mavlink_log_info(mavlink_fd, "[cmd] ARMED by commandline");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_command(struct vehicle_status_s *status, const struct safety_s *safety, struct vehicle_command_s *cmd, struct actuator_armed_s *armed)
|
||||
{
|
||||
/* result of the command */
|
||||
@@ -554,13 +602,6 @@ bool handle_command(struct vehicle_status_s *status, const struct safety_s *safe
|
||||
|
||||
}
|
||||
|
||||
static struct vehicle_status_s status;
|
||||
|
||||
/* armed topic */
|
||||
static struct actuator_armed_s armed;
|
||||
|
||||
static struct safety_s safety;
|
||||
|
||||
int commander_thread_main(int argc, char *argv[])
|
||||
{
|
||||
/* not yet initialized */
|
||||
@@ -613,16 +654,11 @@ int commander_thread_main(int argc, char *argv[])
|
||||
|
||||
mavlink_fd = open(MAVLINK_LOG_DEVICE, 0);
|
||||
|
||||
/* Main state machine */
|
||||
/* make sure we are in preflight state */
|
||||
/* vehicle status topic */
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.condition_landed = true; // initialize to safe value
|
||||
|
||||
/* armed topic */
|
||||
orb_advert_t armed_pub;
|
||||
/* Initialize armed with all false */
|
||||
memset(&armed, 0, sizeof(armed));
|
||||
|
||||
// We want to accept RC inputs as default
|
||||
status.rc_input_blocked = false;
|
||||
status.main_state = MAIN_STATE_MANUAL;
|
||||
status.set_nav_state = NAV_STATE_NONE;
|
||||
status.set_nav_state_timestamp = 0;
|
||||
@@ -645,14 +681,20 @@ int commander_thread_main(int argc, char *argv[])
|
||||
// XXX for now just set sensors as initialized
|
||||
status.condition_system_sensors_initialized = true;
|
||||
|
||||
/* advertise to ORB */
|
||||
status_pub = orb_advertise(ORB_ID(vehicle_status), &status);
|
||||
/* publish current state machine */
|
||||
|
||||
/* publish initial state */
|
||||
status.counter++;
|
||||
status.timestamp = hrt_absolute_time();
|
||||
orb_publish(ORB_ID(vehicle_status), status_pub, &status);
|
||||
|
||||
/* publish initial state */
|
||||
status_pub = orb_advertise(ORB_ID(vehicle_status), &status);
|
||||
|
||||
/* armed topic */
|
||||
orb_advert_t armed_pub;
|
||||
/* Initialize armed with all false */
|
||||
memset(&armed, 0, sizeof(armed));
|
||||
|
||||
/* vehicle control mode topic */
|
||||
memset(&control_mode, 0, sizeof(control_mode));
|
||||
orb_advert_t control_mode_pub = orb_advertise(ORB_ID(vehicle_control_mode), &control_mode);
|
||||
|
||||
armed_pub = orb_advertise(ORB_ID(actuator_armed), &armed);
|
||||
|
||||
@@ -872,7 +914,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* update condition_global_position_valid */
|
||||
check_valid(global_position.timestamp, POSITION_TIMEOUT, global_position.valid, &(status.condition_global_position_valid), &status_changed);
|
||||
check_valid(global_position.timestamp, POSITION_TIMEOUT, global_position.global_valid, &(status.condition_global_position_valid), &status_changed);
|
||||
|
||||
/* update local position estimate */
|
||||
orb_check(local_position_sub, &updated);
|
||||
@@ -886,10 +928,12 @@ int commander_thread_main(int argc, char *argv[])
|
||||
check_valid(local_position.timestamp, POSITION_TIMEOUT, local_position.xy_valid, &(status.condition_local_position_valid), &status_changed);
|
||||
check_valid(local_position.timestamp, POSITION_TIMEOUT, local_position.z_valid, &(status.condition_local_altitude_valid), &status_changed);
|
||||
|
||||
static bool published_condition_landed_fw = false;
|
||||
if (status.is_rotary_wing && status.condition_local_altitude_valid) {
|
||||
if (status.condition_landed != local_position.landed) {
|
||||
status.condition_landed = local_position.landed;
|
||||
status_changed = true;
|
||||
published_condition_landed_fw = false; //make sure condition_landed is published again if the system type changes
|
||||
|
||||
if (status.condition_landed) {
|
||||
mavlink_log_critical(mavlink_fd, "#audio: LANDED");
|
||||
@@ -898,6 +942,12 @@ int commander_thread_main(int argc, char *argv[])
|
||||
mavlink_log_critical(mavlink_fd, "#audio: IN AIR");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!published_condition_landed_fw) {
|
||||
status.condition_landed = false; // Fixedwing does not have a landing detector currently
|
||||
published_condition_landed_fw = true;
|
||||
status_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* update battery status */
|
||||
@@ -1031,7 +1081,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
if (!status.condition_home_position_valid && gps_position.fix_type >= 3 &&
|
||||
(gps_position.eph_m < hdop_threshold_m) && (gps_position.epv_m < vdop_threshold_m) &&
|
||||
(hrt_absolute_time() < gps_position.timestamp_position + POSITION_TIMEOUT) && !armed.armed
|
||||
&& global_position.valid) {
|
||||
&& global_position.global_valid) {
|
||||
|
||||
/* copy position data to uORB home message, store it locally as well */
|
||||
home.lat = global_position.lat;
|
||||
@@ -1056,7 +1106,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* start RC input check */
|
||||
if (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;
|
||||
@@ -1244,8 +1294,13 @@ int commander_thread_main(int argc, char *argv[])
|
||||
|
||||
/* publish states (armed, control mode, vehicle status) at least with 5 Hz */
|
||||
if (counter % (200000 / COMMANDER_MONITORING_INTERVAL) == 0 || status_changed) {
|
||||
set_control_mode();
|
||||
control_mode.timestamp = t1;
|
||||
orb_publish(ORB_ID(vehicle_control_mode), control_mode_pub, &control_mode);
|
||||
|
||||
status.timestamp = t1;
|
||||
orb_publish(ORB_ID(vehicle_status), status_pub, &status);
|
||||
|
||||
armed.timestamp = t1;
|
||||
orb_publish(ORB_ID(actuator_armed), armed_pub, &armed);
|
||||
}
|
||||
@@ -1422,7 +1477,7 @@ check_mode_switches(struct manual_control_setpoint_s *sp_man, struct vehicle_sta
|
||||
{
|
||||
/* main mode switch */
|
||||
if (!isfinite(sp_man->mode_switch)) {
|
||||
warnx("mode sw not finite");
|
||||
/* default to manual if signal is invalid */
|
||||
status->mode_switch = MODE_SWITCH_MANUAL;
|
||||
|
||||
} else if (sp_man->mode_switch > STICK_ON_OFF_LIMIT) {
|
||||
@@ -1472,7 +1527,7 @@ check_mode_switches(struct manual_control_setpoint_s *sp_man, struct vehicle_sta
|
||||
transition_result_t
|
||||
set_main_state_rc(struct vehicle_status_s *status)
|
||||
{
|
||||
/* evaluate the main state machine */
|
||||
/* set main state according to RC switches */
|
||||
transition_result_t res = TRANSITION_DENIED;
|
||||
|
||||
switch (status->mode_switch) {
|
||||
@@ -1489,7 +1544,7 @@ set_main_state_rc(struct vehicle_status_s *status)
|
||||
break; // changed successfully or already in this state
|
||||
|
||||
// else fallback to SEATBELT
|
||||
print_reject_mode("EASY");
|
||||
print_reject_mode(status, "EASY");
|
||||
}
|
||||
|
||||
res = main_state_transition(status, MAIN_STATE_SEATBELT);
|
||||
@@ -1498,7 +1553,7 @@ set_main_state_rc(struct vehicle_status_s *status)
|
||||
break; // changed successfully or already in this mode
|
||||
|
||||
if (status->assisted_switch != ASSISTED_SWITCH_EASY) // don't print both messages
|
||||
print_reject_mode("SEATBELT");
|
||||
print_reject_mode(status, "SEATBELT");
|
||||
|
||||
// else fallback to MANUAL
|
||||
res = main_state_transition(status, MAIN_STATE_MANUAL);
|
||||
@@ -1512,7 +1567,7 @@ set_main_state_rc(struct vehicle_status_s *status)
|
||||
break; // changed successfully or already in this state
|
||||
|
||||
// else fallback to SEATBELT (EASY likely will not work too)
|
||||
print_reject_mode("AUTO");
|
||||
print_reject_mode(status, "AUTO");
|
||||
res = main_state_transition(status, MAIN_STATE_SEATBELT);
|
||||
|
||||
if (res != TRANSITION_DENIED)
|
||||
@@ -1531,16 +1586,122 @@ set_main_state_rc(struct vehicle_status_s *status)
|
||||
}
|
||||
|
||||
void
|
||||
print_reject_mode(const char *msg)
|
||||
|
||||
set_control_mode()
|
||||
{
|
||||
/* set vehicle_control_mode according to main state and failsafe state */
|
||||
control_mode.flag_armed = armed.armed;
|
||||
control_mode.flag_external_manual_override_ok = !status.is_rotary_wing;
|
||||
control_mode.flag_system_hil_enabled = status.hil_state == HIL_STATE_ON;
|
||||
|
||||
control_mode.flag_control_termination_enabled = false;
|
||||
|
||||
/* set this flag when navigator should act */
|
||||
bool navigator_enabled = false;
|
||||
|
||||
switch (status.failsafe_state) {
|
||||
case FAILSAFE_STATE_NORMAL:
|
||||
switch (status.main_state) {
|
||||
case MAIN_STATE_MANUAL:
|
||||
control_mode.flag_control_manual_enabled = true;
|
||||
control_mode.flag_control_auto_enabled = false;
|
||||
control_mode.flag_control_rates_enabled = status.is_rotary_wing;
|
||||
control_mode.flag_control_attitude_enabled = status.is_rotary_wing;
|
||||
control_mode.flag_control_altitude_enabled = false;
|
||||
control_mode.flag_control_climb_rate_enabled = false;
|
||||
control_mode.flag_control_position_enabled = false;
|
||||
control_mode.flag_control_velocity_enabled = false;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_SEATBELT:
|
||||
control_mode.flag_control_manual_enabled = true;
|
||||
control_mode.flag_control_auto_enabled = false;
|
||||
control_mode.flag_control_rates_enabled = true;
|
||||
control_mode.flag_control_attitude_enabled = true;
|
||||
control_mode.flag_control_altitude_enabled = true;
|
||||
control_mode.flag_control_climb_rate_enabled = true;
|
||||
control_mode.flag_control_position_enabled = false;
|
||||
control_mode.flag_control_velocity_enabled = false;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_EASY:
|
||||
control_mode.flag_control_manual_enabled = true;
|
||||
control_mode.flag_control_auto_enabled = false;
|
||||
control_mode.flag_control_rates_enabled = true;
|
||||
control_mode.flag_control_attitude_enabled = true;
|
||||
control_mode.flag_control_altitude_enabled = true;
|
||||
control_mode.flag_control_climb_rate_enabled = true;
|
||||
control_mode.flag_control_position_enabled = true;
|
||||
control_mode.flag_control_velocity_enabled = true;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_AUTO:
|
||||
navigator_enabled = true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_RTL:
|
||||
navigator_enabled = true;
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_LAND:
|
||||
navigator_enabled = true;
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_TERMINATION:
|
||||
/* disable all controllers on termination */
|
||||
control_mode.flag_control_manual_enabled = false;
|
||||
control_mode.flag_control_auto_enabled = false;
|
||||
control_mode.flag_control_rates_enabled = false;
|
||||
control_mode.flag_control_attitude_enabled = false;
|
||||
control_mode.flag_control_position_enabled = false;
|
||||
control_mode.flag_control_velocity_enabled = false;
|
||||
control_mode.flag_control_altitude_enabled = false;
|
||||
control_mode.flag_control_climb_rate_enabled = false;
|
||||
control_mode.flag_control_termination_enabled = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* navigator has control, set control mode flags according to nav state*/
|
||||
if (navigator_enabled) {
|
||||
control_mode.flag_control_manual_enabled = false;
|
||||
control_mode.flag_control_auto_enabled = true;
|
||||
control_mode.flag_control_rates_enabled = true;
|
||||
control_mode.flag_control_attitude_enabled = true;
|
||||
control_mode.flag_control_position_enabled = true;
|
||||
control_mode.flag_control_velocity_enabled = true;
|
||||
control_mode.flag_control_altitude_enabled = true;
|
||||
control_mode.flag_control_climb_rate_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_reject_mode(struct vehicle_status_s *status, const char *msg)
|
||||
{
|
||||
hrt_abstime t = hrt_absolute_time();
|
||||
|
||||
if (t - last_print_mode_reject_time > PRINT_MODE_REJECT_INTERVAL) {
|
||||
last_print_mode_reject_time = t;
|
||||
char s[80];
|
||||
sprintf(s, "#audio: warning: reject %s", msg);
|
||||
sprintf(s, "#audio: REJECT %s", msg);
|
||||
mavlink_log_critical(mavlink_fd, s);
|
||||
tune_negative();
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1688,7 +1849,15 @@ void *commander_low_prio_loop(void *arg)
|
||||
} else if ((int)(cmd.param4) == 1) {
|
||||
/* RC calibration */
|
||||
answer_command(cmd, VEHICLE_CMD_RESULT_ACCEPTED);
|
||||
calib_ret = do_rc_calibration(mavlink_fd);
|
||||
/* disable RC control input completely */
|
||||
status.rc_input_blocked = true;
|
||||
calib_ret = OK;
|
||||
mavlink_log_info(mavlink_fd, "CAL: Disabling RC IN");
|
||||
|
||||
} else if ((int)(cmd.param4) == 2) {
|
||||
/* RC trim calibration */
|
||||
answer_command(cmd, VEHICLE_CMD_RESULT_ACCEPTED);
|
||||
calib_ret = do_trim_calibration(mavlink_fd);
|
||||
|
||||
} else if ((int)(cmd.param5) == 1) {
|
||||
/* accelerometer calibration */
|
||||
@@ -1699,6 +1868,18 @@ void *commander_low_prio_loop(void *arg)
|
||||
/* airspeed calibration */
|
||||
answer_command(cmd, VEHICLE_CMD_RESULT_ACCEPTED);
|
||||
calib_ret = do_airspeed_calibration(mavlink_fd);
|
||||
} else if ((int)(cmd.param4) == 0) {
|
||||
/* RC calibration ended - have we been in one worth confirming? */
|
||||
if (status.rc_input_blocked) {
|
||||
answer_command(cmd, VEHICLE_CMD_RESULT_ACCEPTED);
|
||||
/* enable RC control input */
|
||||
status.rc_input_blocked = false;
|
||||
mavlink_log_info(mavlink_fd, "CAL: Re-enabling RC IN");
|
||||
}
|
||||
|
||||
/* this always succeeds */
|
||||
calib_ret = OK;
|
||||
|
||||
}
|
||||
|
||||
if (calib_ret == OK)
|
||||
@@ -1757,6 +1938,10 @@ void *commander_low_prio_loop(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case VEHICLE_CMD_START_RX_PAIR:
|
||||
/* handled in the IO driver */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* don't answer on unsupported commands, it will be done in main loop */
|
||||
break;
|
||||
|
||||
@@ -123,11 +123,16 @@ void tune_neutral()
|
||||
}
|
||||
|
||||
void tune_negative()
|
||||
{
|
||||
led_negative();
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_NOTIFY_NEGATIVE_TUNE);
|
||||
}
|
||||
|
||||
void led_negative()
|
||||
{
|
||||
blink_msg_end = hrt_absolute_time() + BLINK_MSG_TIME;
|
||||
rgbled_set_color(RGBLED_COLOR_RED);
|
||||
rgbled_set_mode(RGBLED_MODE_BLINK_FAST);
|
||||
ioctl(buzzer, TONE_SET_ALARM, TONE_NOTIFY_NEGATIVE_TUNE);
|
||||
}
|
||||
|
||||
int tune_arm()
|
||||
|
||||
@@ -62,6 +62,9 @@ int tune_arm(void);
|
||||
int tune_low_bat(void);
|
||||
int tune_critical_bat(void);
|
||||
void tune_stop(void);
|
||||
|
||||
void led_negative();
|
||||
|
||||
int blink_msg_state();
|
||||
|
||||
int led_init(void);
|
||||
|
||||
@@ -53,17 +53,16 @@
|
||||
#endif
|
||||
static const int ERROR = -1;
|
||||
|
||||
int do_rc_calibration(int mavlink_fd)
|
||||
int do_trim_calibration(int mavlink_fd)
|
||||
{
|
||||
mavlink_log_info(mavlink_fd, "trim calibration starting");
|
||||
|
||||
int sub_man = orb_subscribe(ORB_ID(manual_control_setpoint));
|
||||
usleep(200000);
|
||||
struct manual_control_setpoint_s sp;
|
||||
bool changed;
|
||||
orb_check(sub_man, &changed);
|
||||
|
||||
if (!changed) {
|
||||
mavlink_log_critical(mavlink_fd, "no manual control, aborting");
|
||||
mavlink_log_critical(mavlink_fd, "no inputs, aborting");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -82,12 +81,12 @@ int do_rc_calibration(int mavlink_fd)
|
||||
int save_ret = param_save_default();
|
||||
|
||||
if (save_ret != 0) {
|
||||
mavlink_log_critical(mavlink_fd, "TRIM CAL: WARN: auto-save of params failed");
|
||||
mavlink_log_critical(mavlink_fd, "TRIM: SAVE FAIL");
|
||||
close(sub_man);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
mavlink_log_info(mavlink_fd, "trim calibration done");
|
||||
mavlink_log_info(mavlink_fd, "trim cal done");
|
||||
close(sub_man);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int do_rc_calibration(int mavlink_fd);
|
||||
int do_trim_calibration(int mavlink_fd);
|
||||
|
||||
#endif /* RC_CALIBRATION_H_ */
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
@@ -50,6 +52,7 @@
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <drivers/drv_device.h>
|
||||
#include <mavlink/mavlink_log.h>
|
||||
|
||||
#include "state_machine_helper.h"
|
||||
@@ -332,6 +335,33 @@ int hil_state_transition(hil_state_t new_state, int status_pub, struct vehicle_s
|
||||
|
||||
mavlink_log_critical(mavlink_fd, "Switched to ON hil state");
|
||||
valid_transition = true;
|
||||
|
||||
// Disable publication of all attached sensors
|
||||
|
||||
/* list directory */
|
||||
DIR *d;
|
||||
struct dirent *direntry;
|
||||
d = opendir("/dev");
|
||||
if (d) {
|
||||
|
||||
while ((direntry = readdir(d)) != NULL) {
|
||||
|
||||
int sensfd = ::open(direntry->d_name, 0);
|
||||
int block_ret = ::ioctl(sensfd, DEVIOCSPUBBLOCK, 0);
|
||||
close(sensfd);
|
||||
|
||||
printf("Disabling %s\n: %s", direntry->d_name, (!block_ret) ? "OK" : "FAIL");
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
warnx("directory listing ok (FS mounted and readable)");
|
||||
|
||||
} else {
|
||||
/* failed opening dir */
|
||||
warnx("FAILED LISTING DEVICE ROOT DIRECTORY");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -382,16 +412,22 @@ transition_result_t failsafe_state_transition(struct vehicle_status_s *status, f
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_RTL:
|
||||
|
||||
/* global position and home position required for RTL */
|
||||
if (status->condition_global_position_valid && status->condition_home_position_valid) {
|
||||
status->set_nav_state = NAV_STATE_RTL;
|
||||
status->set_nav_state_timestamp = hrt_absolute_time();
|
||||
ret = TRANSITION_CHANGED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_LAND:
|
||||
|
||||
/* at least relative altitude estimate required for landing */
|
||||
if (status->condition_local_altitude_valid || status->condition_global_position_valid) {
|
||||
status->set_nav_state = NAV_STATE_LAND;
|
||||
status->set_nav_state_timestamp = hrt_absolute_time();
|
||||
ret = TRANSITION_CHANGED;
|
||||
}
|
||||
|
||||
|
||||
+108
-70
@@ -126,45 +126,46 @@ static const char *k_data_manager_device_path = "/fs/microsd/dataman";
|
||||
/* The data manager work queues */
|
||||
|
||||
typedef struct {
|
||||
sq_queue_t q;
|
||||
sem_t mutex; /* Mutual exclusion on work queue adds and deletes */
|
||||
unsigned size;
|
||||
unsigned max_size;
|
||||
sq_queue_t q; /* Nuttx queue */
|
||||
sem_t mutex; /* Mutual exclusion on work queue adds and deletes */
|
||||
unsigned size; /* Current size of queue */
|
||||
unsigned max_size; /* Maximum queue size reached */
|
||||
} work_q_t;
|
||||
|
||||
static work_q_t g_free_q;
|
||||
static work_q_t g_work_q;
|
||||
static work_q_t g_free_q; /* queue of free work items. So that we don't always need to call malloc and free*/
|
||||
static work_q_t g_work_q; /* pending work items. To be consumed by worker thread */
|
||||
|
||||
sem_t g_work_queued_sema;
|
||||
sem_t g_work_queued_sema; /* To notify worker thread a work item has been queued */
|
||||
sem_t g_init_sema;
|
||||
|
||||
static bool g_task_should_exit; /**< if true, dataman task should exit */
|
||||
|
||||
#define DM_SECTOR_HDR_SIZE 4
|
||||
static const unsigned k_sector_size = DM_MAX_DATA_SIZE + DM_SECTOR_HDR_SIZE;
|
||||
#define DM_SECTOR_HDR_SIZE 4 /* data manager per item header overhead */
|
||||
static const unsigned k_sector_size = DM_MAX_DATA_SIZE + DM_SECTOR_HDR_SIZE; /* total item sorage space */
|
||||
|
||||
static void init_q(work_q_t *q)
|
||||
{
|
||||
sq_init(&(q->q));
|
||||
sem_init(&(q->mutex), 1, 1);
|
||||
q->size = q->max_size = 0;
|
||||
sq_init(&(q->q)); /* Initialize the NuttX queue structure */
|
||||
sem_init(&(q->mutex), 1, 1); /* Queue is initially unlocked */
|
||||
q->size = q->max_size = 0; /* Queue is initially empty */
|
||||
}
|
||||
|
||||
static void destroy_q(work_q_t *q)
|
||||
static inline void
|
||||
destroy_q(work_q_t *q)
|
||||
{
|
||||
sem_destroy(&(q->mutex));
|
||||
sem_destroy(&(q->mutex)); /* Destroy the queue lock */
|
||||
}
|
||||
|
||||
static inline void
|
||||
lock_queue(work_q_t *q)
|
||||
{
|
||||
sem_wait(&(q->mutex));
|
||||
sem_wait(&(q->mutex)); /* Acquire the queue lock */
|
||||
}
|
||||
|
||||
static inline void
|
||||
unlock_queue(work_q_t *q)
|
||||
{
|
||||
sem_post(&(q->mutex));
|
||||
sem_post(&(q->mutex)); /* Release the queue lock */
|
||||
}
|
||||
|
||||
static work_q_item_t *
|
||||
@@ -172,54 +173,47 @@ create_work_item(void)
|
||||
{
|
||||
work_q_item_t *item;
|
||||
|
||||
/* 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 */
|
||||
if (item == NULL)
|
||||
item = (work_q_item_t *)malloc(sizeof(work_q_item_t));
|
||||
|
||||
/* If we got one then lock the item*/
|
||||
if (item)
|
||||
sem_init(&item->wait_sem, 1, 0); /* Caller will wait on this... initially locked */
|
||||
|
||||
/* return the item pointer, or NULL if all failed */
|
||||
return item;
|
||||
}
|
||||
|
||||
/* Work queue management functions */
|
||||
static void
|
||||
enqueue_work_item(work_q_item_t *item)
|
||||
{
|
||||
/* put the work item on the work queue */
|
||||
lock_queue(&g_work_q);
|
||||
sq_addlast(&item->link, &(g_work_q.q));
|
||||
|
||||
if (++g_work_q.size > g_work_q.max_size)
|
||||
g_work_q.max_size = g_work_q.size;
|
||||
|
||||
unlock_queue(&g_work_q);
|
||||
|
||||
/* tell the work thread that work is available */
|
||||
sem_post(&g_work_queued_sema);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
destroy_work_item(work_q_item_t *item)
|
||||
{
|
||||
sem_destroy(&item->wait_sem);
|
||||
sem_destroy(&item->wait_sem); /* Destroy the item lock */
|
||||
/* Return the item to the free item queue for later reuse */
|
||||
lock_queue(&g_free_q);
|
||||
sq_addfirst(&item->link, &(g_free_q.q));
|
||||
|
||||
/* Update the queue size and potentially the maximum queue size */
|
||||
if (++g_free_q.size > g_free_q.max_size)
|
||||
g_free_q.max_size = g_free_q.size;
|
||||
|
||||
unlock_queue(&g_free_q);
|
||||
}
|
||||
|
||||
static work_q_item_t *
|
||||
static inline work_q_item_t *
|
||||
dequeue_work_item(void)
|
||||
{
|
||||
work_q_item_t *work;
|
||||
|
||||
/* retrieve the 1st item on the work queue */
|
||||
lock_queue(&g_work_q);
|
||||
|
||||
if ((work = (work_q_item_t *)sq_remfirst(&g_work_q.q)))
|
||||
@@ -229,6 +223,32 @@ dequeue_work_item(void)
|
||||
return work;
|
||||
}
|
||||
|
||||
static int
|
||||
enqueue_work_item_and_wait_for_result(work_q_item_t *item)
|
||||
{
|
||||
/* put the work item at the end of the work queue */
|
||||
lock_queue(&g_work_q);
|
||||
sq_addlast(&item->link, &(g_work_q.q));
|
||||
|
||||
/* Adjust the queue size and potentially the maximum queue size */
|
||||
if (++g_work_q.size > g_work_q.max_size)
|
||||
g_work_q.max_size = g_work_q.size;
|
||||
|
||||
unlock_queue(&g_work_q);
|
||||
|
||||
/* tell the work thread that work is available */
|
||||
sem_post(&g_work_queued_sema);
|
||||
|
||||
/* wait for the result */
|
||||
sem_wait(&item->wait_sem);
|
||||
|
||||
int result = item->result;
|
||||
|
||||
destroy_work_item(item);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Calculate the offset in file of specific item */
|
||||
static int
|
||||
calculate_offset(dm_item_t item, unsigned char index)
|
||||
@@ -250,6 +270,8 @@ calculate_offset(dm_item_t item, unsigned char index)
|
||||
*
|
||||
* byte 0: Length of user data item
|
||||
* byte 1: Persistence of this data item
|
||||
* byte 2: Unused (for future use)
|
||||
* byte 3: Unused (for future use)
|
||||
* byte DM_SECTOR_HDR_SIZE... : data item value
|
||||
*
|
||||
* The total size must not exceed k_sector_size
|
||||
@@ -266,6 +288,7 @@ _write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const v
|
||||
/* Get the offset for this item */
|
||||
offset = calculate_offset(item, index);
|
||||
|
||||
/* If item type or index out of range, return error */
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
@@ -283,10 +306,12 @@ _write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const v
|
||||
|
||||
len = -1;
|
||||
|
||||
/* Seek to the right spot in the data manager file and write the data item */
|
||||
if (lseek(g_task_fd, offset, SEEK_SET) == offset)
|
||||
if ((len = write(g_task_fd, buffer, count)) == count)
|
||||
fsync(g_task_fd);
|
||||
fsync(g_task_fd); /* Make sure data is written to physical media */
|
||||
|
||||
/* Make sure the write succeeded */
|
||||
if (len != count)
|
||||
return -1;
|
||||
|
||||
@@ -304,6 +329,7 @@ _read(dm_item_t item, unsigned char index, void *buf, size_t count)
|
||||
/* Get the offset for this item */
|
||||
offset = calculate_offset(item, index);
|
||||
|
||||
/* If item type or index out of range, return error */
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
@@ -316,14 +342,17 @@ _read(dm_item_t item, unsigned char index, void *buf, size_t count)
|
||||
if (lseek(g_task_fd, offset, SEEK_SET) == offset)
|
||||
len = read(g_task_fd, buffer, count + DM_SECTOR_HDR_SIZE);
|
||||
|
||||
/* Check for length issues */
|
||||
/* Check for read error */
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
/* A zero length entry is a empty entry */
|
||||
if (len == 0)
|
||||
buffer[0] = 0;
|
||||
|
||||
/* See if we got data */
|
||||
if (buffer[0] > 0) {
|
||||
/* We got more than requested!!! */
|
||||
if (buffer[0] > count)
|
||||
return -1;
|
||||
|
||||
@@ -340,11 +369,14 @@ _clear(dm_item_t item)
|
||||
{
|
||||
int i, result = 0;
|
||||
|
||||
/* Get the offset of 1st item of this type */
|
||||
int offset = calculate_offset(item, 0);
|
||||
|
||||
/* Check for item type out of range */
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
/* Clear all items of this type */
|
||||
for (i = 0; (unsigned)i < g_per_item_max_index[item]; i++) {
|
||||
char buf[1];
|
||||
|
||||
@@ -353,9 +385,11 @@ _clear(dm_item_t item)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Avoid SD flash wear by only doing writes where necessary */
|
||||
if (read(g_task_fd, buf, 1) < 1)
|
||||
break;
|
||||
|
||||
/* If item has length greater than 0 it needs to be overwritten */
|
||||
if (buf[0]) {
|
||||
if (lseek(g_task_fd, offset, SEEK_SET) != offset) {
|
||||
result = -1;
|
||||
@@ -373,6 +407,7 @@ _clear(dm_item_t item)
|
||||
offset += k_sector_size;
|
||||
}
|
||||
|
||||
/* Make sure data is actually written to physical media */
|
||||
fsync(g_task_fd);
|
||||
return result;
|
||||
}
|
||||
@@ -452,12 +487,13 @@ dm_write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const
|
||||
{
|
||||
work_q_item_t *work;
|
||||
|
||||
/* Make sure data manager has been started and is not shutting down */
|
||||
if ((g_fd < 0) || g_task_should_exit)
|
||||
return -1;
|
||||
|
||||
/* Will return with queues locked */
|
||||
/* get a work item and queue up a write request */
|
||||
if ((work = create_work_item()) == NULL)
|
||||
return -1; /* queues unlocked on failure */
|
||||
return -1;
|
||||
|
||||
work->func = dm_write_func;
|
||||
work->write_params.item = item;
|
||||
@@ -465,12 +501,9 @@ dm_write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const
|
||||
work->write_params.persistence = persistence;
|
||||
work->write_params.buf = buf;
|
||||
work->write_params.count = count;
|
||||
enqueue_work_item(work);
|
||||
|
||||
sem_wait(&work->wait_sem);
|
||||
ssize_t result = work->result;
|
||||
destroy_work_item(work);
|
||||
return result;
|
||||
/* Enqueue the item on the work queue and wait for the worker thread to complete processing it */
|
||||
return (ssize_t)enqueue_work_item_and_wait_for_result(work);
|
||||
}
|
||||
|
||||
/* Retrieve from the data manager file */
|
||||
@@ -479,24 +512,22 @@ dm_read(dm_item_t item, unsigned char index, void *buf, size_t count)
|
||||
{
|
||||
work_q_item_t *work;
|
||||
|
||||
/* Make sure data manager has been started and is not shutting down */
|
||||
if ((g_fd < 0) || g_task_should_exit)
|
||||
return -1;
|
||||
|
||||
/* Will return with queues locked */
|
||||
/* get a work item and queue up a read request */
|
||||
if ((work = create_work_item()) == NULL)
|
||||
return -1; /* queues unlocked on failure */
|
||||
return -1;
|
||||
|
||||
work->func = dm_read_func;
|
||||
work->read_params.item = item;
|
||||
work->read_params.index = index;
|
||||
work->read_params.buf = buf;
|
||||
work->read_params.count = count;
|
||||
enqueue_work_item(work);
|
||||
|
||||
sem_wait(&work->wait_sem);
|
||||
ssize_t result = work->result;
|
||||
destroy_work_item(work);
|
||||
return result;
|
||||
/* Enqueue the item on the work queue and wait for the worker thread to complete processing it */
|
||||
return (ssize_t)enqueue_work_item_and_wait_for_result(work);
|
||||
}
|
||||
|
||||
__EXPORT int
|
||||
@@ -504,21 +535,19 @@ dm_clear(dm_item_t item)
|
||||
{
|
||||
work_q_item_t *work;
|
||||
|
||||
/* Make sure data manager has been started and is not shutting down */
|
||||
if ((g_fd < 0) || g_task_should_exit)
|
||||
return -1;
|
||||
|
||||
/* Will return with queues locked */
|
||||
/* get a work item and queue up a clear request */
|
||||
if ((work = create_work_item()) == NULL)
|
||||
return -1; /* queues unlocked on failure */
|
||||
return -1;
|
||||
|
||||
work->func = dm_clear_func;
|
||||
work->clear_params.item = item;
|
||||
enqueue_work_item(work);
|
||||
|
||||
sem_wait(&work->wait_sem);
|
||||
int result = work->result;
|
||||
destroy_work_item(work);
|
||||
return result;
|
||||
/* Enqueue the item on the work queue and wait for the worker thread to complete processing it */
|
||||
return enqueue_work_item_and_wait_for_result(work);
|
||||
}
|
||||
|
||||
/* Tell the data manager about the type of the last reset */
|
||||
@@ -527,21 +556,19 @@ dm_restart(dm_reset_reason reason)
|
||||
{
|
||||
work_q_item_t *work;
|
||||
|
||||
/* Make sure data manager has been started and is not shutting down */
|
||||
if ((g_fd < 0) || g_task_should_exit)
|
||||
return -1;
|
||||
|
||||
/* Will return with queues locked */
|
||||
/* get a work item and queue up a restart request */
|
||||
if ((work = create_work_item()) == NULL)
|
||||
return -1; /* queues unlocked on failure */
|
||||
return -1;
|
||||
|
||||
work->func = dm_restart_func;
|
||||
work->restart_params.reason = reason;
|
||||
enqueue_work_item(work);
|
||||
|
||||
sem_wait(&work->wait_sem);
|
||||
int result = work->result;
|
||||
destroy_work_item(work);
|
||||
return result;
|
||||
/* Enqueue the item on the work queue and wait for the worker thread to complete processing it */
|
||||
return enqueue_work_item_and_wait_for_result(work);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -570,24 +597,29 @@ task_main(int argc, char *argv[])
|
||||
|
||||
sem_init(&g_work_queued_sema, 1, 0);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
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 */
|
||||
/* They are actually the same but we need to some way to reject caller request while the */
|
||||
/* worker thread is shutting down but still processing requests */
|
||||
g_fd = g_task_fd;
|
||||
|
||||
warnx("Initialized, data manager file '%s' size is %d bytes", k_data_manager_device_path, max_offset);
|
||||
|
||||
/* Tell startup that the worker thread has completed its initialization */
|
||||
sem_post(&g_init_sema);
|
||||
|
||||
/* Start the endless loop, waiting for then processing work requests */
|
||||
@@ -595,7 +627,7 @@ task_main(int argc, char *argv[])
|
||||
|
||||
/* do we need to exit ??? */
|
||||
if ((g_task_should_exit) && (g_fd >= 0)) {
|
||||
/* Close the file handle to stop further queueing */
|
||||
/* Close the file handle to stop further queuing */
|
||||
g_fd = -1;
|
||||
}
|
||||
|
||||
@@ -607,6 +639,7 @@ task_main(int argc, char *argv[])
|
||||
/* Empty the work queue */
|
||||
while ((work = dequeue_work_item())) {
|
||||
|
||||
/* handle each work item with the appropriate handler */
|
||||
switch (work->func) {
|
||||
case dm_write_func:
|
||||
g_func_counts[dm_write_func]++;
|
||||
@@ -647,7 +680,7 @@ task_main(int argc, char *argv[])
|
||||
close(g_task_fd);
|
||||
g_task_fd = -1;
|
||||
|
||||
/* Empty the work queue */
|
||||
/* The work queue is now empty, empty the free queue */
|
||||
for (;;) {
|
||||
if ((work = (work_q_item_t *)sq_remfirst(&(g_free_q.q))) == NULL)
|
||||
break;
|
||||
@@ -669,7 +702,7 @@ start(void)
|
||||
|
||||
sem_init(&g_init_sema, 1, 0);
|
||||
|
||||
/* start the task */
|
||||
/* start the worker thread */
|
||||
if ((task = task_spawn_cmd("dataman", SCHED_DEFAULT, SCHED_PRIORITY_MAX - 5, 2048, task_main, NULL)) <= 0) {
|
||||
warn("task start failed");
|
||||
return -1;
|
||||
@@ -704,7 +737,7 @@ stop(void)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
errx(1, "usage: dataman {start|stop|status}");
|
||||
errx(1, "usage: dataman {start|stop|status|poweronrestart|inflightrestart}");
|
||||
}
|
||||
|
||||
int
|
||||
@@ -726,6 +759,7 @@ dataman_main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Worker thread should be running for all other commands */
|
||||
if (g_fd < 0)
|
||||
errx(1, "not running");
|
||||
|
||||
@@ -733,6 +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
|
||||
usage();
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ private:
|
||||
float land_slope_length;
|
||||
float land_H1_virt;
|
||||
float land_flare_alt_relative;
|
||||
float land_thrust_lim_horizontal_distance;
|
||||
float land_thrust_lim_alt_relative;
|
||||
float land_heading_hold_horizontal_distance;
|
||||
|
||||
} _parameters; /**< local copies of interesting parameters */
|
||||
@@ -281,7 +281,7 @@ private:
|
||||
param_t land_slope_length;
|
||||
param_t land_H1_virt;
|
||||
param_t land_flare_alt_relative;
|
||||
param_t land_thrust_lim_horizontal_distance;
|
||||
param_t land_thrust_lim_alt_relative;
|
||||
param_t land_heading_hold_horizontal_distance;
|
||||
|
||||
} _parameter_handles; /**< handles for interesting parameters */
|
||||
@@ -434,7 +434,7 @@ FixedwingPositionControl::FixedwingPositionControl() :
|
||||
_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_horizontal_distance = param_find("FW_LND_TLDIST");
|
||||
_parameter_handles.land_thrust_lim_alt_relative = param_find("FW_LND_TLALT");
|
||||
_parameter_handles.land_heading_hold_horizontal_distance = param_find("FW_LND_HHDIST");
|
||||
|
||||
_parameter_handles.time_const = param_find("FW_T_TIME_CONST");
|
||||
@@ -523,7 +523,7 @@ FixedwingPositionControl::parameters_update()
|
||||
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_horizontal_distance, &(_parameters.land_thrust_lim_horizontal_distance));
|
||||
param_get(_parameter_handles.land_thrust_lim_alt_relative, &(_parameters.land_thrust_lim_alt_relative));
|
||||
param_get(_parameter_handles.land_heading_hold_horizontal_distance, &(_parameters.land_heading_hold_horizontal_distance));
|
||||
|
||||
_l1_control.set_l1_damping(_parameters.l1_damping);
|
||||
@@ -558,7 +558,7 @@ FixedwingPositionControl::parameters_update()
|
||||
}
|
||||
|
||||
/* Update the landing slope */
|
||||
landingslope.update(math::radians(_parameters.land_slope_angle), _parameters.land_flare_alt_relative, _parameters.land_thrust_lim_horizontal_distance, _parameters.land_H1_virt);
|
||||
landingslope.update(math::radians(_parameters.land_slope_angle), _parameters.land_flare_alt_relative, _parameters.land_thrust_lim_alt_relative, _parameters.land_H1_virt);
|
||||
|
||||
/* Update and publish the navigation capabilities */
|
||||
_nav_capabilities.landing_slope_angle_rad = landingslope.landing_slope_angle_rad();
|
||||
@@ -785,26 +785,26 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
_tecs.set_speed_weight(_parameters.speed_weight);
|
||||
|
||||
/* current waypoint (the one currently heading for) */
|
||||
math::Vector<2> next_wp(pos_sp_triplet.current.lat, pos_sp_triplet.current.lon);
|
||||
math::Vector<2> next_wp((float)pos_sp_triplet.current.lat, (float)pos_sp_triplet.current.lon);
|
||||
|
||||
/* current waypoint (the one currently heading for) */
|
||||
math::Vector<2> curr_wp(pos_sp_triplet.current.lat, pos_sp_triplet.current.lon);
|
||||
math::Vector<2> curr_wp((float)pos_sp_triplet.current.lat, (float)pos_sp_triplet.current.lon);
|
||||
|
||||
|
||||
/* previous waypoint */
|
||||
math::Vector<2> prev_wp;
|
||||
|
||||
if (pos_sp_triplet.previous.valid) {
|
||||
prev_wp(0) = pos_sp_triplet.previous.lat;
|
||||
prev_wp(1) = pos_sp_triplet.previous.lon;
|
||||
prev_wp(0) = (float)pos_sp_triplet.previous.lat;
|
||||
prev_wp(1) = (float)pos_sp_triplet.previous.lon;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* No valid previous waypoint, go for the current wp.
|
||||
* This is automatically handled by the L1 library.
|
||||
*/
|
||||
prev_wp(0) = pos_sp_triplet.current.lat;
|
||||
prev_wp(1) = pos_sp_triplet.current.lon;
|
||||
prev_wp(0) = (float)pos_sp_triplet.current.lat;
|
||||
prev_wp(1) = (float)pos_sp_triplet.current.lon;
|
||||
|
||||
}
|
||||
|
||||
@@ -836,6 +836,8 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
|
||||
} else if (pos_sp_triplet.current.type == SETPOINT_TYPE_LAND) {
|
||||
|
||||
float bearing_lastwp_currwp = get_bearing_to_next_waypoint(prev_wp(0), prev_wp(1), curr_wp(0), curr_wp(1));
|
||||
|
||||
/* Horizontal landing control */
|
||||
/* switch to heading hold for the last meters, continue heading hold after */
|
||||
float wp_distance = get_distance_to_next_waypoint(current_position(0), current_position(1), curr_wp(0), curr_wp(1));
|
||||
@@ -846,7 +848,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
|
||||
if (!land_noreturn_horizontal) {//set target_bearing in first occurrence
|
||||
if (pos_sp_triplet.previous.valid) {
|
||||
target_bearing = get_bearing_to_next_waypoint(prev_wp(0), prev_wp(1), curr_wp(0), curr_wp(1));
|
||||
target_bearing = bearing_lastwp_currwp;
|
||||
} else {
|
||||
target_bearing = _att.yaw;
|
||||
}
|
||||
@@ -888,10 +890,9 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
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;
|
||||
float L_altitude = landingslope.getLandingSlopeAbsoluteAltitude(L_wp_distance, _pos_sp_triplet.current.alt);//getLandingSlopeAbsoluteAltitude(L_wp_distance, _pos_sp_triplet.current.alt, landing_slope_angle_rad, horizontal_slope_displacement);
|
||||
float landing_slope_alt_desired = landingslope.getLandingSlopeAbsoluteAltitude(wp_distance, _pos_sp_triplet.current.alt);//getLandingSlopeAbsoluteAltitude(wp_distance, _pos_sp_triplet.current.alt, landing_slope_angle_rad, horizontal_slope_displacement);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if ( (_global_pos.alt < _pos_sp_triplet.current.alt + landingslope.flare_relative_alt()) || land_noreturn_vertical) { //checking for land_noreturn to avoid unwanted climb out
|
||||
|
||||
@@ -903,7 +904,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
/* kill the throttle if param requests it */
|
||||
throttle_max = _parameters.throttle_max;
|
||||
|
||||
if (wp_distance < landingslope.motor_lim_horizontal_distance() || land_motor_lim) {
|
||||
if (_global_pos.alt < _pos_sp_triplet.current.alt + landingslope.motor_lim_relative_alt() || land_motor_lim) {
|
||||
throttle_max = math::min(throttle_max, _parameters.throttle_land_max);
|
||||
if (!land_motor_lim) {
|
||||
land_motor_lim = true;
|
||||
@@ -912,7 +913,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> ¤t_positi
|
||||
|
||||
}
|
||||
|
||||
float flare_curve_alt = landingslope.getFlareCurveAltitude(wp_distance, _pos_sp_triplet.current.alt);
|
||||
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)
|
||||
@@ -1263,7 +1264,7 @@ FixedwingPositionControl::task_main()
|
||||
// vehicle_baro_poll();
|
||||
|
||||
math::Vector<2> ground_speed(_global_pos.vel_n, _global_pos.vel_e);
|
||||
math::Vector<2> current_position(_global_pos.lat / 1e7f, _global_pos.lon / 1e7f);
|
||||
math::Vector<2> current_position((float)_global_pos.lat, (float)_global_pos.lon);
|
||||
|
||||
/*
|
||||
* Attempt to control position, on success (= sensors present and not in manual mode),
|
||||
|
||||
@@ -168,9 +168,9 @@ PARAM_DEFINE_FLOAT(FW_T_SINK_MAX, 5.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_T_HRATE_P, 0.05f);
|
||||
PARAM_DEFINE_FLOAT(FW_T_SRATE_P, 0.05f);
|
||||
|
||||
PARAM_DEFINE_FLOAT(FW_LND_ANG, 10.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_ANG, 5.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_SLLR, 0.9f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_HVIRT, 10.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_FLALT, 15.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_TLDIST, 30.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_TLALT, 5.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_LND_HHDIST, 15.0f);
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
|
||||
void Landingslope::update(float landing_slope_angle_rad,
|
||||
float flare_relative_alt,
|
||||
float motor_lim_horizontal_distance,
|
||||
float motor_lim_relative_alt,
|
||||
float H1_virt)
|
||||
{
|
||||
|
||||
_landing_slope_angle_rad = landing_slope_angle_rad;
|
||||
_flare_relative_alt = flare_relative_alt;
|
||||
_motor_lim_horizontal_distance = motor_lim_horizontal_distance;
|
||||
_motor_lim_relative_alt = motor_lim_relative_alt;
|
||||
_H1_virt = H1_virt;
|
||||
|
||||
calculateSlopeValues();
|
||||
@@ -74,9 +74,21 @@ float Landingslope::getLandingSlopeAbsoluteAltitude(float wp_distance, float wp_
|
||||
return Landingslope::getLandingSlopeAbsoluteAltitude(wp_distance, wp_altitude, _horizontal_slope_displacement, _landing_slope_angle_rad);
|
||||
}
|
||||
|
||||
float Landingslope::getFlareCurveAltitude(float wp_landing_distance, float wp_landing_altitude)
|
||||
float Landingslope::getLandingSlopeAbsoluteAltitudeSave(float wp_distance, float bearing_lastwp_currwp, float bearing_airplane_currwp, float wp_altitude)
|
||||
{
|
||||
return wp_landing_altitude + _H0 * expf(-math::max(0.0f, _flare_length - wp_landing_distance)/_flare_constant) - _H1_virt;
|
||||
|
||||
/* If airplane is in front of waypoint return slope altitude, else return waypoint altitude */
|
||||
if (fabsf(bearing_airplane_currwp - bearing_lastwp_currwp) < math::radians(90.0f))
|
||||
return getLandingSlopeAbsoluteAltitude(wp_distance, wp_altitude);
|
||||
else
|
||||
return wp_altitude;
|
||||
}
|
||||
|
||||
float Landingslope::getFlareCurveAltitudeSave(float wp_landing_distance, float bearing_lastwp_currwp, float bearing_airplane_currwp, float wp_landing_altitude)
|
||||
{
|
||||
/* If airplane is in front of waypoint return flare curve altitude, else return waypoint altitude */
|
||||
if (fabsf(bearing_airplane_currwp - bearing_lastwp_currwp) < math::radians(90.0f))
|
||||
return wp_landing_altitude + _H0 * expf(-math::max(0.0f, _flare_length - wp_landing_distance)/_flare_constant) - _H1_virt;
|
||||
else
|
||||
return wp_landing_altitude;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
/* see Documentation/fw_landing.png for a plot of the landing slope */
|
||||
float _landing_slope_angle_rad; /**< phi in the plot */
|
||||
float _flare_relative_alt; /**< h_flare,rel in the plot */
|
||||
float _motor_lim_horizontal_distance;
|
||||
float _motor_lim_relative_alt;
|
||||
float _H1_virt; /**< H1 in the plot */
|
||||
float _H0; /**< h_flare,rel + H1 in the plot */
|
||||
float _d1; /**< d1 in the plot */
|
||||
@@ -63,7 +63,18 @@ public:
|
||||
Landingslope() {}
|
||||
~Landingslope() {}
|
||||
|
||||
float getLandingSlopeAbsoluteAltitude(float wp_landing_distance, float wp_landing_altitude);
|
||||
/**
|
||||
*
|
||||
* @return Absolute altitude of point on landing slope at distance to landing waypoint=wp_landing_distance
|
||||
*/
|
||||
float getLandingSlopeAbsoluteAltitude(float wp_distance, float wp_altitude);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Absolute altitude of point on landing slope at distance to landing waypoint=wp_landing_distance
|
||||
* Performs check if aircraft is in front of waypoint to avoid climbout
|
||||
*/
|
||||
float getLandingSlopeAbsoluteAltitudeSave(float wp_landing_distance, float bearing_lastwp_currwp, float bearing_airplane_currwp, float wp_landing_altitude);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -85,17 +96,17 @@ public:
|
||||
}
|
||||
|
||||
|
||||
float getFlareCurveAltitude(float wp_distance, float wp_altitude);
|
||||
float getFlareCurveAltitudeSave(float wp_distance, float bearing_lastwp_currwp, float bearing_airplane_currwp, float wp_altitude);
|
||||
|
||||
void update(float landing_slope_angle_rad,
|
||||
float flare_relative_alt,
|
||||
float motor_lim_horizontal_distance,
|
||||
float motor_lim_relative_alt,
|
||||
float H1_virt);
|
||||
|
||||
|
||||
inline float landing_slope_angle_rad() {return _landing_slope_angle_rad;}
|
||||
inline float flare_relative_alt() {return _flare_relative_alt;}
|
||||
inline float motor_lim_horizontal_distance() {return _motor_lim_horizontal_distance;}
|
||||
inline float motor_lim_relative_alt() {return _motor_lim_relative_alt;}
|
||||
inline float H1_virt() {return _H1_virt;}
|
||||
inline float H0() {return _H0;}
|
||||
inline float d1() {return _d1;}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
// #include <stdlib.h>
|
||||
// #include <poll.h>
|
||||
|
||||
//
|
||||
//
|
||||
// #include <systemlib/systemlib.h>
|
||||
// #include <systemlib/err.h>
|
||||
// #include <mavlink/mavlink_log.h>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
#include <uORB/topics/home_position.h>
|
||||
#include <uORB/topics/mission_result.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/position_setpoint_triplet.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
#include <uORB/topics/mission.h>
|
||||
#include <systemlib/param/param.h>
|
||||
@@ -502,28 +502,36 @@ Mavlink::get_mavlink_mode_and_state(uint8_t *mavlink_state, uint8_t *mavlink_bas
|
||||
*mavlink_base_mode |= MAV_MODE_FLAG_CUSTOM_MODE_ENABLED;
|
||||
union px4_custom_mode custom_mode;
|
||||
custom_mode.data = 0;
|
||||
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) {
|
||||
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) {
|
||||
*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 {
|
||||
/* 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 (control_mode.nav_state == NAV_STATE_NONE) { // failsafe, shouldn't happen
|
||||
if (pos_sp_triplet.nav_state == NAV_STATE_READY) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_READY;
|
||||
} else if (control_mode.nav_state == NAV_STATE_READY) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_READY;
|
||||
} else if (control_mode.nav_state == NAV_STATE_LOITER) {
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_LOITER) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_LOITER;
|
||||
} else if (control_mode.nav_state == NAV_STATE_MISSION) {
|
||||
} else if (pos_sp_triplet.nav_state == NAV_STATE_MISSION) {
|
||||
custom_mode.sub_mode = PX4_CUSTOM_SUB_MODE_AUTO_MISSION;
|
||||
} else if (control_mode.nav_state == NAV_STATE_RTL) {
|
||||
} 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;
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#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/position_setpoint_triplet.h>
|
||||
#include <uORB/topics/optical_flow.h>
|
||||
#include <uORB/topics/actuator_outputs.h>
|
||||
#include <uORB/topics/actuator_controls_effective.h>
|
||||
@@ -233,7 +233,7 @@ public:
|
||||
int get_sub;
|
||||
int airspeed_sub;
|
||||
int navigation_capabilities_sub;
|
||||
int control_mode_sub;
|
||||
int position_setpoint_triplet_sub;
|
||||
int rc_sub;
|
||||
int status_sub;
|
||||
int home_sub;
|
||||
@@ -252,12 +252,12 @@ public:
|
||||
struct navigation_capabilities_s nav_cap;
|
||||
/** Vehicle status */
|
||||
struct vehicle_status_s v_status;
|
||||
/** Vehicle control mode */
|
||||
struct vehicle_control_mode_s control_mode;
|
||||
/** RC channels */
|
||||
struct rc_channels_s rc;
|
||||
/** Actuator armed state */
|
||||
struct actuator_armed_s armed;
|
||||
/** Position setpoint triplet */
|
||||
struct position_setpoint_triplet_s pos_sp_triplet;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
||||
@@ -94,7 +94,6 @@ MavlinkOrbListener::MavlinkOrbListener(Mavlink* parent) :
|
||||
add_listener(MavlinkOrbListener::l_vehicle_gps_position, &(_mavlink->get_subs()->gps_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_vehicle_status, &(_mavlink->get_subs()->status_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_home, &(_mavlink->get_subs()->home_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_control_mode, &(_mavlink->get_subs()->control_mode_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_rc_channels, &(_mavlink->get_subs()->rc_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_input_rc, &(_mavlink->get_subs()->input_rc_sub), 0);
|
||||
add_listener(MavlinkOrbListener::l_global_position, &(_mavlink->get_subs()->global_pos_sub), 0);
|
||||
@@ -277,6 +276,7 @@ MavlinkOrbListener::l_vehicle_status(const struct listener *l)
|
||||
/* immediately communicate state _mavlink->get_chan()ges back to user */
|
||||
orb_copy(ORB_ID(vehicle_status), l->mavlink->get_subs()->status_sub, &(l->mavlink->v_status));
|
||||
orb_copy(ORB_ID(actuator_armed), l->mavlink->get_subs()->armed_sub, &l->listener->armed);
|
||||
orb_copy(ORB_ID(position_setpoint_triplet), l->mavlink->get_subs()->position_setpoint_triplet_sub, &(l->mavlink->pos_sp_triplet));
|
||||
|
||||
/* enable or disable HIL */
|
||||
if (l->listener->v_status.hil_state == HIL_STATE_ON)
|
||||
@@ -317,10 +317,10 @@ MavlinkOrbListener::l_input_rc(const struct listener *l)
|
||||
|
||||
const unsigned port_width = 8;
|
||||
|
||||
for (unsigned i = 0; (i * port_width) < (l->listener->rc_raw.channel_count + port_width); i++) {
|
||||
for (unsigned i = 0; (i * port_width) < l->listener->rc_raw.channel_count; i++) {
|
||||
/* Channels are sent in MAVLink main loop at a fixed interval */
|
||||
mavlink_msg_rc_channels_raw_send(l->mavlink->get_chan(),
|
||||
l->listener->rc_raw.timestamp / 1000,
|
||||
l->listener->rc_raw.timestamp_publication / 1000,
|
||||
i,
|
||||
(l->listener->rc_raw.channel_count > (i * port_width) + 0) ? l->listener->rc_raw.values[(i * port_width) + 0] : UINT16_MAX,
|
||||
(l->listener->rc_raw.channel_count > (i * port_width) + 1) ? l->listener->rc_raw.values[(i * port_width) + 1] : UINT16_MAX,
|
||||
@@ -644,26 +644,6 @@ MavlinkOrbListener::l_nav_cap(const struct listener *l)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MavlinkOrbListener::l_control_mode(const struct listener *l)
|
||||
{
|
||||
orb_copy(ORB_ID(vehicle_control_mode), l->mavlink->get_subs()->control_mode_sub, &l->listener->control_mode);
|
||||
|
||||
/* 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;
|
||||
l->mavlink->get_mavlink_mode_and_state(&mavlink_state, &mavlink_base_mode, &mavlink_custom_mode);
|
||||
|
||||
/* send heartbeat */
|
||||
mavlink_msg_heartbeat_send(l->mavlink->get_chan(),
|
||||
mavlink_system.type,
|
||||
MAV_AUTOPILOT_PX4,
|
||||
mavlink_base_mode,
|
||||
mavlink_custom_mode,
|
||||
mavlink_state);
|
||||
}
|
||||
|
||||
void *
|
||||
MavlinkOrbListener::uorb_receive_thread(void *arg)
|
||||
{
|
||||
@@ -759,9 +739,9 @@ MavlinkOrbListener::uorb_receive_start(Mavlink* mavlink)
|
||||
mavlink->get_subs()->status_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
orb_set_interval(mavlink->get_subs()->status_sub, 300); /* max 3.33 Hz updates */
|
||||
|
||||
/* --- CONTROL MODE --- */
|
||||
mavlink->get_subs()->control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
|
||||
orb_set_interval(mavlink->get_subs()->control_mode_sub, 300); /* max 3.33 Hz updates */
|
||||
/* --- POSITION SETPOINT TRIPLET --- */
|
||||
mavlink->get_subs()->position_setpoint_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
|
||||
orb_set_interval(mavlink->get_subs()->position_setpoint_triplet_sub, 0); /* not polled, don't limit */
|
||||
|
||||
/* --- RC CHANNELS VALUE --- */
|
||||
mavlink->get_subs()->rc_sub = orb_subscribe(ORB_ID(rc_channels));
|
||||
|
||||
@@ -57,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>
|
||||
@@ -158,13 +157,11 @@ private:
|
||||
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 void l_control_mode(const struct listener *l);
|
||||
|
||||
struct vehicle_global_position_s global_pos;
|
||||
struct vehicle_local_position_s local_pos;
|
||||
struct navigation_capabilities_s nav_cap;
|
||||
struct vehicle_status_s v_status;
|
||||
struct vehicle_control_mode_s control_mode;
|
||||
struct rc_channels_s rc;
|
||||
struct rc_input_values rc_raw;
|
||||
struct actuator_armed_s armed;
|
||||
|
||||
@@ -330,7 +330,7 @@ MavlinkReceiver::handle_message(mavlink_message_t *msg)
|
||||
tstatus.rxerrors = rstatus.rxerrors;
|
||||
tstatus.fixed = rstatus.fixed;
|
||||
|
||||
if (telemetry_status_pub == 0) {
|
||||
if (telemetry_status_pub <= 0) {
|
||||
telemetry_status_pub = orb_advertise(ORB_ID(telemetry_status), &tstatus);
|
||||
|
||||
} else {
|
||||
@@ -613,7 +613,7 @@ MavlinkReceiver::handle_message(mavlink_message_t *msg)
|
||||
orb_publish(ORB_ID(vehicle_global_position), pub_hil_global_pos, &hil_global_pos);
|
||||
// global position packet
|
||||
hil_global_pos.timestamp = timestamp;
|
||||
hil_global_pos.valid = true;
|
||||
hil_global_pos.global_valid = true;
|
||||
hil_global_pos.lat = hil_state.lat;
|
||||
hil_global_pos.lon = hil_state.lon;
|
||||
hil_global_pos.alt = hil_state.alt / 1000.0f;
|
||||
|
||||
@@ -57,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>
|
||||
@@ -122,6 +121,7 @@ private:
|
||||
struct vehicle_gps_position_s hil_gps;
|
||||
struct sensor_combined_s hil_sensors;
|
||||
struct battery_status_s hil_battery_status;
|
||||
struct position_setpoint_triplet_s pos_sp_triplet;
|
||||
orb_advert_t pub_hil_global_pos;
|
||||
orb_advert_t pub_hil_local_pos;
|
||||
orb_advert_t pub_hil_attitude;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,13 +41,16 @@
|
||||
|
||||
#include <systemlib/param/param.h>
|
||||
|
||||
PARAM_DEFINE_FLOAT(MC_ATT_P, 6.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ATT_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ROLL_P, 6.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ROLLRATE_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(MC_ROLLRATE_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ROLLRATE_D, 0.002f);
|
||||
PARAM_DEFINE_FLOAT(MC_PITCH_P, 6.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_PITCHRATE_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(MC_PITCHRATE_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_PITCHRATE_D, 0.002f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAW_P, 2.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAW_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ATTRATE_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(MC_ATTRATE_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_ATTRATE_D, 0.002f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAWRATE_P, 0.3f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAWRATE_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAWRATE_D, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(MC_YAW_FF, 0.5f);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -84,6 +84,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "navigator_state.h"
|
||||
#include "navigator_mission.h"
|
||||
#include "mission_feasibility_checker.h"
|
||||
#include "geofence.h"
|
||||
@@ -151,10 +152,10 @@ private:
|
||||
int _offboard_mission_sub; /**< notification of offboard mission updates */
|
||||
int _onboard_mission_sub; /**< notification of onboard mission updates */
|
||||
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 _mission_result_pub; /**< publish mission result topic */
|
||||
orb_advert_t _control_mode_pub; /**< publish vehicle control mode topic */
|
||||
|
||||
struct vehicle_status_s _vstatus; /**< vehicle status */
|
||||
struct vehicle_control_mode_s _control_mode; /**< vehicle control mode */
|
||||
@@ -177,6 +178,7 @@ 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 _waypoint_position_reached;
|
||||
bool _waypoint_yaw_reached;
|
||||
@@ -188,6 +190,8 @@ private:
|
||||
|
||||
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];
|
||||
|
||||
struct {
|
||||
@@ -233,8 +237,7 @@ private:
|
||||
RTL_STATE_NONE = 0,
|
||||
RTL_STATE_CLIMB,
|
||||
RTL_STATE_RETURN,
|
||||
RTL_STATE_DESCEND,
|
||||
RTL_STATE_LAND
|
||||
RTL_STATE_DESCEND
|
||||
};
|
||||
|
||||
enum RTLState _rtl_state;
|
||||
@@ -274,6 +277,10 @@ private:
|
||||
*/
|
||||
void vehicle_status_update();
|
||||
|
||||
/**
|
||||
* Retrieve vehicle control mode
|
||||
*/
|
||||
void vehicle_control_mode_update();
|
||||
|
||||
/**
|
||||
* Shim for calling task_main from task_create.
|
||||
@@ -296,6 +303,7 @@ private:
|
||||
void start_mission();
|
||||
void start_rtl();
|
||||
void start_land();
|
||||
void start_land_home();
|
||||
|
||||
/**
|
||||
* Guards offboard mission
|
||||
@@ -341,11 +349,6 @@ private:
|
||||
* Publish a new mission item triplet for position controller
|
||||
*/
|
||||
void publish_position_setpoint_triplet();
|
||||
|
||||
/**
|
||||
* Publish vehicle_control_mode topic for controllers
|
||||
*/
|
||||
void publish_control_mode();
|
||||
};
|
||||
|
||||
namespace navigator
|
||||
@@ -373,6 +376,7 @@ 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),
|
||||
@@ -381,7 +385,6 @@ Navigator::Navigator() :
|
||||
/* publications */
|
||||
_pos_sp_triplet_pub(-1),
|
||||
_mission_result_pub(-1),
|
||||
_control_mode_pub(-1),
|
||||
|
||||
/* performance counters */
|
||||
_loop_perf(perf_alloc(PC_ELAPSED, "navigator")),
|
||||
@@ -391,6 +394,7 @@ Navigator::Navigator() :
|
||||
_fence_valid(false),
|
||||
_inside_fence(true),
|
||||
_mission(),
|
||||
_global_pos_valid(false),
|
||||
_reset_loiter_pos(true),
|
||||
_waypoint_position_reached(false),
|
||||
_waypoint_yaw_reached(false),
|
||||
@@ -399,6 +403,7 @@ Navigator::Navigator() :
|
||||
_mission_item_valid(false),
|
||||
_need_takeoff(true),
|
||||
_do_takeoff(false),
|
||||
_pos_sp_triplet_updated(false),
|
||||
_geofence_violation_warning_sent(false)
|
||||
{
|
||||
_parameter_handles.min_altitude = param_find("NAV_MIN_ALT");
|
||||
@@ -541,9 +546,19 @@ Navigator::onboard_mission_update()
|
||||
void
|
||||
Navigator::vehicle_status_update()
|
||||
{
|
||||
/* try to load initial states */
|
||||
if (orb_copy(ORB_ID(vehicle_status), _vstatus_sub, &_vstatus) != OK) {
|
||||
_vstatus.arming_state = ARMING_STATE_STANDBY; /* in case the commander is not be running */
|
||||
/* in case the commander is not be running */
|
||||
_vstatus.arming_state = ARMING_STATE_STANDBY;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::vehicle_control_mode_update()
|
||||
{
|
||||
if (orb_copy(ORB_ID(vehicle_control_mode), _control_mode_sub, &_control_mode) != OK) {
|
||||
/* in case the commander is not be running */
|
||||
_control_mode.flag_control_auto_enabled = false;
|
||||
_control_mode.flag_armed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,11 +604,13 @@ Navigator::task_main()
|
||||
_onboard_mission_sub = orb_subscribe(ORB_ID(onboard_mission));
|
||||
_capabilities_sub = orb_subscribe(ORB_ID(navigation_capabilities));
|
||||
_vstatus_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
|
||||
_params_sub = orb_subscribe(ORB_ID(parameter_update));
|
||||
_home_pos_sub = orb_subscribe(ORB_ID(home_position));
|
||||
|
||||
/* copy all topics first time */
|
||||
vehicle_status_update();
|
||||
vehicle_control_mode_update();
|
||||
parameters_update();
|
||||
global_position_update();
|
||||
home_position_update();
|
||||
@@ -605,12 +622,11 @@ Navigator::task_main()
|
||||
orb_set_interval(_global_pos_sub, 20);
|
||||
|
||||
unsigned prevState = NAV_STATE_NONE;
|
||||
bool pub_control_mode = true;
|
||||
hrt_abstime mavlink_open_time = 0;
|
||||
const hrt_abstime mavlink_open_interval = 500000;
|
||||
|
||||
/* wakeup source(s) */
|
||||
struct pollfd fds[7];
|
||||
struct pollfd fds[8];
|
||||
|
||||
/* Setup of loop */
|
||||
fds[0].fd = _params_sub;
|
||||
@@ -627,6 +643,8 @@ Navigator::task_main()
|
||||
fds[5].events = POLLIN;
|
||||
fds[6].fd = _vstatus_sub;
|
||||
fds[6].events = POLLIN;
|
||||
fds[7].fd = _control_mode_sub;
|
||||
fds[7].events = POLLIN;
|
||||
|
||||
while (!_task_should_exit) {
|
||||
|
||||
@@ -652,127 +670,118 @@ Navigator::task_main()
|
||||
_mavlink_fd = open(MAVLINK_LOG_DEVICE, 0);
|
||||
}
|
||||
|
||||
/* vehicle control mode updated */
|
||||
if (fds[7].revents & POLLIN) {
|
||||
vehicle_control_mode_update();
|
||||
}
|
||||
|
||||
/* vehicle status updated */
|
||||
if (fds[6].revents & POLLIN) {
|
||||
vehicle_status_update();
|
||||
pub_control_mode = true;
|
||||
|
||||
/* evaluate state machine from commander and set the navigator mode accordingly */
|
||||
if (_vstatus.arming_state == ARMING_STATE_ARMED || _vstatus.arming_state == ARMING_STATE_ARMED_ERROR) {
|
||||
if (_vstatus.failsafe_state == FAILSAFE_STATE_NORMAL) {
|
||||
if (_vstatus.main_state == MAIN_STATE_AUTO) {
|
||||
bool stick_mode = false;
|
||||
if (_control_mode.flag_armed && _control_mode.flag_control_auto_enabled) {
|
||||
bool stick_mode = false;
|
||||
|
||||
if (!_vstatus.rc_signal_lost) {
|
||||
/* RC signal available, use control switches to set mode */
|
||||
/* RETURN switch, overrides MISSION switch */
|
||||
if (_vstatus.return_switch == RETURN_SWITCH_RETURN) {
|
||||
if (myState != NAV_STATE_READY || _rtl_state != RTL_STATE_LAND) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
|
||||
stick_mode = true;
|
||||
|
||||
} else {
|
||||
/* MISSION switch */
|
||||
if (_vstatus.mission_switch == MISSION_SWITCH_LOITER) {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
stick_mode = true;
|
||||
|
||||
} else if (_vstatus.mission_switch == MISSION_SWITCH_MISSION) {
|
||||
/* switch to mission only if available */
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
|
||||
stick_mode = true;
|
||||
}
|
||||
|
||||
if (!stick_mode && _vstatus.return_switch == RETURN_SWITCH_NORMAL && myState == NAV_STATE_RTL) {
|
||||
/* RETURN switch is in normal mode, no MISSION switch mapped, interrupt if in RTL state */
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
stick_mode = true;
|
||||
}
|
||||
}
|
||||
if (!_vstatus.rc_signal_lost) {
|
||||
/* RC signal available, use control switches to set mode */
|
||||
/* RETURN switch, overrides MISSION switch */
|
||||
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)) &&
|
||||
_vstatus.condition_home_position_valid) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
|
||||
if (!stick_mode) {
|
||||
if (_vstatus.set_nav_state_timestamp != _set_nav_state_timestamp) {
|
||||
/* commander requested new navigation mode, try to set it */
|
||||
_set_nav_state_timestamp = _vstatus.set_nav_state_timestamp;
|
||||
stick_mode = true;
|
||||
|
||||
switch (_vstatus.set_nav_state) {
|
||||
case NAV_STATE_NONE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
} else {
|
||||
/* MISSION switch */
|
||||
if (_vstatus.mission_switch == MISSION_SWITCH_LOITER) {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
stick_mode = true;
|
||||
|
||||
case NAV_STATE_LOITER:
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
break;
|
||||
|
||||
case NAV_STATE_MISSION:
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NAV_STATE_RTL:
|
||||
if (myState != NAV_STATE_READY || _rtl_state != RTL_STATE_LAND) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
warnx("ERROR: Requested navigation state not supported");
|
||||
break;
|
||||
}
|
||||
} else if (_vstatus.mission_switch == MISSION_SWITCH_MISSION) {
|
||||
/* switch to mission only if available */
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
/* on first switch to AUTO try mission by default, if none is available fallback to loiter */
|
||||
if (myState == NAV_STATE_NONE) {
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
}
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
|
||||
stick_mode = true;
|
||||
}
|
||||
|
||||
if (!stick_mode && _vstatus.return_switch == RETURN_SWITCH_NORMAL && myState == NAV_STATE_RTL) {
|
||||
/* RETURN switch is in normal mode, no MISSION switch mapped, interrupt if in RTL state */
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
stick_mode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!stick_mode) {
|
||||
if (_vstatus.set_nav_state_timestamp != _set_nav_state_timestamp) {
|
||||
/* commander requested new navigation mode, try to set it */
|
||||
_set_nav_state_timestamp = _vstatus.set_nav_state_timestamp;
|
||||
|
||||
switch (_vstatus.set_nav_state) {
|
||||
case NAV_STATE_NONE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
|
||||
case NAV_STATE_LOITER:
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
break;
|
||||
|
||||
case NAV_STATE_MISSION:
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NAV_STATE_RTL:
|
||||
if (!(_rtl_state == RTL_STATE_DESCEND &&
|
||||
(myState == NAV_STATE_READY || myState == NAV_STATE_LAND || myState == NAV_STATE_LOITER)) &&
|
||||
_vstatus.condition_home_position_valid) {
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NAV_STATE_LAND:
|
||||
if (myState != NAV_STATE_READY) {
|
||||
dispatch(EVENT_LAND_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
warnx("ERROR: Requested navigation state not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* not in AUTO mode */
|
||||
dispatch(EVENT_NONE_REQUESTED);
|
||||
/* on first switch to AUTO try mission by default, if none is available fallback to loiter */
|
||||
if (myState == NAV_STATE_NONE) {
|
||||
if (_mission.current_mission_available()) {
|
||||
dispatch(EVENT_MISSION_REQUESTED);
|
||||
|
||||
} else {
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_vstatus.failsafe_state == FAILSAFE_STATE_RTL) {
|
||||
/* RTL on failsafe */
|
||||
if (myState != NAV_STATE_READY || _rtl_state != RTL_STATE_LAND) {
|
||||
|
||||
dispatch(EVENT_RTL_REQUESTED);
|
||||
}
|
||||
|
||||
} else if (_vstatus.failsafe_state == FAILSAFE_STATE_LAND) {
|
||||
/* LAND on failsafe */
|
||||
if (myState != NAV_STATE_READY) {
|
||||
dispatch(EVENT_LAND_REQUESTED);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* shouldn't act */
|
||||
dispatch(EVENT_NONE_REQUESTED);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* not armed */
|
||||
/* navigator shouldn't act */
|
||||
dispatch(EVENT_NONE_REQUESTED);
|
||||
}
|
||||
}
|
||||
@@ -813,10 +822,22 @@ Navigator::task_main()
|
||||
if (fds[1].revents & POLLIN) {
|
||||
global_position_update();
|
||||
|
||||
/* only check if waypoint has been reached in MISSION and RTL modes */
|
||||
if (myState == NAV_STATE_MISSION || myState == NAV_STATE_RTL) {
|
||||
if (check_mission_item_reached()) {
|
||||
on_mission_item_reached();
|
||||
/* publish position setpoint triplet on each position update if navigator active */
|
||||
if (_control_mode.flag_armed && _control_mode.flag_control_auto_enabled) {
|
||||
_pos_sp_triplet_updated = true;
|
||||
|
||||
if (myState == NAV_STATE_LAND && _global_pos.global_valid && !_global_pos_valid) {
|
||||
/* got global position when landing, update setpoint */
|
||||
start_land();
|
||||
}
|
||||
|
||||
_global_pos_valid = _global_pos.global_valid;
|
||||
|
||||
/* check if waypoint has been reached in MISSION, RTL and LAND modes */
|
||||
if (myState == NAV_STATE_MISSION || myState == NAV_STATE_RTL || myState == NAV_STATE_LAND) {
|
||||
if (check_mission_item_reached()) {
|
||||
on_mission_item_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,16 +857,19 @@ Navigator::task_main()
|
||||
}
|
||||
}
|
||||
|
||||
/* publish position setpoint triplet if updated */
|
||||
if (_pos_sp_triplet_updated) {
|
||||
_pos_sp_triplet_updated = false;
|
||||
publish_position_setpoint_triplet();
|
||||
}
|
||||
|
||||
/* notify user about state changes */
|
||||
if (myState != prevState) {
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] nav state: %s", nav_states_str[myState]);
|
||||
prevState = myState;
|
||||
pub_control_mode = true;
|
||||
}
|
||||
|
||||
/* publish control mode if updated */
|
||||
if (pub_control_mode) {
|
||||
publish_control_mode();
|
||||
/* reset time counter on state changes */
|
||||
_time_first_inside_orbit = 0;
|
||||
}
|
||||
|
||||
perf_end(_loop_perf);
|
||||
@@ -881,9 +905,9 @@ Navigator::start()
|
||||
void
|
||||
Navigator::status()
|
||||
{
|
||||
warnx("Global position is %svalid", _global_pos.valid ? "" : "in");
|
||||
warnx("Global position is %svalid", _global_pos.global_valid ? "" : "in");
|
||||
|
||||
if (_global_pos.valid) {
|
||||
if (_global_pos.global_valid) {
|
||||
warnx("Longitude %5.5f degrees, latitude %5.5f degrees", _global_pos.lon, _global_pos.lat);
|
||||
warnx("Altitude %5.5f meters, altitude above home %5.5f meters",
|
||||
(double)_global_pos.alt, (double)(_global_pos.alt - _home_pos.alt));
|
||||
@@ -977,7 +1001,7 @@ StateTable::Tran const Navigator::myTable[NAV_STATE_MAX][MAX_EVENT] = {
|
||||
/* EVENT_LOITER_REQUESTED */ {ACTION(&Navigator::start_loiter), NAV_STATE_LOITER},
|
||||
/* EVENT_MISSION_REQUESTED */ {ACTION(&Navigator::start_mission), NAV_STATE_MISSION},
|
||||
/* EVENT_RTL_REQUESTED */ {NO_ACTION, NAV_STATE_RTL},
|
||||
/* EVENT_LAND_REQUESTED */ {ACTION(&Navigator::start_land), NAV_STATE_LAND},
|
||||
/* EVENT_LAND_REQUESTED */ {ACTION(&Navigator::start_land_home), NAV_STATE_LAND},
|
||||
/* EVENT_MISSION_CHANGED */ {NO_ACTION, NAV_STATE_RTL},
|
||||
/* EVENT_HOME_POSITION_CHANGED */ {ACTION(&Navigator::start_rtl), NAV_STATE_RTL}, // TODO need to reset rtl_state
|
||||
},
|
||||
@@ -1006,26 +1030,29 @@ Navigator::start_none()
|
||||
_do_takeoff = false;
|
||||
_rtl_state = RTL_STATE_NONE;
|
||||
|
||||
publish_position_setpoint_triplet();
|
||||
_pos_sp_triplet_updated = true;
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::start_ready()
|
||||
{
|
||||
_pos_sp_triplet.previous.valid = false;
|
||||
_pos_sp_triplet.current.valid = false;
|
||||
_pos_sp_triplet.current.valid = true;
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
_pos_sp_triplet.current.type = SETPOINT_TYPE_IDLE;
|
||||
|
||||
_mission_item_valid = false;
|
||||
|
||||
_reset_loiter_pos = true;
|
||||
_do_takeoff = false;
|
||||
|
||||
if (_rtl_state != RTL_STATE_LAND) {
|
||||
/* allow RTL if landed not at home */
|
||||
if (_rtl_state != RTL_STATE_DESCEND) {
|
||||
/* reset RTL state if landed not at home */
|
||||
_rtl_state = RTL_STATE_NONE;
|
||||
}
|
||||
|
||||
publish_position_setpoint_triplet();
|
||||
_pos_sp_triplet_updated = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1053,12 +1080,7 @@ Navigator::start_loiter()
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] loiter at current altitude");
|
||||
}
|
||||
|
||||
_pos_sp_triplet.current.type = SETPOINT_TYPE_NORMAL;
|
||||
|
||||
if (_rtl_state == RTL_STATE_LAND) {
|
||||
/* if RTL landing was interrupted, avoid landing from MIN_ALT on next RTL */
|
||||
_rtl_state = RTL_STATE_DESCEND;
|
||||
}
|
||||
_pos_sp_triplet.current.type = SETPOINT_TYPE_LOITER;
|
||||
}
|
||||
|
||||
_pos_sp_triplet.current.loiter_radius = _parameters.loiter_radius;
|
||||
@@ -1068,7 +1090,7 @@ Navigator::start_loiter()
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
_mission_item_valid = false;
|
||||
|
||||
publish_position_setpoint_triplet();
|
||||
_pos_sp_triplet_updated = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1095,6 +1117,9 @@ 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_item_valid = true;
|
||||
position_setpoint_from_mission_item(&_pos_sp_triplet.current, &_mission_item);
|
||||
|
||||
@@ -1181,7 +1206,7 @@ Navigator::set_mission_item()
|
||||
}
|
||||
}
|
||||
|
||||
publish_position_setpoint_triplet();
|
||||
_pos_sp_triplet_updated = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1189,20 +1214,22 @@ Navigator::start_rtl()
|
||||
{
|
||||
_do_takeoff = false;
|
||||
|
||||
/* decide if we need climb */
|
||||
if (_rtl_state == RTL_STATE_NONE) {
|
||||
if (_global_pos.alt < _home_pos.alt + _parameters.rtl_alt) {
|
||||
_rtl_state = RTL_STATE_CLIMB;
|
||||
|
||||
} else {
|
||||
_rtl_state = RTL_STATE_RETURN;
|
||||
|
||||
if (_reset_loiter_pos) {
|
||||
_mission_item.altitude_is_relative = false;
|
||||
_mission_item.altitude = _global_pos.alt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if switching directly to return state, reset altitude setpoint */
|
||||
if (_rtl_state == RTL_STATE_RETURN) {
|
||||
_mission_item.altitude_is_relative = false;
|
||||
_mission_item.altitude = _global_pos.alt;
|
||||
}
|
||||
|
||||
_reset_loiter_pos = true;
|
||||
set_rtl_item();
|
||||
}
|
||||
@@ -1210,25 +1237,70 @@ Navigator::start_rtl()
|
||||
void
|
||||
Navigator::start_land()
|
||||
{
|
||||
/* 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;
|
||||
_reset_loiter_pos = true;
|
||||
|
||||
_pos_sp_triplet.previous.valid = false;
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
memcpy(&_pos_sp_triplet.previous, &_pos_sp_triplet.current, sizeof(position_setpoint_s));
|
||||
|
||||
_pos_sp_triplet.current.valid = true;
|
||||
_pos_sp_triplet.current.type = SETPOINT_TYPE_LAND;
|
||||
_pos_sp_triplet.current.lat = _global_pos.lat;
|
||||
_pos_sp_triplet.current.lon = _global_pos.lon;
|
||||
_pos_sp_triplet.current.alt = _global_pos.alt;
|
||||
_pos_sp_triplet.current.loiter_direction = 1;
|
||||
_pos_sp_triplet.current.loiter_radius = _parameters.loiter_radius;
|
||||
_pos_sp_triplet.current.yaw = NAN;
|
||||
_mission_item_valid = true;
|
||||
|
||||
_mission_item.lat = _global_pos.lat;
|
||||
_mission_item.lon = _global_pos.lon;
|
||||
_mission_item.altitude_is_relative = false;
|
||||
_mission_item.altitude = _global_pos.alt;
|
||||
_mission_item.yaw = NAN;
|
||||
_mission_item.loiter_radius = _parameters.loiter_radius;
|
||||
_mission_item.loiter_direction = 1;
|
||||
_mission_item.nav_cmd = NAV_CMD_LAND;
|
||||
_mission_item.acceptance_radius = _parameters.acceptance_radius;
|
||||
_mission_item.time_inside = 0.0f;
|
||||
_mission_item.pitch_min = 0.0f;
|
||||
_mission_item.autocontinue = true;
|
||||
_mission_item.origin = ORIGIN_ONBOARD;
|
||||
|
||||
position_setpoint_from_mission_item(&_pos_sp_triplet.current, &_mission_item);
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::start_land_home()
|
||||
{
|
||||
/* land to home position, should be called when hovering above home, from RTL state */
|
||||
_do_takeoff = false;
|
||||
_reset_loiter_pos = true;
|
||||
|
||||
memcpy(&_pos_sp_triplet.previous, &_pos_sp_triplet.current, sizeof(position_setpoint_s));
|
||||
|
||||
_mission_item_valid = true;
|
||||
|
||||
_mission_item.lat = _home_pos.lat;
|
||||
_mission_item.lon = _home_pos.lon;
|
||||
_mission_item.altitude_is_relative = false;
|
||||
_mission_item.altitude = _home_pos.alt;
|
||||
_mission_item.yaw = NAN;
|
||||
_mission_item.loiter_radius = _parameters.loiter_radius;
|
||||
_mission_item.loiter_direction = 1;
|
||||
_mission_item.nav_cmd = NAV_CMD_LAND;
|
||||
_mission_item.acceptance_radius = _parameters.acceptance_radius;
|
||||
_mission_item.time_inside = 0.0f;
|
||||
_mission_item.pitch_min = 0.0f;
|
||||
_mission_item.autocontinue = true;
|
||||
_mission_item.origin = ORIGIN_ONBOARD;
|
||||
|
||||
position_setpoint_from_mission_item(&_pos_sp_triplet.current, &_mission_item);
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::set_rtl_item()
|
||||
{
|
||||
/*reset time counter for new RTL item */
|
||||
_time_first_inside_orbit = 0;
|
||||
|
||||
switch (_rtl_state) {
|
||||
case RTL_STATE_CLIMB: {
|
||||
memcpy(&_pos_sp_triplet.previous, &_pos_sp_triplet.current, sizeof(position_setpoint_s));
|
||||
@@ -1285,7 +1357,7 @@ Navigator::set_rtl_item()
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: return");
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: return at %.1fm above home", _mission_item.altitude - _home_pos.alt);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1316,33 +1388,6 @@ Navigator::set_rtl_item()
|
||||
break;
|
||||
}
|
||||
|
||||
case RTL_STATE_LAND: {
|
||||
memcpy(&_pos_sp_triplet.previous, &_pos_sp_triplet.current, sizeof(position_setpoint_s));
|
||||
|
||||
_mission_item_valid = true;
|
||||
|
||||
_mission_item.lat = _home_pos.lat;
|
||||
_mission_item.lon = _home_pos.lon;
|
||||
_mission_item.altitude_is_relative = false;
|
||||
_mission_item.altitude = _home_pos.alt;
|
||||
_mission_item.yaw = NAN;
|
||||
_mission_item.loiter_radius = _parameters.loiter_radius;
|
||||
_mission_item.loiter_direction = 1;
|
||||
_mission_item.nav_cmd = NAV_CMD_LAND;
|
||||
_mission_item.acceptance_radius = _parameters.acceptance_radius;
|
||||
_mission_item.time_inside = 0.0f;
|
||||
_mission_item.pitch_min = 0.0f;
|
||||
_mission_item.autocontinue = true;
|
||||
_mission_item.origin = ORIGIN_ONBOARD;
|
||||
|
||||
position_setpoint_from_mission_item(&_pos_sp_triplet.current, &_mission_item);
|
||||
|
||||
_pos_sp_triplet.next.valid = false;
|
||||
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL: land");
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
mavlink_log_critical(_mavlink_fd, "[navigator] error: unknown RTL state: %d", _rtl_state);
|
||||
start_loiter();
|
||||
@@ -1350,7 +1395,7 @@ Navigator::set_rtl_item()
|
||||
}
|
||||
}
|
||||
|
||||
publish_position_setpoint_triplet();
|
||||
_pos_sp_triplet_updated = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1400,14 +1445,7 @@ Navigator::check_mission_item_reached()
|
||||
}
|
||||
|
||||
if (_mission_item.nav_cmd == NAV_CMD_LAND) {
|
||||
if (_vstatus.is_rotary_wing) {
|
||||
return _vstatus.condition_landed;
|
||||
|
||||
} else {
|
||||
/* For fw there is currently no landing detector:
|
||||
* make sure control is not stopped when overshooting the landing waypoint */
|
||||
return false;
|
||||
}
|
||||
return _vstatus.condition_landed;
|
||||
}
|
||||
|
||||
/* XXX TODO count turns */
|
||||
@@ -1527,27 +1565,42 @@ Navigator::on_mission_item_reached()
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* RTL finished */
|
||||
if (_rtl_state == RTL_STATE_LAND) {
|
||||
/* landed at home position */
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL completed, landed");
|
||||
dispatch(EVENT_READY_REQUESTED);
|
||||
} else if (myState == NAV_STATE_RTL) {
|
||||
/* RTL completed */
|
||||
if (_rtl_state == RTL_STATE_DESCEND) {
|
||||
/* hovering above home position, land if needed or loiter */
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] RTL completed");
|
||||
|
||||
if (_mission_item.autocontinue) {
|
||||
dispatch(EVENT_LAND_REQUESTED);
|
||||
|
||||
} else {
|
||||
_reset_loiter_pos = false;
|
||||
dispatch(EVENT_LOITER_REQUESTED);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* next RTL step */
|
||||
_rtl_state = (RTLState)(_rtl_state + 1);
|
||||
set_rtl_item();
|
||||
}
|
||||
|
||||
} else if (myState == NAV_STATE_LAND) {
|
||||
/* landing completed */
|
||||
mavlink_log_info(_mavlink_fd, "[navigator] landing completed");
|
||||
dispatch(EVENT_READY_REQUESTED);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::publish_position_setpoint_triplet()
|
||||
{
|
||||
/* lazily publish the mission triplet only once available */
|
||||
/* update navigation state */
|
||||
_pos_sp_triplet.nav_state = static_cast<nav_state_t>(myState);
|
||||
|
||||
/* lazily publish the position setpoint triplet only once available */
|
||||
if (_pos_sp_triplet_pub > 0) {
|
||||
/* publish the mission triplet */
|
||||
/* publish the position setpoint triplet */
|
||||
orb_publish(ORB_ID(position_setpoint_triplet), _pos_sp_triplet_pub, &_pos_sp_triplet);
|
||||
|
||||
} else {
|
||||
@@ -1556,140 +1609,6 @@ Navigator::publish_position_setpoint_triplet()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::publish_control_mode()
|
||||
{
|
||||
/* update vehicle_control_mode topic*/
|
||||
_control_mode.main_state = _vstatus.main_state;
|
||||
_control_mode.nav_state = static_cast<nav_state_t>(myState);
|
||||
_control_mode.flag_armed = _vstatus.arming_state == ARMING_STATE_ARMED || _vstatus.arming_state == ARMING_STATE_ARMED_ERROR;
|
||||
_control_mode.flag_external_manual_override_ok = !_vstatus.is_rotary_wing;
|
||||
_control_mode.flag_system_hil_enabled = _vstatus.hil_state == HIL_STATE_ON;
|
||||
|
||||
_control_mode.flag_control_offboard_enabled = false;
|
||||
_control_mode.flag_control_termination_enabled = false;
|
||||
|
||||
/* set this flag when navigator has control */
|
||||
bool navigator_enabled = false;
|
||||
|
||||
switch (_vstatus.failsafe_state) {
|
||||
case FAILSAFE_STATE_NORMAL:
|
||||
switch (_vstatus.main_state) {
|
||||
case MAIN_STATE_MANUAL:
|
||||
_control_mode.flag_control_manual_enabled = true;
|
||||
_control_mode.flag_control_rates_enabled = _vstatus.is_rotary_wing;
|
||||
_control_mode.flag_control_attitude_enabled = _vstatus.is_rotary_wing;
|
||||
_control_mode.flag_control_altitude_enabled = false;
|
||||
_control_mode.flag_control_climb_rate_enabled = false;
|
||||
_control_mode.flag_control_position_enabled = false;
|
||||
_control_mode.flag_control_velocity_enabled = false;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_SEATBELT:
|
||||
_control_mode.flag_control_manual_enabled = true;
|
||||
_control_mode.flag_control_rates_enabled = true;
|
||||
_control_mode.flag_control_attitude_enabled = true;
|
||||
_control_mode.flag_control_altitude_enabled = true;
|
||||
_control_mode.flag_control_climb_rate_enabled = true;
|
||||
_control_mode.flag_control_position_enabled = false;
|
||||
_control_mode.flag_control_velocity_enabled = false;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_EASY:
|
||||
_control_mode.flag_control_manual_enabled = true;
|
||||
_control_mode.flag_control_rates_enabled = true;
|
||||
_control_mode.flag_control_attitude_enabled = true;
|
||||
_control_mode.flag_control_altitude_enabled = true;
|
||||
_control_mode.flag_control_climb_rate_enabled = true;
|
||||
_control_mode.flag_control_position_enabled = true;
|
||||
_control_mode.flag_control_velocity_enabled = true;
|
||||
break;
|
||||
|
||||
case MAIN_STATE_AUTO:
|
||||
navigator_enabled = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_RTL:
|
||||
navigator_enabled = true;
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_LAND:
|
||||
navigator_enabled = true;
|
||||
break;
|
||||
|
||||
case FAILSAFE_STATE_TERMINATION:
|
||||
navigator_enabled = true;
|
||||
/* disable all controllers on termination */
|
||||
_control_mode.flag_control_manual_enabled = false;
|
||||
_control_mode.flag_control_rates_enabled = false;
|
||||
_control_mode.flag_control_attitude_enabled = false;
|
||||
_control_mode.flag_control_position_enabled = false;
|
||||
_control_mode.flag_control_velocity_enabled = false;
|
||||
_control_mode.flag_control_altitude_enabled = false;
|
||||
_control_mode.flag_control_climb_rate_enabled = false;
|
||||
_control_mode.flag_control_termination_enabled = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* navigator has control, set control mode flags according to nav state*/
|
||||
if (navigator_enabled) {
|
||||
_control_mode.flag_control_manual_enabled = false;
|
||||
|
||||
switch (myState) {
|
||||
case NAV_STATE_READY:
|
||||
/* disable all controllers, armed but idle */
|
||||
_control_mode.flag_control_rates_enabled = false;
|
||||
_control_mode.flag_control_attitude_enabled = false;
|
||||
_control_mode.flag_control_position_enabled = false;
|
||||
_control_mode.flag_control_velocity_enabled = false;
|
||||
_control_mode.flag_control_altitude_enabled = false;
|
||||
_control_mode.flag_control_climb_rate_enabled = false;
|
||||
break;
|
||||
|
||||
case NAV_STATE_LAND:
|
||||
/* land with or without position control */
|
||||
_control_mode.flag_control_manual_enabled = false;
|
||||
_control_mode.flag_control_rates_enabled = true;
|
||||
_control_mode.flag_control_attitude_enabled = true;
|
||||
_control_mode.flag_control_position_enabled = _vstatus.condition_global_position_valid;
|
||||
_control_mode.flag_control_velocity_enabled = _vstatus.condition_global_position_valid;
|
||||
_control_mode.flag_control_altitude_enabled = true;
|
||||
_control_mode.flag_control_climb_rate_enabled = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
_control_mode.flag_control_rates_enabled = true;
|
||||
_control_mode.flag_control_attitude_enabled = true;
|
||||
_control_mode.flag_control_position_enabled = true;
|
||||
_control_mode.flag_control_velocity_enabled = true;
|
||||
_control_mode.flag_control_altitude_enabled = true;
|
||||
_control_mode.flag_control_climb_rate_enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_control_mode.timestamp = hrt_absolute_time();
|
||||
|
||||
/* lazily publish the mission triplet only once available */
|
||||
if (_control_mode_pub > 0) {
|
||||
/* publish the mission triplet */
|
||||
orb_publish(ORB_ID(vehicle_control_mode), _control_mode_pub, &_control_mode);
|
||||
|
||||
} else {
|
||||
/* advertise and publish */
|
||||
_control_mode_pub = orb_advertise(ORB_ID(vehicle_control_mode), &_control_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void Navigator::add_fence_point(int argc, char *argv[])
|
||||
{
|
||||
_geofence.addPoint(argc, argv);
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
static const int ERROR = -1;
|
||||
|
||||
|
||||
Mission::Mission() :
|
||||
|
||||
Mission::Mission() :
|
||||
|
||||
_offboard_dataman_id(-1),
|
||||
_current_offboard_mission_index(0),
|
||||
_current_onboard_mission_index(0),
|
||||
@@ -65,7 +65,7 @@ Mission::Mission() :
|
||||
|
||||
Mission::~Mission()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -126,33 +126,39 @@ Mission::get_current_mission_item(struct mission_item_s *new_mission_item, bool
|
||||
{
|
||||
/* try onboard mission first */
|
||||
if (current_onboard_mission_available()) {
|
||||
|
||||
|
||||
const ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
if (dm_read(DM_KEY_WAYPOINTS_ONBOARD, _current_onboard_mission_index, new_mission_item, len) != len) {
|
||||
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
_current_mission_type = MISSION_TYPE_ONBOARD;
|
||||
*onboard = true;
|
||||
*index = _current_onboard_mission_index;
|
||||
|
||||
/* otherwise fallback to offboard */
|
||||
/* otherwise fallback to offboard */
|
||||
|
||||
} else if (current_offboard_mission_available()) {
|
||||
|
||||
dm_item_t dm_current;
|
||||
|
||||
if (_offboard_dataman_id == 0) {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||
|
||||
} else {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||
}
|
||||
|
||||
const ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
if (dm_read(dm_current, _current_offboard_mission_index, new_mission_item, len) != len) {
|
||||
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
||||
_current_mission_type = MISSION_TYPE_NONE;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
_current_mission_type = MISSION_TYPE_OFFBOARD;
|
||||
*onboard = false;
|
||||
*index = _current_offboard_mission_index;
|
||||
@@ -171,25 +177,29 @@ Mission::get_next_mission_item(struct mission_item_s *new_mission_item)
|
||||
{
|
||||
/* try onboard mission first */
|
||||
if (next_onboard_mission_available()) {
|
||||
|
||||
|
||||
const ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
if (dm_read(DM_KEY_WAYPOINTS_ONBOARD, _current_onboard_mission_index + 1, new_mission_item, len) != len) {
|
||||
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* otherwise fallback to offboard */
|
||||
/* otherwise fallback to offboard */
|
||||
|
||||
} else if (next_offboard_mission_available()) {
|
||||
|
||||
dm_item_t dm_current;
|
||||
|
||||
if (_offboard_dataman_id == 0) {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||
|
||||
} else {
|
||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||
}
|
||||
|
||||
const ssize_t len = sizeof(struct mission_item_s);
|
||||
|
||||
if (dm_read(dm_current, _current_offboard_mission_index + 1, new_mission_item, len) != len) {
|
||||
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
||||
return ERROR;
|
||||
@@ -244,14 +254,16 @@ void
|
||||
Mission::move_to_next()
|
||||
{
|
||||
switch (_current_mission_type) {
|
||||
case MISSION_TYPE_ONBOARD:
|
||||
_current_onboard_mission_index++;
|
||||
break;
|
||||
case MISSION_TYPE_OFFBOARD:
|
||||
_current_offboard_mission_index++;
|
||||
break;
|
||||
case MISSION_TYPE_NONE:
|
||||
default:
|
||||
break;
|
||||
case MISSION_TYPE_ONBOARD:
|
||||
_current_onboard_mission_index++;
|
||||
break;
|
||||
|
||||
case MISSION_TYPE_OFFBOARD:
|
||||
_current_offboard_mission_index++;
|
||||
break;
|
||||
|
||||
case MISSION_TYPE_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -55,9 +55,9 @@
|
||||
|
||||
PARAM_DEFINE_FLOAT(NAV_MIN_ALT, 50.0f);
|
||||
PARAM_DEFINE_FLOAT(NAV_ACCEPT_RAD, 10.0f);
|
||||
PARAM_DEFINE_FLOAT(NAV_LOITER_RAD, 100.0f);
|
||||
PARAM_DEFINE_FLOAT(NAV_LOITER_RAD, 50.0f);
|
||||
PARAM_DEFINE_INT32(NAV_ONB_MIS_EN, 0);
|
||||
PARAM_DEFINE_FLOAT(NAV_TAKEOFF_ALT, 10.0f); // default TAKEOFF altitude
|
||||
PARAM_DEFINE_FLOAT(NAV_LAND_ALT, 5.0f); // slow descend from this altitude when landing
|
||||
PARAM_DEFINE_FLOAT(NAV_RTL_ALT, 30.0f); // min altitude for going home in RTL mode
|
||||
PARAM_DEFINE_FLOAT(NAV_RTL_LAND_T, 10.0f); // delay after descend before landing
|
||||
PARAM_DEFINE_FLOAT(NAV_RTL_LAND_T, -1.0f); // delay after descend before landing, if set to -1 the system will not land but loiter at NAV_LAND_ALT
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* navigator_state.h
|
||||
*
|
||||
* Created on: 27.01.2014
|
||||
* Author: ton
|
||||
*/
|
||||
|
||||
#ifndef NAVIGATOR_STATE_H_
|
||||
#define NAVIGATOR_STATE_H_
|
||||
|
||||
typedef enum {
|
||||
NAV_STATE_NONE = 0,
|
||||
NAV_STATE_READY,
|
||||
NAV_STATE_LOITER,
|
||||
NAV_STATE_MISSION,
|
||||
NAV_STATE_RTL,
|
||||
NAV_STATE_LAND,
|
||||
NAV_STATE_MAX
|
||||
} nav_state_t;
|
||||
|
||||
#endif /* NAVIGATOR_STATE_H_ */
|
||||
@@ -202,8 +202,6 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
bool landed = true;
|
||||
hrt_abstime landed_time = 0;
|
||||
|
||||
bool flag_armed = false;
|
||||
|
||||
uint32_t accel_counter = 0;
|
||||
uint32_t baro_counter = 0;
|
||||
|
||||
@@ -329,6 +327,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
mavlink_log_info(mavlink_fd, "[inav] baro offs: %.2f", baro_offset);
|
||||
local_pos.z_valid = true;
|
||||
local_pos.v_z_valid = true;
|
||||
global_pos.baro_valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,17 +378,6 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(actuator_armed), armed_sub, &armed);
|
||||
|
||||
/* reset ground level on arm */
|
||||
if (armed.armed && !flag_armed) {
|
||||
flag_armed = armed.armed;
|
||||
baro_offset -= z_est[0];
|
||||
corr_baro = 0.0f;
|
||||
local_pos.ref_alt -= z_est[0];
|
||||
local_pos.ref_timestamp = t;
|
||||
z_est[0] = 0.0f;
|
||||
alt_avg = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* sensor combined */
|
||||
@@ -539,13 +527,13 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (gps.fix_type >= 3) {
|
||||
/* hysteresis for GPS quality */
|
||||
if (gps_valid) {
|
||||
if (gps.eph_m > 10.0f || gps.epv_m > 10.0f) {
|
||||
if (gps.eph_m > 10.0f || gps.epv_m > 20.0f) {
|
||||
gps_valid = false;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal lost");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (gps.eph_m < 5.0f && gps.epv_m < 5.0f) {
|
||||
if (gps.eph_m < 5.0f && gps.epv_m < 10.0f) {
|
||||
gps_valid = true;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal found");
|
||||
}
|
||||
@@ -601,8 +589,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
corr_gps[2][1] = 0.0f;
|
||||
}
|
||||
|
||||
w_gps_xy = 1.0f / fmaxf(1.0f, gps.eph_m);
|
||||
w_gps_z = 1.0f / fmaxf(1.0f, gps.epv_m);
|
||||
w_gps_xy = 2.0f / fmaxf(2.0f, gps.eph_m);
|
||||
w_gps_z = 4.0f / fmaxf(4.0f, gps.epv_m);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -637,6 +625,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);
|
||||
t_prev = t;
|
||||
|
||||
/* use GPS if it's valid and reference position initialized */
|
||||
@@ -679,7 +668,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (use_gps_z) {
|
||||
float offs_corr = corr_gps[2][0] * w_z_gps_p * dt;
|
||||
baro_offset += offs_corr;
|
||||
baro_counter += offs_corr;
|
||||
corr_baro += offs_corr;
|
||||
}
|
||||
|
||||
/* accelerometer bias correction */
|
||||
@@ -835,7 +824,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
|
||||
|
||||
/* publish global position */
|
||||
global_pos.valid = local_pos.xy_global;
|
||||
global_pos.global_valid = local_pos.xy_global;
|
||||
|
||||
if (local_pos.xy_global) {
|
||||
double est_lat, est_lon;
|
||||
@@ -855,6 +844,10 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
global_pos.alt = local_pos.ref_alt - local_pos.z;
|
||||
}
|
||||
|
||||
if (local_pos.z_valid) {
|
||||
global_pos.baro_alt = baro_offset - local_pos.z;
|
||||
}
|
||||
|
||||
if (local_pos.v_z_valid) {
|
||||
global_pos.vel_d = local_pos.vz;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
#include "position_estimator_inav_params.h"
|
||||
|
||||
PARAM_DEFINE_FLOAT(INAV_W_Z_BARO, 1.0f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_Z_BARO, 0.5f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_Z_GPS_P, 0.005f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_Z_ACC, 20.0f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_Z_SONAR, 3.0f);
|
||||
|
||||
@@ -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
|
||||
@@ -59,6 +59,11 @@ static perf_counter_t c_gather_ppm;
|
||||
void
|
||||
controls_init(void)
|
||||
{
|
||||
/* no channels */
|
||||
r_raw_rc_count = 0;
|
||||
system_state.rc_channels_timestamp_received = 0;
|
||||
system_state.rc_channels_timestamp_valid = 0;
|
||||
|
||||
/* DSM input (USART1) */
|
||||
dsm_init("/dev/ttyS0");
|
||||
|
||||
@@ -97,35 +102,62 @@ controls_tick() {
|
||||
/* receive signal strenght indicator (RSSI). 0 = no connection, 255: perfect connection */
|
||||
uint16_t rssi = 0;
|
||||
|
||||
#ifdef ADC_RSSI
|
||||
if (r_setup_features & PX4IO_P_SETUP_FEATURES_ADC_RSSI) {
|
||||
unsigned counts = adc_measure(ADC_RSSI);
|
||||
if (counts != 0xffff) {
|
||||
/* use 1:1 scaling on 3.3V ADC input */
|
||||
unsigned mV = counts * 3300 / 4096;
|
||||
|
||||
/* scale to 0..253 */
|
||||
rssi = mV / 13;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
perf_begin(c_gather_dsm);
|
||||
uint16_t temp_count = r_raw_rc_count;
|
||||
bool dsm_updated = dsm_input(r_raw_rc_values, &temp_count);
|
||||
if (dsm_updated) {
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_RC_DSM;
|
||||
r_raw_rc_flags |= PX4IO_P_STATUS_FLAGS_RC_DSM;
|
||||
r_raw_rc_count = temp_count & 0x7fff;
|
||||
if (temp_count & 0x8000)
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_RC_DSM11;
|
||||
r_raw_rc_flags |= PX4IO_P_RAW_RC_FLAGS_RC_DSM11;
|
||||
else
|
||||
r_status_flags &= ~PX4IO_P_STATUS_FLAGS_RC_DSM11;
|
||||
r_raw_rc_flags &= ~PX4IO_P_RAW_RC_FLAGS_RC_DSM11;
|
||||
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FRAME_DROP);
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FAILSAFE);
|
||||
|
||||
rssi = 255;
|
||||
}
|
||||
perf_end(c_gather_dsm);
|
||||
|
||||
perf_begin(c_gather_sbus);
|
||||
bool sbus_updated = sbus_input(r_raw_rc_values, &r_raw_rc_count, &rssi, PX4IO_RC_INPUT_CHANNELS);
|
||||
|
||||
bool sbus_status = (r_status_flags & PX4IO_P_STATUS_FLAGS_RC_SBUS);
|
||||
|
||||
bool sbus_failsafe, sbus_frame_drop;
|
||||
bool sbus_updated = sbus_input(r_raw_rc_values, &r_raw_rc_count, &sbus_failsafe, &sbus_frame_drop, PX4IO_RC_INPUT_CHANNELS);
|
||||
|
||||
if (sbus_updated) {
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_RC_SBUS;
|
||||
}
|
||||
|
||||
/* switch S.Bus output pin as needed */
|
||||
if (sbus_status != (r_status_flags & PX4IO_P_STATUS_FLAGS_RC_SBUS)) {
|
||||
#ifdef ENABLE_SBUS_OUT
|
||||
ENABLE_SBUS_OUT((r_status_flags & PX4IO_P_STATUS_FLAGS_RC_SBUS));
|
||||
#endif
|
||||
rssi = 255;
|
||||
|
||||
if (sbus_frame_drop) {
|
||||
r_raw_rc_flags |= PX4IO_P_RAW_RC_FLAGS_FRAME_DROP;
|
||||
rssi = 100;
|
||||
} else {
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FRAME_DROP);
|
||||
}
|
||||
|
||||
if (sbus_failsafe) {
|
||||
r_raw_rc_flags |= PX4IO_P_RAW_RC_FLAGS_FAILSAFE;
|
||||
rssi = 0;
|
||||
} else {
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FAILSAFE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
perf_end(c_gather_sbus);
|
||||
@@ -136,13 +168,12 @@ controls_tick() {
|
||||
* disable the PPM decoder completely if we have S.bus signal.
|
||||
*/
|
||||
perf_begin(c_gather_ppm);
|
||||
bool ppm_updated = ppm_input(r_raw_rc_values, &r_raw_rc_count, &r_page_status[PX4IO_P_STATUS_RC_DATA]);
|
||||
bool ppm_updated = ppm_input(r_raw_rc_values, &r_raw_rc_count, &r_page_raw_rc_input[PX4IO_P_RAW_RC_DATA]);
|
||||
if (ppm_updated) {
|
||||
|
||||
/* XXX sample RSSI properly here */
|
||||
rssi = 255;
|
||||
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_RC_PPM;
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FRAME_DROP);
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_FAILSAFE);
|
||||
}
|
||||
perf_end(c_gather_ppm);
|
||||
|
||||
@@ -150,6 +181,9 @@ controls_tick() {
|
||||
if (r_raw_rc_count > PX4IO_RC_INPUT_CHANNELS)
|
||||
r_raw_rc_count = PX4IO_RC_INPUT_CHANNELS;
|
||||
|
||||
/* store RSSI */
|
||||
r_page_raw_rc_input[PX4IO_P_RAW_RC_NRSSI] = rssi;
|
||||
|
||||
/*
|
||||
* In some cases we may have received a frame, but input has still
|
||||
* been lost.
|
||||
@@ -161,97 +195,100 @@ controls_tick() {
|
||||
*/
|
||||
if (dsm_updated || sbus_updated || ppm_updated) {
|
||||
|
||||
/* update RC-received timestamp */
|
||||
system_state.rc_channels_timestamp = hrt_absolute_time();
|
||||
|
||||
/* record a bitmask of channels assigned */
|
||||
unsigned assigned_channels = 0;
|
||||
|
||||
/* map raw inputs to mapped inputs */
|
||||
/* XXX mapping should be atomic relative to protocol */
|
||||
for (unsigned i = 0; i < r_raw_rc_count; i++) {
|
||||
/* update RC-received timestamp */
|
||||
system_state.rc_channels_timestamp_received = hrt_absolute_time();
|
||||
|
||||
/* map the input channel */
|
||||
uint16_t *conf = &r_page_rc_input_config[i * PX4IO_P_RC_CONFIG_STRIDE];
|
||||
/* do not command anything in failsafe, kick in the RC loss counter */
|
||||
if (!(r_raw_rc_flags & PX4IO_P_RAW_RC_FLAGS_FAILSAFE)) {
|
||||
|
||||
if (conf[PX4IO_P_RC_CONFIG_OPTIONS] & PX4IO_P_RC_CONFIG_OPTIONS_ENABLED) {
|
||||
/* update RC-received timestamp */
|
||||
system_state.rc_channels_timestamp_valid = system_state.rc_channels_timestamp_received;
|
||||
|
||||
uint16_t raw = r_raw_rc_values[i];
|
||||
/* map raw inputs to mapped inputs */
|
||||
/* XXX mapping should be atomic relative to protocol */
|
||||
for (unsigned i = 0; i < r_raw_rc_count; i++) {
|
||||
|
||||
int16_t scaled;
|
||||
/* map the input channel */
|
||||
uint16_t *conf = &r_page_rc_input_config[i * PX4IO_P_RC_CONFIG_STRIDE];
|
||||
|
||||
/*
|
||||
* 1) Constrain to min/max values, as later processing depends on bounds.
|
||||
*/
|
||||
if (raw < conf[PX4IO_P_RC_CONFIG_MIN])
|
||||
raw = conf[PX4IO_P_RC_CONFIG_MIN];
|
||||
if (raw > conf[PX4IO_P_RC_CONFIG_MAX])
|
||||
raw = conf[PX4IO_P_RC_CONFIG_MAX];
|
||||
if (conf[PX4IO_P_RC_CONFIG_OPTIONS] & PX4IO_P_RC_CONFIG_OPTIONS_ENABLED) {
|
||||
|
||||
/*
|
||||
* 2) Scale around the mid point differently for lower and upper range.
|
||||
*
|
||||
* This is necessary as they don't share the same endpoints and slope.
|
||||
*
|
||||
* First normalize to 0..1 range with correct sign (below or above center),
|
||||
* then scale to 20000 range (if center is an actual center, -10000..10000,
|
||||
* if parameters only support half range, scale to 10000 range, e.g. if
|
||||
* center == min 0..10000, if center == max -10000..0).
|
||||
*
|
||||
* As the min and max bounds were enforced in step 1), division by zero
|
||||
* cannot occur, as for the case of center == min or center == max the if
|
||||
* statement is mutually exclusive with the arithmetic NaN case.
|
||||
*
|
||||
* DO NOT REMOVE OR ALTER STEP 1!
|
||||
*/
|
||||
if (raw > (conf[PX4IO_P_RC_CONFIG_CENTER] + conf[PX4IO_P_RC_CONFIG_DEADZONE])) {
|
||||
scaled = 10000.0f * ((raw - conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE]) / (float)(conf[PX4IO_P_RC_CONFIG_MAX] - conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE]));
|
||||
uint16_t raw = r_raw_rc_values[i];
|
||||
|
||||
} else if (raw < (conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE])) {
|
||||
scaled = 10000.0f * ((raw - conf[PX4IO_P_RC_CONFIG_CENTER] + conf[PX4IO_P_RC_CONFIG_DEADZONE]) / (float)(conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE] - conf[PX4IO_P_RC_CONFIG_MIN]));
|
||||
int16_t scaled;
|
||||
|
||||
} else {
|
||||
/* in the configured dead zone, output zero */
|
||||
scaled = 0;
|
||||
}
|
||||
/*
|
||||
* 1) Constrain to min/max values, as later processing depends on bounds.
|
||||
*/
|
||||
if (raw < conf[PX4IO_P_RC_CONFIG_MIN])
|
||||
raw = conf[PX4IO_P_RC_CONFIG_MIN];
|
||||
if (raw > conf[PX4IO_P_RC_CONFIG_MAX])
|
||||
raw = conf[PX4IO_P_RC_CONFIG_MAX];
|
||||
|
||||
/* invert channel if requested */
|
||||
if (conf[PX4IO_P_RC_CONFIG_OPTIONS] & PX4IO_P_RC_CONFIG_OPTIONS_REVERSE)
|
||||
scaled = -scaled;
|
||||
/*
|
||||
* 2) Scale around the mid point differently for lower and upper range.
|
||||
*
|
||||
* This is necessary as they don't share the same endpoints and slope.
|
||||
*
|
||||
* First normalize to 0..1 range with correct sign (below or above center),
|
||||
* then scale to 20000 range (if center is an actual center, -10000..10000,
|
||||
* if parameters only support half range, scale to 10000 range, e.g. if
|
||||
* center == min 0..10000, if center == max -10000..0).
|
||||
*
|
||||
* As the min and max bounds were enforced in step 1), division by zero
|
||||
* cannot occur, as for the case of center == min or center == max the if
|
||||
* statement is mutually exclusive with the arithmetic NaN case.
|
||||
*
|
||||
* DO NOT REMOVE OR ALTER STEP 1!
|
||||
*/
|
||||
if (raw > (conf[PX4IO_P_RC_CONFIG_CENTER] + conf[PX4IO_P_RC_CONFIG_DEADZONE])) {
|
||||
scaled = 10000.0f * ((raw - conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE]) / (float)(conf[PX4IO_P_RC_CONFIG_MAX] - conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE]));
|
||||
|
||||
/* and update the scaled/mapped version */
|
||||
unsigned mapped = conf[PX4IO_P_RC_CONFIG_ASSIGNMENT];
|
||||
if (mapped < PX4IO_CONTROL_CHANNELS) {
|
||||
} else if (raw < (conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE])) {
|
||||
scaled = 10000.0f * ((raw - conf[PX4IO_P_RC_CONFIG_CENTER] + conf[PX4IO_P_RC_CONFIG_DEADZONE]) / (float)(conf[PX4IO_P_RC_CONFIG_CENTER] - conf[PX4IO_P_RC_CONFIG_DEADZONE] - conf[PX4IO_P_RC_CONFIG_MIN]));
|
||||
|
||||
/* invert channel if pitch - pulling the lever down means pitching up by convention */
|
||||
if (mapped == 1) /* roll, pitch, yaw, throttle, override is the standard order */
|
||||
} else {
|
||||
/* in the configured dead zone, output zero */
|
||||
scaled = 0;
|
||||
}
|
||||
|
||||
/* invert channel if requested */
|
||||
if (conf[PX4IO_P_RC_CONFIG_OPTIONS] & PX4IO_P_RC_CONFIG_OPTIONS_REVERSE)
|
||||
scaled = -scaled;
|
||||
|
||||
r_rc_values[mapped] = SIGNED_TO_REG(scaled);
|
||||
assigned_channels |= (1 << mapped);
|
||||
/* and update the scaled/mapped version */
|
||||
unsigned mapped = conf[PX4IO_P_RC_CONFIG_ASSIGNMENT];
|
||||
if (mapped < PX4IO_CONTROL_CHANNELS) {
|
||||
|
||||
/* invert channel if pitch - pulling the lever down means pitching up by convention */
|
||||
if (mapped == 1) /* roll, pitch, yaw, throttle, override is the standard order */
|
||||
scaled = -scaled;
|
||||
|
||||
r_rc_values[mapped] = SIGNED_TO_REG(scaled);
|
||||
assigned_channels |= (1 << mapped);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set un-assigned controls to zero */
|
||||
for (unsigned i = 0; i < PX4IO_CONTROL_CHANNELS; i++) {
|
||||
if (!(assigned_channels & (1 << i)))
|
||||
r_rc_values[i] = 0;
|
||||
}
|
||||
/* set un-assigned controls to zero */
|
||||
for (unsigned i = 0; i < PX4IO_CONTROL_CHANNELS; i++) {
|
||||
if (!(assigned_channels & (1 << i)))
|
||||
r_rc_values[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got an update with zero channels, treat it as
|
||||
* a loss of input.
|
||||
*
|
||||
* This might happen if a protocol-based receiver returns an update
|
||||
* that contains no channels that we have mapped.
|
||||
*/
|
||||
if (assigned_channels == 0 || rssi == 0) {
|
||||
rc_input_lost = true;
|
||||
} else {
|
||||
/* set RC OK flag */
|
||||
/* set RC OK flag, as we got an update */
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_RC_OK;
|
||||
|
||||
/* if we have enough channels (5) to control the vehicle, the mapping is ok */
|
||||
if (assigned_channels > 4) {
|
||||
r_raw_rc_flags |= PX4IO_P_RAW_RC_FLAGS_MAPPING_OK;
|
||||
} else {
|
||||
r_raw_rc_flags &= ~(PX4IO_P_RAW_RC_FLAGS_MAPPING_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -264,7 +301,7 @@ controls_tick() {
|
||||
* If we haven't seen any new control data in 200ms, assume we
|
||||
* have lost input.
|
||||
*/
|
||||
if (hrt_elapsed_time(&system_state.rc_channels_timestamp) > 200000) {
|
||||
if (hrt_elapsed_time(&system_state.rc_channels_timestamp_received) > 200000) {
|
||||
rc_input_lost = true;
|
||||
|
||||
/* clear the input-kind flags here */
|
||||
@@ -272,24 +309,32 @@ controls_tick() {
|
||||
PX4IO_P_STATUS_FLAGS_RC_PPM |
|
||||
PX4IO_P_STATUS_FLAGS_RC_DSM |
|
||||
PX4IO_P_STATUS_FLAGS_RC_SBUS);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle losing RC input
|
||||
*/
|
||||
if (rc_input_lost) {
|
||||
|
||||
/* this kicks in if the receiver is gone or the system went to failsafe */
|
||||
if (rc_input_lost || (r_raw_rc_flags & PX4IO_P_RAW_RC_FLAGS_FAILSAFE)) {
|
||||
/* Clear the RC input status flag, clear manual override flag */
|
||||
r_status_flags &= ~(
|
||||
PX4IO_P_STATUS_FLAGS_OVERRIDE |
|
||||
PX4IO_P_STATUS_FLAGS_RC_OK);
|
||||
|
||||
/* Mark all channels as invalid, as we just lost the RX */
|
||||
r_rc_valid = 0;
|
||||
|
||||
/* Set the RC_LOST alarm */
|
||||
r_status_alarms |= PX4IO_P_STATUS_ALARMS_RC_LOST;
|
||||
}
|
||||
|
||||
/* Mark the arrays as empty */
|
||||
/* this kicks in if the receiver is completely gone */
|
||||
if (rc_input_lost) {
|
||||
|
||||
/* Set channel count to zero */
|
||||
r_raw_rc_count = 0;
|
||||
r_rc_valid = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -223,14 +223,25 @@ mixer_tick(void)
|
||||
}
|
||||
}
|
||||
|
||||
if ((should_arm || should_always_enable_pwm) && !mixer_servos_armed) {
|
||||
/* set arming */
|
||||
bool needs_to_arm = (should_arm || should_always_enable_pwm);
|
||||
|
||||
/* check any conditions that prevent arming */
|
||||
if (r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN) {
|
||||
needs_to_arm = false;
|
||||
}
|
||||
if (!should_arm && !should_always_enable_pwm) {
|
||||
needs_to_arm = false;
|
||||
}
|
||||
|
||||
if (needs_to_arm && !mixer_servos_armed) {
|
||||
/* need to arm, but not armed */
|
||||
up_pwm_servo_arm(true);
|
||||
mixer_servos_armed = true;
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED;
|
||||
isr_debug(5, "> PWM enabled");
|
||||
|
||||
} else if ((!should_arm && !should_always_enable_pwm) && mixer_servos_armed) {
|
||||
} else if (!needs_to_arm && mixer_servos_armed) {
|
||||
/* armed but need to disarm */
|
||||
up_pwm_servo_arm(false);
|
||||
mixer_servos_armed = false;
|
||||
|
||||
@@ -111,7 +111,6 @@
|
||||
#define PX4IO_P_STATUS_FLAGS_INIT_OK (1 << 10) /* initialisation of the IO completed without error */
|
||||
#define PX4IO_P_STATUS_FLAGS_FAILSAFE (1 << 11) /* failsafe is active */
|
||||
#define PX4IO_P_STATUS_FLAGS_SAFETY_OFF (1 << 12) /* safety is off */
|
||||
#define PX4IO_P_STATUS_FLAGS_RC_DSM11 (1 << 13) /* DSM input is 11 bit data */
|
||||
|
||||
#define PX4IO_P_STATUS_ALARMS 3 /* alarm flags - alarms latch, write 1 to a bit to clear it */
|
||||
#define PX4IO_P_STATUS_ALARMS_VBATT_LOW (1 << 0) /* [1] VBatt is very close to regulator dropout */
|
||||
@@ -128,8 +127,6 @@
|
||||
#define PX4IO_P_STATUS_VSERVO 6 /* [2] servo rail voltage in mV */
|
||||
#define PX4IO_P_STATUS_VRSSI 7 /* [2] RSSI voltage */
|
||||
#define PX4IO_P_STATUS_PRSSI 8 /* [2] RSSI PWM value */
|
||||
#define PX4IO_P_STATUS_NRSSI 9 /* [2] Normalized RSSI value, 0: no reception, 255: perfect reception */
|
||||
#define PX4IO_P_STATUS_RC_DATA 10 /* [1] + [2] Details about the RC source (PPM frame length, Spektrum protocol type) */
|
||||
|
||||
/* array of post-mix actuator outputs, -10000..10000 */
|
||||
#define PX4IO_PAGE_ACTUATORS 2 /* 0..CONFIG_ACTUATOR_COUNT-1 */
|
||||
@@ -140,7 +137,17 @@
|
||||
/* array of raw RC input values, microseconds */
|
||||
#define PX4IO_PAGE_RAW_RC_INPUT 4
|
||||
#define PX4IO_P_RAW_RC_COUNT 0 /* number of valid channels */
|
||||
#define PX4IO_P_RAW_RC_BASE 1 /* CONFIG_RC_INPUT_COUNT channels from here */
|
||||
#define PX4IO_P_RAW_RC_FLAGS 1 /* RC detail status flags */
|
||||
#define PX4IO_P_RAW_RC_FLAGS_FRAME_DROP (1 << 0) /* single frame drop */
|
||||
#define PX4IO_P_RAW_RC_FLAGS_FAILSAFE (1 << 1) /* receiver is in failsafe mode */
|
||||
#define PX4IO_P_RAW_RC_FLAGS_RC_DSM11 (1 << 2) /* DSM decoding is 11 bit mode */
|
||||
#define PX4IO_P_RAW_RC_FLAGS_MAPPING_OK (1 << 3) /* Channel mapping is ok */
|
||||
|
||||
#define PX4IO_P_RAW_RC_NRSSI 2 /* [2] Normalized RSSI value, 0: no reception, 255: perfect reception */
|
||||
#define PX4IO_P_RAW_RC_DATA 3 /* [1] + [2] Details about the RC source (PPM frame length, Spektrum protocol type) */
|
||||
#define PX4IO_P_RAW_FRAME_COUNT 4 /* Number of total received frames (wrapping counter) */
|
||||
#define PX4IO_P_RAW_LOST_FRAME_COUNT 5 /* Number of total dropped frames (wrapping counter) */
|
||||
#define PX4IO_P_RAW_RC_BASE 6 /* CONFIG_RC_INPUT_COUNT channels from here */
|
||||
|
||||
/* array of scaled RC input values, -10000..10000 */
|
||||
#define PX4IO_PAGE_RC_INPUT 5
|
||||
@@ -157,6 +164,10 @@
|
||||
/* setup page */
|
||||
#define PX4IO_PAGE_SETUP 50
|
||||
#define PX4IO_P_SETUP_FEATURES 0
|
||||
#define PX4IO_P_SETUP_FEATURES_SBUS1_OUT (1 << 0) /* enable S.Bus v1 output */
|
||||
#define PX4IO_P_SETUP_FEATURES_SBUS2_OUT (1 << 1) /* enable S.Bus v2 output */
|
||||
#define PX4IO_P_SETUP_FEATURES_PWM_RSSI (1 << 2) /* enable PWM RSSI parsing */
|
||||
#define PX4IO_P_SETUP_FEATURES_ADC_RSSI (1 << 3) /* enable ADC RSSI parsing */
|
||||
|
||||
#define PX4IO_P_SETUP_ARMING 1 /* arming controls */
|
||||
#define PX4IO_P_SETUP_ARMING_IO_ARM_OK (1 << 0) /* OK to arm the IO side */
|
||||
@@ -166,6 +177,7 @@
|
||||
#define PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK (1 << 4) /* OK to try in-air restart */
|
||||
#define PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE (1 << 5) /* Output of PWM right after startup enabled to help ESCs initialize and prevent them from beeping */
|
||||
#define PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED (1 << 6) /* Disable the IO-internal evaluation of the RC */
|
||||
#define PX4IO_P_SETUP_ARMING_LOCKDOWN (1 << 7) /* If set, the system operates normally, but won't actuate any servos */
|
||||
|
||||
#define PX4IO_P_SETUP_PWM_RATES 2 /* bitmask, 0 = low rate, 1 = high rate */
|
||||
#define PX4IO_P_SETUP_PWM_DEFAULTRATE 3 /* 'low' PWM frame output rate in Hz */
|
||||
|
||||
@@ -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
|
||||
@@ -96,8 +96,9 @@ extern uint16_t r_page_servo_disarmed[]; /* PX4IO_PAGE_DISARMED_PWM */
|
||||
|
||||
#define r_raw_rc_count r_page_raw_rc_input[PX4IO_P_RAW_RC_COUNT]
|
||||
#define r_raw_rc_values (&r_page_raw_rc_input[PX4IO_P_RAW_RC_BASE])
|
||||
#define r_raw_rc_flags r_page_raw_rc_input[PX4IO_P_RAW_RC_FLAGS]
|
||||
#define r_rc_valid r_page_rc_input[PX4IO_P_RC_VALID]
|
||||
#define r_rc_values (&r_page_rc_input[PX4IO_P_RAW_RC_BASE])
|
||||
#define r_rc_values (&r_page_rc_input[PX4IO_P_RC_BASE])
|
||||
|
||||
#define r_setup_features r_page_setup[PX4IO_P_SETUP_FEATURES]
|
||||
#define r_setup_arming r_page_setup[PX4IO_P_SETUP_ARMING]
|
||||
@@ -115,7 +116,8 @@ extern uint16_t r_page_servo_disarmed[]; /* PX4IO_PAGE_DISARMED_PWM */
|
||||
*/
|
||||
struct sys_state_s {
|
||||
|
||||
volatile uint64_t rc_channels_timestamp;
|
||||
volatile uint64_t rc_channels_timestamp_received;
|
||||
volatile uint64_t rc_channels_timestamp_valid;
|
||||
|
||||
/**
|
||||
* Last FMU receive time, in microseconds since system boot
|
||||
@@ -215,7 +217,7 @@ extern int dsm_init(const char *device);
|
||||
extern bool dsm_input(uint16_t *values, uint16_t *num_values);
|
||||
extern void dsm_bind(uint16_t cmd, int pulses);
|
||||
extern int sbus_init(const char *device);
|
||||
extern bool sbus_input(uint16_t *values, uint16_t *num_values, uint16_t *rssi, uint16_t max_channels);
|
||||
extern bool sbus_input(uint16_t *values, uint16_t *num_values, bool *sbus_failsafe, bool *sbus_frame_drop, uint16_t max_channels);
|
||||
|
||||
/** global debug level for isr_debug() */
|
||||
extern volatile uint8_t debug_level;
|
||||
|
||||
@@ -90,8 +90,6 @@ uint16_t r_page_status[] = {
|
||||
[PX4IO_P_STATUS_VSERVO] = 0,
|
||||
[PX4IO_P_STATUS_VRSSI] = 0,
|
||||
[PX4IO_P_STATUS_PRSSI] = 0,
|
||||
[PX4IO_P_STATUS_NRSSI] = 0,
|
||||
[PX4IO_P_STATUS_RC_DATA] = 0
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -116,6 +114,12 @@ uint16_t r_page_servos[PX4IO_SERVO_COUNT];
|
||||
uint16_t r_page_raw_rc_input[] =
|
||||
{
|
||||
[PX4IO_P_RAW_RC_COUNT] = 0,
|
||||
[PX4IO_P_RAW_RC_FLAGS] = 0,
|
||||
[PX4IO_P_RAW_RC_NRSSI] = 0,
|
||||
[PX4IO_P_RAW_RC_DATA] = 0,
|
||||
[PX4IO_P_RAW_FRAME_COUNT] = 0,
|
||||
[PX4IO_P_RAW_LOST_FRAME_COUNT] = 0,
|
||||
[PX4IO_P_RAW_RC_DATA] = 0,
|
||||
[PX4IO_P_RAW_RC_BASE ... (PX4IO_P_RAW_RC_BASE + PX4IO_RC_INPUT_CHANNELS)] = 0
|
||||
};
|
||||
|
||||
@@ -144,7 +148,12 @@ uint16_t r_page_scratch[32];
|
||||
*/
|
||||
volatile uint16_t r_page_setup[] =
|
||||
{
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4IO_V2
|
||||
/* default to RSSI ADC functionality */
|
||||
[PX4IO_P_SETUP_FEATURES] = PX4IO_P_SETUP_FEATURES_ADC_RSSI,
|
||||
#else
|
||||
[PX4IO_P_SETUP_FEATURES] = 0,
|
||||
#endif
|
||||
[PX4IO_P_SETUP_ARMING] = 0,
|
||||
[PX4IO_P_SETUP_PWM_RATES] = 0,
|
||||
[PX4IO_P_SETUP_PWM_DEFAULTRATE] = 50,
|
||||
@@ -162,14 +171,22 @@ volatile uint16_t r_page_setup[] =
|
||||
[PX4IO_P_SETUP_CRC ... (PX4IO_P_SETUP_CRC+1)] = 0,
|
||||
};
|
||||
|
||||
#define PX4IO_P_SETUP_FEATURES_VALID (0)
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4IO_V2
|
||||
#define PX4IO_P_SETUP_FEATURES_VALID (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | \
|
||||
PX4IO_P_SETUP_FEATURES_SBUS2_OUT | \
|
||||
PX4IO_P_SETUP_FEATURES_ADC_RSSI | \
|
||||
PX4IO_P_SETUP_FEATURES_PWM_RSSI)
|
||||
#else
|
||||
#define PX4IO_P_SETUP_FEATURES_VALID 0
|
||||
#endif
|
||||
#define PX4IO_P_SETUP_ARMING_VALID (PX4IO_P_SETUP_ARMING_FMU_ARMED | \
|
||||
PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK | \
|
||||
PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK | \
|
||||
PX4IO_P_SETUP_ARMING_IO_ARM_OK | \
|
||||
PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM | \
|
||||
PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE | \
|
||||
PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED)
|
||||
PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED | \
|
||||
PX4IO_P_SETUP_ARMING_LOCKDOWN)
|
||||
#define PX4IO_P_SETUP_RATES_VALID ((1 << PX4IO_SERVO_COUNT) - 1)
|
||||
#define PX4IO_P_SETUP_RELAYS_VALID ((1 << PX4IO_RELAY_CHANNELS) - 1)
|
||||
|
||||
@@ -438,9 +455,35 @@ registers_set_one(uint8_t page, uint8_t offset, uint16_t value)
|
||||
case PX4IO_P_SETUP_FEATURES:
|
||||
|
||||
value &= PX4IO_P_SETUP_FEATURES_VALID;
|
||||
r_setup_features = value;
|
||||
|
||||
/* no implemented feature selection at this point */
|
||||
/* some of the options conflict - give S.BUS out precedence, then ADC RSSI, then PWM RSSI */
|
||||
|
||||
/* switch S.Bus output pin as needed */
|
||||
#ifdef ENABLE_SBUS_OUT
|
||||
ENABLE_SBUS_OUT(value & (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | PX4IO_P_SETUP_FEATURES_SBUS2_OUT));
|
||||
|
||||
/* disable the conflicting options */
|
||||
if (value & (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | PX4IO_P_SETUP_FEATURES_SBUS2_OUT)) {
|
||||
value &= ~(PX4IO_P_SETUP_FEATURES_PWM_RSSI | PX4IO_P_SETUP_FEATURES_ADC_RSSI);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* disable the conflicting options with ADC RSSI */
|
||||
if (value & (PX4IO_P_SETUP_FEATURES_ADC_RSSI)) {
|
||||
value &= ~(PX4IO_P_SETUP_FEATURES_PWM_RSSI |
|
||||
PX4IO_P_SETUP_FEATURES_SBUS1_OUT |
|
||||
PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
|
||||
}
|
||||
|
||||
/* disable the conflicting options with PWM RSSI (without effect here, but for completeness) */
|
||||
if (value & (PX4IO_P_SETUP_FEATURES_PWM_RSSI)) {
|
||||
value &= ~(PX4IO_P_SETUP_FEATURES_ADC_RSSI |
|
||||
PX4IO_P_SETUP_FEATURES_SBUS1_OUT |
|
||||
PX4IO_P_SETUP_FEATURES_SBUS2_OUT);
|
||||
}
|
||||
|
||||
/* apply changes */
|
||||
r_setup_features = value;
|
||||
|
||||
break;
|
||||
|
||||
@@ -456,11 +499,6 @@ registers_set_one(uint8_t page, uint8_t offset, uint16_t value)
|
||||
* lockup of the IO arming state.
|
||||
*/
|
||||
|
||||
// XXX do not reset IO's safety state by FMU for now
|
||||
// if ((r_setup_arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) && !(value & PX4IO_P_SETUP_ARMING_FMU_ARMED)) {
|
||||
// r_status_flags &= ~PX4IO_P_STATUS_FLAGS_ARMED;
|
||||
// }
|
||||
|
||||
if (value & PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED) {
|
||||
r_status_flags |= PX4IO_P_STATUS_FLAGS_INIT_OK;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ static unsigned partial_frame_count;
|
||||
|
||||
unsigned sbus_frame_drops;
|
||||
|
||||
static bool sbus_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values, uint16_t *rssi, uint16_t max_channels);
|
||||
static bool sbus_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values, bool *sbus_failsafe, bool *sbus_frame_drop, uint16_t max_channels);
|
||||
|
||||
int
|
||||
sbus_init(const char *device)
|
||||
@@ -118,7 +118,7 @@ sbus_init(const char *device)
|
||||
}
|
||||
|
||||
bool
|
||||
sbus_input(uint16_t *values, uint16_t *num_values, uint16_t *rssi, uint16_t max_channels)
|
||||
sbus_input(uint16_t *values, uint16_t *num_values, bool *sbus_failsafe, bool *sbus_frame_drop, uint16_t max_channels)
|
||||
{
|
||||
ssize_t ret;
|
||||
hrt_abstime now;
|
||||
@@ -175,7 +175,7 @@ sbus_input(uint16_t *values, uint16_t *num_values, uint16_t *rssi, uint16_t max_
|
||||
* decode it.
|
||||
*/
|
||||
partial_frame_count = 0;
|
||||
return sbus_decode(now, values, num_values, rssi, max_channels);
|
||||
return sbus_decode(now, values, num_values, sbus_failsafe, sbus_frame_drop, max_channels);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -215,7 +215,7 @@ static const struct sbus_bit_pick sbus_decoder[SBUS_INPUT_CHANNELS][3] = {
|
||||
};
|
||||
|
||||
static bool
|
||||
sbus_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values, uint16_t *rssi, uint16_t max_values)
|
||||
sbus_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values, bool *sbus_failsafe, bool *sbus_frame_drop, uint16_t max_values)
|
||||
{
|
||||
/* check frame boundary markers to avoid out-of-sync cases */
|
||||
if ((frame[0] != 0x0f)) {
|
||||
@@ -289,20 +289,22 @@ sbus_decode(hrt_abstime frame_time, uint16_t *values, uint16_t *num_values, uint
|
||||
/* decode and handle failsafe and frame-lost flags */
|
||||
if (frame[SBUS_FLAGS_BYTE] & (1 << SBUS_FAILSAFE_BIT)) { /* failsafe */
|
||||
/* report that we failed to read anything valid off the receiver */
|
||||
*rssi = 0;
|
||||
return false;
|
||||
*sbus_failsafe = true;
|
||||
*sbus_frame_drop = true;
|
||||
}
|
||||
else if (frame[SBUS_FLAGS_BYTE] & (1 << SBUS_FRAMELOST_BIT)) { /* a frame was lost */
|
||||
/* set a special warning flag or try to calculate some kind of RSSI information - to be implemented
|
||||
/* set a special warning flag
|
||||
*
|
||||
* Attention! This flag indicates a skipped frame only, not a total link loss! Handling this
|
||||
* condition as fail-safe greatly reduces the reliability and range of the radio link,
|
||||
* e.g. by prematurely issueing return-to-launch!!! */
|
||||
|
||||
*rssi = 100; // XXX magic number indicating bad signal, but not a signal loss (yet)
|
||||
*sbus_failsafe = false;
|
||||
*sbus_frame_drop = true;
|
||||
} else {
|
||||
*sbus_failsafe = false;
|
||||
*sbus_frame_drop = false;
|
||||
}
|
||||
|
||||
*rssi = 255;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+30
-17
@@ -62,7 +62,6 @@
|
||||
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/sensor_combined.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
@@ -83,6 +82,7 @@
|
||||
#include <uORB/topics/airspeed.h>
|
||||
#include <uORB/topics/rc_channels.h>
|
||||
#include <uORB/topics/esc_status.h>
|
||||
#include <uORB/topics/telemetry_status.h>
|
||||
|
||||
#include <systemlib/systemlib.h>
|
||||
#include <systemlib/param/param.h>
|
||||
@@ -740,7 +740,6 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
/* warning! using union here to save memory, elements should be used separately! */
|
||||
union {
|
||||
struct vehicle_command_s cmd;
|
||||
struct vehicle_control_mode_s control_mode;
|
||||
struct sensor_combined_s sensor;
|
||||
struct vehicle_attitude_s att;
|
||||
struct vehicle_attitude_setpoint_s att_sp;
|
||||
@@ -760,6 +759,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
struct esc_status_s esc;
|
||||
struct vehicle_global_velocity_setpoint_s global_vel_sp;
|
||||
struct battery_status_s battery;
|
||||
struct telemetry_status_s telemetry;
|
||||
} buf;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
@@ -767,7 +767,6 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
struct {
|
||||
int cmd_sub;
|
||||
int status_sub;
|
||||
int control_mode_sub;
|
||||
int sensor_sub;
|
||||
int att_sub;
|
||||
int att_sp_sub;
|
||||
@@ -786,6 +785,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
int esc_sub;
|
||||
int global_vel_sp_sub;
|
||||
int battery_sub;
|
||||
int telemetry_sub;
|
||||
} subs;
|
||||
|
||||
/* log message buffer: header + body */
|
||||
@@ -814,6 +814,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
struct log_GVSP_s log_GVSP;
|
||||
struct log_BATT_s log_BATT;
|
||||
struct log_DIST_s log_DIST;
|
||||
struct log_TELE_s log_TELE;
|
||||
} body;
|
||||
} log_msg = {
|
||||
LOG_PACKET_HEADER_INIT(0)
|
||||
@@ -847,12 +848,6 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
fds[fdsc_count].events = POLLIN;
|
||||
fdsc_count++;
|
||||
|
||||
/* --- VEHICLE CONTROL MODE --- */
|
||||
subs.control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
|
||||
fds[fdsc_count].fd = subs.control_mode_sub;
|
||||
fds[fdsc_count].events = POLLIN;
|
||||
fdsc_count++;
|
||||
|
||||
/* --- SENSORS COMBINED --- */
|
||||
subs.sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
|
||||
fds[fdsc_count].fd = subs.sensor_sub;
|
||||
@@ -955,6 +950,12 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
fds[fdsc_count].events = POLLIN;
|
||||
fdsc_count++;
|
||||
|
||||
/* --- TELEMETRY STATUS --- */
|
||||
subs.telemetry_sub = orb_subscribe(ORB_ID(telemetry_status));
|
||||
fds[fdsc_count].fd = subs.telemetry_sub;
|
||||
fds[fdsc_count].events = POLLIN;
|
||||
fdsc_count++;
|
||||
|
||||
/* WARNING: If you get the error message below,
|
||||
* then the number of registered messages (fdsc)
|
||||
* differs from the number of messages in the above list.
|
||||
@@ -1002,7 +1003,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
/* decide use usleep() or blocking poll() */
|
||||
bool use_sleep = sleep_delay > 0 && logging_enabled;
|
||||
|
||||
/* poll all topics if logging enabled or only management (first 2) if not */
|
||||
/* poll all topics if logging enabled or only management (first 3) if not */
|
||||
int poll_ret = poll(fds, logging_enabled ? fdsc_count : 3, use_sleep ? 0 : poll_timeout);
|
||||
|
||||
/* handle the poll result */
|
||||
@@ -1064,11 +1065,8 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
/* --- VEHICLE STATUS --- */
|
||||
if (fds[ifds++].revents & POLLIN) {
|
||||
/* don't orb_copy, it's already done few lines above */
|
||||
/* copy VEHICLE CONTROL MODE control mode here to construct STAT message */
|
||||
orb_copy(ORB_ID(vehicle_control_mode), subs.control_mode_sub, &buf.control_mode);
|
||||
log_msg.msg_type = LOG_STAT_MSG;
|
||||
log_msg.body.log_STAT.main_state = (uint8_t) buf.control_mode.main_state;
|
||||
log_msg.body.log_STAT.navigation_state = (uint8_t) buf.control_mode.nav_state;
|
||||
log_msg.body.log_STAT.main_state = (uint8_t) buf_status.main_state;
|
||||
log_msg.body.log_STAT.arming_state = (uint8_t) buf_status.arming_state;
|
||||
log_msg.body.log_STAT.battery_remaining = buf_status.battery_remaining;
|
||||
log_msg.body.log_STAT.battery_warning = (uint8_t) buf_status.battery_warning;
|
||||
@@ -1078,7 +1076,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
|
||||
/* --- GPS POSITION --- */
|
||||
if (fds[ifds++].revents & POLLIN) {
|
||||
orb_copy(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf.gps_pos);
|
||||
/* don't orb_copy, it's already done few lines above */
|
||||
log_msg.msg_type = LOG_GPS_MSG;
|
||||
log_msg.body.log_GPS.gps_time = buf.gps_pos.time_gps_usec;
|
||||
log_msg.body.log_GPS.fix_type = buf.gps_pos.fix_type;
|
||||
@@ -1094,8 +1092,6 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
LOGBUFFER_WRITE_AND_COUNT(GPS);
|
||||
}
|
||||
|
||||
ifds++; // skip CONTROL MODE, already handled
|
||||
|
||||
/* --- SENSOR COMBINED --- */
|
||||
if (fds[ifds++].revents & POLLIN) {
|
||||
orb_copy(ORB_ID(sensor_combined), subs.sensor_sub, &buf.sensor);
|
||||
@@ -1258,6 +1254,8 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
log_msg.body.log_GPOS.vel_n = buf.global_pos.vel_n;
|
||||
log_msg.body.log_GPOS.vel_e = buf.global_pos.vel_e;
|
||||
log_msg.body.log_GPOS.vel_d = buf.global_pos.vel_d;
|
||||
log_msg.body.log_GPOS.baro_alt = buf.global_pos.baro_alt;
|
||||
log_msg.body.log_GPOS.flags = (buf.global_pos.baro_valid ? 1 : 0) | (buf.global_pos.global_valid ? 2 : 0);
|
||||
LOGBUFFER_WRITE_AND_COUNT(GPOS);
|
||||
}
|
||||
|
||||
@@ -1265,6 +1263,7 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
if (fds[ifds++].revents & POLLIN) {
|
||||
orb_copy(ORB_ID(position_setpoint_triplet), subs.triplet_sub, &buf.triplet);
|
||||
log_msg.msg_type = LOG_GPSP_MSG;
|
||||
log_msg.body.log_GPSP.nav_state = buf.triplet.nav_state;
|
||||
log_msg.body.log_GPSP.lat = (int32_t)(buf.triplet.current.lat * 1e7d);
|
||||
log_msg.body.log_GPSP.lon = (int32_t)(buf.triplet.current.lon * 1e7d);
|
||||
log_msg.body.log_GPSP.alt = buf.triplet.current.alt;
|
||||
@@ -1358,6 +1357,20 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
LOGBUFFER_WRITE_AND_COUNT(BATT);
|
||||
}
|
||||
|
||||
/* --- TELEMETRY --- */
|
||||
if (fds[ifds++].revents & POLLIN) {
|
||||
orb_copy(ORB_ID(telemetry_status), subs.telemetry_sub, &buf.telemetry);
|
||||
log_msg.msg_type = LOG_TELE_MSG;
|
||||
log_msg.body.log_TELE.rssi = buf.telemetry.rssi;
|
||||
log_msg.body.log_TELE.remote_rssi = buf.telemetry.remote_rssi;
|
||||
log_msg.body.log_TELE.noise = buf.telemetry.noise;
|
||||
log_msg.body.log_TELE.remote_noise = buf.telemetry.remote_noise;
|
||||
log_msg.body.log_TELE.rxerrors = buf.telemetry.rxerrors;
|
||||
log_msg.body.log_TELE.fixed = buf.telemetry.fixed;
|
||||
log_msg.body.log_TELE.txbuf = buf.telemetry.txbuf;
|
||||
LOGBUFFER_WRITE_AND_COUNT(TELE);
|
||||
}
|
||||
|
||||
/* signal the other thread new data, but not yet unlock */
|
||||
if (logbuffer_count(&lb) > MIN_BYTES_TO_WRITE) {
|
||||
/* only request write if several packets can be written at once */
|
||||
|
||||
@@ -149,7 +149,6 @@ struct log_ATTC_s {
|
||||
#define LOG_STAT_MSG 10
|
||||
struct log_STAT_s {
|
||||
uint8_t main_state;
|
||||
uint8_t navigation_state;
|
||||
uint8_t arming_state;
|
||||
float battery_remaining;
|
||||
uint8_t battery_warning;
|
||||
@@ -205,11 +204,14 @@ struct log_GPOS_s {
|
||||
float vel_n;
|
||||
float vel_e;
|
||||
float vel_d;
|
||||
float baro_alt;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/* --- GPSP - GLOBAL POSITION SETPOINT --- */
|
||||
#define LOG_GPSP_MSG 17
|
||||
struct log_GPSP_s {
|
||||
uint8_t nav_state;
|
||||
int32_t lat;
|
||||
int32_t lon;
|
||||
float alt;
|
||||
@@ -262,6 +264,18 @@ struct log_DIST_s {
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/* --- 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;
|
||||
};
|
||||
|
||||
/********** SYSTEM MESSAGES, ID > 0x80 **********/
|
||||
|
||||
/* --- TIME - TIME STAMP --- */
|
||||
@@ -297,18 +311,20 @@ static const struct log_format_s log_formats[] = {
|
||||
LOG_FORMAT(LPSP, "ffff", "X,Y,Z,Yaw"),
|
||||
LOG_FORMAT(GPS, "QBffLLfffff", "GPSTime,FixType,EPH,EPV,Lat,Lon,Alt,VelN,VelE,VelD,Cog"),
|
||||
LOG_FORMAT(ATTC, "ffff", "Roll,Pitch,Yaw,Thrust"),
|
||||
LOG_FORMAT(STAT, "BBBfBB", "MainState,NavState,ArmState,BatRem,BatWarn,Landed"),
|
||||
LOG_FORMAT(STAT, "BBfBB", "MainState,ArmState,BatRem,BatWarn,Landed"),
|
||||
LOG_FORMAT(RC, "ffffffffB", "Ch0,Ch1,Ch2,Ch3,Ch4,Ch5,Ch6,Ch7,Count"),
|
||||
LOG_FORMAT(OUT0, "ffffffff", "Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7"),
|
||||
LOG_FORMAT(AIRS, "ff", "IndSpeed,TrueSpeed"),
|
||||
LOG_FORMAT(ARSP, "fff", "RollRateSP,PitchRateSP,YawRateSP"),
|
||||
LOG_FORMAT(FLOW, "hhfffBB", "RawX,RawY,CompX,CompY,Dist,Q,SensID"),
|
||||
LOG_FORMAT(GPOS, "LLffff", "Lat,Lon,Alt,VelN,VelE,VelD"),
|
||||
LOG_FORMAT(GPSP, "LLffBfbf", "Lat,Lon,Alt,Yaw,Type,LoitR,LoitDir,PitMin"),
|
||||
LOG_FORMAT(GPOS, "LLfffffB", "Lat,Lon,Alt,VelN,VelE,VelD,BaroAlt,Flags"),
|
||||
LOG_FORMAT(GPSP, "BLLffBfbf", "NavState,Lat,Lon,Alt,Yaw,Type,LoitR,LoitDir,PitMin"),
|
||||
LOG_FORMAT(ESC, "HBBBHHHHHHfH", "Counter,NumESC,Conn,N,Ver,Adr,Volt,Amp,RPM,Temp,SetP,SetPRAW"),
|
||||
LOG_FORMAT(GVSP, "fff", "VX,VY,VZ"),
|
||||
LOG_FORMAT(BATT, "ffff", "V,VFilt,C,Discharged"),
|
||||
LOG_FORMAT(DIST, "ffB", "Bottom,BottomRate,Flags"),
|
||||
LOG_FORMAT(TELE, "BBBBHHB", "RSSI,RemRSSI,Noise,RemNoise,RXErr,Fixed,TXBuf"),
|
||||
|
||||
/* system-level messages, ID >= 0x80 */
|
||||
// FMT: don't write format of format message, it's useless
|
||||
LOG_FORMAT(TIME, "Q", "StartTime"),
|
||||
|
||||
@@ -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
|
||||
@@ -636,41 +635,43 @@ Sensors::parameters_update()
|
||||
if (!rc_valid)
|
||||
warnx("WARNING WARNING WARNING\n\nRC CALIBRATION NOT SANE!\n\n");
|
||||
|
||||
const char *paramerr = "FAIL PARM LOAD";
|
||||
|
||||
/* channel mapping */
|
||||
if (param_get(_parameter_handles.rc_map_roll, &(_parameters.rc_map_roll)) != OK) {
|
||||
warnx("Failed getting roll chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_pitch, &(_parameters.rc_map_pitch)) != OK) {
|
||||
warnx("Failed getting pitch chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_yaw, &(_parameters.rc_map_yaw)) != OK) {
|
||||
warnx("Failed getting yaw chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_throttle, &(_parameters.rc_map_throttle)) != OK) {
|
||||
warnx("Failed getting throttle chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_mode_sw, &(_parameters.rc_map_mode_sw)) != OK) {
|
||||
warnx("Failed getting mode sw chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_return_sw, &(_parameters.rc_map_return_sw)) != OK) {
|
||||
warnx("Failed getting return sw chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_assisted_sw, &(_parameters.rc_map_assisted_sw)) != OK) {
|
||||
warnx("Failed getting assisted sw chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_mission_sw, &(_parameters.rc_map_mission_sw)) != OK) {
|
||||
warnx("Failed getting mission sw chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
if (param_get(_parameter_handles.rc_map_flaps, &(_parameters.rc_map_flaps)) != OK) {
|
||||
warnx("Failed getting flaps chan index");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
// if (param_get(_parameter_handles.rc_map_offboard_ctrl_mode_sw, &(_parameters.rc_map_offboard_ctrl_mode_sw)) != OK) {
|
||||
@@ -742,12 +743,12 @@ Sensors::parameters_update()
|
||||
|
||||
/* scaling of ADC ticks to battery voltage */
|
||||
if (param_get(_parameter_handles.battery_voltage_scaling, &(_parameters.battery_voltage_scaling)) != OK) {
|
||||
warnx("Failed updating voltage scaling param");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
/* scaling of ADC ticks to battery current */
|
||||
if (param_get(_parameter_handles.battery_current_scaling, &(_parameters.battery_current_scaling)) != OK) {
|
||||
warnx("Failed updating current scaling param");
|
||||
warnx(paramerr);
|
||||
}
|
||||
|
||||
param_get(_parameter_handles.board_rotation, &(_parameters.board_rotation));
|
||||
@@ -1274,6 +1275,9 @@ Sensors::rc_poll()
|
||||
|
||||
orb_copy(ORB_ID(input_rc), _rc_sub, &rc_input);
|
||||
|
||||
if (rc_input.rc_lost)
|
||||
return;
|
||||
|
||||
struct manual_control_setpoint_s manual_control;
|
||||
struct actuator_controls_s actuator_group_3;
|
||||
|
||||
@@ -1318,7 +1322,7 @@ Sensors::rc_poll()
|
||||
channel_limit = _rc_max_chan_count;
|
||||
|
||||
/* we are accepting this message */
|
||||
_rc_last_valid = rc_input.timestamp;
|
||||
_rc_last_valid = rc_input.timestamp_last_signal;
|
||||
|
||||
/* Read out values from raw message */
|
||||
for (unsigned int i = 0; i < channel_limit; i++) {
|
||||
@@ -1367,9 +1371,9 @@ Sensors::rc_poll()
|
||||
}
|
||||
|
||||
_rc.chan_count = rc_input.channel_count;
|
||||
_rc.timestamp = rc_input.timestamp;
|
||||
_rc.timestamp = rc_input.timestamp_last_signal;
|
||||
|
||||
manual_control.timestamp = rc_input.timestamp;
|
||||
manual_control.timestamp = rc_input.timestamp_last_signal;
|
||||
|
||||
/* roll input - rolling right is stick-wise and rotation-wise positive */
|
||||
manual_control.roll = limit_minus_one_to_one(_rc.chan[_rc.function[ROLL]].scaled);
|
||||
@@ -1647,17 +1651,17 @@ int sensors_main(int argc, char *argv[])
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
if (sensors::g_sensors != nullptr)
|
||||
errx(0, "sensors task already running");
|
||||
errx(0, "already running");
|
||||
|
||||
sensors::g_sensors = new Sensors;
|
||||
|
||||
if (sensors::g_sensors == nullptr)
|
||||
errx(1, "sensors task alloc failed");
|
||||
errx(1, "alloc failed");
|
||||
|
||||
if (OK != sensors::g_sensors->start()) {
|
||||
delete sensors::g_sensors;
|
||||
sensors::g_sensors = nullptr;
|
||||
err(1, "sensors task start failed");
|
||||
err(1, "start failed");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
@@ -1665,7 +1669,7 @@ int sensors_main(int argc, char *argv[])
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
if (sensors::g_sensors == nullptr)
|
||||
errx(1, "sensors task not running");
|
||||
errx(1, "not running");
|
||||
|
||||
delete sensors::g_sensors;
|
||||
sensors::g_sensors = nullptr;
|
||||
@@ -1674,10 +1678,10 @@ int sensors_main(int argc, char *argv[])
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (sensors::g_sensors) {
|
||||
errx(0, "task is running");
|
||||
errx(0, "is running");
|
||||
|
||||
} else {
|
||||
errx(1, "task is not running");
|
||||
errx(1, "not running");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,8 +93,7 @@ void cpuload_initialize_once()
|
||||
#endif /* CONFIG_SCHED_WORKQUEUE */
|
||||
|
||||
// perform static initialization of "system" threads
|
||||
for (system_load.total_count = 0; system_load.total_count < static_tasks_count; system_load.total_count++)
|
||||
{
|
||||
for (system_load.total_count = 0; system_load.total_count < static_tasks_count; system_load.total_count++) {
|
||||
system_load.tasks[system_load.total_count].start_time = now;
|
||||
system_load.tasks[system_load.total_count].total_runtime = 0;
|
||||
system_load.tasks[system_load.total_count].curr_start_time = 0;
|
||||
|
||||
@@ -40,15 +40,15 @@ __BEGIN_DECLS
|
||||
#include <nuttx/sched.h>
|
||||
|
||||
struct system_load_taskinfo_s {
|
||||
uint64_t total_runtime; ///< Runtime since start (start_time - total_runtime)/(start_time - current_time) = load
|
||||
uint64_t curr_start_time; ///< Start time of the current scheduling slot
|
||||
uint64_t start_time; ///< FIRST start time of task
|
||||
FAR struct tcb_s *tcb; ///<
|
||||
bool valid; ///< Task is currently active / valid
|
||||
uint64_t total_runtime; ///< Runtime since start (start_time - total_runtime)/(start_time - current_time) = load
|
||||
uint64_t curr_start_time; ///< Start time of the current scheduling slot
|
||||
uint64_t start_time; ///< FIRST start time of task
|
||||
FAR struct tcb_s *tcb; ///<
|
||||
bool valid; ///< Task is currently active / valid
|
||||
};
|
||||
|
||||
struct system_load_s {
|
||||
uint64_t start_time; ///< Global start time of measurements
|
||||
uint64_t start_time; ///< Global start time of measurements
|
||||
struct system_load_taskinfo_s tasks[CONFIG_MAX_TASKS];
|
||||
uint8_t initialized;
|
||||
int total_count;
|
||||
|
||||
@@ -52,7 +52,8 @@ int load_mixer_file(const char *fname, char *buf, unsigned maxlen)
|
||||
/* open the mixer definition file */
|
||||
fp = fopen(fname, "r");
|
||||
if (fp == NULL) {
|
||||
return 1;
|
||||
warnx("file not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read valid lines from the file into a buffer */
|
||||
@@ -88,7 +89,8 @@ int load_mixer_file(const char *fname, char *buf, unsigned maxlen)
|
||||
|
||||
/* if the line is too long to fit in the buffer, bail */
|
||||
if ((strlen(line) + strlen(buf) + 1) >= maxlen) {
|
||||
return 1;
|
||||
warnx("line too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* add the line to the buffer */
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../uORB.h"
|
||||
#include <navigator/navigator_state.h>
|
||||
|
||||
/**
|
||||
* @addtogroup topics
|
||||
@@ -53,10 +54,11 @@
|
||||
|
||||
enum SETPOINT_TYPE
|
||||
{
|
||||
SETPOINT_TYPE_NORMAL = 0,
|
||||
SETPOINT_TYPE_LOITER,
|
||||
SETPOINT_TYPE_TAKEOFF,
|
||||
SETPOINT_TYPE_LAND,
|
||||
SETPOINT_TYPE_NORMAL = 0, /**< normal setpoint */
|
||||
SETPOINT_TYPE_LOITER, /**< loiter setpoint */
|
||||
SETPOINT_TYPE_TAKEOFF, /**< takeoff setpoint */
|
||||
SETPOINT_TYPE_LAND, /**< land setpoint, altitude must be ignored, vehicle must descend until landing */
|
||||
SETPOINT_TYPE_IDLE, /**< do nothing, switch off motors or keep at idle speed (MC) */
|
||||
};
|
||||
|
||||
struct position_setpoint_s
|
||||
@@ -82,6 +84,8 @@ struct position_setpoint_triplet_s
|
||||
struct position_setpoint_s previous;
|
||||
struct position_setpoint_s current;
|
||||
struct position_setpoint_s next;
|
||||
|
||||
nav_state_t nav_state; /**< navigation state */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,10 +58,10 @@ enum TELEMETRY_STATUS_RADIO_TYPE {
|
||||
struct telemetry_status_s {
|
||||
uint64_t timestamp;
|
||||
enum TELEMETRY_STATUS_RADIO_TYPE type; /**< type of the radio hardware */
|
||||
unsigned rssi; /**< local signal strength */
|
||||
unsigned remote_rssi; /**< remote signal strength */
|
||||
unsigned rxerrors; /**< receive errors */
|
||||
unsigned fixed; /**< count of error corrected packets */
|
||||
uint8_t rssi; /**< local signal strength */
|
||||
uint8_t remote_rssi; /**< remote signal strength */
|
||||
uint16_t rxerrors; /**< receive errors */
|
||||
uint16_t fixed; /**< count of error corrected packets */
|
||||
uint8_t noise; /**< background noise level */
|
||||
uint8_t remote_noise; /**< remote background noise level */
|
||||
uint8_t txbuf; /**< how full the tx buffer is as a percentage */
|
||||
@@ -73,4 +73,4 @@ struct telemetry_status_s {
|
||||
|
||||
ORB_DECLARE(telemetry_status);
|
||||
|
||||
#endif /* TOPIC_TELEMETRY_STATUS_H */
|
||||
#endif /* TOPIC_TELEMETRY_STATUS_H */
|
||||
|
||||
@@ -61,23 +61,10 @@
|
||||
* Encodes the complete system state and is set by the commander app.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
NAV_STATE_NONE = 0,
|
||||
NAV_STATE_READY,
|
||||
NAV_STATE_LOITER,
|
||||
NAV_STATE_MISSION,
|
||||
NAV_STATE_RTL,
|
||||
NAV_STATE_LAND,
|
||||
NAV_STATE_MAX
|
||||
} nav_state_t;
|
||||
|
||||
struct vehicle_control_mode_s
|
||||
{
|
||||
uint64_t timestamp; /**< in microseconds since system start, is set whenever the writing thread stores new data */
|
||||
|
||||
main_state_t main_state;
|
||||
nav_state_t nav_state;
|
||||
|
||||
bool flag_armed;
|
||||
|
||||
bool flag_external_manual_override_ok; /**< external override non-fatal for system. Only true for fixed wing */
|
||||
@@ -86,14 +73,14 @@ struct vehicle_control_mode_s
|
||||
bool flag_system_hil_enabled;
|
||||
|
||||
bool flag_control_manual_enabled; /**< true if manual input is mixed in */
|
||||
bool flag_control_offboard_enabled; /**< true if offboard control input is on */
|
||||
bool flag_control_auto_enabled; /**< true if onboard autopilot should act */
|
||||
bool flag_control_rates_enabled; /**< true if rates are stabilized */
|
||||
bool flag_control_attitude_enabled; /**< true if attitude stabilization is mixed in */
|
||||
bool flag_control_velocity_enabled; /**< true if horizontal velocity (implies direction) is controlled */
|
||||
bool flag_control_position_enabled; /**< true if position is controlled */
|
||||
bool flag_control_altitude_enabled; /**< true if altitude is controlled */
|
||||
bool flag_control_climb_rate_enabled; /**< true if climb rate is controlled */
|
||||
bool flag_control_termination_enabled; /**< true if flighttermination is enabled */
|
||||
bool flag_control_climb_rate_enabled; /**< true if climb rate is controlled */
|
||||
bool flag_control_termination_enabled; /**< true if flighttermination is enabled */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,17 +61,21 @@
|
||||
*/
|
||||
struct vehicle_global_position_s
|
||||
{
|
||||
uint64_t timestamp; /**< time of this estimate, in microseconds since system start */
|
||||
uint64_t time_gps_usec; /**< GPS timestamp in microseconds */
|
||||
bool valid; /**< true if position satisfies validity criteria of estimator */
|
||||
uint64_t timestamp; /**< Time of this estimate, in microseconds since system start */
|
||||
|
||||
bool global_valid; /**< true if position satisfies validity criteria of estimator */
|
||||
bool baro_valid; /**< true if baro_alt is valid (vel_d is also valid in this case) */
|
||||
|
||||
uint64_t time_gps_usec; /**< GPS timestamp in microseconds */
|
||||
double lat; /**< Latitude in degrees */
|
||||
double lon; /**< Longitude in degrees */
|
||||
float alt; /**< Altitude in meters */
|
||||
float alt; /**< Altitude AMSL in meters */
|
||||
float vel_n; /**< Ground north velocity, m/s */
|
||||
float vel_e; /**< Ground east velocity, m/s */
|
||||
float vel_d; /**< Ground downside velocity, m/s */
|
||||
float yaw; /**< Yaw in radians -PI..+PI. */
|
||||
|
||||
float baro_alt; /**< Barometric altitude (not raw baro but fused with accelerometer) */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#include <stdbool.h>
|
||||
#include "../uORB.h"
|
||||
|
||||
#include <navigator/navigator_state.h>
|
||||
|
||||
/**
|
||||
* @addtogroup topics @{
|
||||
*/
|
||||
@@ -206,6 +208,7 @@ struct vehicle_status_s
|
||||
|
||||
bool rc_signal_found_once;
|
||||
bool rc_signal_lost; /**< true if RC reception lost */
|
||||
bool rc_input_blocked; /**< set if RC input should be ignored */
|
||||
|
||||
bool offboard_control_signal_found_once;
|
||||
bool offboard_control_signal_lost;
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <drivers/drv_gyro.h>
|
||||
#include <drivers/drv_accel.h>
|
||||
#include <drivers/drv_mag.h>
|
||||
#include <drivers/drv_device.h>
|
||||
|
||||
#include "systemlib/systemlib.h"
|
||||
#include "systemlib/err.h"
|
||||
@@ -65,6 +66,7 @@ __EXPORT int config_main(int argc, char *argv[]);
|
||||
static void do_gyro(int argc, char *argv[]);
|
||||
static void do_accel(int argc, char *argv[]);
|
||||
static void do_mag(int argc, char *argv[]);
|
||||
static void do_device(int argc, char *argv[]);
|
||||
|
||||
int
|
||||
config_main(int argc, char *argv[])
|
||||
@@ -72,20 +74,60 @@ config_main(int argc, char *argv[])
|
||||
if (argc >= 2) {
|
||||
if (!strcmp(argv[1], "gyro")) {
|
||||
do_gyro(argc - 2, argv + 2);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "accel")) {
|
||||
} else if (!strcmp(argv[1], "accel")) {
|
||||
do_accel(argc - 2, argv + 2);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "mag")) {
|
||||
} else if (!strcmp(argv[1], "mag")) {
|
||||
do_mag(argc - 2, argv + 2);
|
||||
} else {
|
||||
do_device(argc - 1, argv + 1);
|
||||
}
|
||||
}
|
||||
|
||||
errx(1, "expected a command, try 'gyro', 'accel', 'mag'");
|
||||
}
|
||||
|
||||
static void
|
||||
do_device(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
errx(1, "no device path provided and command provided.");
|
||||
}
|
||||
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
fd = open(argv[0], 0);
|
||||
|
||||
if (fd < 0) {
|
||||
warn("%s", argv[0]);
|
||||
errx(1, "FATAL: no device found");
|
||||
|
||||
} else {
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "block")) {
|
||||
|
||||
/* disable the device publications */
|
||||
ret = ioctl(fd, DEVIOCSPUBBLOCK, 1);
|
||||
|
||||
if (ret)
|
||||
errx(ret,"uORB publications could not be blocked");
|
||||
|
||||
} else if (argc == 2 && !strcmp(argv[1], "unblock")) {
|
||||
|
||||
/* enable the device publications */
|
||||
ret = ioctl(fd, DEVIOCSPUBBLOCK, 0);
|
||||
|
||||
if (ret)
|
||||
errx(ret,"uORB publications could not be unblocked");
|
||||
|
||||
} else {
|
||||
errx("no valid command: %s", argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
do_gyro(int argc, char *argv[])
|
||||
{
|
||||
@@ -124,7 +166,7 @@ do_gyro(int argc, char *argv[])
|
||||
if (ret)
|
||||
errx(ret,"range could not be set");
|
||||
|
||||
} else if(argc == 1 && !strcmp(argv[0], "check")) {
|
||||
} else if (argc == 1 && !strcmp(argv[0], "check")) {
|
||||
ret = ioctl(fd, GYROIOCSELFTEST, 0);
|
||||
|
||||
if (ret) {
|
||||
|
||||
@@ -102,7 +102,8 @@ load(const char *devname, const char *fname)
|
||||
if (ioctl(dev, MIXERIOCRESET, 0))
|
||||
err(1, "can't reset mixers on %s", devname);
|
||||
|
||||
load_mixer_file(fname, &buf[0], sizeof(buf));
|
||||
if (load_mixer_file(fname, &buf[0], sizeof(buf)) < 0)
|
||||
err(1, "can't load mixer: %s", fname);
|
||||
|
||||
/* XXX pass the buffer to the device */
|
||||
int ret = ioctl(dev, MIXERIOCLOADBUF, (unsigned long)buf);
|
||||
|
||||
@@ -257,7 +257,6 @@ mtd_start(char *partition_names[], unsigned n_partitions)
|
||||
|
||||
/* Now create MTD FLASH partitions */
|
||||
|
||||
warnx("Creating partitions");
|
||||
FAR struct mtd_dev_s *part[n_partitions];
|
||||
char blockname[32];
|
||||
|
||||
@@ -266,9 +265,6 @@ mtd_start(char *partition_names[], unsigned n_partitions)
|
||||
|
||||
for (offset = 0, i = 0; i < n_partitions; offset += nblocks, i++) {
|
||||
|
||||
warnx(" Partition %d. Block offset=%lu, size=%lu",
|
||||
i, (unsigned long)offset, (unsigned long)nblocks);
|
||||
|
||||
/* Create the partition */
|
||||
|
||||
part[i] = mtd_partition(mtd_dev, offset, nblocks);
|
||||
|
||||
@@ -320,7 +320,7 @@ do_set(const char* name, const char* val)
|
||||
char* end;
|
||||
f = strtod(val,&end);
|
||||
param_set(param, &f);
|
||||
printf(" -> new: %f\n", f);
|
||||
printf(" -> new: %4.4f\n", (double)f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ task_main(int argc, char *argv[])
|
||||
unsigned hash = i ^ my_id;
|
||||
unsigned len = (hash & 63) + 2;
|
||||
|
||||
int ret = dm_write(DM_KEY_WAYPOINTS_OFFBOARD, hash, DM_PERSIST_IN_FLIGHT_RESET, buffer, len);
|
||||
int ret = dm_write(DM_KEY_WAYPOINTS_OFFBOARD_1, hash, DM_PERSIST_IN_FLIGHT_RESET, buffer, len);
|
||||
warnx("ret: %d", ret);
|
||||
if (ret != len) {
|
||||
warnx("%d write failed, index %d, length %d", my_id, hash, len);
|
||||
@@ -103,7 +103,7 @@ task_main(int argc, char *argv[])
|
||||
for (unsigned i = 0; i < NUM_MISSIONS_SUPPORTED; i++) {
|
||||
unsigned hash = i ^ my_id;
|
||||
unsigned len2, len = (hash & 63) + 2;
|
||||
if ((len2 = dm_read(DM_KEY_WAYPOINTS_OFFBOARD, hash, buffer, sizeof(buffer))) < 2) {
|
||||
if ((len2 = dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, hash, buffer, sizeof(buffer))) < 2) {
|
||||
warnx("%d read failed length test, index %d", my_id, hash);
|
||||
goto fail;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ int test_dataman(int argc, char *argv[])
|
||||
free(sems);
|
||||
dm_restart(DM_INIT_REASON_IN_FLIGHT);
|
||||
for (i = 0; i < NUM_MISSIONS_SUPPORTED; i++) {
|
||||
if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD, i, buffer, sizeof(buffer)) != 0)
|
||||
if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0)
|
||||
break;
|
||||
}
|
||||
if (i >= NUM_MISSIONS_SUPPORTED) {
|
||||
@@ -173,7 +173,7 @@ int test_dataman(int argc, char *argv[])
|
||||
}
|
||||
dm_restart(DM_INIT_REASON_POWER_ON);
|
||||
for (i = 0; i < NUM_MISSIONS_SUPPORTED; i++) {
|
||||
if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD, i, buffer, sizeof(buffer)) != 0) {
|
||||
if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0) {
|
||||
warnx("Restart power-on failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -65,20 +65,20 @@ static int mixer_callback(uintptr_t handle,
|
||||
|
||||
const unsigned output_max = 8;
|
||||
static float actuator_controls[output_max];
|
||||
static bool should_arm = false;
|
||||
uint16_t r_page_servo_disarmed[output_max];
|
||||
uint16_t r_page_servo_control_min[output_max];
|
||||
uint16_t r_page_servo_control_max[output_max];
|
||||
uint16_t r_page_servos[output_max];
|
||||
uint16_t servo_predicted[output_max];
|
||||
|
||||
/*
|
||||
* PWM limit structure
|
||||
*/
|
||||
pwm_limit_t pwm_limit;
|
||||
|
||||
int test_mixer(int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
* PWM limit structure
|
||||
*/
|
||||
pwm_limit_t pwm_limit;
|
||||
static bool should_arm = false;
|
||||
uint16_t r_page_servo_disarmed[output_max];
|
||||
uint16_t r_page_servo_control_min[output_max];
|
||||
uint16_t r_page_servo_control_max[output_max];
|
||||
uint16_t r_page_servos[output_max];
|
||||
uint16_t servo_predicted[output_max];
|
||||
|
||||
warnx("testing mixer");
|
||||
|
||||
char *filename = "/etc/mixers/IO_pass.mix";
|
||||
|
||||
@@ -121,7 +121,7 @@ int test_rc(int argc, char *argv[])
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (hrt_absolute_time() - rc_input.timestamp > 100000) {
|
||||
if (hrt_absolute_time() - rc_input.timestamp_last_signal > 100000) {
|
||||
warnx("TIMEOUT, less than 10 Hz updates");
|
||||
(void)close(_rc_sub);
|
||||
return ERROR;
|
||||
|
||||
Reference in New Issue
Block a user