aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ROMFS/px4fmu_common/init.d/10016_3dr_iris4
-rw-r--r--ROMFS/px4fmu_common/init.d/4008_ardrone35
-rw-r--r--ROMFS/px4fmu_common/init.d/rc.autostart9
-rw-r--r--ROMFS/px4fmu_common/init.d/rc.interface9
-rw-r--r--ROMFS/px4fmu_common/init.d/rcS23
-rw-r--r--Tools/fetch_log.py133
-rw-r--r--Tools/px_romfs_pruner.py83
-rw-r--r--makefiles/config_px4fmu-v1_default.mk1
-rw-r--r--makefiles/config_px4fmu-v2_default.mk3
-rw-r--r--makefiles/firmware.mk4
-rw-r--r--nuttx-configs/px4fmu-v1/nsh/defconfig6
-rw-r--r--src/drivers/mb12xx/mb12xx.cpp244
-rw-r--r--src/drivers/px4fmu/fmu.cpp2
-rw-r--r--src/drivers/sf0x/module.mk40
-rw-r--r--src/drivers/sf0x/sf0x.cpp977
-rw-r--r--src/lib/launchdetection/CatapultLaunchMethod.cpp21
-rw-r--r--src/lib/launchdetection/CatapultLaunchMethod.h14
-rw-r--r--src/lib/launchdetection/LaunchDetector.cpp24
-rw-r--r--src/lib/launchdetection/LaunchDetector.h10
-rw-r--r--src/lib/launchdetection/LaunchMethod.h8
-rwxr-xr-xsrc/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp3
-rw-r--r--src/modules/fw_att_control/fw_att_control_main.cpp56
-rw-r--r--src/modules/fw_att_control/fw_att_control_params.c10
-rw-r--r--src/modules/fw_pos_control_l1/fw_pos_control_l1_main.cpp55
-rw-r--r--src/modules/gpio_led/gpio_led.c105
-rw-r--r--src/modules/navigator/geofence.cpp11
-rw-r--r--src/modules/navigator/geofence.h6
-rw-r--r--src/modules/position_estimator_inav/inertial_filter.c5
-rw-r--r--src/modules/position_estimator_inav/position_estimator_inav_main.c2
-rw-r--r--src/modules/sdlog2/logbuffer.c3
-rw-r--r--src/modules/sdlog2/sdlog2.c899
-rw-r--r--src/modules/sdlog2/sdlog2_messages.h14
-rw-r--r--src/systemcmds/dumpfile/dumpfile.c116
-rw-r--r--src/systemcmds/dumpfile/module.mk41
34 files changed, 2230 insertions, 746 deletions
diff --git a/ROMFS/px4fmu_common/init.d/10016_3dr_iris b/ROMFS/px4fmu_common/init.d/10016_3dr_iris
index d691a6f2e..f11aa704e 100644
--- a/ROMFS/px4fmu_common/init.d/10016_3dr_iris
+++ b/ROMFS/px4fmu_common/init.d/10016_3dr_iris
@@ -10,11 +10,11 @@ sh /etc/init.d/rc.mc_defaults
if [ $DO_AUTOCONFIG == yes ]
then
# TODO tune roll/pitch separately
- param set MC_ROLL_P 9.0
+ param set MC_ROLL_P 7.0
param set MC_ROLLRATE_P 0.13
param set MC_ROLLRATE_I 0.0
param set MC_ROLLRATE_D 0.004
- param set MC_PITCH_P 9.0
+ param set MC_PITCH_P 7.0
param set MC_PITCHRATE_P 0.13
param set MC_PITCHRATE_I 0.0
param set MC_PITCHRATE_D 0.004
diff --git a/ROMFS/px4fmu_common/init.d/4008_ardrone b/ROMFS/px4fmu_common/init.d/4008_ardrone
new file mode 100644
index 000000000..0f98f7b6c
--- /dev/null
+++ b/ROMFS/px4fmu_common/init.d/4008_ardrone
@@ -0,0 +1,35 @@
+#!nsh
+#
+# ARDrone
+#
+
+echo "[init] 4008_ardrone: PX4FMU on PX4IOAR carrier board"
+
+# Just use the default multicopter settings.
+sh /etc/init.d/rc.mc_defaults
+
+#
+# Load default params for this platform
+#
+if [ $DO_AUTOCONFIG == yes ]
+then
+ # Set all params here, then disable autoconfig
+ param set MC_ROLL_P 5.0
+ param set MC_ROLLRATE_P 0.13
+ param set MC_ROLLRATE_I 0.0
+ param set MC_ROLLRATE_D 0.0
+ param set MC_PITCH_P 5.0
+ param set MC_PITCHRATE_P 0.13
+ param set MC_PITCHRATE_I 0.0
+ param set MC_PITCHRATE_D 0.0
+ param set MC_YAW_P 1.0
+ param set MC_YAW_D 0.1
+ param set MC_YAWRATE_P 0.15
+ param set MC_YAWRATE_I 0.0
+ param set MC_YAWRATE_D 0.0
+ param set MC_YAW_FF 0.15
+fi
+
+set OUTPUT_MODE ardrone
+set USE_IO no
+set MIXER skip
diff --git a/ROMFS/px4fmu_common/init.d/rc.autostart b/ROMFS/px4fmu_common/init.d/rc.autostart
index 3968af58e..7aaf7133e 100644
--- a/ROMFS/px4fmu_common/init.d/rc.autostart
+++ b/ROMFS/px4fmu_common/init.d/rc.autostart
@@ -106,6 +106,15 @@ then
sh /etc/init.d/4001_quad_x
fi
+#
+# ARDrone
+#
+
+if param compare SYS_AUTOSTART 4008 8
+then
+ sh /etc/init.d/4008_ardrone
+fi
+
if param compare SYS_AUTOSTART 4010 10
then
sh /etc/init.d/4010_dji_f330
diff --git a/ROMFS/px4fmu_common/init.d/rc.interface b/ROMFS/px4fmu_common/init.d/rc.interface
index d25f01dde..7f793b219 100644
--- a/ROMFS/px4fmu_common/init.d/rc.interface
+++ b/ROMFS/px4fmu_common/init.d/rc.interface
@@ -3,7 +3,7 @@
# Script to configure control interface
#
-if [ $MIXER != none ]
+if [ $MIXER != none -a $MIXER != skip ]
then
#
# Load mixer
@@ -33,8 +33,11 @@ then
tone_alarm $TUNE_OUT_ERROR
fi
else
- echo "[init] Mixer not defined"
- tone_alarm $TUNE_OUT_ERROR
+ if [ $MIXER != skip ]
+ then
+ echo "[init] Mixer not defined"
+ tone_alarm $TUNE_OUT_ERROR
+ fi
fi
if [ $OUTPUT_MODE == fmu -o $OUTPUT_MODE == io ]
diff --git a/ROMFS/px4fmu_common/init.d/rcS b/ROMFS/px4fmu_common/init.d/rcS
index 76f021e33..57299d772 100644
--- a/ROMFS/px4fmu_common/init.d/rcS
+++ b/ROMFS/px4fmu_common/init.d/rcS
@@ -240,6 +240,11 @@ then
fi
fi
+ if [ $OUTPUT_MODE == ardrone ]
+ then
+ set FMU_MODE gpio_serial
+ fi
+
if [ $HIL == yes ]
then
set OUTPUT_MODE hil
@@ -277,9 +282,9 @@ then
tone_alarm $TUNE_OUT_ERROR
fi
fi
- if [ $OUTPUT_MODE == fmu ]
+ if [ $OUTPUT_MODE == fmu -o $OUTPUT_MODE == ardrone ]
then
- echo "[init] Use FMU PWM as primary output"
+ echo "[init] Use FMU as primary output"
if fmu mode_$FMU_MODE
then
echo "[init] FMU mode_$FMU_MODE started"
@@ -294,7 +299,7 @@ then
then
set TTYS1_BUSY yes
fi
- if [ $FMU_MODE == pwm_gpio ]
+ if [ $FMU_MODE == pwm_gpio -o $OUTPUT_MODE == ardrone ]
then
set TTYS1_BUSY yes
fi
@@ -351,7 +356,7 @@ then
fi
fi
else
- if [ $OUTPUT_MODE != fmu ]
+ if [ $OUTPUT_MODE != fmu -a $OUTPUT_MODE != ardrone ]
then
if fmu mode_$FMU_MODE
then
@@ -367,7 +372,7 @@ then
then
set TTYS1_BUSY yes
fi
- if [ $FMU_MODE == pwm_gpio ]
+ if [ $FMU_MODE == pwm_gpio -o $OUTPUT_MODE == ardrone ]
then
set TTYS1_BUSY yes
fi
@@ -428,6 +433,14 @@ then
fi
#
+ # Start up ARDrone Motor interface
+ #
+ if [ $OUTPUT_MODE == ardrone ]
+ then
+ ardrone_interface start -d /dev/ttyS1
+ fi
+
+ #
# Fixed wing setup
#
if [ $VEHICLE_TYPE == fw ]
diff --git a/Tools/fetch_log.py b/Tools/fetch_log.py
new file mode 100644
index 000000000..edcc6557c
--- /dev/null
+++ b/Tools/fetch_log.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+############################################################################
+#
+# Copyright (C) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Log fetcher
+#
+# Print list of logs:
+# python fetch_log.py
+#
+# Fetch log:
+# python fetch_log.py sess001/log001.bin
+#
+
+import serial, time, sys, os
+
+def wait_for_string(ser, s, timeout=1.0, debug=False):
+ t0 = time.time()
+ buf = []
+ res = []
+ n = 0
+ while (True):
+ c = ser.read()
+ if debug:
+ sys.stderr.write(c)
+ buf.append(c)
+ if len(buf) > len(s):
+ res.append(buf.pop(0))
+ n += 1
+ if n % 10000 == 0:
+ sys.stderr.write(str(n) + "\n")
+ if "".join(buf) == s:
+ break
+ if timeout > 0.0 and time.time() - t0 > timeout:
+ raise Exception("Timeout while waiting for: " + s)
+ return "".join(res)
+
+def exec_cmd(ser, cmd, timeout):
+ ser.write(cmd + "\n")
+ ser.flush()
+ wait_for_string(ser, cmd + "\r\n", timeout)
+ return wait_for_string(ser, "nsh> \x1b[K", timeout)
+
+def ls_dir(ser, dir, timeout=1.0):
+ res = []
+ for line in exec_cmd(ser, "ls -l " + dir, timeout).splitlines()[1:]:
+ res.append((line[20:], int(line[11:19].strip()), line[1] == "d"))
+ return res
+
+def list_logs(ser):
+ logs_dir = "/fs/microsd/log"
+ res = []
+ for d in ls_dir(ser, logs_dir):
+ if d[2]:
+ sess_dir = d[0][:-1]
+ for f in ls_dir(ser, logs_dir + "/" + sess_dir):
+ log_file = f[0]
+ log_size = f[1]
+ res.append(sess_dir + "/" + log_file + "\t" + str(log_size))
+ return "\n".join(res)
+
+def fetch_log(ser, fn, timeout):
+ cmd = "dumpfile " + fn
+ ser.write(cmd + "\n")
+ ser.flush()
+ wait_for_string(ser, cmd + "\r\n", timeout, True)
+ res = wait_for_string(ser, "\n", timeout, True)
+ data = []
+ if res.startswith("OK"):
+ size = int(res.split()[1])
+ n = 0
+ print "Reading data:"
+ while (n < size):
+ buf = ser.read(min(size - n, 8192))
+ data.append(buf)
+ n += len(buf)
+ sys.stdout.write(".")
+ sys.stdout.flush()
+ print
+ else:
+ raise Exception("Error reading log")
+ wait_for_string(ser, "nsh> \x1b[K", timeout)
+ return "".join(data)
+
+def main():
+ dev = "/dev/tty.usbmodem1"
+ ser = serial.Serial(dev, "115200", timeout=0.2)
+ if len(sys.argv) < 2:
+ print list_logs(ser)
+ else:
+ log_file = sys.argv[1]
+ data = fetch_log(ser, "/fs/microsd/log/" + log_file, 1.0)
+ try:
+ os.mkdir(log_file.split("/")[0])
+ except:
+ pass
+ fout = open(log_file, "wb")
+ fout.write(data)
+ fout.close()
+ ser.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Tools/px_romfs_pruner.py b/Tools/px_romfs_pruner.py
new file mode 100644
index 000000000..ceef9f9be
--- /dev/null
+++ b/Tools/px_romfs_pruner.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+############################################################################
+#
+# Copyright (C) 2014 PX4 Development Team. All rights reserved.
+# Author: Julian Oes <joes@student.ethz.ch>
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+
+"""
+px_romfs_pruner.py:
+Delete all comments and newlines before ROMFS is converted to an image
+"""
+
+from __future__ import print_function
+import argparse
+import os
+
+def main():
+
+ # Parse commandline arguments
+ parser = argparse.ArgumentParser(description="ROMFS pruner.")
+ parser.add_argument('--folder', action="store", help="ROMFS scratch folder.")
+ args = parser.parse_args()
+
+ print("Pruning ROMFS files.")
+
+ # go through
+ for (root, dirs, files) in os.walk(args.folder):
+ for file in files:
+ # only prune text files
+ if ".zip" in file or ".bin" in file:
+ continue
+
+ file_path = os.path.join(root, file)
+
+ # read file line by line
+ pruned_content = ""
+ with open(file_path, "r") as f:
+ for line in f:
+
+ # handle mixer files differently than startup files
+ if file_path.endswith(".mix"):
+ if line.startswith(("Z:", "M:", "R: ", "O:", "S:")):
+ pruned_content += line
+ else:
+ if not line.isspace() and not line.strip().startswith("#"):
+ pruned_content += line
+
+ # overwrite old scratch file
+ with open(file_path, "w") as f:
+ f.write(pruned_content)
+
+
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/makefiles/config_px4fmu-v1_default.mk b/makefiles/config_px4fmu-v1_default.mk
index aff614cbb..651c2ac38 100644
--- a/makefiles/config_px4fmu-v1_default.mk
+++ b/makefiles/config_px4fmu-v1_default.mk
@@ -56,6 +56,7 @@ MODULES += systemcmds/tests
MODULES += systemcmds/config
MODULES += systemcmds/nshterm
MODULES += systemcmds/hw_ver
+MODULES += systemcmds/dumpfile
#
# General system control
diff --git a/makefiles/config_px4fmu-v2_default.mk b/makefiles/config_px4fmu-v2_default.mk
index 2ad2f63a9..c80bc741d 100644
--- a/makefiles/config_px4fmu-v2_default.mk
+++ b/makefiles/config_px4fmu-v2_default.mk
@@ -27,6 +27,7 @@ MODULES += drivers/l3gd20
MODULES += drivers/hmc5883
MODULES += drivers/ms5611
MODULES += drivers/mb12xx
+MODULES += drivers/sf0x
MODULES += drivers/gps
MODULES += drivers/hil
MODULES += drivers/hott/hott_telemetry
@@ -63,6 +64,7 @@ MODULES += systemcmds/config
MODULES += systemcmds/nshterm
MODULES += systemcmds/mtd
MODULES += systemcmds/hw_ver
+MODULES += systemcmds/dumpfile
#
# General system control
@@ -71,6 +73,7 @@ MODULES += modules/commander
MODULES += modules/navigator
MODULES += modules/mavlink
MODULES += modules/mavlink_onboard
+MODULES += modules/gpio_led
#
# Estimation modules (EKF/ SO3 / other filters)
diff --git a/makefiles/firmware.mk b/makefiles/firmware.mk
index cb20d9cd1..1b646d9e0 100644
--- a/makefiles/firmware.mk
+++ b/makefiles/firmware.mk
@@ -355,6 +355,9 @@ ROMFS_OBJ = $(ROMFS_CSRC:.c=.o)
LIBS += $(ROMFS_OBJ)
LINK_DEPS += $(ROMFS_OBJ)
+# Remove all comments from startup and mixer files
+ROMFS_PRUNER = $(PX4_BASE)/Tools/px_romfs_pruner.py
+
# Turn the ROMFS image into an object file
$(ROMFS_OBJ): $(ROMFS_IMG) $(GLOBAL_DEPS)
$(call BIN_TO_OBJ,$<,$@,romfs_img)
@@ -372,6 +375,7 @@ ifneq ($(ROMFS_EXTRA_FILES),)
$(Q) $(MKDIR) -p $(ROMFS_SCRATCH)/extras
$(Q) $(COPY) $(ROMFS_EXTRA_FILES) $(ROMFS_SCRATCH)/extras
endif
+ $(Q) $(PYTHON) -u $(ROMFS_PRUNER) --folder $(ROMFS_SCRATCH)
EXTRA_CLEANS += $(ROMGS_OBJ) $(ROMFS_IMG)
diff --git a/nuttx-configs/px4fmu-v1/nsh/defconfig b/nuttx-configs/px4fmu-v1/nsh/defconfig
index 1dc96b3c3..20edc68aa 100644
--- a/nuttx-configs/px4fmu-v1/nsh/defconfig
+++ b/nuttx-configs/px4fmu-v1/nsh/defconfig
@@ -417,7 +417,7 @@ CONFIG_PREALLOC_TIMERS=50
#
# Stack and heap information
#
-CONFIG_IDLETHREAD_STACKSIZE=6000
+CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_USERMAIN_STACKSIZE=4096
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_PTHREAD_STACK_DEFAULT=2048
@@ -720,11 +720,11 @@ CONFIG_SCHED_WORKQUEUE=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WORKPRIORITY=192
CONFIG_SCHED_WORKPERIOD=5000
-CONFIG_SCHED_WORKSTACKSIZE=4000
+CONFIG_SCHED_WORKSTACKSIZE=2048
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_LPWORKPRIORITY=50
CONFIG_SCHED_LPWORKPERIOD=50000
-CONFIG_SCHED_LPWORKSTACKSIZE=4000
+CONFIG_SCHED_LPWORKSTACKSIZE=2048
# CONFIG_LIB_KBDCODEC is not set
# CONFIG_LIB_SLCDCODEC is not set
diff --git a/src/drivers/mb12xx/mb12xx.cpp b/src/drivers/mb12xx/mb12xx.cpp
index c910e2890..5adb8cf69 100644
--- a/src/drivers/mb12xx/mb12xx.cpp
+++ b/src/drivers/mb12xx/mb12xx.cpp
@@ -37,7 +37,7 @@
*
* Driver for the Maxbotix sonar range finders connected via I2C.
*/
-
+
#include <nuttx/config.h>
#include <drivers/device/i2c.h>
@@ -84,7 +84,7 @@
/* Device limits */
#define MB12XX_MIN_DISTANCE (0.20f)
#define MB12XX_MAX_DISTANCE (7.65f)
-
+
#define MB12XX_CONVERSION_INTERVAL 60000 /* 60ms */
/* oddly, ERROR is not defined for c++ */
@@ -102,17 +102,17 @@ class MB12XX : public device::I2C
public:
MB12XX(int bus = MB12XX_BUS, int address = MB12XX_BASEADDR);
virtual ~MB12XX();
-
+
virtual int init();
-
+
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
-
+
/**
* Diagnostics - print some basic information about the driver.
*/
void print_info();
-
+
protected:
virtual int probe();
@@ -124,13 +124,13 @@ private:
bool _sensor_ok;
int _measure_ticks;
bool _collect_phase;
-
+
orb_advert_t _range_finder_topic;
perf_counter_t _sample_perf;
perf_counter_t _comms_errors;
perf_counter_t _buffer_overflows;
-
+
/**
* Test whether the device supported by the driver is present at a
* specific address.
@@ -139,7 +139,7 @@ private:
* @return True if the device is present.
*/
int probe_address(uint8_t address);
-
+
/**
* Initialise the automatic measurement state machine and start it.
*
@@ -147,12 +147,12 @@ private:
* to make it more aggressive about resetting the bus in case of errors.
*/
void start();
-
+
/**
* Stop the automatic measurement state machine.
*/
void stop();
-
+
/**
* Set the min and max distance thresholds if you want the end points of the sensors
* range to be brought in at all, otherwise it will use the defaults MB12XX_MIN_DISTANCE
@@ -162,7 +162,7 @@ private:
void set_maximum_distance(float max);
float get_minimum_distance();
float get_maximum_distance();
-
+
/**
* Perform a poll cycle; collect from the previous measurement
* and start a new one.
@@ -177,8 +177,8 @@ private:
* @param arg Instance pointer for the driver that is polling.
*/
static void cycle_trampoline(void *arg);
-
-
+
+
};
/*
@@ -200,8 +200,8 @@ MB12XX::MB12XX(int bus, int address) :
_buffer_overflows(perf_alloc(PC_COUNT, "mb12xx_buffer_overflows"))
{
// enable debug() calls
- _debug_enabled = true;
-
+ _debug_enabled = false;
+
// work_cancel in the dtor will explode if we don't do this...
memset(&_work, 0, sizeof(_work));
}
@@ -212,8 +212,9 @@ MB12XX::~MB12XX()
stop();
/* free any existing reports */
- if (_reports != nullptr)
+ if (_reports != nullptr) {
delete _reports;
+ }
}
int
@@ -222,22 +223,25 @@ MB12XX::init()
int ret = ERROR;
/* do I2C init (and probe) first */
- if (I2C::init() != OK)
+ if (I2C::init() != OK) {
goto out;
+ }
/* allocate basic report buffers */
_reports = new RingBuffer(2, sizeof(range_finder_report));
- if (_reports == nullptr)
+ if (_reports == nullptr) {
goto out;
+ }
/* get a publish handle on the range finder topic */
struct range_finder_report zero_report;
memset(&zero_report, 0, sizeof(zero_report));
_range_finder_topic = orb_advertise(ORB_ID(sensor_range_finder), &zero_report);
- if (_range_finder_topic < 0)
+ if (_range_finder_topic < 0) {
debug("failed to create sensor_range_finder object. Did you start uOrb?");
+ }
ret = OK;
/* sensor is ok, but we don't really know if it is within range */
@@ -256,13 +260,13 @@ void
MB12XX::set_minimum_distance(float min)
{
_min_distance = min;
-}
+}
void
MB12XX::set_maximum_distance(float max)
{
_max_distance = max;
-}
+}
float
MB12XX::get_minimum_distance()
@@ -284,20 +288,20 @@ MB12XX::ioctl(struct file *filp, int cmd, unsigned long arg)
case SENSORIOCSPOLLRATE: {
switch (arg) {
- /* switching to manual polling */
+ /* switching to manual polling */
case SENSOR_POLLRATE_MANUAL:
stop();
_measure_ticks = 0;
return OK;
- /* external signalling (DRDY) not supported */
+ /* external signalling (DRDY) not supported */
case SENSOR_POLLRATE_EXTERNAL:
- /* zero would be bad */
+ /* zero would be bad */
case 0:
return -EINVAL;
- /* set default/max polling rate */
+ /* set default/max polling rate */
case SENSOR_POLLRATE_MAX:
case SENSOR_POLLRATE_DEFAULT: {
/* do we need to start internal polling? */
@@ -307,13 +311,14 @@ MB12XX::ioctl(struct file *filp, int cmd, unsigned long arg)
_measure_ticks = USEC2TICK(MB12XX_CONVERSION_INTERVAL);
/* if we need to start the poll state machine, do it */
- if (want_start)
+ if (want_start) {
start();
+ }
return OK;
}
- /* adjust to a legal polling interval in Hz */
+ /* adjust to a legal polling interval in Hz */
default: {
/* do we need to start internal polling? */
bool want_start = (_measure_ticks == 0);
@@ -322,15 +327,17 @@ MB12XX::ioctl(struct file *filp, int cmd, unsigned long arg)
unsigned ticks = USEC2TICK(1000000 / arg);
/* check against maximum rate */
- if (ticks < USEC2TICK(MB12XX_CONVERSION_INTERVAL))
+ if (ticks < USEC2TICK(MB12XX_CONVERSION_INTERVAL)) {
return -EINVAL;
+ }
/* update interval for next measurement */
_measure_ticks = ticks;
/* if we need to start the poll state machine, do it */
- if (want_start)
+ if (want_start) {
start();
+ }
return OK;
}
@@ -338,45 +345,49 @@ MB12XX::ioctl(struct file *filp, int cmd, unsigned long arg)
}
case SENSORIOCGPOLLRATE:
- if (_measure_ticks == 0)
+ if (_measure_ticks == 0) {
return SENSOR_POLLRATE_MANUAL;
+ }
return (1000 / _measure_ticks);
case SENSORIOCSQUEUEDEPTH: {
- /* lower bound is mandatory, upper bound is a sanity check */
- if ((arg < 1) || (arg > 100))
- return -EINVAL;
-
- irqstate_t flags = irqsave();
- if (!_reports->resize(arg)) {
+ /* lower bound is mandatory, upper bound is a sanity check */
+ if ((arg < 1) || (arg > 100)) {
+ return -EINVAL;
+ }
+
+ irqstate_t flags = irqsave();
+
+ if (!_reports->resize(arg)) {
+ irqrestore(flags);
+ return -ENOMEM;
+ }
+
irqrestore(flags);
- return -ENOMEM;
+
+ return OK;
}
- irqrestore(flags);
-
- return OK;
- }
case SENSORIOCGQUEUEDEPTH:
return _reports->size();
-
+
case SENSORIOCRESET:
/* XXX implement this */
return -EINVAL;
-
- case RANGEFINDERIOCSETMINIUMDISTANCE:
- {
- set_minimum_distance(*(float *)arg);
- return 0;
- }
- break;
- case RANGEFINDERIOCSETMAXIUMDISTANCE:
- {
- set_maximum_distance(*(float *)arg);
- return 0;
- }
- break;
+
+ case RANGEFINDERIOCSETMINIUMDISTANCE: {
+ set_minimum_distance(*(float *)arg);
+ return 0;
+ }
+ break;
+
+ case RANGEFINDERIOCSETMAXIUMDISTANCE: {
+ set_maximum_distance(*(float *)arg);
+ return 0;
+ }
+ break;
+
default:
/* give it to the superclass */
return I2C::ioctl(filp, cmd, arg);
@@ -391,8 +402,9 @@ MB12XX::read(struct file *filp, char *buffer, size_t buflen)
int ret = 0;
/* buffer must be large enough */
- if (count < 1)
+ if (count < 1) {
return -ENOSPC;
+ }
/* if automatic measurement is enabled */
if (_measure_ticks > 0) {
@@ -453,14 +465,14 @@ MB12XX::measure()
uint8_t cmd = MB12XX_TAKE_RANGE_REG;
ret = transfer(&cmd, 1, nullptr, 0);
- if (OK != ret)
- {
+ if (OK != ret) {
perf_count(_comms_errors);
log("i2c::transfer returned %d", ret);
return ret;
}
+
ret = OK;
-
+
return ret;
}
@@ -468,32 +480,31 @@ int
MB12XX::collect()
{
int ret = -EIO;
-
+
/* read from the sensor */
uint8_t val[2] = {0, 0};
-
+
perf_begin(_sample_perf);
-
+
ret = transfer(nullptr, 0, &val[0], 2);
-
- if (ret < 0)
- {
+
+ if (ret < 0) {
log("error reading from sensor: %d", ret);
perf_count(_comms_errors);
perf_end(_sample_perf);
return ret;
}
-
+
uint16_t distance = val[0] << 8 | val[1];
- float si_units = (distance * 1.0f)/ 100.0f; /* cm to m */
+ float si_units = (distance * 1.0f) / 100.0f; /* cm to m */
struct range_finder_report report;
/* this should be fairly close to the end of the measurement, so the best approximation of the time */
report.timestamp = hrt_absolute_time();
- report.error_count = perf_event_count(_comms_errors);
+ report.error_count = perf_event_count(_comms_errors);
report.distance = si_units;
report.valid = si_units > get_minimum_distance() && si_units < get_maximum_distance() ? 1 : 0;
-
+
/* publish it */
orb_publish(ORB_ID(sensor_range_finder), _range_finder_topic, &report);
@@ -519,17 +530,19 @@ MB12XX::start()
/* schedule a cycle to start things */
work_queue(HPWORK, &_work, (worker_t)&MB12XX::cycle_trampoline, this, 1);
-
+
/* notify about state change */
struct subsystem_info_s info = {
true,
true,
true,
- SUBSYSTEM_TYPE_RANGEFINDER};
+ SUBSYSTEM_TYPE_RANGEFINDER
+ };
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);
}
@@ -583,8 +596,9 @@ MB12XX::cycle()
}
/* measurement phase */
- if (OK != measure())
+ if (OK != measure()) {
log("measure error");
+ }
/* next phase is collection */
_collect_phase = true;
@@ -635,33 +649,37 @@ start()
{
int fd;
- if (g_dev != nullptr)
+ if (g_dev != nullptr) {
errx(1, "already started");
+ }
/* create the driver */
g_dev = new MB12XX(MB12XX_BUS);
- if (g_dev == nullptr)
+ if (g_dev == nullptr) {
goto fail;
+ }
- if (OK != g_dev->init())
+ if (OK != g_dev->init()) {
goto fail;
+ }
/* set the poll rate to default, starts automatic data collection */
fd = open(RANGE_FINDER_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
goto fail;
+ }
- if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
goto fail;
+ }
exit(0);
fail:
- if (g_dev != nullptr)
- {
+ if (g_dev != nullptr) {
delete g_dev;
g_dev = nullptr;
}
@@ -674,15 +692,14 @@ fail:
*/
void stop()
{
- if (g_dev != nullptr)
- {
+ if (g_dev != nullptr) {
delete g_dev;
g_dev = nullptr;
- }
- else
- {
+
+ } else {
errx(1, "driver not running");
}
+
exit(0);
}
@@ -700,22 +717,25 @@ test()
int fd = open(RANGE_FINDER_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
err(1, "%s open failed (try 'mb12xx start' if the driver is not running", RANGE_FINDER_DEVICE_PATH);
+ }
/* do a simple demand read */
sz = read(fd, &report, sizeof(report));
- if (sz != sizeof(report))
+ if (sz != sizeof(report)) {
err(1, "immediate read failed");
+ }
warnx("single read");
warnx("measurement: %0.2f m", (double)report.distance);
warnx("time: %lld", report.timestamp);
/* start the sensor polling at 2Hz */
- if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2))
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2)) {
errx(1, "failed to set 2Hz poll rate");
+ }
/* read the sensor 5x and report each value */
for (unsigned i = 0; i < 5; i++) {
@@ -726,20 +746,27 @@ test()
fds.events = POLLIN;
ret = poll(&fds, 1, 2000);
- if (ret != 1)
+ if (ret != 1) {
errx(1, "timed out waiting for sensor data");
+ }
/* now go get it */
sz = read(fd, &report, sizeof(report));
- if (sz != sizeof(report))
+ if (sz != sizeof(report)) {
err(1, "periodic read failed");
+ }
warnx("periodic read %u", i);
warnx("measurement: %0.3f", (double)report.distance);
warnx("time: %lld", report.timestamp);
}
+ /* reset the sensor polling to default rate */
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) {
+ errx(1, "failed to set default poll rate");
+ }
+
errx(0, "PASS");
}
@@ -751,14 +778,17 @@ reset()
{
int fd = open(RANGE_FINDER_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
err(1, "failed ");
+ }
- if (ioctl(fd, SENSORIOCRESET, 0) < 0)
+ if (ioctl(fd, SENSORIOCRESET, 0) < 0) {
err(1, "driver reset failed");
+ }
- if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
err(1, "driver poll restart failed");
+ }
exit(0);
}
@@ -769,8 +799,9 @@ reset()
void
info()
{
- if (g_dev == nullptr)
+ if (g_dev == nullptr) {
errx(1, "driver not running");
+ }
printf("state @ %p\n", g_dev);
g_dev->print_info();
@@ -786,32 +817,37 @@ mb12xx_main(int argc, char *argv[])
/*
* Start/load the driver.
*/
- if (!strcmp(argv[1], "start"))
+ if (!strcmp(argv[1], "start")) {
mb12xx::start();
-
- /*
- * Stop the driver
- */
- if (!strcmp(argv[1], "stop"))
- mb12xx::stop();
+ }
+
+ /*
+ * Stop the driver
+ */
+ if (!strcmp(argv[1], "stop")) {
+ mb12xx::stop();
+ }
/*
* Test the driver/device.
*/
- if (!strcmp(argv[1], "test"))
+ if (!strcmp(argv[1], "test")) {
mb12xx::test();
+ }
/*
* Reset the driver.
*/
- if (!strcmp(argv[1], "reset"))
+ if (!strcmp(argv[1], "reset")) {
mb12xx::reset();
+ }
/*
* Print driver information.
*/
- if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status"))
+ if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
mb12xx::info();
+ }
errx(1, "unrecognized command, try 'start', 'test', 'reset' or 'info'");
}
diff --git a/src/drivers/px4fmu/fmu.cpp b/src/drivers/px4fmu/fmu.cpp
index 0fbd84924..a70ff6c5c 100644
--- a/src/drivers/px4fmu/fmu.cpp
+++ b/src/drivers/px4fmu/fmu.cpp
@@ -1714,7 +1714,7 @@ fmu_main(int argc, char *argv[])
}
- fprintf(stderr, "FMU: unrecognised command, try:\n");
+ fprintf(stderr, "FMU: unrecognised command %s, try:\n", verb);
#if defined(CONFIG_ARCH_BOARD_PX4FMU_V1)
fprintf(stderr, " mode_gpio, mode_serial, mode_pwm, mode_gpio_serial, mode_pwm_serial, mode_pwm_gpio, test\n");
#elif defined(CONFIG_ARCH_BOARD_PX4FMU_V2)
diff --git a/src/drivers/sf0x/module.mk b/src/drivers/sf0x/module.mk
new file mode 100644
index 000000000..dc93a90e7
--- /dev/null
+++ b/src/drivers/sf0x/module.mk
@@ -0,0 +1,40 @@
+############################################################################
+#
+# 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.
+#
+############################################################################
+
+#
+# Makefile to build the Lightware laser range finder driver.
+#
+
+MODULE_COMMAND = sf0x
+
+SRCS = sf0x.cpp
diff --git a/src/drivers/sf0x/sf0x.cpp b/src/drivers/sf0x/sf0x.cpp
new file mode 100644
index 000000000..70cd1ab1e
--- /dev/null
+++ b/src/drivers/sf0x/sf0x.cpp
@@ -0,0 +1,977 @@
+/****************************************************************************
+ *
+ * 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 sf0x.cpp
+ * @author Lorenz Meier <lm@inf.ethz.ch>
+ * @author Greg Hulands
+ *
+ * Driver for the Lightware SF0x laser rangefinder series
+ */
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <string.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h>
+#include <termios.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/clock.h>
+
+#include <systemlib/perf_counter.h>
+#include <systemlib/err.h>
+
+#include <drivers/drv_hrt.h>
+#include <drivers/drv_range_finder.h>
+#include <drivers/device/device.h>
+#include <drivers/device/ringbuffer.h>
+
+#include <uORB/uORB.h>
+#include <uORB/topics/subsystem_info.h>
+
+#include <board_config.h>
+
+/* Configuration Constants */
+
+/* oddly, ERROR is not defined for c++ */
+#ifdef ERROR
+# undef ERROR
+#endif
+static const int ERROR = -1;
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+# error This requires CONFIG_SCHED_WORKQUEUE.
+#endif
+
+#define SF0X_CONVERSION_INTERVAL 83334
+#define SF0X_TAKE_RANGE_REG 'd'
+#define SF02F_MIN_DISTANCE 0.0f
+#define SF02F_MAX_DISTANCE 40.0f
+#define SF0X_DEFAULT_PORT "/dev/ttyS2"
+
+class SF0X : public device::CDev
+{
+public:
+ SF0X(const char *port = SF0X_DEFAULT_PORT);
+ virtual ~SF0X();
+
+ virtual int init();
+
+ virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
+ virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
+
+ /**
+ * Diagnostics - print some basic information about the driver.
+ */
+ void print_info();
+
+protected:
+ virtual int probe();
+
+private:
+ float _min_distance;
+ float _max_distance;
+ work_s _work;
+ RingBuffer *_reports;
+ bool _sensor_ok;
+ int _measure_ticks;
+ bool _collect_phase;
+ int _fd;
+ char _linebuf[10];
+ unsigned _linebuf_index;
+ hrt_abstime _last_read;
+
+ orb_advert_t _range_finder_topic;
+
+ perf_counter_t _sample_perf;
+ perf_counter_t _comms_errors;
+ perf_counter_t _buffer_overflows;
+
+ /**
+ * Initialise the automatic measurement state machine and start it.
+ *
+ * @note This function is called at open and error time. It might make sense
+ * to make it more aggressive about resetting the bus in case of errors.
+ */
+ void start();
+
+ /**
+ * Stop the automatic measurement state machine.
+ */
+ void stop();
+
+ /**
+ * Set the min and max distance thresholds if you want the end points of the sensors
+ * range to be brought in at all, otherwise it will use the defaults SF0X_MIN_DISTANCE
+ * and SF0X_MAX_DISTANCE
+ */
+ void set_minimum_distance(float min);
+ void set_maximum_distance(float max);
+ float get_minimum_distance();
+ float get_maximum_distance();
+
+ /**
+ * Perform a poll cycle; collect from the previous measurement
+ * and start a new one.
+ */
+ void cycle();
+ int measure();
+ int collect();
+ /**
+ * Static trampoline from the workq context; because we don't have a
+ * generic workq wrapper yet.
+ *
+ * @param arg Instance pointer for the driver that is polling.
+ */
+ static void cycle_trampoline(void *arg);
+
+
+};
+
+/*
+ * Driver 'main' command.
+ */
+extern "C" __EXPORT int sf0x_main(int argc, char *argv[]);
+
+SF0X::SF0X(const char *port) :
+ CDev("SF0X", RANGE_FINDER_DEVICE_PATH),
+ _min_distance(SF02F_MIN_DISTANCE),
+ _max_distance(SF02F_MAX_DISTANCE),
+ _reports(nullptr),
+ _sensor_ok(false),
+ _measure_ticks(0),
+ _collect_phase(false),
+ _fd(-1),
+ _linebuf_index(0),
+ _last_read(0),
+ _range_finder_topic(-1),
+ _sample_perf(perf_alloc(PC_ELAPSED, "sf0x_read")),
+ _comms_errors(perf_alloc(PC_COUNT, "sf0x_comms_errors")),
+ _buffer_overflows(perf_alloc(PC_COUNT, "sf0x_buffer_overflows"))
+{
+ /* open fd */
+ _fd = ::open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+ if (_fd < 0) {
+ warnx("FAIL: laser fd");
+ }
+
+ /* tell it to stop auto-triggering */
+ char stop_auto = ' ';
+ (void)::write(_fd, &stop_auto, 1);
+ usleep(100);
+ (void)::write(_fd, &stop_auto, 1);
+
+ struct termios uart_config;
+
+ int termios_state;
+
+ /* fill the struct for the new configuration */
+ tcgetattr(_fd, &uart_config);
+
+ /* clear ONLCR flag (which appends a CR for every LF) */
+ uart_config.c_oflag &= ~ONLCR;
+ /* no parity, one stop bit */
+ uart_config.c_cflag &= ~(CSTOPB | PARENB);
+
+ unsigned speed = B9600;
+
+ /* set baud rate */
+ if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
+ warnx("ERR CFG: %d ISPD", termios_state);
+ }
+
+ if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
+ warnx("ERR CFG: %d OSPD\n", termios_state);
+ }
+
+ if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) {
+ warnx("ERR baud %d ATTR", termios_state);
+ }
+
+ // disable debug() calls
+ _debug_enabled = false;
+
+ // work_cancel in the dtor will explode if we don't do this...
+ memset(&_work, 0, sizeof(_work));
+}
+
+SF0X::~SF0X()
+{
+ /* make sure we are truly inactive */
+ stop();
+
+ /* free any existing reports */
+ if (_reports != nullptr) {
+ delete _reports;
+ }
+}
+
+int
+SF0X::init()
+{
+ int ret = ERROR;
+ unsigned i = 0;
+
+ /* do regular cdev init */
+ if (CDev::init() != OK) {
+ goto out;
+ }
+
+ /* allocate basic report buffers */
+ _reports = new RingBuffer(2, sizeof(range_finder_report));
+
+ if (_reports == nullptr) {
+ warnx("mem err");
+ goto out;
+ }
+
+ /* get a publish handle on the range finder topic */
+ struct range_finder_report zero_report;
+ memset(&zero_report, 0, sizeof(zero_report));
+ _range_finder_topic = orb_advertise(ORB_ID(sensor_range_finder), &zero_report);
+
+ if (_range_finder_topic < 0) {
+ warnx("advert err");
+ }
+
+ /* attempt to get a measurement 5 times */
+ while (ret != OK && i < 5) {
+
+ if (measure()) {
+ ret = ERROR;
+ _sensor_ok = false;
+ }
+
+ usleep(100000);
+
+ if (collect()) {
+ ret = ERROR;
+ _sensor_ok = false;
+
+ } else {
+ ret = OK;
+ /* sensor is ok, but we don't really know if it is within range */
+ _sensor_ok = true;
+ }
+
+ i++;
+ }
+
+ /* close the fd */
+ ::close(_fd);
+ _fd = -1;
+out:
+ return ret;
+}
+
+int
+SF0X::probe()
+{
+ return measure();
+}
+
+void
+SF0X::set_minimum_distance(float min)
+{
+ _min_distance = min;
+}
+
+void
+SF0X::set_maximum_distance(float max)
+{
+ _max_distance = max;
+}
+
+float
+SF0X::get_minimum_distance()
+{
+ return _min_distance;
+}
+
+float
+SF0X::get_maximum_distance()
+{
+ return _max_distance;
+}
+
+int
+SF0X::ioctl(struct file *filp, int cmd, unsigned long arg)
+{
+ switch (cmd) {
+
+ case SENSORIOCSPOLLRATE: {
+ switch (arg) {
+
+ /* switching to manual polling */
+ case SENSOR_POLLRATE_MANUAL:
+ stop();
+ _measure_ticks = 0;
+ return OK;
+
+ /* external signalling (DRDY) not supported */
+ case SENSOR_POLLRATE_EXTERNAL:
+
+ /* zero would be bad */
+ case 0:
+ return -EINVAL;
+
+ /* set default/max polling rate */
+ case SENSOR_POLLRATE_MAX:
+ case SENSOR_POLLRATE_DEFAULT: {
+ /* do we need to start internal polling? */
+ bool want_start = (_measure_ticks == 0);
+
+ /* set interval for next measurement to minimum legal value */
+ _measure_ticks = USEC2TICK(SF0X_CONVERSION_INTERVAL);
+
+ /* if we need to start the poll state machine, do it */
+ if (want_start) {
+ start();
+ }
+
+ return OK;
+ }
+
+ /* adjust to a legal polling interval in Hz */
+ default: {
+ /* do we need to start internal polling? */
+ bool want_start = (_measure_ticks == 0);
+
+ /* convert hz to tick interval via microseconds */
+ unsigned ticks = USEC2TICK(1000000 / arg);
+
+ /* check against maximum rate */
+ if (ticks < USEC2TICK(SF0X_CONVERSION_INTERVAL)) {
+ return -EINVAL;
+ }
+
+ /* update interval for next measurement */
+ _measure_ticks = ticks;
+
+ /* if we need to start the poll state machine, do it */
+ if (want_start) {
+ start();
+ }
+
+ return OK;
+ }
+ }
+ }
+
+ case SENSORIOCGPOLLRATE:
+ if (_measure_ticks == 0) {
+ return SENSOR_POLLRATE_MANUAL;
+ }
+
+ return (1000 / _measure_ticks);
+
+ case SENSORIOCSQUEUEDEPTH: {
+ /* lower bound is mandatory, upper bound is a sanity check */
+ if ((arg < 1) || (arg > 100)) {
+ return -EINVAL;
+ }
+
+ irqstate_t flags = irqsave();
+
+ if (!_reports->resize(arg)) {
+ irqrestore(flags);
+ return -ENOMEM;
+ }
+
+ irqrestore(flags);
+
+ return OK;
+ }
+
+ case SENSORIOCGQUEUEDEPTH:
+ return _reports->size();
+
+ case SENSORIOCRESET:
+ /* XXX implement this */
+ return -EINVAL;
+
+ case RANGEFINDERIOCSETMINIUMDISTANCE: {
+ set_minimum_distance(*(float *)arg);
+ return 0;
+ }
+ break;
+
+ case RANGEFINDERIOCSETMAXIUMDISTANCE: {
+ set_maximum_distance(*(float *)arg);
+ return 0;
+ }
+ break;
+
+ default:
+ /* give it to the superclass */
+ return CDev::ioctl(filp, cmd, arg);
+ }
+}
+
+ssize_t
+SF0X::read(struct file *filp, char *buffer, size_t buflen)
+{
+ unsigned count = buflen / sizeof(struct range_finder_report);
+ struct range_finder_report *rbuf = reinterpret_cast<struct range_finder_report *>(buffer);
+ int ret = 0;
+
+ /* buffer must be large enough */
+ if (count < 1) {
+ return -ENOSPC;
+ }
+
+ /* if automatic measurement is enabled */
+ if (_measure_ticks > 0) {
+
+ /*
+ * While there is space in the caller's buffer, and reports, copy them.
+ * Note that we may be pre-empted by the workq thread while we are doing this;
+ * we are careful to avoid racing with them.
+ */
+ while (count--) {
+ if (_reports->get(rbuf)) {
+ ret += sizeof(*rbuf);
+ rbuf++;
+ }
+ }
+
+ /* if there was no data, warn the caller */
+ return ret ? ret : -EAGAIN;
+ }
+
+ /* manual measurement - run one conversion */
+ do {
+ _reports->flush();
+
+ /* trigger a measurement */
+ if (OK != measure()) {
+ ret = -EIO;
+ break;
+ }
+
+ /* wait for it to complete */
+ usleep(SF0X_CONVERSION_INTERVAL);
+
+ /* run the collection phase */
+ if (OK != collect()) {
+ ret = -EIO;
+ break;
+ }
+
+ /* state machine will have generated a report, copy it out */
+ if (_reports->get(rbuf)) {
+ ret = sizeof(*rbuf);
+ }
+
+ } while (0);
+
+ return ret;
+}
+
+int
+SF0X::measure()
+{
+ int ret;
+
+ /*
+ * Send the command to begin a measurement.
+ */
+ char cmd = SF0X_TAKE_RANGE_REG;
+ ret = ::write(_fd, &cmd, 1);
+
+ if (ret != sizeof(cmd)) {
+ perf_count(_comms_errors);
+ log("write fail %d", ret);
+ return ret;
+ }
+
+ ret = OK;
+
+ return ret;
+}
+
+int
+SF0X::collect()
+{
+ int ret;
+
+ perf_begin(_sample_perf);
+
+ /* clear buffer if last read was too long ago */
+ uint64_t read_elapsed = hrt_elapsed_time(&_last_read);
+
+ if (read_elapsed > (SF0X_CONVERSION_INTERVAL * 2)) {
+ _linebuf_index = 0;
+ }
+
+ /* read from the sensor (uart buffer) */
+ ret = ::read(_fd, &_linebuf[_linebuf_index], sizeof(_linebuf) - _linebuf_index);
+
+ if (ret < 0) {
+ _linebuf[sizeof(_linebuf) - 1] = '\0';
+ debug("read err: %d lbi: %d buf: %s", ret, (int)_linebuf_index, _linebuf);
+ perf_count(_comms_errors);
+ perf_end(_sample_perf);
+
+ /* only throw an error if we time out */
+ if (read_elapsed > (SF0X_CONVERSION_INTERVAL * 2)) {
+ return ret;
+
+ } else {
+ return -EAGAIN;
+ }
+ }
+
+ _linebuf_index += ret;
+
+ if (_linebuf_index >= sizeof(_linebuf)) {
+ _linebuf_index = 0;
+ }
+
+ _last_read = hrt_absolute_time();
+
+ if (_linebuf[_linebuf_index - 2] != '\r' || _linebuf[_linebuf_index - 1] != '\n') {
+ /* incomplete read, reschedule ourselves */
+ return -EAGAIN;
+ }
+
+ char *end;
+ float si_units;
+ bool valid;
+
+ /* enforce line ending */
+ _linebuf[sizeof(_linebuf) - 1] = '\0';
+
+ if (_linebuf[0] == '-' && _linebuf[1] == '-' && _linebuf[2] == '.') {
+ si_units = -1.0f;
+ valid = false;
+
+ } else {
+ si_units = strtod(_linebuf, &end);
+ valid = true;
+ }
+
+ debug("val (float): %8.4f, raw: %s\n", si_units, _linebuf);
+
+ /* done with this chunk, resetting */
+ _linebuf_index = 0;
+
+ struct range_finder_report report;
+
+ /* this should be fairly close to the end of the measurement, so the best approximation of the time */
+ report.timestamp = hrt_absolute_time();
+ report.error_count = perf_event_count(_comms_errors);
+ report.distance = si_units;
+ report.valid = valid && (si_units > get_minimum_distance() && si_units < get_maximum_distance() ? 1 : 0);
+
+ /* publish it */
+ orb_publish(ORB_ID(sensor_range_finder), _range_finder_topic, &report);
+
+ if (_reports->force(&report)) {
+ perf_count(_buffer_overflows);
+ }
+
+ /* notify anyone waiting for data */
+ poll_notify(POLLIN);
+
+ ret = OK;
+
+ perf_end(_sample_perf);
+ return ret;
+}
+
+void
+SF0X::start()
+{
+ /* reset the report ring and state machine */
+ _collect_phase = false;
+ _reports->flush();
+
+ /* schedule a cycle to start things */
+ work_queue(HPWORK, &_work, (worker_t)&SF0X::cycle_trampoline, this, 1);
+
+ // /* notify about state change */
+ // struct subsystem_info_s info = {
+ // true,
+ // true,
+ // true,
+ // SUBSYSTEM_TYPE_RANGEFINDER
+ // };
+ // 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);
+ // }
+}
+
+void
+SF0X::stop()
+{
+ work_cancel(HPWORK, &_work);
+}
+
+void
+SF0X::cycle_trampoline(void *arg)
+{
+ SF0X *dev = static_cast<SF0X *>(arg);
+
+ dev->cycle();
+}
+
+void
+SF0X::cycle()
+{
+ /* fds initialized? */
+ if (_fd < 0) {
+ /* open fd */
+ _fd = ::open(SF0X_DEFAULT_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ }
+
+ /* collection phase? */
+ if (_collect_phase) {
+
+ /* perform collection */
+ int collect_ret = collect();
+
+ if (collect_ret == -EAGAIN) {
+ /* reschedule to grab the missing bits, time to transmit 10 bytes @9600 bps */
+ work_queue(HPWORK,
+ &_work,
+ (worker_t)&SF0X::cycle_trampoline,
+ this,
+ USEC2TICK(1100));
+ return;
+ }
+
+ if (OK != collect_ret) {
+ log("collection error");
+ /* restart the measurement state machine */
+ start();
+ return;
+ }
+
+ /* next phase is measurement */
+ _collect_phase = false;
+
+ /*
+ * Is there a collect->measure gap?
+ */
+ if (_measure_ticks > USEC2TICK(SF0X_CONVERSION_INTERVAL)) {
+
+ /* schedule a fresh cycle call when we are ready to measure again */
+ work_queue(HPWORK,
+ &_work,
+ (worker_t)&SF0X::cycle_trampoline,
+ this,
+ _measure_ticks - USEC2TICK(SF0X_CONVERSION_INTERVAL));
+
+ return;
+ }
+ }
+
+ /* measurement phase */
+ if (OK != measure()) {
+ log("measure error");
+ }
+
+ /* next phase is collection */
+ _collect_phase = true;
+
+ /* schedule a fresh cycle call when the measurement is done */
+ work_queue(HPWORK,
+ &_work,
+ (worker_t)&SF0X::cycle_trampoline,
+ this,
+ USEC2TICK(SF0X_CONVERSION_INTERVAL));
+}
+
+void
+SF0X::print_info()
+{
+ perf_print_counter(_sample_perf);
+ perf_print_counter(_comms_errors);
+ perf_print_counter(_buffer_overflows);
+ printf("poll interval: %d ticks\n", _measure_ticks);
+ _reports->print_info("report queue");
+}
+
+/**
+ * Local functions in support of the shell command.
+ */
+namespace sf0x
+{
+
+/* oddly, ERROR is not defined for c++ */
+#ifdef ERROR
+# undef ERROR
+#endif
+const int ERROR = -1;
+
+SF0X *g_dev;
+
+void start();
+void stop();
+void test();
+void reset();
+void info();
+
+/**
+ * Start the driver.
+ */
+void
+start(const char *port)
+{
+ int fd;
+
+ if (g_dev != nullptr) {
+ errx(1, "already started");
+ }
+
+ /* create the driver */
+ g_dev = new SF0X(port);
+
+ if (g_dev == nullptr) {
+ goto fail;
+ }
+
+ if (OK != g_dev->init()) {
+ goto fail;
+ }
+
+ /* set the poll rate to default, starts automatic data collection */
+ fd = open(RANGE_FINDER_DEVICE_PATH, 0);
+
+ if (fd < 0) {
+ warnx("device open fail");
+ goto fail;
+ }
+
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
+ goto fail;
+ }
+
+ exit(0);
+
+fail:
+
+ if (g_dev != nullptr) {
+ delete g_dev;
+ g_dev = nullptr;
+ }
+
+ errx(1, "driver start failed");
+}
+
+/**
+ * Stop the driver
+ */
+void stop()
+{
+ if (g_dev != nullptr) {
+ delete g_dev;
+ g_dev = nullptr;
+
+ } else {
+ errx(1, "driver not running");
+ }
+
+ exit(0);
+}
+
+/**
+ * Perform some basic functional tests on the driver;
+ * make sure we can collect data from the sensor in polled
+ * and automatic modes.
+ */
+void
+test()
+{
+ struct range_finder_report report;
+ ssize_t sz;
+
+ int fd = open(RANGE_FINDER_DEVICE_PATH, O_RDONLY);
+
+ if (fd < 0) {
+ err(1, "%s open failed (try 'sf0x start' if the driver is not running", RANGE_FINDER_DEVICE_PATH);
+ }
+
+ /* do a simple demand read */
+ sz = read(fd, &report, sizeof(report));
+
+ if (sz != sizeof(report)) {
+ err(1, "immediate read failed");
+ }
+
+ warnx("single read");
+ warnx("measurement: %0.2f m", (double)report.distance);
+ warnx("time: %lld", report.timestamp);
+
+ /* start the sensor polling at 2Hz */
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2)) {
+ errx(1, "failed to set 2Hz poll rate");
+ }
+
+ /* read the sensor 5x and report each value */
+ for (unsigned i = 0; i < 5; i++) {
+ struct pollfd fds;
+
+ /* wait for data to be ready */
+ fds.fd = fd;
+ fds.events = POLLIN;
+ int ret = poll(&fds, 1, 2000);
+
+ if (ret != 1) {
+ errx(1, "timed out waiting for sensor data");
+ }
+
+ /* now go get it */
+ sz = read(fd, &report, sizeof(report));
+
+ if (sz != sizeof(report)) {
+ err(1, "periodic read failed");
+ }
+
+ warnx("periodic read %u", i);
+ warnx("measurement: %0.3f", (double)report.distance);
+ warnx("time: %lld", report.timestamp);
+ }
+
+ /* reset the sensor polling to default rate */
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) {
+ errx(1, "failed to set default poll rate");
+ }
+
+ errx(0, "PASS");
+}
+
+/**
+ * Reset the driver.
+ */
+void
+reset()
+{
+ int fd = open(RANGE_FINDER_DEVICE_PATH, O_RDONLY);
+
+ if (fd < 0) {
+ err(1, "failed ");
+ }
+
+ if (ioctl(fd, SENSORIOCRESET, 0) < 0) {
+ err(1, "driver reset failed");
+ }
+
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
+ err(1, "driver poll restart failed");
+ }
+
+ exit(0);
+}
+
+/**
+ * Print a little info about the driver.
+ */
+void
+info()
+{
+ if (g_dev == nullptr) {
+ errx(1, "driver not running");
+ }
+
+ printf("state @ %p\n", g_dev);
+ g_dev->print_info();
+
+ exit(0);
+}
+
+} // namespace
+
+int
+sf0x_main(int argc, char *argv[])
+{
+ /*
+ * Start/load the driver.
+ */
+ if (!strcmp(argv[1], "start")) {
+ if (argc > 2) {
+ sf0x::start(argv[2]);
+
+ } else {
+ sf0x::start(SF0X_DEFAULT_PORT);
+ }
+ }
+
+ /*
+ * Stop the driver
+ */
+ if (!strcmp(argv[1], "stop")) {
+ sf0x::stop();
+ }
+
+ /*
+ * Test the driver/device.
+ */
+ if (!strcmp(argv[1], "test")) {
+ sf0x::test();
+ }
+
+ /*
+ * Reset the driver.
+ */
+ if (!strcmp(argv[1], "reset")) {
+ sf0x::reset();
+ }
+
+ /*
+ * Print driver information.
+ */
+ if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
+ sf0x::info();
+ }
+
+ errx(1, "unrecognized command, try 'start', 'test', 'reset' or 'info'");
+}
diff --git a/src/lib/launchdetection/CatapultLaunchMethod.cpp b/src/lib/launchdetection/CatapultLaunchMethod.cpp
index d5c759b17..12f80c4a3 100644
--- a/src/lib/launchdetection/CatapultLaunchMethod.cpp
+++ b/src/lib/launchdetection/CatapultLaunchMethod.cpp
@@ -41,12 +41,16 @@
#include "CatapultLaunchMethod.h"
#include <systemlib/err.h>
-CatapultLaunchMethod::CatapultLaunchMethod() :
- last_timestamp(0),
+namespace launchdetection
+{
+
+CatapultLaunchMethod::CatapultLaunchMethod(SuperBlock *parent) :
+ SuperBlock(parent, "CAT"),
+ last_timestamp(hrt_absolute_time()),
integrator(0.0f),
launchDetected(false),
- threshold_accel(NULL, "LAUN_CAT_A", false),
- threshold_time(NULL, "LAUN_CAT_T", false)
+ threshold_accel(this, "A"),
+ threshold_time(this, "T")
{
}
@@ -83,8 +87,11 @@ bool CatapultLaunchMethod::getLaunchDetected()
return launchDetected;
}
-void CatapultLaunchMethod::updateParams()
+
+void CatapultLaunchMethod::reset()
{
- threshold_accel.update();
- threshold_time.update();
+ integrator = 0.0f;
+ launchDetected = false;
+}
+
}
diff --git a/src/lib/launchdetection/CatapultLaunchMethod.h b/src/lib/launchdetection/CatapultLaunchMethod.h
index e943f11e9..55c46ff3f 100644
--- a/src/lib/launchdetection/CatapultLaunchMethod.h
+++ b/src/lib/launchdetection/CatapultLaunchMethod.h
@@ -44,22 +44,24 @@
#include "LaunchMethod.h"
#include <drivers/drv_hrt.h>
+#include <controllib/blocks.hpp>
#include <controllib/block/BlockParam.hpp>
-class CatapultLaunchMethod : public LaunchMethod
+namespace launchdetection
+{
+
+class CatapultLaunchMethod : public LaunchMethod, public control::SuperBlock
{
public:
- CatapultLaunchMethod();
+ CatapultLaunchMethod(SuperBlock *parent);
~CatapultLaunchMethod();
void update(float accel_x);
bool getLaunchDetected();
- void updateParams();
+ void reset();
private:
hrt_abstime last_timestamp;
-// float threshold_accel_raw;
-// float threshold_time;
float integrator;
bool launchDetected;
@@ -69,3 +71,5 @@ private:
};
#endif /* CATAPULTLAUNCHMETHOD_H_ */
+
+}
diff --git a/src/lib/launchdetection/LaunchDetector.cpp b/src/lib/launchdetection/LaunchDetector.cpp
index df9f2fe95..bf539701b 100644
--- a/src/lib/launchdetection/LaunchDetector.cpp
+++ b/src/lib/launchdetection/LaunchDetector.cpp
@@ -42,12 +42,16 @@
#include "CatapultLaunchMethod.h"
#include <systemlib/err.h>
+namespace launchdetection
+{
+
LaunchDetector::LaunchDetector() :
- launchdetection_on(NULL, "LAUN_ALL_ON", false),
- throttlePreTakeoff(NULL, "LAUN_THR_PRE", false)
+ SuperBlock(NULL, "LAUN"),
+ launchdetection_on(this, "ALL_ON"),
+ throttlePreTakeoff(this, "THR_PRE")
{
/* init all detectors */
- launchMethods[0] = new CatapultLaunchMethod();
+ launchMethods[0] = new CatapultLaunchMethod(this);
/* update all parameters of all detectors */
@@ -59,6 +63,12 @@ LaunchDetector::~LaunchDetector()
}
+void LaunchDetector::reset()
+{
+ /* Reset all detectors */
+ launchMethods[0]->reset();
+}
+
void LaunchDetector::update(float accel_x)
{
if (launchdetection_on.get() == 1) {
@@ -81,12 +91,4 @@ bool LaunchDetector::getLaunchDetected()
return false;
}
-void LaunchDetector::updateParams() {
-
- launchdetection_on.update();
- throttlePreTakeoff.update();
-
- for (uint8_t i = 0; i < sizeof(launchMethods)/sizeof(LaunchMethod); i++) {
- launchMethods[i]->updateParams();
- }
}
diff --git a/src/lib/launchdetection/LaunchDetector.h b/src/lib/launchdetection/LaunchDetector.h
index 7c2ff826c..8066ebab3 100644
--- a/src/lib/launchdetection/LaunchDetector.h
+++ b/src/lib/launchdetection/LaunchDetector.h
@@ -45,18 +45,21 @@
#include <stdint.h>
#include "LaunchMethod.h"
-
+#include <controllib/blocks.hpp>
#include <controllib/block/BlockParam.hpp>
-class __EXPORT LaunchDetector
+namespace launchdetection
+{
+
+class __EXPORT LaunchDetector : public control::SuperBlock
{
public:
LaunchDetector();
~LaunchDetector();
+ void reset();
void update(float accel_x);
bool getLaunchDetected();
- void updateParams();
bool launchDetectionEnabled() { return (bool)launchdetection_on.get(); };
float getThrottlePreTakeoff() {return throttlePreTakeoff.get(); }
@@ -71,5 +74,6 @@ private:
};
+}
#endif // LAUNCHDETECTOR_H
diff --git a/src/lib/launchdetection/LaunchMethod.h b/src/lib/launchdetection/LaunchMethod.h
index bfb5f8cb4..01fa7050e 100644
--- a/src/lib/launchdetection/LaunchMethod.h
+++ b/src/lib/launchdetection/LaunchMethod.h
@@ -41,14 +41,20 @@
#ifndef LAUNCHMETHOD_H_
#define LAUNCHMETHOD_H_
+namespace launchdetection
+{
+
class LaunchMethod
{
public:
virtual void update(float accel_x) = 0;
virtual bool getLaunchDetected() = 0;
- virtual void updateParams() = 0;
+ virtual void reset() = 0;
+
protected:
private:
};
+}
+
#endif /* LAUNCHMETHOD_H_ */
diff --git a/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
index 620185fb7..00bd23f83 100755
--- a/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
+++ b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
@@ -477,6 +477,9 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
dt = 0.005f;
parameters_update(&ekf_param_handles, &ekf_params);
+ /* update mag declination rotation matrix */
+ R_decl.from_euler(0.0f, 0.0f, ekf_params.mag_decl);
+
x_aposteriori_k[0] = z_k[0];
x_aposteriori_k[1] = z_k[1];
x_aposteriori_k[2] = z_k[2];
diff --git a/src/modules/fw_att_control/fw_att_control_main.cpp b/src/modules/fw_att_control/fw_att_control_main.cpp
index 17b1028f9..5ade835ff 100644
--- a/src/modules/fw_att_control/fw_att_control_main.cpp
+++ b/src/modules/fw_att_control/fw_att_control_main.cpp
@@ -166,6 +166,15 @@ private:
float airspeed_min;
float airspeed_trim;
float airspeed_max;
+
+ float trim_roll;
+ float trim_pitch;
+ float trim_yaw;
+ float rollsp_offset_deg; /**< Roll Setpoint Offset in deg */
+ float pitchsp_offset_deg; /**< Pitch Setpoint Offset in deg */
+ float rollsp_offset_rad; /**< Roll Setpoint Offset in rad */
+ float pitchsp_offset_rad; /**< Pitch Setpoint Offset in rad */
+
} _parameters; /**< local copies of interesting parameters */
struct {
@@ -197,6 +206,12 @@ private:
param_t airspeed_min;
param_t airspeed_trim;
param_t airspeed_max;
+
+ param_t trim_roll;
+ param_t trim_pitch;
+ param_t trim_yaw;
+ param_t rollsp_offset_deg;
+ param_t pitchsp_offset_deg;
} _parameter_handles; /**< handles for interesting parameters */
@@ -335,6 +350,12 @@ FixedwingAttitudeControl::FixedwingAttitudeControl() :
_parameter_handles.y_coordinated_min_speed = param_find("FW_YCO_VMIN");
+ _parameter_handles.trim_roll = param_find("TRIM_ROLL");
+ _parameter_handles.trim_pitch = param_find("TRIM_PITCH");
+ _parameter_handles.trim_yaw = param_find("TRIM_YAW");
+ _parameter_handles.rollsp_offset_deg = param_find("FW_RSP_OFF");
+ _parameter_handles.pitchsp_offset_deg = param_find("FW_PSP_OFF");
+
/* fetch initial parameter values */
parameters_update();
}
@@ -395,6 +416,15 @@ FixedwingAttitudeControl::parameters_update()
param_get(_parameter_handles.airspeed_trim, &(_parameters.airspeed_trim));
param_get(_parameter_handles.airspeed_max, &(_parameters.airspeed_max));
+ param_get(_parameter_handles.trim_roll, &(_parameters.trim_roll));
+ param_get(_parameter_handles.trim_pitch, &(_parameters.trim_pitch));
+ param_get(_parameter_handles.trim_yaw, &(_parameters.trim_yaw));
+ param_get(_parameter_handles.rollsp_offset_deg, &(_parameters.rollsp_offset_deg));
+ param_get(_parameter_handles.pitchsp_offset_deg, &(_parameters.pitchsp_offset_deg));
+ _parameters.rollsp_offset_rad = math::radians(_parameters.rollsp_offset_deg);
+ _parameters.pitchsp_offset_rad = math::radians(_parameters.pitchsp_offset_deg);
+
+
/* pitch control parameters */
_pitch_ctrl.set_time_constant(_parameters.tconst);
_pitch_ctrl.set_k_p(_parameters.p_p);
@@ -648,13 +678,13 @@ FixedwingAttitudeControl::task_main()
float airspeed_scaling = _parameters.airspeed_trim / airspeed;
//warnx("aspd scale: %6.2f act scale: %6.2f", airspeed_scaling, actuator_scaling);
- float roll_sp = 0.0f;
- float pitch_sp = 0.0f;
+ float roll_sp = _parameters.rollsp_offset_rad;
+ float pitch_sp = _parameters.pitchsp_offset_rad;
float throttle_sp = 0.0f;
if (_vcontrol_mode.flag_control_velocity_enabled || _vcontrol_mode.flag_control_position_enabled) {
- roll_sp = _att_sp.roll_body;
- pitch_sp = _att_sp.pitch_body;
+ roll_sp = _att_sp.roll_body + _parameters.rollsp_offset_rad;
+ pitch_sp = _att_sp.pitch_body + _parameters.pitchsp_offset_rad;
throttle_sp = _att_sp.thrust;
/* reset integrals where needed */
@@ -670,9 +700,13 @@ FixedwingAttitudeControl::task_main()
* With this mapping the stick angle is a 1:1 representation of
* the commanded attitude. If more than 45 degrees are desired,
* a scaling parameter can be applied to the remote.
+ *
+ * The trim gets subtracted here from the manual setpoint to get
+ * the intended attitude setpoint. Later, after the rate control step the
+ * trim is added again to the control signal.
*/
- roll_sp = _manual.roll * 0.75f;
- pitch_sp = _manual.pitch * 0.75f;
+ roll_sp = (_manual.roll - _parameters.trim_roll) * 0.75f + _parameters.rollsp_offset_rad;
+ pitch_sp = (_manual.pitch - _parameters.trim_pitch) * 0.75f + _parameters.pitchsp_offset_rad;
throttle_sp = _manual.throttle;
_actuators.control[4] = _manual.flaps;
@@ -685,7 +719,7 @@ FixedwingAttitudeControl::task_main()
att_sp.timestamp = hrt_absolute_time();
att_sp.roll_body = roll_sp;
att_sp.pitch_body = pitch_sp;
- att_sp.yaw_body = 0.0f;
+ att_sp.yaw_body = 0.0f - _parameters.trim_yaw;
att_sp.thrust = throttle_sp;
/* lazily publish the setpoint only once available */
@@ -719,12 +753,12 @@ FixedwingAttitudeControl::task_main()
speed_body_u, speed_body_v, speed_body_w,
_roll_ctrl.get_desired_rate(), _pitch_ctrl.get_desired_rate()); //runs last, because is depending on output of roll and pitch attitude
- /* Run attitude RATE controllers which need the desired attitudes from above */
+ /* Run attitude RATE controllers which need the desired attitudes from above, add trim */
float roll_u = _roll_ctrl.control_bodyrate(_att.pitch,
_att.rollspeed, _att.yawspeed,
_yaw_ctrl.get_desired_rate(),
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
- _actuators.control[0] = (isfinite(roll_u)) ? roll_u : 0.0f;
+ _actuators.control[0] = (isfinite(roll_u)) ? roll_u + _parameters.trim_roll : _parameters.trim_roll;
if (!isfinite(roll_u)) {
warnx("roll_u %.4f", roll_u);
}
@@ -733,7 +767,7 @@ FixedwingAttitudeControl::task_main()
_att.pitchspeed, _att.yawspeed,
_yaw_ctrl.get_desired_rate(),
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
- _actuators.control[1] = (isfinite(pitch_u)) ? pitch_u : 0.0f;
+ _actuators.control[1] = (isfinite(pitch_u)) ? pitch_u + _parameters.trim_pitch : _parameters.trim_pitch;
if (!isfinite(pitch_u)) {
warnx("pitch_u %.4f, _yaw_ctrl.get_desired_rate() %.4f, airspeed %.4f, airspeed_scaling %.4f, roll_sp %.4f, pitch_sp %.4f, _roll_ctrl.get_desired_rate() %.4f, _pitch_ctrl.get_desired_rate() %.4f att_sp.roll_body %.4f",
pitch_u, _yaw_ctrl.get_desired_rate(), airspeed, airspeed_scaling, roll_sp, pitch_sp, _roll_ctrl.get_desired_rate(), _pitch_ctrl.get_desired_rate(), _att_sp.roll_body);
@@ -743,7 +777,7 @@ FixedwingAttitudeControl::task_main()
_att.pitchspeed, _att.yawspeed,
_pitch_ctrl.get_desired_rate(),
_parameters.airspeed_min, _parameters.airspeed_max, airspeed, airspeed_scaling, lock_integrator);
- _actuators.control[2] = (isfinite(yaw_u)) ? yaw_u : 0.0f;
+ _actuators.control[2] = (isfinite(yaw_u)) ? yaw_u + _parameters.trim_yaw : _parameters.trim_yaw;
if (!isfinite(yaw_u)) {
warnx("yaw_u %.4f", yaw_u);
}
diff --git a/src/modules/fw_att_control/fw_att_control_params.c b/src/modules/fw_att_control/fw_att_control_params.c
index 1c615094c..c80a44f2a 100644
--- a/src/modules/fw_att_control/fw_att_control_params.c
+++ b/src/modules/fw_att_control/fw_att_control_params.c
@@ -176,3 +176,13 @@ PARAM_DEFINE_FLOAT(FW_AIRSPD_TRIM, 20.0f);
// @Description If the airspeed is above this value the TECS controller will try to decrease airspeed more aggressively
// @Range 0.0 to 30
PARAM_DEFINE_FLOAT(FW_AIRSPD_MAX, 50.0f);
+
+// @DisplayName Roll Setpoint Offset
+// @Description An airframe specific offset of the roll setpoint in degrees, the value is added to the roll setpoint and should correspond to the typical cruise speed of the airframe
+// @Range -90.0 to 90.0
+PARAM_DEFINE_FLOAT(FW_RSP_OFF, 0.0f);
+
+// @DisplayName Pitch Setpoint Offset
+// @Description An airframe specific offset of the pitch setpoint in degrees, the value is added to the pitch setpoint and should correspond to the typical cruise speed of the airframe
+// @Range -90.0 to 90.0
+PARAM_DEFINE_FLOAT(FW_PSP_OFF, 0.0f);
diff --git a/src/modules/fw_pos_control_l1/fw_pos_control_l1_main.cpp b/src/modules/fw_pos_control_l1/fw_pos_control_l1_main.cpp
index ed6d8792c..7f13df785 100644
--- a/src/modules/fw_pos_control_l1/fw_pos_control_l1_main.cpp
+++ b/src/modules/fw_pos_control_l1/fw_pos_control_l1_main.cpp
@@ -176,6 +176,8 @@ private:
bool launch_detected;
bool usePreTakeoffThrust;
+ bool last_manual; ///< true if the last iteration was in manual mode (used to determine when a reset is needed)
+
/* Landingslope object */
Landingslope landingslope;
@@ -184,7 +186,7 @@ private:
float target_bearing;
/* Launch detection */
- LaunchDetector launchDetector;
+ launchdetection::LaunchDetector launchDetector;
/* throttle and airspeed states */
float _airspeed_error; ///< airspeed error to setpoint in m/s
@@ -344,6 +346,16 @@ private:
* Main sensor collection task.
*/
void task_main() __attribute__((noreturn));
+
+ /*
+ * Reset takeoff state
+ */
+ void reset_takeoff_state();
+
+ /*
+ * Reset landing state
+ */
+ void reset_landing_state();
};
namespace l1_control
@@ -389,6 +401,7 @@ FixedwingPositionControl::FixedwingPositionControl() :
land_motor_lim(false),
land_onslope(false),
launch_detected(false),
+ last_manual(false),
usePreTakeoffThrust(false),
flare_curve_alt_last(0.0f),
launchDetector(),
@@ -976,6 +989,7 @@ FixedwingPositionControl::control_position(const math::Vector<2> &current_positi
} else {
/* no takeoff detection --> fly */
launch_detected = true;
+ warnx("launchdetection off");
}
}
@@ -1022,19 +1036,14 @@ FixedwingPositionControl::control_position(const math::Vector<2> &current_positi
// mission is active
_loiter_hold = false;
- /* reset land state */
+ /* reset landing state */
if (pos_sp_triplet.current.type != SETPOINT_TYPE_LAND) {
- land_noreturn_horizontal = false;
- land_noreturn_vertical = false;
- land_stayonground = false;
- land_motor_lim = false;
- land_onslope = false;
+ reset_landing_state();
}
/* reset takeoff/launch state */
if (pos_sp_triplet.current.type != SETPOINT_TYPE_TAKEOFF) {
- launch_detected = false;
- usePreTakeoffThrust = false;
+ reset_takeoff_state();
}
if (was_circle_mode && !_l1_control.circle_mode()) {
@@ -1131,6 +1140,12 @@ FixedwingPositionControl::control_position(const math::Vector<2> &current_positi
/* no flight mode applies, do not publish an attitude setpoint */
setpoint = false;
+
+ /* reset landing and takeoff state */
+ if (!last_manual) {
+ reset_landing_state();
+ reset_takeoff_state();
+ }
}
if (usePreTakeoffThrust) {
@@ -1141,6 +1156,12 @@ FixedwingPositionControl::control_position(const math::Vector<2> &current_positi
}
_att_sp.pitch_body = _tecs.get_pitch_demand();
+ if (_control_mode.flag_control_position_enabled) {
+ last_manual = false;
+ } else {
+ last_manual = true;
+ }
+
return setpoint;
}
@@ -1291,6 +1312,22 @@ FixedwingPositionControl::task_main()
_exit(0);
}
+void FixedwingPositionControl::reset_takeoff_state()
+{
+ launch_detected = false;
+ usePreTakeoffThrust = false;
+ launchDetector.reset();
+}
+
+void FixedwingPositionControl::reset_landing_state()
+{
+ land_noreturn_horizontal = false;
+ land_noreturn_vertical = false;
+ land_stayonground = false;
+ land_motor_lim = false;
+ land_onslope = false;
+}
+
int
FixedwingPositionControl::start()
{
diff --git a/src/modules/gpio_led/gpio_led.c b/src/modules/gpio_led/gpio_led.c
index d383146f9..6dfd22fdf 100644
--- a/src/modules/gpio_led/gpio_led.c
+++ b/src/modules/gpio_led/gpio_led.c
@@ -51,7 +51,6 @@
#include <systemlib/err.h>
#include <uORB/uORB.h>
#include <uORB/topics/vehicle_status.h>
-#include <uORB/topics/actuator_armed.h>
#include <poll.h>
#include <drivers/drv_gpio.h>
#include <modules/px4iofirmware/protocol.h>
@@ -63,8 +62,6 @@ struct gpio_led_s {
int pin;
struct vehicle_status_s status;
int vehicle_status_sub;
- struct actuator_armed_s armed;
- int actuator_armed_sub;
bool led_state;
int counter;
};
@@ -81,6 +78,7 @@ void gpio_led_cycle(FAR void *arg);
int gpio_led_main(int argc, char *argv[])
{
if (argc < 2) {
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
errx(1, "usage: gpio_led {start|stop} [-p <1|2|a1|a2|r1|r2>]\n"
"\t-p\tUse pin:\n"
"\t\t1\tPX4FMU GPIO_EXT1 (default)\n"
@@ -88,7 +86,14 @@ int gpio_led_main(int argc, char *argv[])
"\t\ta1\tPX4IO ACC1\n"
"\t\ta2\tPX4IO ACC2\n"
"\t\tr1\tPX4IO RELAY1\n"
- "\t\tr2\tPX4IO RELAY2");
+ "\t\tr2\tPX4IO RELAY2"
+ );
+#endif
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
+ errx(1, "usage: gpio_led {start|stop} [-p <n>]\n"
+ "\t-p <n>\tUse specified AUX OUT pin number (default: 1)"
+ );
+#endif
} else {
@@ -98,37 +103,70 @@ int gpio_led_main(int argc, char *argv[])
}
bool use_io = false;
- int pin = GPIO_EXT_1;
+
+ /* by default use GPIO_EXT_1 on FMUv1 and GPIO_SERVO_1 on FMUv2 */
+ int pin = 1;
+
+ /* pin name to display */
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
+ char *pin_name = "PX4FMU GPIO_EXT1";
+#endif
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
+ char pin_name[] = "AUX OUT 1";
+#endif
if (argc > 2) {
if (!strcmp(argv[2], "-p")) {
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
+
if (!strcmp(argv[3], "1")) {
use_io = false;
pin = GPIO_EXT_1;
+ pin_name = "PX4FMU GPIO_EXT1";
} else if (!strcmp(argv[3], "2")) {
use_io = false;
pin = GPIO_EXT_2;
+ pin_name = "PX4FMU GPIO_EXT2";
} else if (!strcmp(argv[3], "a1")) {
use_io = true;
pin = PX4IO_P_SETUP_RELAYS_ACC1;
+ pin_name = "PX4IO ACC1";
} else if (!strcmp(argv[3], "a2")) {
use_io = true;
pin = PX4IO_P_SETUP_RELAYS_ACC2;
+ pin_name = "PX4IO ACC2";
} else if (!strcmp(argv[3], "r1")) {
use_io = true;
pin = PX4IO_P_SETUP_RELAYS_POWER1;
+ pin_name = "PX4IO RELAY1";
} else if (!strcmp(argv[3], "r2")) {
use_io = true;
pin = PX4IO_P_SETUP_RELAYS_POWER2;
+ pin_name = "PX4IO RELAY2";
+
+ } else {
+ errx(1, "unsupported pin: %s", argv[3]);
+ }
+
+#endif
+#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
+ unsigned int n = strtoul(argv[3], NULL, 10);
+
+ if (n >= 1 && n <= 6) {
+ use_io = false;
+ pin = 1 << (n - 1);
+ snprintf(pin_name, sizeof(pin_name), "AUX OUT %d", n);
} else {
errx(1, "unsupported pin: %s", argv[3]);
}
+
+#endif
}
}
@@ -142,21 +180,6 @@ int gpio_led_main(int argc, char *argv[])
} else {
gpio_led_started = true;
- char pin_name[24];
-
- if (use_io) {
- if (pin & (PX4IO_P_SETUP_RELAYS_ACC1 | PX4IO_P_SETUP_RELAYS_ACC2)) {
- sprintf(pin_name, "PX4IO ACC%i", (pin >> 3));
-
- } else {
- sprintf(pin_name, "PX4IO RELAY%i", pin);
- }
-
- } else {
- sprintf(pin_name, "PX4FMU GPIO_EXT%i", pin);
-
- }
-
warnx("start, using pin: %s", pin_name);
}
@@ -186,6 +209,7 @@ void gpio_led_start(FAR void *arg)
if (priv->use_io) {
gpio_dev = PX4IO_DEVICE_PATH;
+
} else {
gpio_dev = PX4FMU_DEVICE_PATH;
}
@@ -204,8 +228,10 @@ void gpio_led_start(FAR void *arg)
/* px4fmu only, px4io doesn't support GPIO_SET_OUTPUT and will ignore */
ioctl(priv->gpio_fd, GPIO_SET_OUTPUT, priv->pin);
- /* subscribe to vehicle status topic */
+ /* initialize vehicle status structure */
memset(&priv->status, 0, sizeof(priv->status));
+
+ /* subscribe to vehicle status topic */
priv->vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
/* add worker to queue */
@@ -224,38 +250,33 @@ void gpio_led_cycle(FAR void *arg)
FAR struct gpio_led_s *priv = (FAR struct gpio_led_s *)arg;
/* check for status updates*/
- bool status_updated;
- orb_check(priv->vehicle_status_sub, &status_updated);
+ bool updated;
+ orb_check(priv->vehicle_status_sub, &updated);
- if (status_updated)
+ if (updated) {
orb_copy(ORB_ID(vehicle_status), priv->vehicle_status_sub, &priv->status);
-
- orb_check(priv->vehicle_status_sub, &status_updated);
-
- if (status_updated)
- orb_copy(ORB_ID(actuator_armed), priv->actuator_armed_sub, &priv->armed);
+ }
/* select pattern for current status */
int pattern = 0;
- if (priv->armed.armed) {
- if (priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE) {
+ if (priv->status.arming_state == ARMING_STATE_ARMED_ERROR) {
+ pattern = 0x2A; // *_*_*_ fast blink (armed, error)
+
+ } else if (priv->status.arming_state == ARMING_STATE_ARMED) {
+ if (priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE && priv->status.failsafe_state == FAILSAFE_STATE_NORMAL) {
pattern = 0x3f; // ****** solid (armed)
} else {
- pattern = 0x2A; // *_*_*_ fast blink (armed, battery warning)
+ pattern = 0x3e; // *****_ slow blink (armed, battery low or failsafe)
}
- } else {
- if (priv->armed.ready_to_arm) {
- pattern = 0x00; // ______ off (disarmed, preflight check)
+ } else if (priv->status.arming_state == ARMING_STATE_STANDBY) {
+ pattern = 0x38; // ***___ slow blink (disarmed, ready)
- } else if (priv->armed.ready_to_arm && priv->status.battery_warning == VEHICLE_BATTERY_WARNING_NONE) {
- pattern = 0x38; // ***___ slow blink (disarmed, ready)
+ } else if (priv->status.arming_state == ARMING_STATE_STANDBY_ERROR) {
+ pattern = 0x28; // *_*___ slow double blink (disarmed, error)
- } else {
- pattern = 0x28; // *_*___ slow double blink (disarmed, not good to arm)
- }
}
/* blink pattern */
@@ -266,6 +287,7 @@ void gpio_led_cycle(FAR void *arg)
if (led_state_new) {
ioctl(priv->gpio_fd, GPIO_SET, priv->pin);
+
} else {
ioctl(priv->gpio_fd, GPIO_CLEAR, priv->pin);
}
@@ -273,8 +295,9 @@ void gpio_led_cycle(FAR void *arg)
priv->counter++;
- if (priv->counter > 5)
+ if (priv->counter > 5) {
priv->counter = 0;
+ }
/* repeat cycle at 5 Hz */
if (gpio_led_started) {
diff --git a/src/modules/navigator/geofence.cpp b/src/modules/navigator/geofence.cpp
index 9bbaf167a..f452a85f7 100644
--- a/src/modules/navigator/geofence.cpp
+++ b/src/modules/navigator/geofence.cpp
@@ -55,11 +55,13 @@
#endif
static const int ERROR = -1;
-Geofence::Geofence() : _fence_pub(-1),
+Geofence::Geofence() :
+ SuperBlock(NULL, "GF"),
+ _fence_pub(-1),
_altitude_min(0),
_altitude_max(0),
_verticesCount(0),
- param_geofence_on(NULL, "GF_ON", false)
+ param_geofence_on(this, "ON")
{
/* Load initial params */
updateParams();
@@ -292,8 +294,3 @@ int Geofence::clearDm()
{
dm_clear(DM_KEY_FENCE_POINTS);
}
-
-void Geofence::updateParams()
-{
- param_geofence_on.update();
-}
diff --git a/src/modules/navigator/geofence.h b/src/modules/navigator/geofence.h
index 5b56ebc7a..9628b7271 100644
--- a/src/modules/navigator/geofence.h
+++ b/src/modules/navigator/geofence.h
@@ -41,11 +41,13 @@
#define GEOFENCE_H_
#include <uORB/topics/fence.h>
+#include <controllib/blocks.hpp>
#include <controllib/block/BlockParam.hpp>
#define GEOFENCE_FILENAME "/fs/microsd/etc/geofence.txt"
-class Geofence {
+class Geofence : public control::SuperBlock
+{
private:
orb_advert_t _fence_pub; /**< publish fence topic */
@@ -85,8 +87,6 @@ public:
int loadFromFile(const char *filename);
bool isEmpty() {return _verticesCount == 0;}
-
- void updateParams();
};
diff --git a/src/modules/position_estimator_inav/inertial_filter.c b/src/modules/position_estimator_inav/inertial_filter.c
index 13328edb4..7cd076948 100644
--- a/src/modules/position_estimator_inav/inertial_filter.c
+++ b/src/modules/position_estimator_inav/inertial_filter.c
@@ -15,10 +15,7 @@ void inertial_filter_predict(float dt, float x[3])
void inertial_filter_correct(float e, float dt, float x[3], int i, float w)
{
- float ewdt = w * dt;
- if (ewdt > 1.0f)
- ewdt = 1.0f; // prevent over-correcting
- ewdt *= e;
+ float ewdt = e * w * dt;
x[i] += ewdt;
if (i == 0) {
diff --git a/src/modules/position_estimator_inav/position_estimator_inav_main.c b/src/modules/position_estimator_inav/position_estimator_inav_main.c
index d6d03367b..a14354138 100644
--- a/src/modules/position_estimator_inav/position_estimator_inav_main.c
+++ b/src/modules/position_estimator_inav/position_estimator_inav_main.c
@@ -623,7 +623,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
}
float dt = t_prev > 0 ? (t - t_prev) / 1000000.0f : 0.0f;
- dt = fmaxf(fminf(0.02, dt), 0.005);
+ dt = fmaxf(fminf(0.02, dt), 0.002); // constrain dt from 2 to 20 ms
t_prev = t;
/* use GPS if it's valid and reference position initialized */
diff --git a/src/modules/sdlog2/logbuffer.c b/src/modules/sdlog2/logbuffer.c
index 6a29d7e5c..2da67d8a9 100644
--- a/src/modules/sdlog2/logbuffer.c
+++ b/src/modules/sdlog2/logbuffer.c
@@ -74,8 +74,9 @@ bool logbuffer_write(struct logbuffer_s *lb, void *ptr, int size)
// bytes available to write
int available = lb->read_ptr - lb->write_ptr - 1;
- if (available < 0)
+ if (available < 0) {
available += lb->size;
+ }
if (size > available) {
// buffer overflow
diff --git a/src/modules/sdlog2/sdlog2.c b/src/modules/sdlog2/sdlog2.c
index 1365d9e70..2514bafee 100644
--- a/src/modules/sdlog2/sdlog2.c
+++ b/src/modules/sdlog2/sdlog2.c
@@ -58,6 +58,8 @@
#include <drivers/drv_hrt.h>
#include <math.h>
+#include <drivers/drv_range_finder.h>
+
#include <uORB/uORB.h>
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/sensor_combined.h>
@@ -134,12 +136,6 @@ static uint64_t gps_time = 0;
/* current state of logging */
static bool logging_enabled = false;
-/* enable logging on start (-e option) */
-static bool log_on_start = false;
-/* enable logging when armed (-a option) */
-static bool log_when_armed = false;
-/* delay = 1 / rate (rate defined by -r option) */
-static useconds_t sleep_delay = 0;
/* use date/time for naming directories and files (-t option) */
static bool log_name_timestamp = false;
@@ -159,6 +155,8 @@ static void *logwriter_thread(void *arg);
*/
__EXPORT int sdlog2_main(int argc, char *argv[]);
+static bool copy_if_updated(orb_id_t topic, int handle, void *buffer);
+
/**
* Mainloop of sd log deamon.
*/
@@ -220,8 +218,9 @@ static int open_log_file(void);
static void
sdlog2_usage(const char *reason)
{
- if (reason)
+ if (reason) {
fprintf(stderr, "%s\n", reason);
+ }
errx(1, "usage: sdlog2 {start|stop|status} [-r <log rate>] [-b <buffer size>] -e -a -t\n"
"\t-r\tLog rate in Hz, 0 means unlimited rate\n"
@@ -241,8 +240,9 @@ sdlog2_usage(const char *reason)
*/
int sdlog2_main(int argc, char *argv[])
{
- if (argc < 2)
+ if (argc < 2) {
sdlog2_usage("missing command");
+ }
if (!strcmp(argv[1], "start")) {
@@ -401,22 +401,29 @@ static void *logwriter_thread(void *arg)
int log_fd = open_log_file();
- if (log_fd < 0)
- return;
+ if (log_fd < 0) {
+ return NULL;
+ }
struct logbuffer_s *logbuf = (struct logbuffer_s *)arg;
/* write log messages formats, version and parameters */
log_bytes_written += write_formats(log_fd);
+
log_bytes_written += write_version(log_fd);
+
log_bytes_written += write_parameters(log_fd);
+
fsync(log_fd);
int poll_count = 0;
void *read_ptr;
+
int n = 0;
+
bool should_wait = false;
+
bool is_part = false;
while (true) {
@@ -449,7 +456,6 @@ static void *logwriter_thread(void *arg)
n = available;
}
- lseek(log_fd, 0, SEEK_CUR);
n = write(log_fd, read_ptr, n);
should_wait = (n == available) && !is_part;
@@ -483,7 +489,7 @@ static void *logwriter_thread(void *arg)
fsync(log_fd);
close(log_fd);
- return;
+ return NULL;
}
void sdlog2_start_log()
@@ -628,6 +634,19 @@ int write_parameters(int fd)
return written;
}
+bool copy_if_updated(orb_id_t topic, int handle, void *buffer)
+{
+ bool updated;
+
+ orb_check(handle, &updated);
+
+ if (updated) {
+ orb_copy(topic, handle, buffer);
+ }
+
+ return updated;
+}
+
int sdlog2_thread_main(int argc, char *argv[])
{
mavlink_fd = open(MAVLINK_LOG_DEVICE, 0);
@@ -636,12 +655,14 @@ int sdlog2_thread_main(int argc, char *argv[])
warnx("failed to open MAVLink log stream, start mavlink app first");
}
- /* log buffer size */
+ /* delay = 1 / rate (rate defined by -r option), default log rate: 50 Hz */
+ useconds_t sleep_delay = 20000;
int log_buffer_size = LOG_BUFFER_SIZE_DEFAULT;
-
logging_enabled = false;
- log_on_start = false;
- log_when_armed = false;
+ /* enable logging on start (-e option) */
+ bool log_on_start = false;
+ /* enable logging when armed (-a option) */
+ bool log_when_armed = false;
log_name_timestamp = false;
flag_system_armed = false;
@@ -651,17 +672,20 @@ int sdlog2_thread_main(int argc, char *argv[])
argv += 2;
int ch;
+ /* don't exit from getopt loop to leave getopt global variables in consistent state,
+ * set error flag instead */
+ bool err_flag = false;
+
while ((ch = getopt(argc, argv, "r:b:eat")) != EOF) {
switch (ch) {
case 'r': {
unsigned long r = strtoul(optarg, NULL, 10);
- if (r == 0) {
- sleep_delay = 0;
-
- } else {
- sleep_delay = 1000000 / r;
+ if (r <= 0) {
+ r = 1;
}
+
+ sleep_delay = 1000000 / r;
}
break;
@@ -698,20 +722,27 @@ int sdlog2_thread_main(int argc, char *argv[])
} else {
warnx("unknown option character `\\x%x'", optopt);
}
+ err_flag = true;
+ break;
default:
- sdlog2_usage("unrecognized flag");
- errx(1, "exiting");
+ warnx("unrecognized flag");
+ err_flag = true;
+ break;
}
}
+ if (err_flag) {
+ sdlog2_usage(NULL);
+ }
+
gps_time = 0;
/* create log root dir */
int mkdir_ret = mkdir(log_root, S_IRWXU | S_IRWXG | S_IRWXO);
if (mkdir_ret != 0 && errno != EEXIST) {
- err("failed creating log root dir: %s", log_root);
+ err(1, "failed creating log root dir: %s", log_root);
}
/* copy conversion scripts */
@@ -734,8 +765,12 @@ int sdlog2_thread_main(int argc, char *argv[])
struct vehicle_status_s buf_status;
+ struct vehicle_gps_position_s buf_gps_pos;
+
memset(&buf_status, 0, sizeof(buf_status));
+ memset(&buf_gps_pos, 0, sizeof(buf_gps_pos));
+
/* warning! using union here to save memory, elements should be used separately! */
union {
struct vehicle_command_s cmd;
@@ -749,7 +784,6 @@ int sdlog2_thread_main(int argc, char *argv[])
struct vehicle_local_position_setpoint_s local_pos_sp;
struct vehicle_global_position_s global_pos;
struct position_setpoint_triplet_s triplet;
- struct vehicle_gps_position_s gps_pos;
struct vehicle_vicon_position_s vicon_pos;
struct optical_flow_s flow;
struct rc_channels_s rc;
@@ -759,34 +793,11 @@ int sdlog2_thread_main(int argc, char *argv[])
struct vehicle_global_velocity_setpoint_s global_vel_sp;
struct battery_status_s battery;
struct telemetry_status_s telemetry;
+ struct range_finder_report range_finder;
} buf;
memset(&buf, 0, sizeof(buf));
- struct {
- int cmd_sub;
- int status_sub;
- int sensor_sub;
- int att_sub;
- int att_sp_sub;
- int rates_sp_sub;
- int act_outputs_sub;
- int act_controls_sub;
- int local_pos_sub;
- int local_pos_sp_sub;
- int global_pos_sub;
- int triplet_sub;
- int gps_pos_sub;
- int vicon_pos_sub;
- int flow_sub;
- int rc_sub;
- int airspeed_sub;
- int esc_sub;
- int global_vel_sp_sub;
- int battery_sub;
- int telemetry_sub;
- } subs;
-
/* log message buffer: header + body */
#pragma pack(push, 1)
struct {
@@ -821,154 +832,53 @@ int sdlog2_thread_main(int argc, char *argv[])
#pragma pack(pop)
memset(&log_msg.body, 0, sizeof(log_msg.body));
- /* --- IMPORTANT: DEFINE NUMBER OF ORB STRUCTS TO WAIT FOR HERE --- */
- /* number of messages */
- const ssize_t fdsc = 25;
- /* Sanity check variable and index */
- ssize_t fdsc_count = 0;
- /* file descriptors to wait for */
- struct pollfd fds[fdsc];
+ struct {
+ int cmd_sub;
+ int status_sub;
+ int sensor_sub;
+ int att_sub;
+ int att_sp_sub;
+ int rates_sp_sub;
+ int act_outputs_sub;
+ int act_controls_sub;
+ int local_pos_sub;
+ int local_pos_sp_sub;
+ int global_pos_sub;
+ int triplet_sub;
+ int gps_pos_sub;
+ int vicon_pos_sub;
+ int flow_sub;
+ int rc_sub;
+ int airspeed_sub;
+ int esc_sub;
+ int global_vel_sp_sub;
+ int battery_sub;
+ int telemetry_sub;
+ int range_finder_sub;
+ } subs;
- /* --- VEHICLE COMMAND --- */
subs.cmd_sub = orb_subscribe(ORB_ID(vehicle_command));
- fds[fdsc_count].fd = subs.cmd_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- VEHICLE STATUS --- */
subs.status_sub = orb_subscribe(ORB_ID(vehicle_status));
- fds[fdsc_count].fd = subs.status_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- GPS POSITION --- */
subs.gps_pos_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
- fds[fdsc_count].fd = subs.gps_pos_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;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- ATTITUDE --- */
subs.att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
- fds[fdsc_count].fd = subs.att_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- ATTITUDE SETPOINT --- */
subs.att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
- fds[fdsc_count].fd = subs.att_sp_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- RATES SETPOINT --- */
subs.rates_sp_sub = orb_subscribe(ORB_ID(vehicle_rates_setpoint));
- fds[fdsc_count].fd = subs.rates_sp_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- ACTUATOR OUTPUTS --- */
subs.act_outputs_sub = orb_subscribe(ORB_ID_VEHICLE_CONTROLS);
- fds[fdsc_count].fd = subs.act_outputs_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- ACTUATOR CONTROL --- */
subs.act_controls_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);
- fds[fdsc_count].fd = subs.act_controls_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- LOCAL POSITION --- */
subs.local_pos_sub = orb_subscribe(ORB_ID(vehicle_local_position));
- fds[fdsc_count].fd = subs.local_pos_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- LOCAL POSITION SETPOINT --- */
subs.local_pos_sp_sub = orb_subscribe(ORB_ID(vehicle_local_position_setpoint));
- fds[fdsc_count].fd = subs.local_pos_sp_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- GLOBAL POSITION --- */
subs.global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
- fds[fdsc_count].fd = subs.global_pos_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- GLOBAL POSITION SETPOINT--- */
subs.triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
- fds[fdsc_count].fd = subs.triplet_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- VICON POSITION --- */
subs.vicon_pos_sub = orb_subscribe(ORB_ID(vehicle_vicon_position));
- fds[fdsc_count].fd = subs.vicon_pos_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- OPTICAL FLOW --- */
subs.flow_sub = orb_subscribe(ORB_ID(optical_flow));
- fds[fdsc_count].fd = subs.flow_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- RC CHANNELS --- */
subs.rc_sub = orb_subscribe(ORB_ID(rc_channels));
- fds[fdsc_count].fd = subs.rc_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- AIRSPEED --- */
subs.airspeed_sub = orb_subscribe(ORB_ID(airspeed));
- fds[fdsc_count].fd = subs.airspeed_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- ESCs --- */
subs.esc_sub = orb_subscribe(ORB_ID(esc_status));
- fds[fdsc_count].fd = subs.esc_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- GLOBAL VELOCITY SETPOINT --- */
subs.global_vel_sp_sub = orb_subscribe(ORB_ID(vehicle_global_velocity_setpoint));
- fds[fdsc_count].fd = subs.global_vel_sp_sub;
- fds[fdsc_count].events = POLLIN;
- fdsc_count++;
-
- /* --- BATTERY --- */
subs.battery_sub = orb_subscribe(ORB_ID(battery_status));
- fds[fdsc_count].fd = subs.battery_sub;
- 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.
- */
- if (fdsc_count > fdsc) {
- warn("WARNING: Not enough space for poll fds allocated. Check %s:%d", __FILE__, __LINE__);
- fdsc_count = fdsc;
- }
-
- /*
- * set up poll to block for new data,
- * wait for a maximum of 1000 ms
- */
- const int poll_timeout = 1000;
+ subs.range_finder_sub = orb_subscribe(ORB_ID(sensor_range_finder));
thread_running = true;
@@ -990,8 +900,8 @@ int sdlog2_thread_main(int argc, char *argv[])
if (log_on_start) {
/* check GPS topic to get GPS time */
if (log_name_timestamp) {
- if (OK == orb_copy(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf.gps_pos)) {
- gps_time = buf.gps_pos.time_gps_usec;
+ if (copy_if_updated(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf_gps_pos)) {
+ gps_time = buf_gps_pos.time_gps_usec;
}
}
@@ -999,394 +909,351 @@ int sdlog2_thread_main(int argc, char *argv[])
}
while (!main_thread_should_exit) {
- /* decide use usleep() or blocking poll() */
- bool use_sleep = sleep_delay > 0 && logging_enabled;
-
- /* 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);
+ usleep(sleep_delay);
- /* handle the poll result */
- if (poll_ret < 0) {
- warnx("ERROR: poll error, stop logging");
- main_thread_should_exit = true;
+ /* --- VEHICLE COMMAND - LOG MANAGEMENT --- */
+ if (copy_if_updated(ORB_ID(vehicle_command), subs.cmd_sub, &buf.cmd)) {
+ handle_command(&buf.cmd);
+ }
- } else if (poll_ret > 0) {
+ /* --- VEHICLE STATUS - LOG MANAGEMENT --- */
+ bool status_updated = copy_if_updated(ORB_ID(vehicle_status), subs.status_sub, &buf_status);
- /* check all data subscriptions only if logging enabled,
- * logging_enabled can be changed while checking vehicle_command and vehicle_status */
- bool check_data = logging_enabled;
- int ifds = 0;
- int handled_topics = 0;
+ if (status_updated) {
+ if (log_when_armed) {
+ handle_status(&buf_status);
+ }
+ }
- /* --- VEHICLE COMMAND - LOG MANAGEMENT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_command), subs.cmd_sub, &buf.cmd);
+ /* --- GPS POSITION - LOG MANAGEMENT --- */
+ bool gps_pos_updated = copy_if_updated(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf_gps_pos);
- handle_command(&buf.cmd);
- handled_topics++;
- }
+ if (gps_pos_updated && log_name_timestamp) {
+ gps_time = buf_gps_pos.time_gps_usec;
+ }
- /* --- VEHICLE STATUS - LOG MANAGEMENT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_status), subs.status_sub, &buf_status);
+ if (!logging_enabled) {
+ continue;
+ }
- if (log_when_armed) {
- handle_status(&buf_status);
- }
+ pthread_mutex_lock(&logbuffer_mutex);
- handled_topics++;
- }
+ /* write time stamp message */
+ log_msg.msg_type = LOG_TIME_MSG;
+ log_msg.body.log_TIME.t = hrt_absolute_time();
+ LOGBUFFER_WRITE_AND_COUNT(TIME);
+
+ /* --- VEHICLE STATUS --- */
+ if (status_updated) {
+ log_msg.msg_type = LOG_STAT_MSG;
+ 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;
+ log_msg.body.log_STAT.landed = (uint8_t) buf_status.condition_landed;
+ LOGBUFFER_WRITE_AND_COUNT(STAT);
+ }
- /* --- GPS POSITION - LOG MANAGEMENT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf.gps_pos);
+ /* --- GPS POSITION --- */
+ if (gps_pos_updated) {
+ 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;
+ log_msg.body.log_GPS.eph = buf_gps_pos.eph_m;
+ log_msg.body.log_GPS.epv = buf_gps_pos.epv_m;
+ log_msg.body.log_GPS.lat = buf_gps_pos.lat;
+ log_msg.body.log_GPS.lon = buf_gps_pos.lon;
+ log_msg.body.log_GPS.alt = buf_gps_pos.alt * 0.001f;
+ log_msg.body.log_GPS.vel_n = buf_gps_pos.vel_n_m_s;
+ log_msg.body.log_GPS.vel_e = buf_gps_pos.vel_e_m_s;
+ log_msg.body.log_GPS.vel_d = buf_gps_pos.vel_d_m_s;
+ log_msg.body.log_GPS.cog = buf_gps_pos.cog_rad;
+ LOGBUFFER_WRITE_AND_COUNT(GPS);
+ }
- if (log_name_timestamp) {
- gps_time = buf.gps_pos.time_gps_usec;
- }
+ /* --- SENSOR COMBINED --- */
+ if (copy_if_updated(ORB_ID(sensor_combined), subs.sensor_sub, &buf.sensor)) {
+ bool write_IMU = false;
+ bool write_SENS = false;
- handled_topics++;
+ if (buf.sensor.gyro_counter != gyro_counter) {
+ gyro_counter = buf.sensor.gyro_counter;
+ write_IMU = true;
}
- if (!logging_enabled || !check_data || handled_topics >= poll_ret) {
- continue;
+ if (buf.sensor.accelerometer_counter != accelerometer_counter) {
+ accelerometer_counter = buf.sensor.accelerometer_counter;
+ write_IMU = true;
}
- ifds = 1; // begin from VEHICLE STATUS again
-
- pthread_mutex_lock(&logbuffer_mutex);
-
- /* write time stamp message */
- log_msg.msg_type = LOG_TIME_MSG;
- log_msg.body.log_TIME.t = hrt_absolute_time();
- LOGBUFFER_WRITE_AND_COUNT(TIME);
-
- /* --- VEHICLE STATUS --- */
- if (fds[ifds++].revents & POLLIN) {
- /* don't orb_copy, it's already done few lines above */
- log_msg.msg_type = LOG_STAT_MSG;
- 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;
- log_msg.body.log_STAT.landed = (uint8_t) buf_status.condition_landed;
- LOGBUFFER_WRITE_AND_COUNT(STAT);
+ if (buf.sensor.magnetometer_counter != magnetometer_counter) {
+ magnetometer_counter = buf.sensor.magnetometer_counter;
+ write_IMU = true;
}
- /* --- GPS POSITION --- */
- if (fds[ifds++].revents & POLLIN) {
- /* 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;
- log_msg.body.log_GPS.eph = buf.gps_pos.eph_m;
- log_msg.body.log_GPS.epv = buf.gps_pos.epv_m;
- log_msg.body.log_GPS.lat = buf.gps_pos.lat;
- log_msg.body.log_GPS.lon = buf.gps_pos.lon;
- log_msg.body.log_GPS.alt = buf.gps_pos.alt * 0.001f;
- log_msg.body.log_GPS.vel_n = buf.gps_pos.vel_n_m_s;
- log_msg.body.log_GPS.vel_e = buf.gps_pos.vel_e_m_s;
- log_msg.body.log_GPS.vel_d = buf.gps_pos.vel_d_m_s;
- log_msg.body.log_GPS.cog = buf.gps_pos.cog_rad;
- LOGBUFFER_WRITE_AND_COUNT(GPS);
+ if (buf.sensor.baro_counter != baro_counter) {
+ baro_counter = buf.sensor.baro_counter;
+ write_SENS = true;
}
- /* --- SENSOR COMBINED --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(sensor_combined), subs.sensor_sub, &buf.sensor);
- bool write_IMU = false;
- bool write_SENS = false;
-
- if (buf.sensor.gyro_counter != gyro_counter) {
- gyro_counter = buf.sensor.gyro_counter;
- write_IMU = true;
- }
-
- if (buf.sensor.accelerometer_counter != accelerometer_counter) {
- accelerometer_counter = buf.sensor.accelerometer_counter;
- write_IMU = true;
- }
-
- if (buf.sensor.magnetometer_counter != magnetometer_counter) {
- magnetometer_counter = buf.sensor.magnetometer_counter;
- write_IMU = true;
- }
-
- if (buf.sensor.baro_counter != baro_counter) {
- baro_counter = buf.sensor.baro_counter;
- write_SENS = true;
- }
-
- if (buf.sensor.differential_pressure_counter != differential_pressure_counter) {
- differential_pressure_counter = buf.sensor.differential_pressure_counter;
- write_SENS = true;
- }
-
- if (write_IMU) {
- log_msg.msg_type = LOG_IMU_MSG;
- log_msg.body.log_IMU.gyro_x = buf.sensor.gyro_rad_s[0];
- log_msg.body.log_IMU.gyro_y = buf.sensor.gyro_rad_s[1];
- log_msg.body.log_IMU.gyro_z = buf.sensor.gyro_rad_s[2];
- log_msg.body.log_IMU.acc_x = buf.sensor.accelerometer_m_s2[0];
- log_msg.body.log_IMU.acc_y = buf.sensor.accelerometer_m_s2[1];
- log_msg.body.log_IMU.acc_z = buf.sensor.accelerometer_m_s2[2];
- log_msg.body.log_IMU.mag_x = buf.sensor.magnetometer_ga[0];
- log_msg.body.log_IMU.mag_y = buf.sensor.magnetometer_ga[1];
- log_msg.body.log_IMU.mag_z = buf.sensor.magnetometer_ga[2];
- LOGBUFFER_WRITE_AND_COUNT(IMU);
- }
-
- if (write_SENS) {
- log_msg.msg_type = LOG_SENS_MSG;
- log_msg.body.log_SENS.baro_pres = buf.sensor.baro_pres_mbar;
- log_msg.body.log_SENS.baro_alt = buf.sensor.baro_alt_meter;
- log_msg.body.log_SENS.baro_temp = buf.sensor.baro_temp_celcius;
- log_msg.body.log_SENS.diff_pres = buf.sensor.differential_pressure_pa;
- LOGBUFFER_WRITE_AND_COUNT(SENS);
- }
+ if (buf.sensor.differential_pressure_counter != differential_pressure_counter) {
+ differential_pressure_counter = buf.sensor.differential_pressure_counter;
+ write_SENS = true;
}
- /* --- ATTITUDE --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_attitude), subs.att_sub, &buf.att);
- log_msg.msg_type = LOG_ATT_MSG;
- log_msg.body.log_ATT.roll = buf.att.roll;
- log_msg.body.log_ATT.pitch = buf.att.pitch;
- log_msg.body.log_ATT.yaw = buf.att.yaw;
- log_msg.body.log_ATT.roll_rate = buf.att.rollspeed;
- log_msg.body.log_ATT.pitch_rate = buf.att.pitchspeed;
- log_msg.body.log_ATT.yaw_rate = buf.att.yawspeed;
- log_msg.body.log_ATT.gx = buf.att.g_comp[0];
- log_msg.body.log_ATT.gy = buf.att.g_comp[1];
- log_msg.body.log_ATT.gz = buf.att.g_comp[2];
- LOGBUFFER_WRITE_AND_COUNT(ATT);
+ if (write_IMU) {
+ log_msg.msg_type = LOG_IMU_MSG;
+ log_msg.body.log_IMU.gyro_x = buf.sensor.gyro_rad_s[0];
+ log_msg.body.log_IMU.gyro_y = buf.sensor.gyro_rad_s[1];
+ log_msg.body.log_IMU.gyro_z = buf.sensor.gyro_rad_s[2];
+ log_msg.body.log_IMU.acc_x = buf.sensor.accelerometer_m_s2[0];
+ log_msg.body.log_IMU.acc_y = buf.sensor.accelerometer_m_s2[1];
+ log_msg.body.log_IMU.acc_z = buf.sensor.accelerometer_m_s2[2];
+ log_msg.body.log_IMU.mag_x = buf.sensor.magnetometer_ga[0];
+ log_msg.body.log_IMU.mag_y = buf.sensor.magnetometer_ga[1];
+ log_msg.body.log_IMU.mag_z = buf.sensor.magnetometer_ga[2];
+ LOGBUFFER_WRITE_AND_COUNT(IMU);
}
- /* --- ATTITUDE SETPOINT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_attitude_setpoint), subs.att_sp_sub, &buf.att_sp);
- log_msg.msg_type = LOG_ATSP_MSG;
- log_msg.body.log_ATSP.roll_sp = buf.att_sp.roll_body;
- log_msg.body.log_ATSP.pitch_sp = buf.att_sp.pitch_body;
- log_msg.body.log_ATSP.yaw_sp = buf.att_sp.yaw_body;
- log_msg.body.log_ATSP.thrust_sp = buf.att_sp.thrust;
- LOGBUFFER_WRITE_AND_COUNT(ATSP);
+ if (write_SENS) {
+ log_msg.msg_type = LOG_SENS_MSG;
+ log_msg.body.log_SENS.baro_pres = buf.sensor.baro_pres_mbar;
+ log_msg.body.log_SENS.baro_alt = buf.sensor.baro_alt_meter;
+ log_msg.body.log_SENS.baro_temp = buf.sensor.baro_temp_celcius;
+ log_msg.body.log_SENS.diff_pres = buf.sensor.differential_pressure_pa;
+ LOGBUFFER_WRITE_AND_COUNT(SENS);
}
+ }
- /* --- RATES SETPOINT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_rates_setpoint), subs.rates_sp_sub, &buf.rates_sp);
- log_msg.msg_type = LOG_ARSP_MSG;
- log_msg.body.log_ARSP.roll_rate_sp = buf.rates_sp.roll;
- log_msg.body.log_ARSP.pitch_rate_sp = buf.rates_sp.pitch;
- log_msg.body.log_ARSP.yaw_rate_sp = buf.rates_sp.yaw;
- LOGBUFFER_WRITE_AND_COUNT(ARSP);
- }
+ /* --- ATTITUDE --- */
+ if (copy_if_updated(ORB_ID(vehicle_attitude), subs.att_sub, &buf.att)) {
+ log_msg.msg_type = LOG_ATT_MSG;
+ log_msg.body.log_ATT.roll = buf.att.roll;
+ log_msg.body.log_ATT.pitch = buf.att.pitch;
+ log_msg.body.log_ATT.yaw = buf.att.yaw;
+ log_msg.body.log_ATT.roll_rate = buf.att.rollspeed;
+ log_msg.body.log_ATT.pitch_rate = buf.att.pitchspeed;
+ log_msg.body.log_ATT.yaw_rate = buf.att.yawspeed;
+ log_msg.body.log_ATT.gx = buf.att.g_comp[0];
+ log_msg.body.log_ATT.gy = buf.att.g_comp[1];
+ log_msg.body.log_ATT.gz = buf.att.g_comp[2];
+ LOGBUFFER_WRITE_AND_COUNT(ATT);
+ }
- /* --- ACTUATOR OUTPUTS --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(actuator_outputs_0), subs.act_outputs_sub, &buf.act_outputs);
- log_msg.msg_type = LOG_OUT0_MSG;
- memcpy(log_msg.body.log_OUT0.output, buf.act_outputs.output, sizeof(log_msg.body.log_OUT0.output));
- LOGBUFFER_WRITE_AND_COUNT(OUT0);
- }
+ /* --- ATTITUDE SETPOINT --- */
+ if (copy_if_updated(ORB_ID(vehicle_attitude_setpoint), subs.att_sp_sub, &buf.att_sp)) {
+ log_msg.msg_type = LOG_ATSP_MSG;
+ log_msg.body.log_ATSP.roll_sp = buf.att_sp.roll_body;
+ log_msg.body.log_ATSP.pitch_sp = buf.att_sp.pitch_body;
+ log_msg.body.log_ATSP.yaw_sp = buf.att_sp.yaw_body;
+ log_msg.body.log_ATSP.thrust_sp = buf.att_sp.thrust;
+ LOGBUFFER_WRITE_AND_COUNT(ATSP);
+ }
- /* --- ACTUATOR CONTROL --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, subs.act_controls_sub, &buf.act_controls);
- log_msg.msg_type = LOG_ATTC_MSG;
- log_msg.body.log_ATTC.roll = buf.act_controls.control[0];
- log_msg.body.log_ATTC.pitch = buf.act_controls.control[1];
- log_msg.body.log_ATTC.yaw = buf.act_controls.control[2];
- log_msg.body.log_ATTC.thrust = buf.act_controls.control[3];
- LOGBUFFER_WRITE_AND_COUNT(ATTC);
- }
+ /* --- RATES SETPOINT --- */
+ if (copy_if_updated(ORB_ID(vehicle_rates_setpoint), subs.rates_sp_sub, &buf.rates_sp)) {
+ log_msg.msg_type = LOG_ARSP_MSG;
+ log_msg.body.log_ARSP.roll_rate_sp = buf.rates_sp.roll;
+ log_msg.body.log_ARSP.pitch_rate_sp = buf.rates_sp.pitch;
+ log_msg.body.log_ARSP.yaw_rate_sp = buf.rates_sp.yaw;
+ LOGBUFFER_WRITE_AND_COUNT(ARSP);
+ }
- /* --- LOCAL POSITION --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_local_position), subs.local_pos_sub, &buf.local_pos);
- log_msg.msg_type = LOG_LPOS_MSG;
- log_msg.body.log_LPOS.x = buf.local_pos.x;
- log_msg.body.log_LPOS.y = buf.local_pos.y;
- log_msg.body.log_LPOS.z = buf.local_pos.z;
- log_msg.body.log_LPOS.vx = buf.local_pos.vx;
- log_msg.body.log_LPOS.vy = buf.local_pos.vy;
- log_msg.body.log_LPOS.vz = buf.local_pos.vz;
- log_msg.body.log_LPOS.ref_lat = buf.local_pos.ref_lat;
- log_msg.body.log_LPOS.ref_lon = buf.local_pos.ref_lon;
- log_msg.body.log_LPOS.ref_alt = buf.local_pos.ref_alt;
- log_msg.body.log_LPOS.xy_flags = (buf.local_pos.xy_valid ? 1 : 0) | (buf.local_pos.v_xy_valid ? 2 : 0) | (buf.local_pos.xy_global ? 8 : 0);
- log_msg.body.log_LPOS.z_flags = (buf.local_pos.z_valid ? 1 : 0) | (buf.local_pos.v_z_valid ? 2 : 0) | (buf.local_pos.z_global ? 8 : 0);
- log_msg.body.log_LPOS.landed = buf.local_pos.landed;
- LOGBUFFER_WRITE_AND_COUNT(LPOS);
-
- if (buf.local_pos.dist_bottom_valid) {
- dist_bottom_present = true;
- }
- if (dist_bottom_present) {
- log_msg.msg_type = LOG_DIST_MSG;
- log_msg.body.log_DIST.bottom = buf.local_pos.dist_bottom;
- log_msg.body.log_DIST.bottom_rate = buf.local_pos.dist_bottom_rate;
- log_msg.body.log_DIST.flags = (buf.local_pos.dist_bottom_valid ? 1 : 0);
- LOGBUFFER_WRITE_AND_COUNT(DIST);
- }
- }
+ /* --- ACTUATOR OUTPUTS --- */
+ if (copy_if_updated(ORB_ID(actuator_outputs_0), subs.act_outputs_sub, &buf.act_outputs)) {
+ log_msg.msg_type = LOG_OUT0_MSG;
+ memcpy(log_msg.body.log_OUT0.output, buf.act_outputs.output, sizeof(log_msg.body.log_OUT0.output));
+ LOGBUFFER_WRITE_AND_COUNT(OUT0);
+ }
- /* --- LOCAL POSITION SETPOINT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_local_position_setpoint), subs.local_pos_sp_sub, &buf.local_pos_sp);
- log_msg.msg_type = LOG_LPSP_MSG;
- log_msg.body.log_LPSP.x = buf.local_pos_sp.x;
- log_msg.body.log_LPSP.y = buf.local_pos_sp.y;
- log_msg.body.log_LPSP.z = buf.local_pos_sp.z;
- log_msg.body.log_LPSP.yaw = buf.local_pos_sp.yaw;
- LOGBUFFER_WRITE_AND_COUNT(LPSP);
- }
+ /* --- ACTUATOR CONTROL --- */
+ if (copy_if_updated(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, subs.act_controls_sub, &buf.act_controls)) {
+ log_msg.msg_type = LOG_ATTC_MSG;
+ log_msg.body.log_ATTC.roll = buf.act_controls.control[0];
+ log_msg.body.log_ATTC.pitch = buf.act_controls.control[1];
+ log_msg.body.log_ATTC.yaw = buf.act_controls.control[2];
+ log_msg.body.log_ATTC.thrust = buf.act_controls.control[3];
+ LOGBUFFER_WRITE_AND_COUNT(ATTC);
+ }
- /* --- GLOBAL POSITION --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_global_position), subs.global_pos_sub, &buf.global_pos);
- log_msg.msg_type = LOG_GPOS_MSG;
- log_msg.body.log_GPOS.lat = buf.global_pos.lat * 1e7;
- log_msg.body.log_GPOS.lon = buf.global_pos.lon * 1e7;
- log_msg.body.log_GPOS.alt = buf.global_pos.alt;
- 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);
+ /* --- LOCAL POSITION --- */
+ if (copy_if_updated(ORB_ID(vehicle_local_position), subs.local_pos_sub, &buf.local_pos)) {
+ log_msg.msg_type = LOG_LPOS_MSG;
+ log_msg.body.log_LPOS.x = buf.local_pos.x;
+ log_msg.body.log_LPOS.y = buf.local_pos.y;
+ log_msg.body.log_LPOS.z = buf.local_pos.z;
+ log_msg.body.log_LPOS.vx = buf.local_pos.vx;
+ log_msg.body.log_LPOS.vy = buf.local_pos.vy;
+ log_msg.body.log_LPOS.vz = buf.local_pos.vz;
+ log_msg.body.log_LPOS.ref_lat = buf.local_pos.ref_lat;
+ log_msg.body.log_LPOS.ref_lon = buf.local_pos.ref_lon;
+ log_msg.body.log_LPOS.ref_alt = buf.local_pos.ref_alt;
+ log_msg.body.log_LPOS.xy_flags = (buf.local_pos.xy_valid ? 1 : 0) | (buf.local_pos.v_xy_valid ? 2 : 0) | (buf.local_pos.xy_global ? 8 : 0);
+ log_msg.body.log_LPOS.z_flags = (buf.local_pos.z_valid ? 1 : 0) | (buf.local_pos.v_z_valid ? 2 : 0) | (buf.local_pos.z_global ? 8 : 0);
+ log_msg.body.log_LPOS.landed = buf.local_pos.landed;
+ LOGBUFFER_WRITE_AND_COUNT(LPOS);
+
+ if (buf.local_pos.dist_bottom_valid) {
+ dist_bottom_present = true;
}
- /* --- GLOBAL POSITION SETPOINT --- */
- 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;
- log_msg.body.log_GPSP.yaw = buf.triplet.current.yaw;
- log_msg.body.log_GPSP.type = buf.triplet.current.type;
- log_msg.body.log_GPSP.loiter_radius = buf.triplet.current.loiter_radius;
- log_msg.body.log_GPSP.loiter_direction = buf.triplet.current.loiter_direction;
- log_msg.body.log_GPSP.pitch_min = buf.triplet.current.pitch_min;
- LOGBUFFER_WRITE_AND_COUNT(GPSP);
+ if (dist_bottom_present) {
+ log_msg.msg_type = LOG_DIST_MSG;
+ log_msg.body.log_DIST.bottom = buf.local_pos.dist_bottom;
+ log_msg.body.log_DIST.bottom_rate = buf.local_pos.dist_bottom_rate;
+ log_msg.body.log_DIST.flags = (buf.local_pos.dist_bottom_valid ? 1 : 0);
+ LOGBUFFER_WRITE_AND_COUNT(DIST);
}
+ }
- /* --- VICON POSITION --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_vicon_position), subs.vicon_pos_sub, &buf.vicon_pos);
- // TODO not implemented yet
- }
+ /* --- LOCAL POSITION SETPOINT --- */
+ if (copy_if_updated(ORB_ID(vehicle_local_position_setpoint), subs.local_pos_sp_sub, &buf.local_pos_sp)) {
+ log_msg.msg_type = LOG_LPSP_MSG;
+ log_msg.body.log_LPSP.x = buf.local_pos_sp.x;
+ log_msg.body.log_LPSP.y = buf.local_pos_sp.y;
+ log_msg.body.log_LPSP.z = buf.local_pos_sp.z;
+ log_msg.body.log_LPSP.yaw = buf.local_pos_sp.yaw;
+ LOGBUFFER_WRITE_AND_COUNT(LPSP);
+ }
- /* --- FLOW --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(optical_flow), subs.flow_sub, &buf.flow);
- log_msg.msg_type = LOG_FLOW_MSG;
- log_msg.body.log_FLOW.flow_raw_x = buf.flow.flow_raw_x;
- log_msg.body.log_FLOW.flow_raw_y = buf.flow.flow_raw_y;
- log_msg.body.log_FLOW.flow_comp_x = buf.flow.flow_comp_x_m;
- log_msg.body.log_FLOW.flow_comp_y = buf.flow.flow_comp_y_m;
- log_msg.body.log_FLOW.distance = buf.flow.ground_distance_m;
- log_msg.body.log_FLOW.quality = buf.flow.quality;
- log_msg.body.log_FLOW.sensor_id = buf.flow.sensor_id;
- LOGBUFFER_WRITE_AND_COUNT(FLOW);
- }
+ /* --- GLOBAL POSITION --- */
+ if (copy_if_updated(ORB_ID(vehicle_global_position), subs.global_pos_sub, &buf.global_pos)) {
+ log_msg.msg_type = LOG_GPOS_MSG;
+ log_msg.body.log_GPOS.lat = buf.global_pos.lat * 1e7;
+ log_msg.body.log_GPOS.lon = buf.global_pos.lon * 1e7;
+ log_msg.body.log_GPOS.alt = buf.global_pos.alt;
+ 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);
+ }
- /* --- RC CHANNELS --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(rc_channels), subs.rc_sub, &buf.rc);
- log_msg.msg_type = LOG_RC_MSG;
- /* Copy only the first 8 channels of 14 */
- memcpy(log_msg.body.log_RC.channel, buf.rc.chan, sizeof(log_msg.body.log_RC.channel));
- log_msg.body.log_RC.channel_count = buf.rc.chan_count;
- LOGBUFFER_WRITE_AND_COUNT(RC);
- }
+ /* --- GLOBAL POSITION SETPOINT --- */
+ if (copy_if_updated(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;
+ log_msg.body.log_GPSP.yaw = buf.triplet.current.yaw;
+ log_msg.body.log_GPSP.type = buf.triplet.current.type;
+ log_msg.body.log_GPSP.loiter_radius = buf.triplet.current.loiter_radius;
+ log_msg.body.log_GPSP.loiter_direction = buf.triplet.current.loiter_direction;
+ log_msg.body.log_GPSP.pitch_min = buf.triplet.current.pitch_min;
+ LOGBUFFER_WRITE_AND_COUNT(GPSP);
+ }
- /* --- AIRSPEED --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(airspeed), subs.airspeed_sub, &buf.airspeed);
- log_msg.msg_type = LOG_AIRS_MSG;
- log_msg.body.log_AIRS.indicated_airspeed = buf.airspeed.indicated_airspeed_m_s;
- log_msg.body.log_AIRS.true_airspeed = buf.airspeed.true_airspeed_m_s;
- LOGBUFFER_WRITE_AND_COUNT(AIRS);
- }
+ /* --- VICON POSITION --- */
+ if (copy_if_updated(ORB_ID(vehicle_vicon_position), subs.vicon_pos_sub, &buf.vicon_pos)) {
+ // TODO not implemented yet
+ }
- /* --- ESCs --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(esc_status), subs.esc_sub, &buf.esc);
-
- for (uint8_t i = 0; i < buf.esc.esc_count; i++) {
- log_msg.msg_type = LOG_ESC_MSG;
- log_msg.body.log_ESC.counter = buf.esc.counter;
- log_msg.body.log_ESC.esc_count = buf.esc.esc_count;
- log_msg.body.log_ESC.esc_connectiontype = buf.esc.esc_connectiontype;
- log_msg.body.log_ESC.esc_num = i;
- log_msg.body.log_ESC.esc_address = buf.esc.esc[i].esc_address;
- log_msg.body.log_ESC.esc_version = buf.esc.esc[i].esc_version;
- log_msg.body.log_ESC.esc_voltage = buf.esc.esc[i].esc_voltage;
- log_msg.body.log_ESC.esc_current = buf.esc.esc[i].esc_current;
- log_msg.body.log_ESC.esc_rpm = buf.esc.esc[i].esc_rpm;
- log_msg.body.log_ESC.esc_temperature = buf.esc.esc[i].esc_temperature;
- log_msg.body.log_ESC.esc_setpoint = buf.esc.esc[i].esc_setpoint;
- log_msg.body.log_ESC.esc_setpoint_raw = buf.esc.esc[i].esc_setpoint_raw;
- LOGBUFFER_WRITE_AND_COUNT(ESC);
- }
- }
+ /* --- FLOW --- */
+ if (copy_if_updated(ORB_ID(optical_flow), subs.flow_sub, &buf.flow)) {
+ log_msg.msg_type = LOG_FLOW_MSG;
+ log_msg.body.log_FLOW.flow_raw_x = buf.flow.flow_raw_x;
+ log_msg.body.log_FLOW.flow_raw_y = buf.flow.flow_raw_y;
+ log_msg.body.log_FLOW.flow_comp_x = buf.flow.flow_comp_x_m;
+ log_msg.body.log_FLOW.flow_comp_y = buf.flow.flow_comp_y_m;
+ log_msg.body.log_FLOW.distance = buf.flow.ground_distance_m;
+ log_msg.body.log_FLOW.quality = buf.flow.quality;
+ log_msg.body.log_FLOW.sensor_id = buf.flow.sensor_id;
+ LOGBUFFER_WRITE_AND_COUNT(FLOW);
+ }
- /* --- GLOBAL VELOCITY SETPOINT --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(vehicle_global_velocity_setpoint), subs.global_vel_sp_sub, &buf.global_vel_sp);
- log_msg.msg_type = LOG_GVSP_MSG;
- log_msg.body.log_GVSP.vx = buf.global_vel_sp.vx;
- log_msg.body.log_GVSP.vy = buf.global_vel_sp.vy;
- log_msg.body.log_GVSP.vz = buf.global_vel_sp.vz;
- LOGBUFFER_WRITE_AND_COUNT(GVSP);
- }
+ /* --- RC CHANNELS --- */
+ if (copy_if_updated(ORB_ID(rc_channels), subs.rc_sub, &buf.rc)) {
+ log_msg.msg_type = LOG_RC_MSG;
+ /* Copy only the first 8 channels of 14 */
+ memcpy(log_msg.body.log_RC.channel, buf.rc.chan, sizeof(log_msg.body.log_RC.channel));
+ log_msg.body.log_RC.channel_count = buf.rc.chan_count;
+ LOGBUFFER_WRITE_AND_COUNT(RC);
+ }
- /* --- BATTERY --- */
- if (fds[ifds++].revents & POLLIN) {
- orb_copy(ORB_ID(battery_status), subs.battery_sub, &buf.battery);
- log_msg.msg_type = LOG_BATT_MSG;
- log_msg.body.log_BATT.voltage = buf.battery.voltage_v;
- log_msg.body.log_BATT.voltage_filtered = buf.battery.voltage_filtered_v;
- log_msg.body.log_BATT.current = buf.battery.current_a;
- log_msg.body.log_BATT.discharged = buf.battery.discharged_mah;
- LOGBUFFER_WRITE_AND_COUNT(BATT);
- }
+ /* --- AIRSPEED --- */
+ if (copy_if_updated(ORB_ID(airspeed), subs.airspeed_sub, &buf.airspeed)) {
+ log_msg.msg_type = LOG_AIRS_MSG;
+ log_msg.body.log_AIRS.indicated_airspeed = buf.airspeed.indicated_airspeed_m_s;
+ log_msg.body.log_AIRS.true_airspeed = buf.airspeed.true_airspeed_m_s;
+ LOGBUFFER_WRITE_AND_COUNT(AIRS);
+ }
- /* --- 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);
+ /* --- ESCs --- */
+ if (copy_if_updated(ORB_ID(esc_status), subs.esc_sub, &buf.esc)) {
+ for (uint8_t i = 0; i < buf.esc.esc_count; i++) {
+ log_msg.msg_type = LOG_ESC_MSG;
+ log_msg.body.log_ESC.counter = buf.esc.counter;
+ log_msg.body.log_ESC.esc_count = buf.esc.esc_count;
+ log_msg.body.log_ESC.esc_connectiontype = buf.esc.esc_connectiontype;
+ log_msg.body.log_ESC.esc_num = i;
+ log_msg.body.log_ESC.esc_address = buf.esc.esc[i].esc_address;
+ log_msg.body.log_ESC.esc_version = buf.esc.esc[i].esc_version;
+ log_msg.body.log_ESC.esc_voltage = buf.esc.esc[i].esc_voltage;
+ log_msg.body.log_ESC.esc_current = buf.esc.esc[i].esc_current;
+ log_msg.body.log_ESC.esc_rpm = buf.esc.esc[i].esc_rpm;
+ log_msg.body.log_ESC.esc_temperature = buf.esc.esc[i].esc_temperature;
+ log_msg.body.log_ESC.esc_setpoint = buf.esc.esc[i].esc_setpoint;
+ log_msg.body.log_ESC.esc_setpoint_raw = buf.esc.esc[i].esc_setpoint_raw;
+ LOGBUFFER_WRITE_AND_COUNT(ESC);
}
+ }
- /* 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 */
- pthread_cond_signal(&logbuffer_cond);
- }
+ /* --- GLOBAL VELOCITY SETPOINT --- */
+ if (copy_if_updated(ORB_ID(vehicle_global_velocity_setpoint), subs.global_vel_sp_sub, &buf.global_vel_sp)) {
+ log_msg.msg_type = LOG_GVSP_MSG;
+ log_msg.body.log_GVSP.vx = buf.global_vel_sp.vx;
+ log_msg.body.log_GVSP.vy = buf.global_vel_sp.vy;
+ log_msg.body.log_GVSP.vz = buf.global_vel_sp.vz;
+ LOGBUFFER_WRITE_AND_COUNT(GVSP);
+ }
+
+ /* --- BATTERY --- */
+ if (copy_if_updated(ORB_ID(battery_status), subs.battery_sub, &buf.battery)) {
+ log_msg.msg_type = LOG_BATT_MSG;
+ log_msg.body.log_BATT.voltage = buf.battery.voltage_v;
+ log_msg.body.log_BATT.voltage_filtered = buf.battery.voltage_filtered_v;
+ log_msg.body.log_BATT.current = buf.battery.current_a;
+ log_msg.body.log_BATT.discharged = buf.battery.discharged_mah;
+ LOGBUFFER_WRITE_AND_COUNT(BATT);
+ }
- /* unlock, now the writer thread may run */
- pthread_mutex_unlock(&logbuffer_mutex);
+ /* --- TELEMETRY --- */
+ if (copy_if_updated(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);
}
- if (use_sleep) {
- usleep(sleep_delay);
+ /* --- BOTTOM DISTANCE --- */
+ if (copy_if_updated(ORB_ID(sensor_range_finder), subs.range_finder_sub, &buf.range_finder)) {
+ log_msg.msg_type = LOG_DIST_MSG;
+ log_msg.body.log_DIST.bottom = buf.range_finder.distance;
+ log_msg.body.log_DIST.bottom_rate = 0.0f;
+ log_msg.body.log_DIST.flags = (buf.range_finder.valid ? 1 : 0);
+ LOGBUFFER_WRITE_AND_COUNT(DIST);
}
+
+ /* 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 */
+ pthread_cond_signal(&logbuffer_cond);
+ }
+
+ /* unlock, now the writer thread may run */
+ pthread_mutex_unlock(&logbuffer_mutex);
}
- if (logging_enabled)
+ if (logging_enabled) {
sdlog2_stop_log();
+ }
pthread_mutex_destroy(&logbuffer_mutex);
pthread_cond_destroy(&logbuffer_cond);
@@ -1461,8 +1328,6 @@ int file_copy(const char *file_old, const char *file_new)
void handle_command(struct vehicle_command_s *cmd)
{
- /* result of the command */
- uint8_t result = VEHICLE_CMD_RESULT_UNSUPPORTED;
int param;
/* request to set different system mode */
diff --git a/src/modules/sdlog2/sdlog2_messages.h b/src/modules/sdlog2/sdlog2_messages.h
index 16bfc355d..e27518aa0 100644
--- a/src/modules/sdlog2/sdlog2_messages.h
+++ b/src/modules/sdlog2/sdlog2_messages.h
@@ -267,13 +267,13 @@ struct log_DIST_s {
/* --- TELE - TELEMETRY STATUS --- */
#define LOG_TELE_MSG 22
struct log_TELE_s {
- uint8_t rssi;
- uint8_t remote_rssi;
- uint8_t noise;
- uint8_t remote_noise;
- uint16_t rxerrors;
- uint16_t fixed;
- uint8_t txbuf;
+ uint8_t rssi;
+ uint8_t remote_rssi;
+ uint8_t noise;
+ uint8_t remote_noise;
+ uint16_t rxerrors;
+ uint16_t fixed;
+ uint8_t txbuf;
};
/********** SYSTEM MESSAGES, ID > 0x80 **********/
diff --git a/src/systemcmds/dumpfile/dumpfile.c b/src/systemcmds/dumpfile/dumpfile.c
new file mode 100644
index 000000000..c18814342
--- /dev/null
+++ b/src/systemcmds/dumpfile/dumpfile.c
@@ -0,0 +1,116 @@
+/****************************************************************************
+ *
+ * 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 dumpfile.c
+ *
+ * Dump file utility. Prints file size and contents in binary mode (don't replace LF with CR LF) to stdout.
+ *
+ * @author Anton Babushkin <anton.babushkin@me.com>
+ */
+
+#include <nuttx/config.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <systemlib/err.h>
+
+__EXPORT int dumpfile_main(int argc, char *argv[]);
+
+int
+dumpfile_main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ errx(1, "usage: dumpfile <filename>");
+ }
+
+ /* open input file */
+ FILE *f;
+ f = fopen(argv[1], "r");
+
+ if (f == NULL) {
+ printf("ERROR\n");
+ exit(1);
+ }
+
+ /* get file size */
+ fseek(f, 0L, SEEK_END);
+ int size = ftell(f);
+ fseek(f, 0L, SEEK_SET);
+
+ printf("OK %d\n", size);
+
+ /* configure stdout */
+ int out = fileno(stdout);
+
+ struct termios tc;
+ struct termios tc_old;
+ tcgetattr(out, &tc);
+
+ /* save old terminal attributes to restore it later on exit */
+ memcpy(&tc_old, &tc, sizeof(tc));
+
+ /* don't add CR on each LF*/
+ tc.c_oflag &= ~ONLCR;
+
+ if (tcsetattr(out, TCSANOW, &tc) < 0) {
+ warnx("ERROR setting stdout attributes");
+ exit(1);
+ }
+
+ char buf[512];
+ int nread;
+
+ /* dump file */
+ while ((nread = fread(buf, 1, sizeof(buf), f)) > 0) {
+ if (write(out, buf, nread) <= 0) {
+ warnx("error dumping file");
+ break;
+ }
+ }
+
+ fsync(out);
+ fclose(f);
+
+ /* restore old terminal attributes */
+ if (tcsetattr(out, TCSANOW, &tc_old) < 0) {
+ warnx("ERROR restoring stdout attributes");
+ exit(1);
+ }
+
+ return OK;
+}
diff --git a/src/systemcmds/dumpfile/module.mk b/src/systemcmds/dumpfile/module.mk
new file mode 100644
index 000000000..36461f477
--- /dev/null
+++ b/src/systemcmds/dumpfile/module.mk
@@ -0,0 +1,41 @@
+############################################################################
+#
+# 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.
+#
+############################################################################
+
+#
+# Dump file utility
+#
+
+MODULE_COMMAND = dumpfile
+SRCS = dumpfile.c
+
+MAXOPTIMIZATION = -Os