mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-16 07:23:33 +08:00
Merge remote-tracking branch 'px4/ekf_params' into navigator_cleanup_ekf_params
Conflicts: src/modules/ekf_att_pos_estimator/fw_att_pos_estimator_main.cpp
This commit is contained in:
@@ -37,3 +37,5 @@ mavlink/include/mavlink/v0.9/
|
||||
tags
|
||||
.tags_sorted_by_file
|
||||
.pydevproject
|
||||
.ropeproject
|
||||
*.orig
|
||||
|
||||
+5
-5
@@ -34,10 +34,10 @@ define _showheap
|
||||
else
|
||||
set $MM_ALLOC_BIT = 0x80000000
|
||||
end
|
||||
printf "HEAP %d %p - %p\n", $index, g_heapstart[$index], g_heapend[$index]
|
||||
printf "HEAP %d %p - %p\n", $index, g_mmheap.mm_heapstart[$index], g_mmheap.mm_heapend[$index]
|
||||
printf "ptr size\n"
|
||||
set $node = (char *)g_heapstart[$index] + sizeof(struct mm_allocnode_s)
|
||||
while $node < g_heapend[$index]
|
||||
set $node = (char *)g_mmheap.mm_heapstart[$index] + sizeof(struct mm_allocnode_s)
|
||||
while $node < g_mmheap.mm_heapend[$index]
|
||||
printf " %p", $node
|
||||
set $nodestruct = (struct mm_allocnode_s *)$node
|
||||
printf " %u", $nodestruct->size
|
||||
@@ -47,7 +47,7 @@ define _showheap
|
||||
else
|
||||
set $used = $used + $nodestruct->size
|
||||
end
|
||||
if ($nodestruct->size > g_heapsize) || (($node + $nodestruct->size) > g_heapend[$index])
|
||||
if ($nodestruct->size > g_mmheap.mm_heapsize) || (($node + $nodestruct->size) > g_mmheap.mm_heapend[$index])
|
||||
printf " (BAD SIZE)"
|
||||
end
|
||||
printf "\n"
|
||||
@@ -59,7 +59,7 @@ define _showheap
|
||||
end
|
||||
|
||||
define showheap
|
||||
set $nheaps = sizeof(g_heapstart) / sizeof(g_heapstart[0])
|
||||
set $nheaps = sizeof(g_mmheap.mm_heapstart) / sizeof(g_mmheap.mm_heapstart[0])
|
||||
printf "Printing %d heaps\n", $nheaps
|
||||
set $heapindex = (int)0
|
||||
while $heapindex < $nheaps
|
||||
|
||||
+10
-6
@@ -306,12 +306,15 @@ class NX_show_heap (gdb.Command):
|
||||
|
||||
def __init__(self):
|
||||
super(NX_show_heap, self).__init__('show heap', gdb.COMMAND_USER)
|
||||
if gdb.lookup_type('struct mm_allocnode_s').sizeof == 8:
|
||||
self._allocflag = 0x80000000
|
||||
self._allocnodesize = 8
|
||||
else:
|
||||
struct_mm_allocnode_s = gdb.lookup_type('struct mm_allocnode_s')
|
||||
preceding_size = struct_mm_allocnode_s['preceding'].type.sizeof
|
||||
if preceding_size == 2:
|
||||
self._allocflag = 0x8000
|
||||
self._allocnodesize = 4
|
||||
elif preceding_size == 4:
|
||||
self._allocflag = 0x80000000
|
||||
else:
|
||||
raise gdb.GdbError('invalid mm_allocnode_s.preceding size %u' % preceding_size)
|
||||
self._allocnodesize = struct_mm_allocnode_s.sizeof
|
||||
|
||||
def _node_allocated(self, allocnode):
|
||||
if allocnode['preceding'] & self._allocflag:
|
||||
@@ -333,7 +336,8 @@ class NX_show_heap (gdb.Command):
|
||||
state = ''
|
||||
else:
|
||||
state = '(free)'
|
||||
print ' {} {} {}'.format(allocnode.address + 8, self._node_size(allocnode), state)
|
||||
print ' {} {} {}'.format(allocnode.address + self._allocnodesize,
|
||||
self._node_size(allocnode), state)
|
||||
cursor += self._node_size(allocnode) / self._allocnodesize
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
sh /etc/init.d/rc.fw_defaults
|
||||
|
||||
set MIXER FMU_RET
|
||||
set MIXER easystar.mix
|
||||
|
||||
@@ -11,7 +11,7 @@ px4io recovery
|
||||
# Adjust PX4IO update rate limit
|
||||
#
|
||||
set PX4IO_LIMIT 400
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
set PX4IO_LIMIT 200
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
if [ -d /fs/microsd ]
|
||||
then
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
echo "Start sdlog2 at 50Hz"
|
||||
sdlog2 start -r 50 -a -b 8 -t
|
||||
|
||||
@@ -32,9 +32,9 @@ then
|
||||
param set MPC_Z_VEL_D 0.0
|
||||
param set MPC_Z_VEL_MAX 3
|
||||
param set MPC_Z_FF 0.5
|
||||
param set MPC_TILT_MAX 1.0
|
||||
param set MPC_TILTMAX_AIR 45.0
|
||||
param set MPC_TILTMAX_LND 15.0
|
||||
param set MPC_LAND_SPEED 1.0
|
||||
param set MPC_LAND_TILT 0.3
|
||||
|
||||
param set PE_VELNE_NOISE 0.5
|
||||
param set PE_VELNE_NOISE 0.7
|
||||
|
||||
@@ -22,7 +22,7 @@ then
|
||||
echo "[init] Using L3GD20(H)"
|
||||
fi
|
||||
|
||||
if hw_ver compare PX4FMU_V2
|
||||
if ver hwcmp PX4FMU_V2
|
||||
then
|
||||
if lsm303d start
|
||||
then
|
||||
|
||||
@@ -120,6 +120,8 @@ then
|
||||
set EXIT_ON_END no
|
||||
set MAV_TYPE none
|
||||
set LOAD_DEFAULT_APPS yes
|
||||
set GPS yes
|
||||
set GPS_FAKE no
|
||||
|
||||
#
|
||||
# Set DO_AUTOCONFIG flag to use it in AUTOSTART scripts
|
||||
@@ -246,7 +248,7 @@ then
|
||||
echo "[init] ERROR: PX4IO not found, disabling output"
|
||||
|
||||
# Avoid using ttyS0 for MAVLink on FMUv1
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
set FMU_MODE serial
|
||||
fi
|
||||
@@ -260,7 +262,7 @@ then
|
||||
if [ $HIL == yes ]
|
||||
then
|
||||
set OUTPUT_MODE hil
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
set FMU_MODE serial
|
||||
fi
|
||||
@@ -306,7 +308,7 @@ then
|
||||
tone_alarm $TUNE_OUT_ERROR
|
||||
fi
|
||||
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
if [ $FMU_MODE == pwm -o $FMU_MODE == gpio ]
|
||||
then
|
||||
@@ -381,7 +383,7 @@ then
|
||||
tone_alarm $TUNE_OUT_ERROR
|
||||
fi
|
||||
|
||||
if hw_ver compare PX4FMU_V1
|
||||
if ver hwcmp PX4FMU_V1
|
||||
then
|
||||
if [ $FMU_MODE == pwm -o $FMU_MODE == gpio ]
|
||||
then
|
||||
@@ -437,9 +439,19 @@ then
|
||||
echo "[init] Start logging"
|
||||
sh /etc/init.d/rc.logging
|
||||
fi
|
||||
|
||||
gps start
|
||||
|
||||
if [ $GPS == yes ]
|
||||
then
|
||||
echo "[init] Start GPS"
|
||||
if [ $GPS_FAKE == yes ]
|
||||
then
|
||||
echo "[init] Faking GPS"
|
||||
gps start -f
|
||||
else
|
||||
gps start
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Start up ARDrone Motor interface
|
||||
#
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
EASYSTAR / EASYSTAR II MIXER
|
||||
============================
|
||||
|
||||
Aileron mixer
|
||||
-------------
|
||||
One output - would be easy to add support for 2 servos
|
||||
|
||||
M: 1
|
||||
O: 10000 10000 0 -10000 10000
|
||||
S: 0 0 10000 10000 0 -10000 10000
|
||||
|
||||
Elevator mixer
|
||||
------------
|
||||
|
||||
M: 1
|
||||
O: 10000 10000 0 -10000 10000
|
||||
S: 0 1 -10000 -10000 0 -10000 10000
|
||||
|
||||
Rudder mixer
|
||||
------------
|
||||
|
||||
M: 1
|
||||
O: 10000 10000 0 -10000 10000
|
||||
S: 0 2 -10000 -10000 0 -10000 10000
|
||||
|
||||
Motor speed mixer
|
||||
-----------------
|
||||
|
||||
M: 1
|
||||
O: 10000 10000 0 -10000 10000
|
||||
S: 0 3 0 20000 -10000 -10000 10000
|
||||
+15
-14
@@ -43,29 +43,30 @@ 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
|
||||
|
||||
# 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:
|
||||
if ".zip" in file or ".bin" in file or ".swp" in file:
|
||||
continue
|
||||
|
||||
file_path = os.path.join(root, file)
|
||||
|
||||
|
||||
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:
|
||||
|
||||
for line in f:
|
||||
|
||||
# handle mixer files differently than startup files
|
||||
if file_path.endswith(".mix"):
|
||||
if line.startswith(("Z:", "M:", "R: ", "O:", "S:")):
|
||||
@@ -73,11 +74,11 @@ def main():
|
||||
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()
|
||||
main()
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
./obj/*
|
||||
mixer_test
|
||||
sbus2_test
|
||||
autodeclination_test
|
||||
|
||||
+26
-34
@@ -1,47 +1,39 @@
|
||||
|
||||
CC=g++
|
||||
CFLAGS=-I. -I../../src/modules -I ../../src/include -I../../src/drivers -I../../src -D__EXPORT="" -Dnullptr="0"
|
||||
CFLAGS=-I. -I../../src/modules -I ../../src/include -I../../src/drivers \
|
||||
-I../../src -I../../src/lib -D__EXPORT="" -Dnullptr="0" -lm
|
||||
|
||||
ODIR=obj
|
||||
LDIR =../lib
|
||||
all: mixer_test sbus2_test autodeclination_test
|
||||
|
||||
LIBS=-lm
|
||||
MIXER_FILES=../../src/systemcmds/tests/test_mixer.cpp \
|
||||
../../src/systemcmds/tests/test_conv.cpp \
|
||||
../../src/modules/systemlib/mixer/mixer_simple.cpp \
|
||||
../../src/modules/systemlib/mixer/mixer_multirotor.cpp \
|
||||
../../src/modules/systemlib/mixer/mixer.cpp \
|
||||
../../src/modules/systemlib/mixer/mixer_group.cpp \
|
||||
../../src/modules/systemlib/mixer/mixer_load.c \
|
||||
../../src/modules/systemlib/pwm_limit/pwm_limit.c \
|
||||
hrt.cpp \
|
||||
mixer_test.cpp
|
||||
|
||||
#_DEPS = test.h
|
||||
#DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
||||
SBUS2_FILES=../../src/modules/px4iofirmware/sbus.c \
|
||||
hrt.cpp \
|
||||
sbus2_test.cpp
|
||||
|
||||
_OBJ = mixer_test.o test_mixer.o mixer_simple.o mixer_multirotor.o \
|
||||
mixer.o mixer_group.o mixer_load.o test_conv.o pwm_limit.o hrt.o
|
||||
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
||||
AUTODECLINATION_FILES= ../../src/lib/geo/geo_mag_declination.c \
|
||||
hrt.cpp \
|
||||
autodeclination_test.cpp
|
||||
|
||||
#$(DEPS)
|
||||
$(ODIR)/%.o: %.cpp
|
||||
mkdir -p obj
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
mixer_test: $(MIXER_FILES)
|
||||
$(CC) -o mixer_test $(MIXER_FILES) $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/systemcmds/tests/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
sbus2_test: $(SBUS2_FILES)
|
||||
$(CC) -o sbus2_test $(SBUS2_FILES) $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/modules/systemlib/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/modules/systemlib/mixer/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/modules/systemlib/pwm_limit/%.cpp
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/modules/systemlib/pwm_limit/%.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(ODIR)/%.o: ../../src/modules/systemlib/mixer/%.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
#
|
||||
mixer_test: $(OBJ)
|
||||
g++ -o $@ $^ $(CFLAGS) $(LIBS)
|
||||
autodeclination_test: $(SBUS2_FILES)
|
||||
$(CC) -o autodeclination_test $(AUTODECLINATION_FILES) $(CFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
|
||||
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ mixer_test sbus2_test autodeclination_test
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <systemlib/mixer/mixer.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <px4iofirmware/px4io.h>
|
||||
#include "../../src/systemcmds/tests/tests.h"
|
||||
#include <geo/geo.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
warnx("autodeclination test started");
|
||||
|
||||
if (argc < 3)
|
||||
errx(1, "Need lat/lon!");
|
||||
|
||||
char* p_end;
|
||||
|
||||
float lat = strtod(argv[1], &p_end);
|
||||
float lon = strtod(argv[2], &p_end);
|
||||
|
||||
float declination = get_mag_declination(lat, lon);
|
||||
|
||||
printf("lat: %f lon: %f, dec: %f\n", lat, lon, declination);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <systemlib/err.h>
|
||||
#define lowsyslog warnx
|
||||
@@ -11,4 +11,4 @@ int main(int argc, char *argv[]) {
|
||||
test_mixer(3, args);
|
||||
|
||||
test_conv(1, args);
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
make clean
|
||||
make all
|
||||
./mixer_test
|
||||
./sbus2_test ../../../../data/sbus2/sbus2_r7008SB_gps_baro_tx_off.txt
|
||||
@@ -0,0 +1,75 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <systemlib/mixer/mixer.h>
|
||||
#include <systemlib/err.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <px4iofirmware/px4io.h>
|
||||
#include "../../src/systemcmds/tests/tests.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
warnx("SBUS2 test started");
|
||||
|
||||
if (argc < 2)
|
||||
errx(1, "Need a filename for the input file");
|
||||
|
||||
warnx("loading data from: %s", argv[1]);
|
||||
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(argv[1],"rt");
|
||||
|
||||
if (!fp)
|
||||
errx(1, "failed opening file");
|
||||
|
||||
float f;
|
||||
unsigned x;
|
||||
int ret;
|
||||
|
||||
// Trash the first 20 lines
|
||||
for (unsigned i = 0; i < 20; i++) {
|
||||
(void)fscanf(fp, "%f,%x,,", &f, &x);
|
||||
}
|
||||
|
||||
// Init the parser
|
||||
uint8_t frame[30];
|
||||
unsigned partial_frame_count = 0;
|
||||
uint16_t rc_values[18];
|
||||
uint16_t num_values;
|
||||
bool sbus_failsafe;
|
||||
bool sbus_frame_drop;
|
||||
uint16_t max_channels = sizeof(rc_values) / sizeof(rc_values[0]);
|
||||
|
||||
float last_time = 0;
|
||||
|
||||
while (EOF != (ret = fscanf(fp, "%f,%x,,", &f, &x))) {
|
||||
if (((f - last_time) * 1000 * 1000) > 3000) {
|
||||
partial_frame_count = 0;
|
||||
warnx("FRAME RESET\n\n");
|
||||
}
|
||||
|
||||
frame[partial_frame_count] = x;
|
||||
partial_frame_count++;
|
||||
|
||||
//warnx("%f: 0x%02x, first: 0x%02x, last: 0x%02x, pcount: %u", (double)f, x, frame[0], frame[24], partial_frame_count);
|
||||
|
||||
if (partial_frame_count == sizeof(frame))
|
||||
partial_frame_count = 0;
|
||||
|
||||
last_time = f;
|
||||
|
||||
// Pipe the data into the parser
|
||||
hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
//if (partial_frame_count % 25 == 0)
|
||||
//sbus_parse(now, frame, &partial_frame_count, rc_values, &num_values, &sbus_failsafe, &sbus_frame_drop, max_channels);
|
||||
}
|
||||
|
||||
if (ret == EOF) {
|
||||
warnx("Test finished, reached end of file");
|
||||
} else {
|
||||
warnx("Test aborted, errno: %d", ret);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,8 +55,8 @@ MODULES += systemcmds/top
|
||||
MODULES += systemcmds/tests
|
||||
MODULES += systemcmds/config
|
||||
MODULES += systemcmds/nshterm
|
||||
MODULES += systemcmds/hw_ver
|
||||
MODULES += systemcmds/dumpfile
|
||||
MODULES += systemcmds/ver
|
||||
|
||||
#
|
||||
# General system control
|
||||
|
||||
@@ -63,8 +63,8 @@ MODULES += systemcmds/tests
|
||||
MODULES += systemcmds/config
|
||||
MODULES += systemcmds/nshterm
|
||||
MODULES += systemcmds/mtd
|
||||
MODULES += systemcmds/hw_ver
|
||||
MODULES += systemcmds/dumpfile
|
||||
MODULES += systemcmds/ver
|
||||
|
||||
#
|
||||
# General system control
|
||||
|
||||
@@ -29,7 +29,7 @@ MODULES += systemcmds/reboot
|
||||
MODULES += systemcmds/tests
|
||||
MODULES += systemcmds/nshterm
|
||||
MODULES += systemcmds/mtd
|
||||
MODULES += systemcmds/hw_ver
|
||||
MODULES += systemcmds/ver
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -113,7 +113,7 @@ endif
|
||||
$(info % GIT_DESC = $(GIT_DESC))
|
||||
|
||||
#
|
||||
# Set a default target so that included makefiles or errors here don't
|
||||
# Set a default target so that included makefiles or errors here don't
|
||||
# cause confusion.
|
||||
#
|
||||
# XXX We could do something cute here with $(DEFAULT_GOAL) if it's not one
|
||||
@@ -177,7 +177,7 @@ GLOBAL_DEPS += $(MAKEFILE_LIST)
|
||||
#
|
||||
# Extra things we should clean
|
||||
#
|
||||
EXTRA_CLEANS =
|
||||
EXTRA_CLEANS =
|
||||
|
||||
|
||||
#
|
||||
@@ -371,6 +371,8 @@ $(ROMFS_IMG): $(ROMFS_SCRATCH) $(ROMFS_DEPS) $(GLOBAL_DEPS)
|
||||
$(ROMFS_SCRATCH): $(ROMFS_DEPS) $(GLOBAL_DEPS)
|
||||
$(Q) $(MKDIR) -p $(ROMFS_SCRATCH)
|
||||
$(Q) $(COPYDIR) $(ROMFS_ROOT)/* $(ROMFS_SCRATCH)
|
||||
# delete all files in ROMFS_SCRATCH which start with a . or end with a ~
|
||||
$(Q) $(RM) $(ROMFS_SCRATCH)/*/.[!.]* $(ROMFS_SCRATCH)/*/*~
|
||||
ifneq ($(ROMFS_EXTRA_FILES),)
|
||||
$(Q) $(MKDIR) -p $(ROMFS_SCRATCH)/extras
|
||||
$(Q) $(COPY) $(ROMFS_EXTRA_FILES) $(ROMFS_SCRATCH)/extras
|
||||
|
||||
@@ -103,8 +103,6 @@
|
||||
#define GPIO_USART2_RTS 0xffffffff
|
||||
#undef GPIO_USART2_CK
|
||||
#define GPIO_USART2_CK 0xffffffff
|
||||
#undef GPIO_USART3_TX
|
||||
#define GPIO_USART3_TX 0xffffffff
|
||||
#undef GPIO_USART3_CK
|
||||
#define GPIO_USART3_CK 0xffffffff
|
||||
#undef GPIO_USART3_CTS
|
||||
|
||||
@@ -104,9 +104,9 @@ CONFIG_ARMV7M_CMNVECTOR=y
|
||||
# CONFIG_STM32_JTAG_SW_ENABLE - Set JTAG-DP disabled and SW-DP enabled
|
||||
#
|
||||
CONFIG_STM32_DFU=n
|
||||
CONFIG_STM32_JTAG_FULL_ENABLE=y
|
||||
CONFIG_STM32_JTAG_FULL_ENABLE=n
|
||||
CONFIG_STM32_JTAG_NOJNTRST_ENABLE=n
|
||||
CONFIG_STM32_JTAG_SW_ENABLE=n
|
||||
CONFIG_STM32_JTAG_SW_ENABLE=y
|
||||
|
||||
#
|
||||
# Individual subsystems can be enabled:
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <queue.h>
|
||||
|
||||
@@ -199,6 +199,9 @@ ORB_DECLARE(output_pwm);
|
||||
/** get the lockdown override flag to enable outputs in HIL */
|
||||
#define PWM_SERVO_GET_DISABLE_LOCKDOWN _IOC(_PWM_SERVO_BASE, 22)
|
||||
|
||||
/** force safety switch off (to disable use of safety switch) */
|
||||
#define PWM_SERVO_SET_FORCE_SAFETY_OFF _IOC(_PWM_SERVO_BASE, 23)
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
|
||||
@@ -148,6 +148,7 @@ enum {
|
||||
TONE_BATTERY_WARNING_FAST_TUNE,
|
||||
TONE_GPS_WARNING_TUNE,
|
||||
TONE_ARMING_FAILURE_TUNE,
|
||||
TONE_PARACHUTE_RELEASE_TUNE,
|
||||
TONE_NUMBER_OF_TUNES
|
||||
};
|
||||
|
||||
|
||||
@@ -526,6 +526,7 @@ void
|
||||
MS5611::cycle()
|
||||
{
|
||||
int ret;
|
||||
unsigned dummy;
|
||||
|
||||
/* collection phase? */
|
||||
if (_collect_phase) {
|
||||
@@ -542,6 +543,8 @@ MS5611::cycle()
|
||||
} else {
|
||||
//log("collection error %d", ret);
|
||||
}
|
||||
/* issue a reset command to the sensor */
|
||||
_interface->ioctl(IOCTL_RESET, dummy);
|
||||
/* reset the collection state machine and try again */
|
||||
start_cycle();
|
||||
return;
|
||||
@@ -573,6 +576,8 @@ MS5611::cycle()
|
||||
ret = measure();
|
||||
if (ret != OK) {
|
||||
//log("measure error %d", ret);
|
||||
/* issue a reset command to the sensor */
|
||||
_interface->ioctl(IOCTL_RESET, dummy);
|
||||
/* reset the collection state machine and try again */
|
||||
start_cycle();
|
||||
return;
|
||||
|
||||
+168
-108
@@ -120,19 +120,25 @@ private:
|
||||
uint32_t _pwm_alt_rate_channels;
|
||||
unsigned _current_update_rate;
|
||||
int _task;
|
||||
int _t_actuators;
|
||||
int _t_actuator_armed;
|
||||
orb_advert_t _t_outputs;
|
||||
int _armed_sub;
|
||||
orb_advert_t _outputs_pub;
|
||||
actuator_armed_s _armed;
|
||||
unsigned _num_outputs;
|
||||
bool _primary_pwm_device;
|
||||
|
||||
volatile bool _task_should_exit;
|
||||
bool _armed;
|
||||
bool _servo_armed;
|
||||
bool _pwm_on;
|
||||
|
||||
MixerGroup *_mixers;
|
||||
|
||||
actuator_controls_s _controls;
|
||||
uint32_t _groups_required;
|
||||
uint32_t _groups_subscribed;
|
||||
int _control_subs[NUM_ACTUATOR_CONTROL_GROUPS];
|
||||
actuator_controls_s _controls[NUM_ACTUATOR_CONTROL_GROUPS];
|
||||
orb_id_t _control_topics[NUM_ACTUATOR_CONTROL_GROUPS];
|
||||
pollfd _poll_fds[NUM_ACTUATOR_CONTROL_GROUPS];
|
||||
unsigned _poll_fds_num;
|
||||
|
||||
pwm_limit_t _pwm_limit;
|
||||
uint16_t _failsafe_pwm[_max_actuators];
|
||||
@@ -149,7 +155,7 @@ private:
|
||||
uint8_t control_group,
|
||||
uint8_t control_index,
|
||||
float &input);
|
||||
|
||||
void subscribe();
|
||||
int set_pwm_rate(unsigned rate_map, unsigned default_rate, unsigned alt_rate);
|
||||
int pwm_ioctl(file *filp, int cmd, unsigned long arg);
|
||||
|
||||
@@ -216,15 +222,18 @@ PX4FMU::PX4FMU() :
|
||||
_pwm_alt_rate_channels(0),
|
||||
_current_update_rate(0),
|
||||
_task(-1),
|
||||
_t_actuators(-1),
|
||||
_t_actuator_armed(-1),
|
||||
_t_outputs(0),
|
||||
_control_subs({-1}),
|
||||
_poll_fds_num(0),
|
||||
_armed_sub(-1),
|
||||
_outputs_pub(-1),
|
||||
_num_outputs(0),
|
||||
_primary_pwm_device(false),
|
||||
_task_should_exit(false),
|
||||
_armed(false),
|
||||
_servo_armed(false),
|
||||
_pwm_on(false),
|
||||
_mixers(nullptr),
|
||||
_groups_required(0),
|
||||
_groups_subscribed(0),
|
||||
_failsafe_pwm({0}),
|
||||
_disarmed_pwm({0}),
|
||||
_num_failsafe_set(0),
|
||||
@@ -235,6 +244,14 @@ PX4FMU::PX4FMU() :
|
||||
_max_pwm[i] = PWM_DEFAULT_MAX;
|
||||
}
|
||||
|
||||
_control_topics[0] = ORB_ID(actuator_controls_0);
|
||||
_control_topics[1] = ORB_ID(actuator_controls_1);
|
||||
_control_topics[2] = ORB_ID(actuator_controls_2);
|
||||
_control_topics[3] = ORB_ID(actuator_controls_3);
|
||||
|
||||
memset(_controls, 0, sizeof(_controls));
|
||||
memset(_poll_fds, 0, sizeof(_poll_fds));
|
||||
|
||||
_debug_enabled = true;
|
||||
}
|
||||
|
||||
@@ -447,33 +464,43 @@ PX4FMU::set_pwm_alt_channels(uint32_t channels)
|
||||
return set_pwm_rate(channels, _pwm_default_rate, _pwm_alt_rate);
|
||||
}
|
||||
|
||||
void
|
||||
PX4FMU::subscribe()
|
||||
{
|
||||
/* subscribe/unsubscribe to required actuator control groups */
|
||||
uint32_t sub_groups = _groups_required & ~_groups_subscribed;
|
||||
uint32_t unsub_groups = _groups_subscribed & ~_groups_required;
|
||||
_poll_fds_num = 0;
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROL_GROUPS; i++) {
|
||||
if (sub_groups & (1 << i)) {
|
||||
warnx("subscribe to actuator_controls_%d", i);
|
||||
_control_subs[i] = orb_subscribe(_control_topics[i]);
|
||||
}
|
||||
if (unsub_groups & (1 << i)) {
|
||||
warnx("unsubscribe from actuator_controls_%d", i);
|
||||
::close(_control_subs[i]);
|
||||
_control_subs[i] = -1;
|
||||
}
|
||||
|
||||
if (_control_subs[i] > 0) {
|
||||
_poll_fds[_poll_fds_num].fd = _control_subs[i];
|
||||
_poll_fds[_poll_fds_num].events = POLLIN;
|
||||
_poll_fds_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PX4FMU::task_main()
|
||||
{
|
||||
/*
|
||||
* Subscribe to the appropriate PWM output topic based on whether we are the
|
||||
* primary PWM output or not.
|
||||
*/
|
||||
_t_actuators = orb_subscribe(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS :
|
||||
ORB_ID(actuator_controls_1));
|
||||
/* force a reset of the update rate */
|
||||
_current_update_rate = 0;
|
||||
|
||||
_t_actuator_armed = orb_subscribe(ORB_ID(actuator_armed));
|
||||
orb_set_interval(_t_actuator_armed, 200); /* 5Hz update rate */
|
||||
_armed_sub = orb_subscribe(ORB_ID(actuator_armed));
|
||||
|
||||
/* advertise the mixed control outputs */
|
||||
actuator_outputs_s outputs;
|
||||
memset(&outputs, 0, sizeof(outputs));
|
||||
/* advertise the mixed control outputs */
|
||||
_t_outputs = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1),
|
||||
&outputs);
|
||||
|
||||
pollfd fds[2];
|
||||
fds[0].fd = _t_actuators;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = _t_actuator_armed;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
#ifdef HRT_PPM_CHANNEL
|
||||
// rc input, published to ORB
|
||||
@@ -491,6 +518,12 @@ PX4FMU::task_main()
|
||||
|
||||
/* loop until killed */
|
||||
while (!_task_should_exit) {
|
||||
if (_groups_subscribed != _groups_required) {
|
||||
subscribe();
|
||||
_groups_subscribed = _groups_required;
|
||||
/* force setting update rate */
|
||||
_current_update_rate = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust actuator topic update rate to keep up with
|
||||
@@ -515,7 +548,11 @@ PX4FMU::task_main()
|
||||
}
|
||||
|
||||
debug("adjusted actuator update interval to %ums", update_rate_in_ms);
|
||||
orb_set_interval(_t_actuators, update_rate_in_ms);
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROL_GROUPS; i++) {
|
||||
if (_control_subs[i] > 0) {
|
||||
orb_set_interval(_control_subs[i], update_rate_in_ms);
|
||||
}
|
||||
}
|
||||
|
||||
// set to current max rate, even if we are actually checking slower/faster
|
||||
_current_update_rate = max_rate;
|
||||
@@ -523,7 +560,7 @@ PX4FMU::task_main()
|
||||
|
||||
/* sleep waiting for data, stopping to check for PPM
|
||||
* input at 100Hz */
|
||||
int ret = ::poll(&fds[0], 2, CONTROL_INPUT_DROP_LIMIT_MS);
|
||||
int ret = ::poll(_poll_fds, _poll_fds_num, CONTROL_INPUT_DROP_LIMIT_MS);
|
||||
|
||||
/* this would be bad... */
|
||||
if (ret < 0) {
|
||||
@@ -537,89 +574,98 @@ PX4FMU::task_main()
|
||||
|
||||
} else {
|
||||
|
||||
/* do we have a control update? */
|
||||
if (fds[0].revents & POLLIN) {
|
||||
|
||||
/* get controls - must always do this to avoid spinning */
|
||||
orb_copy(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS : ORB_ID(actuator_controls_1), _t_actuators, &_controls);
|
||||
|
||||
/* can we mix? */
|
||||
if (_mixers != nullptr) {
|
||||
|
||||
unsigned num_outputs;
|
||||
|
||||
switch (_mode) {
|
||||
case MODE_2PWM:
|
||||
num_outputs = 2;
|
||||
break;
|
||||
|
||||
case MODE_4PWM:
|
||||
num_outputs = 4;
|
||||
break;
|
||||
|
||||
case MODE_6PWM:
|
||||
num_outputs = 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
num_outputs = 0;
|
||||
break;
|
||||
/* get controls for required topics */
|
||||
unsigned poll_id = 0;
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROL_GROUPS; i++) {
|
||||
if (_control_subs[i] > 0) {
|
||||
if (_poll_fds[poll_id].revents & POLLIN) {
|
||||
orb_copy(_control_topics[i], _control_subs[i], &_controls[i]);
|
||||
}
|
||||
|
||||
/* do mixing */
|
||||
outputs.noutputs = _mixers->mix(&outputs.output[0], num_outputs);
|
||||
outputs.timestamp = hrt_absolute_time();
|
||||
|
||||
/* iterate actuators */
|
||||
for (unsigned i = 0; i < num_outputs; i++) {
|
||||
/* last resort: catch NaN, INF and out-of-band errors */
|
||||
if (i >= outputs.noutputs ||
|
||||
!isfinite(outputs.output[i]) ||
|
||||
outputs.output[i] < -1.0f ||
|
||||
outputs.output[i] > 1.0f) {
|
||||
/*
|
||||
* Value is NaN, INF or out of band - set to the minimum value.
|
||||
* This will be clearly visible on the servo status and will limit the risk of accidentally
|
||||
* spinning motors. It would be deadly in flight.
|
||||
*/
|
||||
outputs.output[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t pwm_limited[num_outputs];
|
||||
|
||||
pwm_limit_calc(_armed, num_outputs, _disarmed_pwm, _min_pwm, _max_pwm, outputs.output, pwm_limited, &_pwm_limit);
|
||||
|
||||
/* output to the servos */
|
||||
for (unsigned i = 0; i < num_outputs; i++) {
|
||||
up_pwm_servo_set(i, pwm_limited[i]);
|
||||
}
|
||||
|
||||
/* and publish for anyone that cares to see */
|
||||
orb_publish(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), _t_outputs, &outputs);
|
||||
poll_id++;
|
||||
}
|
||||
}
|
||||
|
||||
/* how about an arming update? */
|
||||
if (fds[1].revents & POLLIN) {
|
||||
actuator_armed_s aa;
|
||||
/* can we mix? */
|
||||
if (_mixers != nullptr) {
|
||||
|
||||
/* get new value */
|
||||
orb_copy(ORB_ID(actuator_armed), _t_actuator_armed, &aa);
|
||||
unsigned num_outputs;
|
||||
|
||||
/* update the armed status and check that we're not locked down */
|
||||
bool set_armed = aa.armed && !aa.lockdown;
|
||||
switch (_mode) {
|
||||
case MODE_2PWM:
|
||||
num_outputs = 2;
|
||||
break;
|
||||
|
||||
if (_armed != set_armed)
|
||||
_armed = set_armed;
|
||||
case MODE_4PWM:
|
||||
num_outputs = 4;
|
||||
break;
|
||||
|
||||
/* update PWM status if armed or if disarmed PWM values are set */
|
||||
bool pwm_on = (aa.armed || _num_disarmed_set > 0);
|
||||
case MODE_6PWM:
|
||||
num_outputs = 6;
|
||||
break;
|
||||
|
||||
if (_pwm_on != pwm_on) {
|
||||
_pwm_on = pwm_on;
|
||||
up_pwm_servo_arm(pwm_on);
|
||||
default:
|
||||
num_outputs = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* do mixing */
|
||||
outputs.noutputs = _mixers->mix(&outputs.output[0], num_outputs);
|
||||
outputs.timestamp = hrt_absolute_time();
|
||||
|
||||
/* iterate actuators */
|
||||
for (unsigned i = 0; i < num_outputs; i++) {
|
||||
/* last resort: catch NaN, INF and out-of-band errors */
|
||||
if (i >= outputs.noutputs ||
|
||||
!isfinite(outputs.output[i]) ||
|
||||
outputs.output[i] < -1.0f ||
|
||||
outputs.output[i] > 1.0f) {
|
||||
/*
|
||||
* Value is NaN, INF or out of band - set to the minimum value.
|
||||
* This will be clearly visible on the servo status and will limit the risk of accidentally
|
||||
* spinning motors. It would be deadly in flight.
|
||||
*/
|
||||
outputs.output[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t pwm_limited[num_outputs];
|
||||
|
||||
pwm_limit_calc(_servo_armed, num_outputs, _disarmed_pwm, _min_pwm, _max_pwm, outputs.output, pwm_limited, &_pwm_limit);
|
||||
|
||||
/* output to the servos */
|
||||
for (unsigned i = 0; i < num_outputs; i++) {
|
||||
up_pwm_servo_set(i, pwm_limited[i]);
|
||||
}
|
||||
|
||||
/* publish mixed control outputs */
|
||||
if (_outputs_pub < 0) {
|
||||
_outputs_pub = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), &outputs);
|
||||
} else {
|
||||
|
||||
orb_publish(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), _outputs_pub, &outputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check arming state */
|
||||
bool updated = false;
|
||||
orb_check(_armed_sub, &updated);
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(actuator_armed), _armed_sub, &_armed);
|
||||
|
||||
/* update the armed status and check that we're not locked down */
|
||||
bool set_armed = _armed.armed && !_armed.lockdown;
|
||||
|
||||
if (_servo_armed != set_armed)
|
||||
_servo_armed = set_armed;
|
||||
|
||||
/* update PWM status if armed or if disarmed PWM values are set */
|
||||
bool pwm_on = (_armed.armed || _num_disarmed_set > 0);
|
||||
|
||||
if (_pwm_on != pwm_on) {
|
||||
_pwm_on = pwm_on;
|
||||
up_pwm_servo_arm(pwm_on);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,8 +707,13 @@ PX4FMU::task_main()
|
||||
|
||||
}
|
||||
|
||||
::close(_t_actuators);
|
||||
::close(_t_actuator_armed);
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROL_GROUPS; i++) {
|
||||
if (_control_subs > 0) {
|
||||
::close(_control_subs[i]);
|
||||
_control_subs[i] = -1;
|
||||
}
|
||||
}
|
||||
::close(_armed_sub);
|
||||
|
||||
/* make sure servos are off */
|
||||
up_pwm_servo_deinit();
|
||||
@@ -684,7 +735,7 @@ PX4FMU::control_callback(uintptr_t handle,
|
||||
{
|
||||
const actuator_controls_s *controls = (actuator_controls_s *)handle;
|
||||
|
||||
input = controls->control[control_index];
|
||||
input = controls[control_group].control[control_index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -736,6 +787,7 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
|
||||
case PWM_SERVO_SET_ARM_OK:
|
||||
case PWM_SERVO_CLEAR_ARM_OK:
|
||||
case PWM_SERVO_SET_FORCE_SAFETY_OFF:
|
||||
// these are no-ops, as no safety switch
|
||||
break;
|
||||
|
||||
@@ -1052,6 +1104,7 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
if (_mixers != nullptr) {
|
||||
delete _mixers;
|
||||
_mixers = nullptr;
|
||||
_groups_required = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1060,18 +1113,20 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
mixer_simple_s *mixinfo = (mixer_simple_s *)arg;
|
||||
|
||||
SimpleMixer *mixer = new SimpleMixer(control_callback,
|
||||
(uintptr_t)&_controls, mixinfo);
|
||||
(uintptr_t)_controls, mixinfo);
|
||||
|
||||
if (mixer->check()) {
|
||||
delete mixer;
|
||||
_groups_required = 0;
|
||||
ret = -EINVAL;
|
||||
|
||||
} else {
|
||||
if (_mixers == nullptr)
|
||||
_mixers = new MixerGroup(control_callback,
|
||||
(uintptr_t)&_controls);
|
||||
(uintptr_t)_controls);
|
||||
|
||||
_mixers->add_mixer(mixer);
|
||||
_mixers->groups_required(_groups_required);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1082,9 +1137,10 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
unsigned buflen = strnlen(buf, 1024);
|
||||
|
||||
if (_mixers == nullptr)
|
||||
_mixers = new MixerGroup(control_callback, (uintptr_t)&_controls);
|
||||
_mixers = new MixerGroup(control_callback, (uintptr_t)_controls);
|
||||
|
||||
if (_mixers == nullptr) {
|
||||
_groups_required = 0;
|
||||
ret = -ENOMEM;
|
||||
|
||||
} else {
|
||||
@@ -1095,7 +1151,11 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
|
||||
debug("mixer load failed with %d", ret);
|
||||
delete _mixers;
|
||||
_mixers = nullptr;
|
||||
_groups_required = 0;
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
|
||||
_mixers->groups_required(_groups_required);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
|
||||
#include "uploader.h"
|
||||
|
||||
#include "modules/dataman/dataman.h"
|
||||
|
||||
extern device::Device *PX4IO_i2c_interface() weak_function;
|
||||
extern device::Device *PX4IO_serial_interface() weak_function;
|
||||
|
||||
@@ -568,9 +570,15 @@ int
|
||||
PX4IO::init()
|
||||
{
|
||||
int ret;
|
||||
param_t sys_restart_param;
|
||||
int sys_restart_val = DM_INIT_REASON_VOLATILE;
|
||||
|
||||
ASSERT(_task == -1);
|
||||
|
||||
sys_restart_param = param_find("SYS_RESTART_TYPE");
|
||||
/* Indicate restart type is unknown */
|
||||
param_set(sys_restart_param, &sys_restart_val);
|
||||
|
||||
/* do regular cdev init */
|
||||
ret = CDev::init();
|
||||
|
||||
@@ -675,6 +683,25 @@ PX4IO::init()
|
||||
|
||||
/* send command to arm system via command API */
|
||||
vehicle_command_s cmd;
|
||||
/* send this to itself */
|
||||
param_t sys_id_param = param_find("MAV_SYS_ID");
|
||||
param_t comp_id_param = param_find("MAV_COMP_ID");
|
||||
|
||||
int32_t sys_id;
|
||||
int32_t comp_id;
|
||||
|
||||
if (param_get(sys_id_param, &sys_id)) {
|
||||
errx(1, "PRM SYSID");
|
||||
}
|
||||
|
||||
if (param_get(comp_id_param, &comp_id)) {
|
||||
errx(1, "PRM CMPID");
|
||||
}
|
||||
|
||||
cmd.target_system = sys_id;
|
||||
cmd.target_component = comp_id;
|
||||
cmd.source_system = sys_id;
|
||||
cmd.source_component = comp_id;
|
||||
/* request arming */
|
||||
cmd.param1 = 1.0f;
|
||||
cmd.param2 = 0;
|
||||
@@ -684,10 +711,7 @@ PX4IO::init()
|
||||
cmd.param6 = 0;
|
||||
cmd.param7 = 0;
|
||||
cmd.command = VEHICLE_CMD_COMPONENT_ARM_DISARM;
|
||||
// cmd.target_system = status.system_id;
|
||||
// cmd.target_component = status.component_id;
|
||||
// cmd.source_system = status.system_id;
|
||||
// cmd.source_component = status.component_id;
|
||||
|
||||
/* ask to confirm command */
|
||||
cmd.confirmation = 1;
|
||||
|
||||
@@ -720,6 +744,11 @@ PX4IO::init()
|
||||
/* keep waiting for state change for 2 s */
|
||||
} while (!safety.armed);
|
||||
|
||||
/* Indicate restart type is in-flight */
|
||||
sys_restart_val = DM_INIT_REASON_IN_FLIGHT;
|
||||
param_set(sys_restart_param, &sys_restart_val);
|
||||
|
||||
|
||||
/* regular boot, no in-air restart, init IO */
|
||||
|
||||
} else {
|
||||
@@ -745,6 +774,10 @@ PX4IO::init()
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate restart type is power on */
|
||||
sys_restart_val = DM_INIT_REASON_POWER_ON;
|
||||
param_set(sys_restart_param, &sys_restart_val);
|
||||
|
||||
}
|
||||
|
||||
/* try to claim the generic PWM output device node as well - it's OK if we fail at this */
|
||||
@@ -2129,6 +2162,10 @@ PX4IO::ioctl(file * filep, int cmd, unsigned long arg)
|
||||
|
||||
case PWM_SERVO_GET_DISABLE_LOCKDOWN:
|
||||
*(unsigned *)arg = _lockdown_override;
|
||||
|
||||
case PWM_SERVO_SET_FORCE_SAFETY_OFF:
|
||||
/* force safety swith off */
|
||||
ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FORCE_SAFETY_OFF, PX4IO_FORCE_SAFETY_MAGIC);
|
||||
break;
|
||||
|
||||
case DSM_BIND_START:
|
||||
|
||||
@@ -335,6 +335,7 @@ ToneAlarm::ToneAlarm() :
|
||||
_default_tunes[TONE_BATTERY_WARNING_FAST_TUNE] = "MBNT255a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8"; //battery warning fast
|
||||
_default_tunes[TONE_GPS_WARNING_TUNE] = "MFT255L4AAAL1F#"; //gps warning slow
|
||||
_default_tunes[TONE_ARMING_FAILURE_TUNE] = "MFT255L4<<<BAP";
|
||||
_default_tunes[TONE_PARACHUTE_RELEASE_TUNE] = "MFT255L16agagagag"; // parachute release
|
||||
|
||||
_tune_names[TONE_STARTUP_TUNE] = "startup"; // startup tune
|
||||
_tune_names[TONE_ERROR_TUNE] = "error"; // ERROR tone
|
||||
@@ -346,6 +347,7 @@ ToneAlarm::ToneAlarm() :
|
||||
_tune_names[TONE_BATTERY_WARNING_FAST_TUNE] = "fast_bat"; // battery warning fast
|
||||
_tune_names[TONE_GPS_WARNING_TUNE] = "gps_warning"; // gps warning
|
||||
_tune_names[TONE_ARMING_FAILURE_TUNE] = "arming_failure"; //fail to arm
|
||||
_tune_names[TONE_PARACHUTE_RELEASE_TUNE] = "parachute_release"; // parachute release
|
||||
}
|
||||
|
||||
ToneAlarm::~ToneAlarm()
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#include "geo/geo_mag_declination.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONSTANTS_ONE_G 9.80665f /* m/s^2 */
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 MAV GEO Library (MAVGEO). 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 MAVGEO 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 geo_mag_declination.c
|
||||
*
|
||||
* Calculation / lookup table for earth magnetic field declination.
|
||||
*
|
||||
* Lookup table from Scott Ferguson <scottfromscott@gmail.com>
|
||||
*
|
||||
* XXX Lookup table currently too coarse in resolution (only full degrees)
|
||||
* and lat/lon res - needs extension medium term.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <geo/geo.h>
|
||||
|
||||
/** set this always to the sampling in degrees for the table below */
|
||||
#define SAMPLING_RES 10.0f
|
||||
#define SAMPLING_MIN_LAT -60.0f
|
||||
#define SAMPLING_MAX_LAT 60.0f
|
||||
#define SAMPLING_MIN_LON -180.0f
|
||||
#define SAMPLING_MAX_LON 180.0f
|
||||
|
||||
static const int8_t declination_table[13][37] = \
|
||||
{
|
||||
46, 45, 44, 42, 41, 40, 38, 36, 33, 28, 23, 16, 10, 4, -1, -5, -9, -14, -19, -26, -33, -40, -48, -55, -61, \
|
||||
-66, -71, -74, -75, -72, -61, -25, 22, 40, 45, 47, 46, 30, 30, 30, 30, 29, 29, 29, 29, 27, 24, 18, 11, 3, \
|
||||
-3, -9, -12, -15, -17, -21, -26, -32, -39, -45, -51, -55, -57, -56, -53, -44, -31, -14, 0, 13, 21, 26, \
|
||||
29, 30, 21, 22, 22, 22, 22, 22, 22, 22, 21, 18, 13, 5, -3, -11, -17, -20, -21, -22, -23, -25, -29, -35, \
|
||||
-40, -44, -45, -44, -40, -32, -22, -12, -3, 3, 9, 14, 18, 20, 21, 16, 17, 17, 17, 17, 17, 16, 16, 16, 13, \
|
||||
8, 0, -9, -16, -21, -24, -25, -25, -23, -20, -21, -24, -28, -31, -31, -29, -24, -17, -9, -3, 0, 4, 7, \
|
||||
10, 13, 15, 16, 12, 13, 13, 13, 13, 13, 12, 12, 11, 9, 3, -4, -12, -19, -23, -24, -24, -22, -17, -12, -9, \
|
||||
-10, -13, -17, -18, -16, -13, -8, -3, 0, 1, 3, 6, 8, 10, 12, 12, 10, 10, 10, 10, 10, 10, 10, 9, 9, 6, 0, -6, \
|
||||
-14, -20, -22, -22, -19, -15, -10, -6, -2, -2, -4, -7, -8, -8, -7, -4, 0, 1, 1, 2, 4, 6, 8, 10, 10, 9, 9, 9, \
|
||||
9, 9, 9, 8, 8, 7, 4, -1, -8, -15, -19, -20, -18, -14, -9, -5, -2, 0, 1, 0, -2, -3, -4, -3, -2, 0, 0, 0, 1, 3, 5, \
|
||||
7, 8, 9, 8, 8, 8, 9, 9, 9, 8, 8, 6, 2, -3, -9, -15, -18, -17, -14, -10, -6, -2, 0, 1, 2, 2, 0, -1, -1, -2, -1, 0, \
|
||||
0, 0, 0, 1, 3, 5, 7, 8, 8, 9, 9, 10, 10, 10, 10, 8, 5, 0, -5, -11, -15, -16, -15, -12, -8, -4, -1, 0, 2, 3, 2, 1, 0, \
|
||||
0, 0, 0, 0, -1, -2, -2, -1, 0, 3, 6, 8, 6, 9, 10, 11, 12, 12, 11, 9, 5, 0, -7, -12, -15, -15, -13, -10, -7, -3, \
|
||||
0, 1, 2, 3, 3, 3, 2, 1, 0, 0, -1, -3, -4, -5, -5, -2, 0, 3, 6, 5, 8, 11, 13, 15, 15, 14, 11, 5, -1, -9, -14, -17, \
|
||||
-16, -14, -11, -7, -3, 0, 1, 3, 4, 5, 5, 5, 4, 3, 1, -1, -4, -7, -8, -8, -6, -2, 1, 5, 4, 8, 12, 15, 17, 18, 16, \
|
||||
12, 5, -3, -12, -18, -20, -19, -16, -13, -8, -4, -1, 1, 4, 6, 8, 9, 9, 9, 7, 3, -1, -6, -10, -12, -11, -9, -5, \
|
||||
0, 4, 3, 9, 14, 17, 20, 21, 19, 14, 4, -8, -19, -25, -26, -25, -21, -17, -12, -7, -2, 1, 5, 9, 13, 15, 16, 16, \
|
||||
13, 7, 0, -7, -12, -15, -14, -11, -6, -1, 3
|
||||
};
|
||||
|
||||
static float get_lookup_table_val(unsigned lat, unsigned lon);
|
||||
|
||||
__EXPORT float get_mag_declination(float lat, float lon)
|
||||
{
|
||||
/*
|
||||
* If the values exceed valid ranges, return zero as default
|
||||
* as we have no way of knowing what the closest real value
|
||||
* would be.
|
||||
*/
|
||||
if (lat < -90.0f || lat > 90.0f ||
|
||||
lon < -180.0f || lon > 180.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* round down to nearest sampling resolution */
|
||||
int min_lat = (int)(lat / SAMPLING_RES) * SAMPLING_RES;
|
||||
int min_lon = (int)(lon / SAMPLING_RES) * SAMPLING_RES;
|
||||
|
||||
/* for the rare case of hitting the bounds exactly
|
||||
* the rounding logic wouldn't fit, so enforce it.
|
||||
*/
|
||||
|
||||
/* limit to table bounds - required for maxima even when table spans full globe range */
|
||||
if (lat <= SAMPLING_MIN_LAT) {
|
||||
min_lat = SAMPLING_MIN_LAT;
|
||||
}
|
||||
|
||||
if (lat >= SAMPLING_MAX_LAT) {
|
||||
min_lat = (int)(lat / SAMPLING_RES) * SAMPLING_RES - SAMPLING_RES;
|
||||
}
|
||||
|
||||
if (lon <= SAMPLING_MIN_LON) {
|
||||
min_lon = SAMPLING_MIN_LON;
|
||||
}
|
||||
|
||||
if (lon >= SAMPLING_MAX_LON) {
|
||||
min_lon = (int)(lon / SAMPLING_RES) * SAMPLING_RES - SAMPLING_RES;
|
||||
}
|
||||
|
||||
/* find index of nearest low sampling point */
|
||||
unsigned min_lat_index = (-(SAMPLING_MIN_LAT) + min_lat) / SAMPLING_RES;
|
||||
unsigned min_lon_index = (-(SAMPLING_MIN_LON) + min_lon) / SAMPLING_RES;
|
||||
|
||||
float declination_sw = get_lookup_table_val(min_lat_index, min_lon_index);
|
||||
float declination_se = get_lookup_table_val(min_lat_index, min_lon_index + 1);
|
||||
float declination_ne = get_lookup_table_val(min_lat_index + 1, min_lon_index + 1);
|
||||
float declination_nw = get_lookup_table_val(min_lat_index + 1, min_lon_index);
|
||||
|
||||
/* perform bilinear interpolation on the four grid corners */
|
||||
|
||||
float declination_min = ((lon - min_lon) / SAMPLING_RES) * (declination_se - declination_sw) + declination_sw;
|
||||
float declination_max = ((lon - min_lon) / SAMPLING_RES) * (declination_ne - declination_nw) + declination_nw;
|
||||
|
||||
return ((lat - min_lat) / SAMPLING_RES) * (declination_max - declination_min) + declination_min;
|
||||
}
|
||||
|
||||
float get_lookup_table_val(unsigned lat_index, unsigned lon_index)
|
||||
{
|
||||
return declination_table[lat_index][lon_index];
|
||||
}
|
||||
+12
-13
@@ -1,8 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
*
|
||||
* Copyright (c) 2014 MAV GEO Library (MAVGEO). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -14,7 +12,7 @@
|
||||
* 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
|
||||
* 3. Neither the name MAVGEO nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
@@ -33,16 +31,17 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file Fixed Wing Attitude Rate Control */
|
||||
/**
|
||||
* @file geo_mag_declination.h
|
||||
*
|
||||
* Calculation / lookup table for earth magnetic field declination.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FIXEDWING_ATT_CONTROL_RATE_H_
|
||||
#define FIXEDWING_ATT_CONTROL_RATE_H_
|
||||
#pragma once
|
||||
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
int fixedwing_att_control_rates(const struct vehicle_rates_setpoint_s *rate_sp,
|
||||
const float rates[],
|
||||
struct actuator_controls_s *actuators);
|
||||
__EXPORT float get_mag_declination(float lat, float lon);
|
||||
|
||||
#endif /* FIXEDWING_ATT_CONTROL_RATE_H_ */
|
||||
__END_DECLS
|
||||
@@ -35,4 +35,5 @@
|
||||
# Geo library
|
||||
#
|
||||
|
||||
SRCS = geo.c
|
||||
SRCS = geo.c \
|
||||
geo_mag_declination.c
|
||||
|
||||
@@ -5193,7 +5193,7 @@ void arm_rfft_fast_f32(
|
||||
*pIa = Ialpha;
|
||||
|
||||
/* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */
|
||||
*pIb = -0.5 * Ialpha + (float32_t) 0.8660254039 *Ibeta;
|
||||
*pIb = (float32_t)-0.5 * Ialpha + (float32_t) 0.8660254039 *Ibeta;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -117,9 +117,10 @@ extern struct system_load_s system_load;
|
||||
#define STICK_ON_OFF_HYSTERESIS_TIME_MS 1000
|
||||
#define STICK_ON_OFF_COUNTER_LIMIT (STICK_ON_OFF_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC)
|
||||
|
||||
#define POSITION_TIMEOUT 50000 /**< consider the local or global position estimate invalid after 50ms */
|
||||
#define RC_TIMEOUT 500000
|
||||
#define DIFFPRESS_TIMEOUT 2000000
|
||||
#define POSITION_TIMEOUT (600 * 1000) /**< consider the local or global position estimate invalid after 600ms */
|
||||
#define FAILSAFE_DEFAULT_TIMEOUT (3 * 1000 * 1000) /**< hysteresis time - the failsafe will trigger after 3 seconds in this state */
|
||||
#define RC_TIMEOUT 500000
|
||||
#define DIFFPRESS_TIMEOUT 2000000
|
||||
|
||||
#define PRINT_INTERVAL 5000000
|
||||
#define PRINT_MODE_REJECT_INTERVAL 2000000
|
||||
@@ -467,6 +468,11 @@ bool handle_command(struct vehicle_status_s *status, const struct safety_s *safe
|
||||
if (cmd->param1 != 0.0f && (fabsf(cmd->param1 - 1.0f) > 2.0f * FLT_EPSILON)) {
|
||||
mavlink_log_info(mavlink_fd, "Unsupported ARM_DISARM parameter: %.6f", cmd->param1);
|
||||
} else {
|
||||
|
||||
// Flick to inair restore first if this comes from an onboard system
|
||||
if (cmd->source_system == status->system_id && cmd->source_component == status->component_id) {
|
||||
status->arming_state = ARMING_STATE_IN_AIR_RESTORE;
|
||||
}
|
||||
transition_result_t arming_res = arm_disarm(cmd->param1 != 0.0f, mavlink_fd, "arm/disarm component command");
|
||||
if (arming_res == TRANSITION_DENIED) {
|
||||
mavlink_log_critical(mavlink_fd, "#audio: REJECTING component arm cmd");
|
||||
@@ -718,8 +724,9 @@ int commander_thread_main(int argc, char *argv[])
|
||||
bool low_battery_voltage_actions_done = false;
|
||||
bool critical_battery_voltage_actions_done = false;
|
||||
|
||||
uint64_t last_idle_time = 0;
|
||||
uint64_t start_time = 0;
|
||||
hrt_abstime last_idle_time = 0;
|
||||
hrt_abstime start_time = 0;
|
||||
hrt_abstime last_auto_state_valid = 0;
|
||||
|
||||
bool status_changed = true;
|
||||
bool param_init_forced = true;
|
||||
@@ -748,6 +755,9 @@ int commander_thread_main(int argc, char *argv[])
|
||||
int global_position_sub = orb_subscribe(ORB_ID(vehicle_global_position));
|
||||
struct vehicle_global_position_s global_position;
|
||||
memset(&global_position, 0, sizeof(global_position));
|
||||
/* Init EPH and EPV */
|
||||
global_position.eph = 1000.0f;
|
||||
global_position.epv = 1000.0f;
|
||||
|
||||
/* Subscribe to local position data */
|
||||
int local_position_sub = orb_subscribe(ORB_ID(vehicle_local_position));
|
||||
@@ -918,11 +928,15 @@ int commander_thread_main(int argc, char *argv[])
|
||||
if (status.condition_global_position_valid) {
|
||||
if (global_position.eph > eph_epv_threshold * 2.0f || global_position.epv > eph_epv_threshold * 2.0f) {
|
||||
eph_epv_good = false;
|
||||
} else {
|
||||
eph_epv_good = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (global_position.eph < eph_epv_threshold && global_position.epv < eph_epv_threshold) {
|
||||
eph_epv_good = true;
|
||||
} else {
|
||||
eph_epv_good = false;
|
||||
}
|
||||
}
|
||||
check_valid(global_position.timestamp, POSITION_TIMEOUT, eph_epv_good, &(status.condition_global_position_valid), &status_changed);
|
||||
@@ -1229,13 +1243,25 @@ int commander_thread_main(int argc, char *argv[])
|
||||
/* check if AUTO mode still allowed */
|
||||
transition_result_t res = main_state_transition(&status, MAIN_STATE_AUTO);
|
||||
|
||||
if (res == TRANSITION_DENIED) {
|
||||
if (res == TRANSITION_NOT_CHANGED) {
|
||||
last_auto_state_valid = hrt_absolute_time();
|
||||
}
|
||||
|
||||
/* still invalid state after the timeout interval, execute failsafe */
|
||||
if ((hrt_elapsed_time(&last_auto_state_valid) > FAILSAFE_DEFAULT_TIMEOUT) && (res == TRANSITION_DENIED)) {
|
||||
/* AUTO mode denied, don't try RTL, switch to failsafe state LAND */
|
||||
res = failsafe_state_transition(&status, FAILSAFE_STATE_LAND);
|
||||
|
||||
if (res == TRANSITION_DENIED) {
|
||||
/* LAND not allowed, set TERMINATION state */
|
||||
transition_result_t res = failsafe_state_transition(&status, FAILSAFE_STATE_TERMINATION);
|
||||
|
||||
if (res == TRANSITION_CHANGED) {
|
||||
mavlink_log_critical(mavlink_fd, "#a FAILSAFE: TERMINATION");
|
||||
}
|
||||
|
||||
} else if (res == TRANSITION_CHANGED) {
|
||||
mavlink_log_critical(mavlink_fd, "#a FAILSAFE: LANDING");
|
||||
}
|
||||
} else {
|
||||
status.set_nav_state = NAVIGATION_STATE_MISSION;
|
||||
@@ -1248,15 +1274,25 @@ int commander_thread_main(int argc, char *argv[])
|
||||
if (!status.condition_landed) {
|
||||
/* vehicle is not landed, try to perform RTL */
|
||||
res = failsafe_state_transition(&status, FAILSAFE_STATE_RTL);
|
||||
|
||||
if (res == TRANSITION_CHANGED) {
|
||||
mavlink_log_critical(mavlink_fd, "#a FAILSAFE: RETURN TO LAND");
|
||||
}
|
||||
}
|
||||
|
||||
if (res == TRANSITION_DENIED) {
|
||||
/* RTL not allowed (no global position estimate) or not wanted, try LAND */
|
||||
res = failsafe_state_transition(&status, FAILSAFE_STATE_LAND);
|
||||
|
||||
if (res == TRANSITION_CHANGED) {
|
||||
mavlink_log_critical(mavlink_fd, "#a FAILSAFE: LANDING");
|
||||
}
|
||||
|
||||
if (res == TRANSITION_DENIED) {
|
||||
/* LAND not allowed, set TERMINATION state */
|
||||
res = failsafe_state_transition(&status, FAILSAFE_STATE_TERMINATION);
|
||||
} else if (res == TRANSITION_CHANGED) {
|
||||
mavlink_log_critical(mavlink_fd, "#a FAILSAFE: TERMINATION");
|
||||
}
|
||||
} else {
|
||||
status.set_nav_state = NAVIGATION_STATE_RTL;
|
||||
|
||||
@@ -199,15 +199,9 @@ int led_init()
|
||||
}
|
||||
|
||||
/* the blue LED is only available on FMUv1 but not FMUv2 */
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
|
||||
|
||||
if (ioctl(leds, LED_ON, LED_BLUE)) {
|
||||
warnx("Blue LED: ioctl fail\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
(void)ioctl(leds, LED_ON, LED_BLUE);
|
||||
|
||||
/* we consider the amber led mandatory */
|
||||
if (ioctl(leds, LED_ON, LED_AMBER)) {
|
||||
warnx("Amber LED: ioctl fail\n");
|
||||
return ERROR;
|
||||
@@ -217,11 +211,7 @@ int led_init()
|
||||
rgbleds = open(RGBLED_DEVICE_PATH, 0);
|
||||
|
||||
if (rgbleds == -1) {
|
||||
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2
|
||||
errx(1, "Unable to open " RGBLED_DEVICE_PATH);
|
||||
#else
|
||||
warnx("No RGB LED found");
|
||||
#endif
|
||||
warnx("No RGB LED found at " RGBLED_DEVICE_PATH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -416,26 +416,26 @@ static int
|
||||
_restart(dm_reset_reason reason)
|
||||
{
|
||||
unsigned char buffer[2];
|
||||
int offset, result = 0;
|
||||
int offset = 0, result = 0;
|
||||
|
||||
/* We need to scan the entire file and invalidate and data that should not persist after the last reset */
|
||||
|
||||
/* Loop through all of the data segments and delete those that are not persistent */
|
||||
offset = 0;
|
||||
|
||||
while (1) {
|
||||
size_t len;
|
||||
|
||||
/* Get data segment at current offset */
|
||||
if (lseek(g_task_fd, offset, SEEK_SET) != offset) {
|
||||
result = -1;
|
||||
/* must be at eof */
|
||||
break;
|
||||
}
|
||||
|
||||
len = read(g_task_fd, buffer, sizeof(buffer));
|
||||
|
||||
if (len == 0)
|
||||
if (len != sizeof(buffer)) {
|
||||
/* must be at eof */
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if segment contains data */
|
||||
if (buffer[0]) {
|
||||
@@ -443,12 +443,12 @@ _restart(dm_reset_reason reason)
|
||||
|
||||
/* Whether data gets deleted depends on reset type and data segment's persistence setting */
|
||||
if (reason == DM_INIT_REASON_POWER_ON) {
|
||||
if (buffer[1] != DM_PERSIST_POWER_ON_RESET) {
|
||||
if (buffer[1] > DM_PERSIST_POWER_ON_RESET) {
|
||||
clear_entry = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((buffer[1] != DM_PERSIST_POWER_ON_RESET) && (buffer[1] != DM_PERSIST_IN_FLIGHT_RESET)) {
|
||||
if (buffer[1] > DM_PERSIST_IN_FLIGHT_RESET) {
|
||||
clear_entry = 1;
|
||||
}
|
||||
}
|
||||
@@ -628,6 +628,23 @@ task_main(int argc, char *argv[])
|
||||
|
||||
fsync(g_task_fd);
|
||||
|
||||
/* see if we need to erase any items based on restart type */
|
||||
int sys_restart_val;
|
||||
if (param_get(param_find("SYS_RESTART_TYPE"), &sys_restart_val) == OK) {
|
||||
if (sys_restart_val == DM_INIT_REASON_POWER_ON) {
|
||||
warnx("Power on restart");
|
||||
_restart(DM_INIT_REASON_POWER_ON);
|
||||
}
|
||||
else if (sys_restart_val == DM_INIT_REASON_IN_FLIGHT) {
|
||||
warnx("In flight restart");
|
||||
_restart(DM_INIT_REASON_IN_FLIGHT);
|
||||
}
|
||||
else
|
||||
warnx("Unknown restart");
|
||||
}
|
||||
else
|
||||
warnx("Unknown restart");
|
||||
|
||||
/* We use two file descriptors, one for the caller context and one for the worker thread */
|
||||
/* They are actually the same but we need to some way to reject caller request while the */
|
||||
/* worker thread is shutting down but still processing requests */
|
||||
@@ -724,7 +741,7 @@ start(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait for the thread to actuall initialize */
|
||||
/* wait for the thread to actually initialize */
|
||||
sem_wait(&g_init_sema);
|
||||
sem_destroy(&g_init_sema);
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ extern "C" {
|
||||
/* The reason for the last reset */
|
||||
typedef enum {
|
||||
DM_INIT_REASON_POWER_ON = 0, /* Data survives resets */
|
||||
DM_INIT_REASON_IN_FLIGHT /* Data survives in-flight resets only */
|
||||
DM_INIT_REASON_IN_FLIGHT, /* Data survives in-flight resets only */
|
||||
DM_INIT_REASON_VOLATILE /* Data does not survive reset */
|
||||
} dm_reset_reason;
|
||||
|
||||
/* Maximum size in bytes of a single item instance */
|
||||
@@ -100,7 +101,7 @@ extern "C" {
|
||||
size_t buflen /* Length in bytes of data to retrieve */
|
||||
);
|
||||
|
||||
/* Retrieve from the data manager store */
|
||||
/* Erase all items of this type */
|
||||
__EXPORT int
|
||||
dm_clear(
|
||||
dm_item_t item /* The item type to clear */
|
||||
|
||||
@@ -138,34 +138,15 @@ void swap_var(float &d1, float &d2)
|
||||
d2 = tmp;
|
||||
}
|
||||
|
||||
AttPosEKF::AttPosEKF() :
|
||||
fusionModeGPS(0),
|
||||
covSkipCount(0),
|
||||
statesInitialised(false),
|
||||
fuseVelData(false),
|
||||
fusePosData(false),
|
||||
fuseHgtData(false),
|
||||
fuseMagData(false),
|
||||
fuseVtasData(false),
|
||||
onGround(true),
|
||||
staticMode(true),
|
||||
useAirspeed(true),
|
||||
useCompass(true),
|
||||
useRangeFinder(true),
|
||||
numericalProtection(true),
|
||||
refSet(false),
|
||||
storeIndex(0),
|
||||
gpsHgt(0.0f),
|
||||
baroHgt(0.0f),
|
||||
GPSstatus(0),
|
||||
VtasMeas(0.0f)
|
||||
{
|
||||
velNED[0] = 0.0f;
|
||||
velNED[1] = 0.0f;
|
||||
velNED[2] = 0.0f;
|
||||
AttPosEKF::AttPosEKF()
|
||||
|
||||
/* NOTE: DO NOT initialize class members here. Use ZeroVariables()
|
||||
* instead to allow clean in-air re-initialization.
|
||||
*/
|
||||
{
|
||||
|
||||
InitialiseParameters();
|
||||
ZeroVariables();
|
||||
InitialiseParameters();
|
||||
}
|
||||
|
||||
AttPosEKF::~AttPosEKF()
|
||||
@@ -2341,13 +2322,13 @@ int AttPosEKF::CheckAndBound()
|
||||
if (StatesNaN(&last_ekf_error)) {
|
||||
ekf_debug("re-initializing dynamic");
|
||||
|
||||
InitializeDynamic(velNED);
|
||||
InitializeDynamic(velNED, magDeclination);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Reset the filter if the IMU data is too old
|
||||
if (dtIMU > 0.2f) {
|
||||
if (dtIMU > 0.3f) {
|
||||
|
||||
ResetVelocity();
|
||||
ResetPosition();
|
||||
@@ -2374,7 +2355,7 @@ int AttPosEKF::CheckAndBound()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float *initQuat)
|
||||
void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat)
|
||||
{
|
||||
float initialRoll, initialPitch;
|
||||
float cosRoll, sinRoll, cosPitch, sinPitch;
|
||||
@@ -2394,6 +2375,8 @@ void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, f
|
||||
magY = my * cosRoll - mz * sinRoll;
|
||||
|
||||
initialHdg = atan2f(-magY, magX);
|
||||
/* true heading is the mag heading minus declination */
|
||||
initialHdg += declination;
|
||||
|
||||
cosRoll = cosf(initialRoll * 0.5f);
|
||||
sinRoll = sinf(initialRoll * 0.5f);
|
||||
@@ -2408,28 +2391,36 @@ void AttPosEKF::AttitudeInit(float ax, float ay, float az, float mx, float my, f
|
||||
initQuat[1] = sinRoll * cosPitch * cosHeading - cosRoll * sinPitch * sinHeading;
|
||||
initQuat[2] = cosRoll * sinPitch * cosHeading + sinRoll * cosPitch * sinHeading;
|
||||
initQuat[3] = cosRoll * cosPitch * sinHeading - sinRoll * sinPitch * cosHeading;
|
||||
|
||||
/* normalize */
|
||||
float norm = sqrtf(initQuat[0]*initQuat[0] + initQuat[1]*initQuat[1] + initQuat[2]*initQuat[2] + initQuat[3]*initQuat[3]);
|
||||
|
||||
initQuat[0] /= norm;
|
||||
initQuat[1] /= norm;
|
||||
initQuat[2] /= norm;
|
||||
initQuat[3] /= norm;
|
||||
}
|
||||
|
||||
void AttPosEKF::InitializeDynamic(float (&initvelNED)[3])
|
||||
void AttPosEKF::InitializeDynamic(float (&initvelNED)[3], float declination)
|
||||
{
|
||||
|
||||
// Clear the init flag
|
||||
statesInitialised = false;
|
||||
|
||||
ZeroVariables();
|
||||
// Fill variables with valid data
|
||||
velNED[0] = initvelNED[0];
|
||||
velNED[1] = initvelNED[1];
|
||||
velNED[2] = initvelNED[2];
|
||||
magDeclination = declination;
|
||||
|
||||
// Calculate initial filter quaternion states from raw measurements
|
||||
float initQuat[4];
|
||||
Vector3f initMagXYZ;
|
||||
initMagXYZ = magData - magBias;
|
||||
AttitudeInit(accel.x, accel.y, accel.z, initMagXYZ.x, initMagXYZ.y, initMagXYZ.z, initQuat);
|
||||
AttitudeInit(accel.x, accel.y, accel.z, initMagXYZ.x, initMagXYZ.y, initMagXYZ.z, declination, initQuat);
|
||||
|
||||
// Calculate initial Tbn matrix and rotate Mag measurements into NED
|
||||
// to set initial NED magnetic field states
|
||||
Mat3f DCM;
|
||||
quat2Tbn(DCM, initQuat);
|
||||
Vector3f initMagNED;
|
||||
initMagXYZ = magData - magBias;
|
||||
initMagNED.x = DCM.x.x*initMagXYZ.x + DCM.x.y*initMagXYZ.y + DCM.x.z*initMagXYZ.z;
|
||||
initMagNED.y = DCM.y.x*initMagXYZ.x + DCM.y.y*initMagXYZ.y + DCM.y.z*initMagXYZ.z;
|
||||
initMagNED.z = DCM.z.x*initMagXYZ.x + DCM.z.y*initMagXYZ.y + DCM.z.z*initMagXYZ.z;
|
||||
@@ -2438,9 +2429,9 @@ void AttPosEKF::InitializeDynamic(float (&initvelNED)[3])
|
||||
magstate.q1 = initQuat[1];
|
||||
magstate.q2 = initQuat[2];
|
||||
magstate.q3 = initQuat[3];
|
||||
magstate.magN = magData.x;
|
||||
magstate.magE = magData.y;
|
||||
magstate.magD = magData.z;
|
||||
magstate.magN = initMagNED.x;
|
||||
magstate.magE = initMagNED.y;
|
||||
magstate.magD = initMagNED.z;
|
||||
magstate.magXbias = magBias.x;
|
||||
magstate.magYbias = magBias.y;
|
||||
magstate.magZbias = magBias.z;
|
||||
@@ -2471,16 +2462,9 @@ void AttPosEKF::InitializeDynamic(float (&initvelNED)[3])
|
||||
//Define Earth rotation vector in the NED navigation frame
|
||||
calcEarthRateNED(earthRateNED, latRef);
|
||||
|
||||
//Initialise summed variables used by covariance prediction
|
||||
summedDelAng.x = 0.0f;
|
||||
summedDelAng.y = 0.0f;
|
||||
summedDelAng.z = 0.0f;
|
||||
summedDelVel.x = 0.0f;
|
||||
summedDelVel.y = 0.0f;
|
||||
summedDelVel.z = 0.0f;
|
||||
}
|
||||
|
||||
void AttPosEKF::InitialiseFilter(float (&initvelNED)[3], double referenceLat, double referenceLon, float referenceHgt)
|
||||
void AttPosEKF::InitialiseFilter(float (&initvelNED)[3], double referenceLat, double referenceLon, float referenceHgt, float declination)
|
||||
{
|
||||
//store initial lat,long and height
|
||||
latRef = referenceLat;
|
||||
@@ -2490,11 +2474,35 @@ void AttPosEKF::InitialiseFilter(float (&initvelNED)[3], double referenceLat, do
|
||||
|
||||
memset(&last_ekf_error, 0, sizeof(last_ekf_error));
|
||||
|
||||
InitializeDynamic(initvelNED);
|
||||
InitializeDynamic(initvelNED, declination);
|
||||
}
|
||||
|
||||
void AttPosEKF::ZeroVariables()
|
||||
{
|
||||
|
||||
// Initialize on-init initialized variables
|
||||
fusionModeGPS = 0;
|
||||
covSkipCount = 0;
|
||||
statesInitialised = false;
|
||||
fuseVelData = false;
|
||||
fusePosData = false;
|
||||
fuseHgtData = false;
|
||||
fuseMagData = false;
|
||||
fuseVtasData = false;
|
||||
onGround = true;
|
||||
staticMode = true;
|
||||
useAirspeed = true;
|
||||
useCompass = true;
|
||||
useRangeFinder = true;
|
||||
numericalProtection = true;
|
||||
refSet = false;
|
||||
storeIndex = 0;
|
||||
gpsHgt = 0.0f;
|
||||
baroHgt = 0.0f;
|
||||
GPSstatus = 0;
|
||||
VtasMeas = 0.0f;
|
||||
magDeclination = 0.0f;
|
||||
|
||||
// Do the data structure init
|
||||
for (unsigned i = 0; i < n_states; i++) {
|
||||
for (unsigned j = 0; j < n_states; j++) {
|
||||
@@ -2511,6 +2519,9 @@ void AttPosEKF::ZeroVariables()
|
||||
summedDelAng.zero();
|
||||
summedDelVel.zero();
|
||||
|
||||
dAngIMU.zero();
|
||||
dVelIMU.zero();
|
||||
|
||||
for (unsigned i = 0; i < data_buffer_size; i++) {
|
||||
|
||||
for (unsigned j = 0; j < n_states; j++) {
|
||||
|
||||
@@ -208,6 +208,7 @@ public:
|
||||
float innovRng; ///< Range finder innovation
|
||||
float varInnovVtas; // innovation variance output
|
||||
float VtasMeas; // true airspeed measurement (m/s)
|
||||
float magDeclination; ///< magnetic declination
|
||||
double latRef; // WGS-84 latitude of reference point (rad)
|
||||
double lonRef; // WGS-84 longitude of reference point (rad)
|
||||
float hgtRef; // WGS-84 height of reference point (m)
|
||||
@@ -309,7 +310,7 @@ void OnGroundCheck();
|
||||
|
||||
void CovarianceInit();
|
||||
|
||||
void InitialiseFilter(float (&initvelNED)[3], double referenceLat, double referenceLon, float referenceHgt);
|
||||
void InitialiseFilter(float (&initvelNED)[3], double referenceLat, double referenceLon, float referenceHgt, float declination);
|
||||
|
||||
float ConstrainFloat(float val, float min, float max);
|
||||
|
||||
@@ -334,7 +335,7 @@ void GetLastErrorState(struct ekf_status_report *last_error);
|
||||
bool StatesNaN(struct ekf_status_report *err_report);
|
||||
void FillErrorReport(struct ekf_status_report *err);
|
||||
|
||||
void InitializeDynamic(float (&initvelNED)[3]);
|
||||
void InitializeDynamic(float (&initvelNED)[3], float declination);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -342,7 +343,7 @@ bool FilterHealthy();
|
||||
|
||||
void ResetHeight(void);
|
||||
|
||||
void AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float *initQuat);
|
||||
void AttitudeInit(float ax, float ay, float az, float mx, float my, float mz, float declination, float *initQuat);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -194,6 +194,9 @@ private:
|
||||
bool _baro_init;
|
||||
bool _gps_initialized;
|
||||
uint64_t _gps_start_time;
|
||||
bool _gyro_valid;
|
||||
bool _accel_valid;
|
||||
bool _mag_valid;
|
||||
|
||||
int _mavlink_fd;
|
||||
|
||||
@@ -345,6 +348,9 @@ FixedwingEstimator::FixedwingEstimator() :
|
||||
_initialized(false),
|
||||
_baro_init(false),
|
||||
_gps_initialized(false),
|
||||
_gyro_valid(false),
|
||||
_accel_valid(false),
|
||||
_mag_valid(false),
|
||||
_mavlink_fd(-1),
|
||||
_ekf(nullptr),
|
||||
_velocity_xy_filtered(0.0f),
|
||||
@@ -547,24 +553,8 @@ FixedwingEstimator::task_main()
|
||||
/* sets also parameters in the EKF object */
|
||||
parameters_update();
|
||||
|
||||
/* set initial filter state */
|
||||
_ekf->fuseVelData = false;
|
||||
_ekf->fusePosData = false;
|
||||
_ekf->fuseHgtData = false;
|
||||
_ekf->fuseMagData = false;
|
||||
_ekf->fuseVtasData = false;
|
||||
_ekf->statesInitialised = false;
|
||||
|
||||
/* initialize measurement data */
|
||||
_ekf->VtasMeas = 0.0f;
|
||||
Vector3f lastAngRate = {0.0f, 0.0f, 0.0f};
|
||||
Vector3f lastAccel = {0.0f, 0.0f, -9.81f};
|
||||
_ekf->dVelIMU.x = 0.0f;
|
||||
_ekf->dVelIMU.y = 0.0f;
|
||||
_ekf->dVelIMU.z = 0.0f;
|
||||
_ekf->dAngIMU.x = 0.0f;
|
||||
_ekf->dAngIMU.y = 0.0f;
|
||||
_ekf->dAngIMU.z = 0.0f;
|
||||
Vector3f lastAccel = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* wakeup source(s) */
|
||||
struct pollfd fds[2];
|
||||
@@ -622,20 +612,45 @@ FixedwingEstimator::task_main()
|
||||
bool accel_updated;
|
||||
bool mag_updated;
|
||||
|
||||
hrt_abstime last_sensor_timestamp;
|
||||
|
||||
perf_count(_perf_gyro);
|
||||
|
||||
/* Reset baro reference if switching to HIL */
|
||||
/* Reset baro reference if switching to HIL, reset sensor states */
|
||||
if (!prev_hil && (_vstatus.hil_state == HIL_STATE_ON)) {
|
||||
/* system is in HIL now, wait for measurements to come in one last round */
|
||||
usleep(60000);
|
||||
|
||||
#ifndef SENSOR_COMBINED_SUB
|
||||
orb_copy(ORB_ID(sensor_gyro), _gyro_sub, &_gyro);
|
||||
orb_copy(ORB_ID(sensor_accel), _accel_sub, &_accel);
|
||||
orb_copy(ORB_ID(sensor_mag), _mag_sub, &_mag);
|
||||
#else
|
||||
/* now read all sensor publications to ensure all real sensor data is purged */
|
||||
orb_copy(ORB_ID(sensor_combined), _sensor_combined_sub, &_sensor_combined);
|
||||
#endif
|
||||
|
||||
/* set sensors to de-initialized state */
|
||||
_gyro_valid = false;
|
||||
_accel_valid = false;
|
||||
_mag_valid = false;
|
||||
|
||||
_baro_init = false;
|
||||
_gps_initialized = false;
|
||||
last_sensor_timestamp = hrt_absolute_time();
|
||||
last_run = last_sensor_timestamp;
|
||||
|
||||
_ekf->ZeroVariables();
|
||||
_ekf->dtIMU = 0.01f;
|
||||
|
||||
/* now skip this loop and get data on the next one, which will also re-init the filter */
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* PART ONE: COLLECT ALL DATA
|
||||
**/
|
||||
|
||||
hrt_abstime last_sensor_timestamp;
|
||||
|
||||
/* load local copies */
|
||||
#ifndef SENSOR_COMBINED_SUB
|
||||
orb_copy(ORB_ID(sensor_gyro), _gyro_sub, &_gyro);
|
||||
@@ -649,7 +664,7 @@ FixedwingEstimator::task_main()
|
||||
}
|
||||
|
||||
last_sensor_timestamp = _gyro.timestamp;
|
||||
_ekf.IMUmsec = _gyro.timestamp / 1e3f;
|
||||
IMUmsec = _gyro.timestamp / 1e3f;
|
||||
|
||||
float deltaT = (_gyro.timestamp - last_run) / 1e6f;
|
||||
last_run = _gyro.timestamp;
|
||||
@@ -670,12 +685,24 @@ FixedwingEstimator::task_main()
|
||||
_ekf->angRate.x = _gyro.x;
|
||||
_ekf->angRate.y = _gyro.y;
|
||||
_ekf->angRate.z = _gyro.z;
|
||||
|
||||
if (!_gyro_valid) {
|
||||
lastAngRate = _ekf->angRate;
|
||||
}
|
||||
|
||||
_gyro_valid = true;
|
||||
}
|
||||
|
||||
if (accel_updated) {
|
||||
_ekf->accel.x = _accel.x;
|
||||
_ekf->accel.y = _accel.y;
|
||||
_ekf->accel.z = _accel.z;
|
||||
|
||||
if (!_accel_valid) {
|
||||
lastAccel = _ekf->accel;
|
||||
}
|
||||
|
||||
_accel_valid = true;
|
||||
}
|
||||
|
||||
_ekf->dAngIMU = 0.5f * (angRate + lastAngRate) * dtIMU;
|
||||
@@ -720,12 +747,24 @@ FixedwingEstimator::task_main()
|
||||
_ekf->angRate.x = _sensor_combined.gyro_rad_s[0];
|
||||
_ekf->angRate.y = _sensor_combined.gyro_rad_s[1];
|
||||
_ekf->angRate.z = _sensor_combined.gyro_rad_s[2];
|
||||
|
||||
if (!_gyro_valid) {
|
||||
lastAngRate = _ekf->angRate;
|
||||
}
|
||||
|
||||
_gyro_valid = true;
|
||||
}
|
||||
|
||||
if (accel_updated) {
|
||||
_ekf->accel.x = _sensor_combined.accelerometer_m_s2[0];
|
||||
_ekf->accel.y = _sensor_combined.accelerometer_m_s2[1];
|
||||
_ekf->accel.z = _sensor_combined.accelerometer_m_s2[2];
|
||||
|
||||
if (!_accel_valid) {
|
||||
lastAccel = _ekf->accel;
|
||||
}
|
||||
|
||||
_accel_valid = true;
|
||||
}
|
||||
|
||||
_ekf->dAngIMU = 0.5f * (_ekf->angRate + lastAngRate) * _ekf->dtIMU;
|
||||
@@ -844,6 +883,8 @@ FixedwingEstimator::task_main()
|
||||
|
||||
if (mag_updated) {
|
||||
|
||||
_mag_valid = true;
|
||||
|
||||
perf_count(_perf_mag);
|
||||
|
||||
#ifndef SENSOR_COMBINED_SUB
|
||||
@@ -911,7 +952,7 @@ FixedwingEstimator::task_main()
|
||||
{
|
||||
const char* str = "switching to dynamic state";
|
||||
warnx("%s", str);
|
||||
mavlink_log_critical(_mavlink_fd, "%s%s", ekfname, str);
|
||||
mavlink_log_info(_mavlink_fd, "%s%s", ekfname, str);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -961,6 +1002,22 @@ FixedwingEstimator::task_main()
|
||||
_estimator_status_pub = orb_advertise(ORB_ID(estimator_status), &rep);
|
||||
}
|
||||
|
||||
/* set sensors to de-initialized state */
|
||||
_gyro_valid = false;
|
||||
_accel_valid = false;
|
||||
_mag_valid = false;
|
||||
|
||||
_baro_init = false;
|
||||
_gps_initialized = false;
|
||||
last_sensor_timestamp = hrt_absolute_time();
|
||||
last_run = last_sensor_timestamp;
|
||||
|
||||
_ekf->ZeroVariables();
|
||||
_ekf->dtIMU = 0.01f;
|
||||
|
||||
// Let the system re-initialize itself
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -968,21 +1025,15 @@ FixedwingEstimator::task_main()
|
||||
* PART TWO: EXECUTE THE FILTER
|
||||
**/
|
||||
|
||||
// Wait long enough to ensure all sensors updated once
|
||||
// XXX we rather want to check all updated
|
||||
if (_baro_init && _gyro_valid && _accel_valid && _mag_valid) {
|
||||
|
||||
float initVelNED[3];
|
||||
|
||||
if (hrt_elapsed_time(&_gps_start_time) > 50000) {
|
||||
if (!_gps_initialized && _gps.fix_type > 2 && _gps.eph_m < _parameters.pos_stddev_threshold && _gps.epv_m < _parameters.pos_stddev_threshold) {
|
||||
|
||||
// bool home_set;
|
||||
// orb_check(_home_sub, &home_set);
|
||||
// struct home_position_s home;
|
||||
// orb_copy(ORB_ID(home_position), _home_sub, &home);
|
||||
|
||||
if (!_gps_initialized && _gps.fix_type > 2 && _gps.eph < _parameters.pos_stddev_threshold && _gps.epv < _parameters.pos_stddev_threshold) {
|
||||
_ekf->velNED[0] = _gps.vel_n_m_s;
|
||||
_ekf->velNED[1] = _gps.vel_e_m_s;
|
||||
_ekf->velNED[2] = _gps.vel_d_m_s;
|
||||
initVelNED[0] = _gps.vel_n_m_s;
|
||||
initVelNED[1] = _gps.vel_e_m_s;
|
||||
initVelNED[2] = _gps.vel_d_m_s;
|
||||
|
||||
// GPS is in scaled integers, convert
|
||||
double lat = _gps.lat / 1.0e7;
|
||||
@@ -997,19 +1048,19 @@ FixedwingEstimator::task_main()
|
||||
|
||||
// Set up position variables correctly
|
||||
_ekf->GPSstatus = _gps.fix_type;
|
||||
_ekf->velNED[0] = _gps.vel_n_m_s;
|
||||
_ekf->velNED[1] = _gps.vel_e_m_s;
|
||||
_ekf->velNED[2] = _gps.vel_d_m_s;
|
||||
|
||||
_ekf->gpsLat = math::radians(_gps.lat / (double)1e7);
|
||||
_ekf->gpsLon = math::radians(_gps.lon / (double)1e7) - M_PI;
|
||||
_ekf->gpsHgt = _gps.alt / 1e3f;
|
||||
_ekf->gpsLat = math::radians(lat);
|
||||
_ekf->gpsLon = math::radians(lon) - M_PI;
|
||||
_ekf->gpsHgt = gps_alt;
|
||||
|
||||
_ekf->InitialiseFilter(_ekf->velNED, math::radians(lat), math::radians(lon) - M_PI, gps_alt);
|
||||
// Look up mag declination based on current position
|
||||
float declination = math::radians(get_mag_declination(lat, lon));
|
||||
|
||||
_ekf->InitialiseFilter(initVelNED, math::radians(lat), math::radians(lon) - M_PI, gps_alt, declination);
|
||||
|
||||
// Initialize projection
|
||||
_local_pos.ref_lat = _gps.lat;
|
||||
_local_pos.ref_lon = _gps.alt;
|
||||
_local_pos.ref_lat = lat;
|
||||
_local_pos.ref_lon = lon;
|
||||
_local_pos.ref_alt = _baro_ref + _baro_gps_offset;
|
||||
_local_pos.ref_timestamp = _gps.timestamp_position;
|
||||
|
||||
@@ -1017,21 +1068,23 @@ FixedwingEstimator::task_main()
|
||||
mavlink_log_info(_mavlink_fd, "[ekf] ref: LA %.4f,LO %.4f,ALT %.2f", lat, lon, (double)gps_alt);
|
||||
warnx("HOME/REF: LA %8.4f,LO %8.4f,ALT %8.2f V: %8.4f %8.4f %8.4f", lat, lon, (double)gps_alt,
|
||||
(double)_ekf->velNED[0], (double)_ekf->velNED[1], (double)_ekf->velNED[2]);
|
||||
warnx("GPS: eph: %8.4f, epv: %8.4f", (double)_gps.eph, (double)_gps.epv);
|
||||
warnx("BARO: %8.4f m / ref: %8.4f m", _ekf->baroHgt, _ekf->hgtMea);
|
||||
warnx("GPS: eph: %8.4f, epv: %8.4f, declination: %8.4f", (double)_gps.eph, (double)_gps.epv, (double)math::degrees(declination));
|
||||
|
||||
_gps_initialized = true;
|
||||
|
||||
} else if (!_ekf->statesInitialised) {
|
||||
_ekf->velNED[0] = 0.0f;
|
||||
_ekf->velNED[1] = 0.0f;
|
||||
_ekf->velNED[2] = 0.0f;
|
||||
|
||||
initVelNED[0] = 0.0f;
|
||||
initVelNED[1] = 0.0f;
|
||||
initVelNED[2] = 0.0f;
|
||||
_ekf->posNED[0] = 0.0f;
|
||||
_ekf->posNED[1] = 0.0f;
|
||||
_ekf->posNED[2] = 0.0f;
|
||||
|
||||
_ekf->posNE[0] = _ekf->posNED[0];
|
||||
_ekf->posNE[1] = _ekf->posNED[1];
|
||||
_ekf->InitialiseFilter(_ekf->velNED, 0.0, 0.0, 0.0f);
|
||||
_ekf->InitialiseFilter(initVelNED, 0.0, 0.0, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,13 +1444,13 @@ int FixedwingEstimator::trip_nan() {
|
||||
_ekf->states[5] = nan_val;
|
||||
usleep(100000);
|
||||
|
||||
// warnx("tripping covariance #1 with NaN values");
|
||||
// KH[2][2] = nan_val; // intermediate result used for covariance updates
|
||||
// usleep(100000);
|
||||
warnx("tripping covariance #1 with NaN values");
|
||||
_ekf->KH[2][2] = nan_val; // intermediate result used for covariance updates
|
||||
usleep(100000);
|
||||
|
||||
// warnx("tripping covariance #2 with NaN values");
|
||||
// KHP[5][5] = nan_val; // intermediate result used for covariance updates
|
||||
// usleep(100000);
|
||||
warnx("tripping covariance #2 with NaN values");
|
||||
_ekf->KHP[5][5] = nan_val; // intermediate result used for covariance updates
|
||||
usleep(100000);
|
||||
|
||||
warnx("tripping covariance #3 with NaN values");
|
||||
_ekf->P[3][3] = nan_val; // covariance matrix
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file fixedwing_att_control_rate.c
|
||||
* Implementation of a fixed wing attitude controller.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <uORB/uORB.h>
|
||||
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/pid/pid.h>
|
||||
#include <systemlib/geo/geo.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
|
||||
#include "fixedwing_att_control_att.h"
|
||||
|
||||
|
||||
struct fw_att_control_params {
|
||||
float roll_p;
|
||||
float rollrate_lim;
|
||||
float pitch_p;
|
||||
float pitchrate_lim;
|
||||
float yawrate_lim;
|
||||
float pitch_roll_compensation_p;
|
||||
};
|
||||
|
||||
struct fw_pos_control_param_handles {
|
||||
param_t roll_p;
|
||||
param_t rollrate_lim;
|
||||
param_t pitch_p;
|
||||
param_t pitchrate_lim;
|
||||
param_t yawrate_lim;
|
||||
param_t pitch_roll_compensation_p;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Internal Prototypes */
|
||||
static int parameters_init(struct fw_pos_control_param_handles *h);
|
||||
static int parameters_update(const struct fw_pos_control_param_handles *h, struct fw_att_control_params *p);
|
||||
|
||||
static int parameters_init(struct fw_pos_control_param_handles *h)
|
||||
{
|
||||
/* PID parameters */
|
||||
h->roll_p = param_find("FW_ROLL_P");
|
||||
h->rollrate_lim = param_find("FW_ROLLR_LIM");
|
||||
h->pitch_p = param_find("FW_PITCH_P");
|
||||
h->pitchrate_lim = param_find("FW_PITCHR_LIM");
|
||||
h->yawrate_lim = param_find("FW_YAWR_LIM");
|
||||
h->pitch_roll_compensation_p = param_find("FW_PITCH_RCOMP");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int parameters_update(const struct fw_pos_control_param_handles *h, struct fw_att_control_params *p)
|
||||
{
|
||||
param_get(h->roll_p, &(p->roll_p));
|
||||
param_get(h->rollrate_lim, &(p->rollrate_lim));
|
||||
param_get(h->pitch_p, &(p->pitch_p));
|
||||
param_get(h->pitchrate_lim, &(p->pitchrate_lim));
|
||||
param_get(h->yawrate_lim, &(p->yawrate_lim));
|
||||
param_get(h->pitch_roll_compensation_p, &(p->pitch_roll_compensation_p));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int fixedwing_att_control_attitude(const struct vehicle_attitude_setpoint_s *att_sp,
|
||||
const struct vehicle_attitude_s *att,
|
||||
const float speed_body[],
|
||||
struct vehicle_rates_setpoint_s *rates_sp)
|
||||
{
|
||||
static int counter = 0;
|
||||
static bool initialized = false;
|
||||
|
||||
static struct fw_att_control_params p;
|
||||
static struct fw_pos_control_param_handles h;
|
||||
|
||||
static PID_t roll_controller;
|
||||
static PID_t pitch_controller;
|
||||
|
||||
|
||||
if (!initialized) {
|
||||
parameters_init(&h);
|
||||
parameters_update(&h, &p);
|
||||
pid_init(&roll_controller, p.roll_p, 0, 0, 0, p.rollrate_lim, PID_MODE_DERIVATIV_NONE, 0.0f); //P Controller
|
||||
pid_init(&pitch_controller, p.pitch_p, 0, 0, 0, p.pitchrate_lim, PID_MODE_DERIVATIV_NONE, 0.0f); //P Controller
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/* load new parameters with lower rate */
|
||||
if (counter % 100 == 0) {
|
||||
/* update parameters from storage */
|
||||
parameters_update(&h, &p);
|
||||
pid_set_parameters(&roll_controller, p.roll_p, 0, 0, 0, p.rollrate_lim);
|
||||
pid_set_parameters(&pitch_controller, p.pitch_p, 0, 0, 0, p.pitchrate_lim);
|
||||
}
|
||||
|
||||
/* Roll (P) */
|
||||
rates_sp->roll = pid_calculate(&roll_controller, att_sp->roll_body, att->roll, 0, 0);
|
||||
|
||||
|
||||
/* Pitch (P) */
|
||||
|
||||
/* compensate feedforward for loss of lift due to non-horizontal angle of wing */
|
||||
float pitch_sp_rollcompensation = p.pitch_roll_compensation_p * fabsf(sinf(att_sp->roll_body));
|
||||
/* set pitch plus feedforward roll compensation */
|
||||
rates_sp->pitch = pid_calculate(&pitch_controller,
|
||||
att_sp->pitch_body + pitch_sp_rollcompensation,
|
||||
att->pitch, 0, 0);
|
||||
|
||||
/* Yaw (from coordinated turn constraint or lateral force) */
|
||||
rates_sp->yaw = (att->rollspeed * rates_sp->roll + 9.81f * sinf(att->roll) * cosf(att->pitch) + speed_body[0] * rates_sp->pitch * sinf(att->roll))
|
||||
/ (speed_body[0] * cosf(att->roll) * cosf(att->pitch) + speed_body[2] * sinf(att->pitch));
|
||||
|
||||
// printf("rates_sp->yaw %.4f \n", (double)rates_sp->yaw);
|
||||
|
||||
counter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* @file Fixed Wing Attitude Control */
|
||||
|
||||
#ifndef FIXEDWING_ATT_CONTROL_ATT_H_
|
||||
#define FIXEDWING_ATT_CONTROL_ATT_H_
|
||||
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
|
||||
int fixedwing_att_control_attitude(const struct vehicle_attitude_setpoint_s *att_sp,
|
||||
const struct vehicle_attitude_s *att,
|
||||
const float speed_body[],
|
||||
struct vehicle_rates_setpoint_s *rates_sp);
|
||||
|
||||
#endif /* FIXEDWING_ATT_CONTROL_ATT_H_ */
|
||||
@@ -1,367 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Doug Weibel <douglas.weibel@colorado.edu>
|
||||
*
|
||||
* 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 fixedwing_att_control.c
|
||||
* Implementation of a fixed wing attitude controller.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_global_position_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/debug_key_value.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/pid/pid.h>
|
||||
#include <systemlib/geo/geo.h>
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
|
||||
#include "fixedwing_att_control_rate.h"
|
||||
#include "fixedwing_att_control_att.h"
|
||||
|
||||
/* Prototypes */
|
||||
/**
|
||||
* Deamon management function.
|
||||
*/
|
||||
__EXPORT int fixedwing_att_control_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Mainloop of deamon.
|
||||
*/
|
||||
int fixedwing_att_control_thread_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Print the correct usage.
|
||||
*/
|
||||
static void usage(const char *reason);
|
||||
|
||||
/* Variables */
|
||||
static bool thread_should_exit = false; /**< Deamon exit flag */
|
||||
static bool thread_running = false; /**< Deamon status flag */
|
||||
static int deamon_task; /**< Handle of deamon task / thread */
|
||||
|
||||
/* Main Thread */
|
||||
int fixedwing_att_control_thread_main(int argc, char *argv[])
|
||||
{
|
||||
/* read arguments */
|
||||
bool verbose = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome user */
|
||||
printf("[fixedwing att control] started\n");
|
||||
|
||||
/* declare and safely initialize all structs */
|
||||
struct vehicle_attitude_s att;
|
||||
memset(&att, 0, sizeof(att));
|
||||
struct vehicle_attitude_setpoint_s att_sp;
|
||||
memset(&att_sp, 0, sizeof(att_sp));
|
||||
struct vehicle_rates_setpoint_s rates_sp;
|
||||
memset(&rates_sp, 0, sizeof(rates_sp));
|
||||
struct vehicle_global_position_s global_pos;
|
||||
memset(&global_pos, 0, sizeof(global_pos));
|
||||
struct manual_control_setpoint_s manual_sp;
|
||||
memset(&manual_sp, 0, sizeof(manual_sp));
|
||||
struct vehicle_control_mode_s control_mode;
|
||||
memset(&control_mode, 0, sizeof(control_mode));
|
||||
struct vehicle_status_s vstatus;
|
||||
memset(&vstatus, 0, sizeof(vstatus));
|
||||
|
||||
/* output structs */
|
||||
struct actuator_controls_s actuators;
|
||||
memset(&actuators, 0, sizeof(actuators));
|
||||
|
||||
|
||||
/* publish actuator controls */
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++) {
|
||||
actuators.control[i] = 0.0f;
|
||||
}
|
||||
|
||||
orb_advert_t actuator_pub = orb_advertise(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, &actuators);
|
||||
orb_advert_t rates_pub = orb_advertise(ORB_ID(vehicle_rates_setpoint), &rates_sp);
|
||||
|
||||
/* subscribe */
|
||||
int att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
int att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
|
||||
int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
|
||||
int manual_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
|
||||
int control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
|
||||
int vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
|
||||
/* Setup of loop */
|
||||
float gyro[3] = {0.0f, 0.0f, 0.0f};
|
||||
float speed_body[3] = {0.0f, 0.0f, 0.0f};
|
||||
struct pollfd fds = { .fd = att_sub, .events = POLLIN };
|
||||
|
||||
while (!thread_should_exit) {
|
||||
/* wait for a sensor update, check for exit condition every 500 ms */
|
||||
poll(&fds, 1, 500);
|
||||
|
||||
/* Check if there is a new position measurement or attitude setpoint */
|
||||
bool pos_updated;
|
||||
orb_check(global_pos_sub, &pos_updated);
|
||||
bool att_sp_updated;
|
||||
orb_check(att_sp_sub, &att_sp_updated);
|
||||
|
||||
/* get a local copy of attitude */
|
||||
orb_copy(ORB_ID(vehicle_attitude), att_sub, &att);
|
||||
|
||||
if (att_sp_updated)
|
||||
orb_copy(ORB_ID(vehicle_attitude_setpoint), att_sp_sub, &att_sp);
|
||||
|
||||
if (pos_updated) {
|
||||
orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos);
|
||||
|
||||
if (att.R_valid) {
|
||||
speed_body[0] = att.R[0][0] * global_pos.vx + att.R[0][1] * global_pos.vy + att.R[0][2] * global_pos.vz;
|
||||
speed_body[1] = att.R[1][0] * global_pos.vx + att.R[1][1] * global_pos.vy + att.R[1][2] * global_pos.vz;
|
||||
speed_body[2] = att.R[2][0] * global_pos.vx + att.R[2][1] * global_pos.vy + att.R[2][2] * global_pos.vz;
|
||||
|
||||
} else {
|
||||
speed_body[0] = 0;
|
||||
speed_body[1] = 0;
|
||||
speed_body[2] = 0;
|
||||
|
||||
printf("FW ATT CONTROL: Did not get a valid R\n");
|
||||
}
|
||||
}
|
||||
|
||||
orb_copy(ORB_ID(manual_control_setpoint), manual_sp_sub, &manual_sp);
|
||||
orb_copy(ORB_ID(vehicle_control_mode), control_mode_sub, &control_mode);
|
||||
orb_copy(ORB_ID(vehicle_status), vehicle_status_sub, &vstatus);
|
||||
|
||||
gyro[0] = att.rollspeed;
|
||||
gyro[1] = att.pitchspeed;
|
||||
gyro[2] = att.yawspeed;
|
||||
|
||||
/* set manual setpoints if required */
|
||||
if (control_mode.flag_control_manual_enabled) {
|
||||
if (control_mode.flag_control_attitude_enabled) {
|
||||
|
||||
/* if the RC signal is lost, try to stay level and go slowly back down to ground */
|
||||
if (vstatus.rc_signal_lost) {
|
||||
|
||||
/* put plane into loiter */
|
||||
att_sp.roll_body = 0.3f;
|
||||
att_sp.pitch_body = 0.0f;
|
||||
|
||||
/* limit throttle to 60 % of last value if sane */
|
||||
if (isfinite(manual_sp.throttle) &&
|
||||
(manual_sp.throttle >= 0.0f) &&
|
||||
(manual_sp.throttle <= 1.0f)) {
|
||||
att_sp.thrust = 0.6f * manual_sp.throttle;
|
||||
|
||||
} else {
|
||||
att_sp.thrust = 0.0f;
|
||||
}
|
||||
|
||||
att_sp.yaw_body = 0;
|
||||
|
||||
// XXX disable yaw control, loiter
|
||||
|
||||
} else {
|
||||
|
||||
att_sp.roll_body = manual_sp.roll;
|
||||
att_sp.pitch_body = manual_sp.pitch;
|
||||
att_sp.yaw_body = 0;
|
||||
att_sp.thrust = manual_sp.throttle;
|
||||
}
|
||||
|
||||
att_sp.timestamp = hrt_absolute_time();
|
||||
|
||||
/* pass through flaps */
|
||||
if (isfinite(manual_sp.flaps)) {
|
||||
actuators.control[4] = manual_sp.flaps;
|
||||
|
||||
} else {
|
||||
actuators.control[4] = 0.0f;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* directly pass through values */
|
||||
actuators.control[0] = manual_sp.roll;
|
||||
/* positive pitch means negative actuator -> pull up */
|
||||
actuators.control[1] = manual_sp.pitch;
|
||||
actuators.control[2] = manual_sp.yaw;
|
||||
actuators.control[3] = manual_sp.throttle;
|
||||
|
||||
if (isfinite(manual_sp.flaps)) {
|
||||
actuators.control[4] = manual_sp.flaps;
|
||||
|
||||
} else {
|
||||
actuators.control[4] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* execute attitude control if requested */
|
||||
if (control_mode.flag_control_attitude_enabled) {
|
||||
/* attitude control */
|
||||
fixedwing_att_control_attitude(&att_sp, &att, speed_body, &rates_sp);
|
||||
|
||||
/* angular rate control */
|
||||
fixedwing_att_control_rates(&rates_sp, gyro, &actuators);
|
||||
|
||||
/* pass through throttle */
|
||||
actuators.control[3] = att_sp.thrust;
|
||||
|
||||
/* set flaps to zero */
|
||||
actuators.control[4] = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
/* publish rates */
|
||||
orb_publish(ORB_ID(vehicle_rates_setpoint), rates_pub, &rates_sp);
|
||||
|
||||
/* sanity check and publish actuator outputs */
|
||||
if (isfinite(actuators.control[0]) &&
|
||||
isfinite(actuators.control[1]) &&
|
||||
isfinite(actuators.control[2]) &&
|
||||
isfinite(actuators.control[3])) {
|
||||
orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
|
||||
}
|
||||
}
|
||||
|
||||
printf("[fixedwing_att_control] exiting, stopping all motors.\n");
|
||||
thread_running = false;
|
||||
|
||||
/* kill all outputs */
|
||||
for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++)
|
||||
actuators.control[i] = 0.0f;
|
||||
|
||||
orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
|
||||
|
||||
|
||||
|
||||
close(att_sub);
|
||||
close(actuator_pub);
|
||||
close(rates_pub);
|
||||
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Startup Functions */
|
||||
|
||||
static void
|
||||
usage(const char *reason)
|
||||
{
|
||||
if (reason)
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
|
||||
fprintf(stderr, "usage: fixedwing_att_control {start|stop|status}\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deamon app only briefly exists to start
|
||||
* the background job. The stack size assigned in the
|
||||
* Makefile does only apply to this management task.
|
||||
*
|
||||
* The actual stack size should be set in the call
|
||||
* to task_create().
|
||||
*/
|
||||
int fixedwing_att_control_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
usage("missing command");
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
if (thread_running) {
|
||||
printf("fixedwing_att_control already running\n");
|
||||
/* this is not an error */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn_cmd("fixedwing_att_control",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
2048,
|
||||
fixedwing_att_control_thread_main,
|
||||
(argv) ? (const char **)&argv[2] : (const char **)NULL);
|
||||
thread_running = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
thread_should_exit = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
printf("\tfixedwing_att_control is running\n");
|
||||
|
||||
} else {
|
||||
printf("\tfixedwing_att_control not started\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage("unrecognized command");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file fixedwing_att_control_rate.c
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
*
|
||||
* Implementation of a fixed wing attitude controller.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <uORB/uORB.h>
|
||||
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/pid/pid.h>
|
||||
#include <systemlib/geo/geo.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
|
||||
#include "fixedwing_att_control_rate.h"
|
||||
|
||||
/*
|
||||
* Controller parameters, accessible via MAVLink
|
||||
*
|
||||
*/
|
||||
// Roll control parameters
|
||||
PARAM_DEFINE_FLOAT(FW_ROLLR_P, 0.9f);
|
||||
PARAM_DEFINE_FLOAT(FW_ROLLR_I, 0.2f);
|
||||
PARAM_DEFINE_FLOAT(FW_ROLLR_AWU, 0.9f);
|
||||
PARAM_DEFINE_FLOAT(FW_ROLLR_LIM, 0.7f); // Roll rate limit in radians/sec, applies to the roll controller
|
||||
PARAM_DEFINE_FLOAT(FW_ROLL_P, 4.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_PITCH_RCOMP, 0.1f);
|
||||
|
||||
//Pitch control parameters
|
||||
PARAM_DEFINE_FLOAT(FW_PITCHR_P, 0.8f);
|
||||
PARAM_DEFINE_FLOAT(FW_PITCHR_I, 0.2f);
|
||||
PARAM_DEFINE_FLOAT(FW_PITCHR_AWU, 0.8f);
|
||||
PARAM_DEFINE_FLOAT(FW_PITCHR_LIM, 0.35f); // Pitch rate limit in radians/sec, applies to the pitch controller
|
||||
PARAM_DEFINE_FLOAT(FW_PITCH_P, 8.0f);
|
||||
|
||||
//Yaw control parameters //XXX TODO this is copy paste, asign correct values
|
||||
PARAM_DEFINE_FLOAT(FW_YAWR_P, 0.3f);
|
||||
PARAM_DEFINE_FLOAT(FW_YAWR_I, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_YAWR_AWU, 0.0f);
|
||||
PARAM_DEFINE_FLOAT(FW_YAWR_LIM, 0.35f); // Yaw rate limit in radians/sec
|
||||
|
||||
/* feedforward compensation */
|
||||
PARAM_DEFINE_FLOAT(FW_PITCH_THR_P, 0.1f); /**< throttle to pitch coupling feedforward */
|
||||
|
||||
struct fw_rate_control_params {
|
||||
float rollrate_p;
|
||||
float rollrate_i;
|
||||
float rollrate_awu;
|
||||
float pitchrate_p;
|
||||
float pitchrate_i;
|
||||
float pitchrate_awu;
|
||||
float yawrate_p;
|
||||
float yawrate_i;
|
||||
float yawrate_awu;
|
||||
float pitch_thr_ff;
|
||||
};
|
||||
|
||||
struct fw_rate_control_param_handles {
|
||||
param_t rollrate_p;
|
||||
param_t rollrate_i;
|
||||
param_t rollrate_awu;
|
||||
param_t pitchrate_p;
|
||||
param_t pitchrate_i;
|
||||
param_t pitchrate_awu;
|
||||
param_t yawrate_p;
|
||||
param_t yawrate_i;
|
||||
param_t yawrate_awu;
|
||||
param_t pitch_thr_ff;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Internal Prototypes */
|
||||
static int parameters_init(struct fw_rate_control_param_handles *h);
|
||||
static int parameters_update(const struct fw_rate_control_param_handles *h, struct fw_rate_control_params *p);
|
||||
|
||||
static int parameters_init(struct fw_rate_control_param_handles *h)
|
||||
{
|
||||
/* PID parameters */
|
||||
h->rollrate_p = param_find("FW_ROLLR_P"); //TODO define rate params for fixed wing
|
||||
h->rollrate_i = param_find("FW_ROLLR_I");
|
||||
h->rollrate_awu = param_find("FW_ROLLR_AWU");
|
||||
|
||||
h->pitchrate_p = param_find("FW_PITCHR_P");
|
||||
h->pitchrate_i = param_find("FW_PITCHR_I");
|
||||
h->pitchrate_awu = param_find("FW_PITCHR_AWU");
|
||||
|
||||
h->yawrate_p = param_find("FW_YAWR_P");
|
||||
h->yawrate_i = param_find("FW_YAWR_I");
|
||||
h->yawrate_awu = param_find("FW_YAWR_AWU");
|
||||
h->pitch_thr_ff = param_find("FW_PITCH_THR_P");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int parameters_update(const struct fw_rate_control_param_handles *h, struct fw_rate_control_params *p)
|
||||
{
|
||||
param_get(h->rollrate_p, &(p->rollrate_p));
|
||||
param_get(h->rollrate_i, &(p->rollrate_i));
|
||||
param_get(h->rollrate_awu, &(p->rollrate_awu));
|
||||
param_get(h->pitchrate_p, &(p->pitchrate_p));
|
||||
param_get(h->pitchrate_i, &(p->pitchrate_i));
|
||||
param_get(h->pitchrate_awu, &(p->pitchrate_awu));
|
||||
param_get(h->yawrate_p, &(p->yawrate_p));
|
||||
param_get(h->yawrate_i, &(p->yawrate_i));
|
||||
param_get(h->yawrate_awu, &(p->yawrate_awu));
|
||||
param_get(h->pitch_thr_ff, &(p->pitch_thr_ff));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int fixedwing_att_control_rates(const struct vehicle_rates_setpoint_s *rate_sp,
|
||||
const float rates[],
|
||||
struct actuator_controls_s *actuators)
|
||||
{
|
||||
static int counter = 0;
|
||||
static bool initialized = false;
|
||||
|
||||
static struct fw_rate_control_params p;
|
||||
static struct fw_rate_control_param_handles h;
|
||||
|
||||
static PID_t roll_rate_controller;
|
||||
static PID_t pitch_rate_controller;
|
||||
static PID_t yaw_rate_controller;
|
||||
|
||||
static uint64_t last_run = 0;
|
||||
const float deltaT = (hrt_absolute_time() - last_run) / 1000000.0f;
|
||||
last_run = hrt_absolute_time();
|
||||
|
||||
if (!initialized) {
|
||||
parameters_init(&h);
|
||||
parameters_update(&h, &p);
|
||||
pid_init(&roll_rate_controller, p.rollrate_p, p.rollrate_i, 0, p.rollrate_awu, 1, PID_MODE_DERIVATIV_NONE, 0.0f); // set D part to 0 because the controller layout is with a PI rate controller
|
||||
pid_init(&pitch_rate_controller, p.pitchrate_p, p.pitchrate_i, 0, p.pitchrate_awu, 1, PID_MODE_DERIVATIV_NONE, 0.0f); // set D part to 0 because the contpitcher layout is with a PI rate contpitcher
|
||||
pid_init(&yaw_rate_controller, p.yawrate_p, p.yawrate_i, 0, p.yawrate_awu, 1, PID_MODE_DERIVATIV_NONE, 0.0f); // set D part to 0 because the contpitcher layout is with a PI rate contpitcher
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/* load new parameters with lower rate */
|
||||
if (counter % 100 == 0) {
|
||||
/* update parameters from storage */
|
||||
parameters_update(&h, &p);
|
||||
pid_set_parameters(&roll_rate_controller, p.rollrate_p, p.rollrate_i, 0, p.rollrate_awu, 1);
|
||||
pid_set_parameters(&pitch_rate_controller, p.pitchrate_p, p.pitchrate_i, 0, p.pitchrate_awu, 1);
|
||||
pid_set_parameters(&yaw_rate_controller, p.yawrate_p, p.yawrate_i, 0, p.yawrate_awu, 1);
|
||||
}
|
||||
|
||||
|
||||
/* roll rate (PI) */
|
||||
actuators->control[0] = pid_calculate(&roll_rate_controller, rate_sp->roll, rates[0], 0.0f, deltaT);
|
||||
/* pitch rate (PI) */
|
||||
actuators->control[1] = -pid_calculate(&pitch_rate_controller, rate_sp->pitch, rates[1], 0.0f, deltaT);
|
||||
/* yaw rate (PI) */
|
||||
actuators->control[2] = pid_calculate(&yaw_rate_controller, rate_sp->yaw, rates[2], 0.0f, deltaT);
|
||||
|
||||
counter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Fixedwing Attitude Control application
|
||||
#
|
||||
|
||||
MODULE_COMMAND = fixedwing_att_control
|
||||
|
||||
SRCS = fixedwing_att_control_main.c \
|
||||
fixedwing_att_control_att.c \
|
||||
fixedwing_att_control_rate.c
|
||||
@@ -1,479 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Doug Weibel <douglas.weibel@colorado.edu>
|
||||
*
|
||||
* 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 fixedwing_pos_control.c
|
||||
* Implementation of a fixed wing attitude controller.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_global_position_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
#include <systemlib/param/param.h>
|
||||
#include <systemlib/pid/pid.h>
|
||||
#include <systemlib/geo/geo.h>
|
||||
#include <systemlib/perf_counter.h>
|
||||
#include <systemlib/systemlib.h>
|
||||
|
||||
/*
|
||||
* Controller parameters, accessible via MAVLink
|
||||
*
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_HEAD_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(FW_HEADR_I, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(FW_HEADR_LIM, 1.5f); //TODO: think about reasonable value
|
||||
PARAM_DEFINE_FLOAT(FW_XTRACK_P, 0.01745f); // Radians per meter off track
|
||||
PARAM_DEFINE_FLOAT(FW_ALT_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(FW_ROLL_LIM, 0.7f); // Roll angle limit in radians
|
||||
PARAM_DEFINE_FLOAT(FW_HEADR_P, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(FW_PITCH_LIM, 0.35f); /**< Pitch angle limit in radians per second */
|
||||
|
||||
struct fw_pos_control_params {
|
||||
float heading_p;
|
||||
float headingr_p;
|
||||
float headingr_i;
|
||||
float headingr_lim;
|
||||
float xtrack_p;
|
||||
float altitude_p;
|
||||
float roll_lim;
|
||||
float pitch_lim;
|
||||
};
|
||||
|
||||
struct fw_pos_control_param_handles {
|
||||
param_t heading_p;
|
||||
param_t headingr_p;
|
||||
param_t headingr_i;
|
||||
param_t headingr_lim;
|
||||
param_t xtrack_p;
|
||||
param_t altitude_p;
|
||||
param_t roll_lim;
|
||||
param_t pitch_lim;
|
||||
};
|
||||
|
||||
|
||||
struct planned_path_segments_s {
|
||||
bool segment_type;
|
||||
double start_lat; // Start of line or center of arc
|
||||
double start_lon;
|
||||
double end_lat;
|
||||
double end_lon;
|
||||
float radius; // Radius of arc
|
||||
float arc_start_bearing; // Bearing from center to start of arc
|
||||
float arc_sweep; // Angle (radians) swept out by arc around center.
|
||||
// Positive for clockwise, negative for counter-clockwise
|
||||
};
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
/* Internal Prototypes */
|
||||
static int parameters_init(struct fw_pos_control_param_handles *h);
|
||||
static int parameters_update(const struct fw_pos_control_param_handles *h, struct fw_pos_control_params *p);
|
||||
|
||||
/**
|
||||
* Deamon management function.
|
||||
*/
|
||||
__EXPORT int fixedwing_pos_control_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Mainloop of deamon.
|
||||
*/
|
||||
int fixedwing_pos_control_thread_main(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Print the correct usage.
|
||||
*/
|
||||
static void usage(const char *reason);
|
||||
|
||||
/* Variables */
|
||||
static bool thread_should_exit = false; /**< Deamon exit flag */
|
||||
static bool thread_running = false; /**< Deamon status flag */
|
||||
static int deamon_task; /**< Handle of deamon task / thread */
|
||||
|
||||
|
||||
/**
|
||||
* Parameter management
|
||||
*/
|
||||
static int parameters_init(struct fw_pos_control_param_handles *h)
|
||||
{
|
||||
/* PID parameters */
|
||||
h->heading_p = param_find("FW_HEAD_P");
|
||||
h->headingr_p = param_find("FW_HEADR_P");
|
||||
h->headingr_i = param_find("FW_HEADR_I");
|
||||
h->headingr_lim = param_find("FW_HEADR_LIM");
|
||||
h->xtrack_p = param_find("FW_XTRACK_P");
|
||||
h->altitude_p = param_find("FW_ALT_P");
|
||||
h->roll_lim = param_find("FW_ROLL_LIM");
|
||||
h->pitch_lim = param_find("FW_PITCH_LIM");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int parameters_update(const struct fw_pos_control_param_handles *h, struct fw_pos_control_params *p)
|
||||
{
|
||||
param_get(h->heading_p, &(p->heading_p));
|
||||
param_get(h->headingr_p, &(p->headingr_p));
|
||||
param_get(h->headingr_i, &(p->headingr_i));
|
||||
param_get(h->headingr_lim, &(p->headingr_lim));
|
||||
param_get(h->xtrack_p, &(p->xtrack_p));
|
||||
param_get(h->altitude_p, &(p->altitude_p));
|
||||
param_get(h->roll_lim, &(p->roll_lim));
|
||||
param_get(h->pitch_lim, &(p->pitch_lim));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* Main Thread */
|
||||
int fixedwing_pos_control_thread_main(int argc, char *argv[])
|
||||
{
|
||||
/* read arguments */
|
||||
bool verbose = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
|
||||
verbose = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome user */
|
||||
printf("[fixedwing pos control] started\n");
|
||||
|
||||
/* declare and safely initialize all structs */
|
||||
struct vehicle_global_position_s global_pos;
|
||||
memset(&global_pos, 0, sizeof(global_pos));
|
||||
struct vehicle_global_position_s start_pos; // Temporary variable, replace with
|
||||
memset(&start_pos, 0, sizeof(start_pos)); // previous waypoint when available
|
||||
struct vehicle_global_position_setpoint_s global_setpoint;
|
||||
memset(&global_setpoint, 0, sizeof(global_setpoint));
|
||||
struct vehicle_attitude_s att;
|
||||
memset(&att, 0, sizeof(att));
|
||||
struct crosstrack_error_s xtrack_err;
|
||||
memset(&xtrack_err, 0, sizeof(xtrack_err));
|
||||
struct parameter_update_s param_update;
|
||||
memset(¶m_update, 0, sizeof(param_update));
|
||||
|
||||
/* output structs */
|
||||
struct vehicle_attitude_setpoint_s attitude_setpoint;
|
||||
memset(&attitude_setpoint, 0, sizeof(attitude_setpoint));
|
||||
|
||||
/* publish attitude setpoint */
|
||||
attitude_setpoint.roll_body = 0.0f;
|
||||
attitude_setpoint.pitch_body = 0.0f;
|
||||
attitude_setpoint.yaw_body = 0.0f;
|
||||
attitude_setpoint.thrust = 0.0f;
|
||||
orb_advert_t attitude_setpoint_pub = orb_advertise(ORB_ID(vehicle_attitude_setpoint), &attitude_setpoint);
|
||||
|
||||
/* subscribe */
|
||||
int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
|
||||
int global_setpoint_sub = orb_subscribe(ORB_ID(vehicle_global_position_setpoint));
|
||||
int att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
int param_sub = orb_subscribe(ORB_ID(parameter_update));
|
||||
|
||||
/* Setup of loop */
|
||||
struct pollfd fds[2] = {
|
||||
{ .fd = param_sub, .events = POLLIN },
|
||||
{ .fd = att_sub, .events = POLLIN }
|
||||
};
|
||||
bool global_sp_updated_set_once = false;
|
||||
|
||||
float psi_track = 0.0f;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
struct fw_pos_control_params p;
|
||||
struct fw_pos_control_param_handles h;
|
||||
|
||||
PID_t heading_controller;
|
||||
PID_t heading_rate_controller;
|
||||
PID_t offtrack_controller;
|
||||
PID_t altitude_controller;
|
||||
|
||||
parameters_init(&h);
|
||||
parameters_update(&h, &p);
|
||||
pid_init(&heading_controller, p.heading_p, 0.0f, 0.0f, 0.0f, 10000.0f, PID_MODE_DERIVATIV_NONE, 0.0f); //arbitrary high limit
|
||||
pid_init(&heading_rate_controller, p.headingr_p, p.headingr_i, 0.0f, 0.0f, p.roll_lim, PID_MODE_DERIVATIV_NONE, 0.0f);
|
||||
pid_init(&altitude_controller, p.altitude_p, 0.0f, 0.0f, 0.0f, p.pitch_lim, PID_MODE_DERIVATIV_NONE, 0.0f);
|
||||
pid_init(&offtrack_controller, p.xtrack_p, 0.0f, 0.0f, 0.0f , 60.0f * M_DEG_TO_RAD, PID_MODE_DERIVATIV_NONE, 0.0f); //TODO: remove hardcoded value
|
||||
|
||||
/* error and performance monitoring */
|
||||
perf_counter_t fw_interval_perf = perf_alloc(PC_INTERVAL, "fixedwing_pos_control_interval");
|
||||
perf_counter_t fw_err_perf = perf_alloc(PC_COUNT, "fixedwing_pos_control_err");
|
||||
|
||||
while (!thread_should_exit) {
|
||||
/* wait for a sensor update, check for exit condition every 500 ms */
|
||||
int ret = poll(fds, 2, 500);
|
||||
|
||||
if (ret < 0) {
|
||||
/* poll error, count it in perf */
|
||||
perf_count(fw_err_perf);
|
||||
|
||||
} else if (ret == 0) {
|
||||
/* no return value, ignore */
|
||||
} else {
|
||||
|
||||
/* only update parameters if they changed */
|
||||
if (fds[0].revents & POLLIN) {
|
||||
/* read from param to clear updated flag */
|
||||
struct parameter_update_s update;
|
||||
orb_copy(ORB_ID(parameter_update), param_sub, &update);
|
||||
|
||||
/* update parameters from storage */
|
||||
parameters_update(&h, &p);
|
||||
pid_set_parameters(&heading_controller, p.heading_p, 0, 0, 0, 10000.0f); //arbitrary high limit
|
||||
pid_set_parameters(&heading_rate_controller, p.headingr_p, p.headingr_i, 0, 0, p.roll_lim);
|
||||
pid_set_parameters(&altitude_controller, p.altitude_p, 0, 0, 0, p.pitch_lim);
|
||||
pid_set_parameters(&offtrack_controller, p.xtrack_p, 0, 0, 0, 60.0f * M_DEG_TO_RAD); //TODO: remove hardcoded value
|
||||
}
|
||||
|
||||
/* only run controller if attitude changed */
|
||||
if (fds[1].revents & POLLIN) {
|
||||
|
||||
|
||||
static uint64_t last_run = 0;
|
||||
const float deltaT = (hrt_absolute_time() - last_run) / 1000000.0f;
|
||||
last_run = hrt_absolute_time();
|
||||
|
||||
/* check if there is a new position or setpoint */
|
||||
bool pos_updated;
|
||||
orb_check(global_pos_sub, &pos_updated);
|
||||
bool global_sp_updated;
|
||||
orb_check(global_setpoint_sub, &global_sp_updated);
|
||||
|
||||
/* load local copies */
|
||||
orb_copy(ORB_ID(vehicle_attitude), att_sub, &att);
|
||||
|
||||
if (pos_updated) {
|
||||
orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos);
|
||||
}
|
||||
|
||||
if (global_sp_updated) {
|
||||
orb_copy(ORB_ID(vehicle_global_position_setpoint), global_setpoint_sub, &global_setpoint);
|
||||
start_pos = global_pos; //for now using the current position as the startpoint (= approx. last waypoint because the setpoint switch occurs at the waypoint)
|
||||
global_sp_updated_set_once = true;
|
||||
psi_track = get_bearing_to_next_waypoint(global_pos.lat, global_pos.lon,
|
||||
(double)global_setpoint.lat / (double)1e7d, (double)global_setpoint.lon / (double)1e7d);
|
||||
|
||||
printf("next wp direction: %0.4f\n", (double)psi_track);
|
||||
}
|
||||
|
||||
/* Simple Horizontal Control */
|
||||
if (global_sp_updated_set_once) {
|
||||
// if (counter % 100 == 0)
|
||||
// printf("lat_sp %d, ln_sp %d, lat: %d, lon: %d\n", global_setpoint.lat, global_setpoint.lon, global_pos.lat, global_pos.lon);
|
||||
|
||||
/* calculate crosstrack error */
|
||||
// Only the case of a straight line track following handled so far
|
||||
int distance_res = get_distance_to_line(&xtrack_err, (double)global_pos.lat / (double)1e7d, (double)global_pos.lon / (double)1e7d,
|
||||
(double)start_pos.lat / (double)1e7d, (double)start_pos.lon / (double)1e7d,
|
||||
(double)global_setpoint.lat / (double)1e7d, (double)global_setpoint.lon / (double)1e7d);
|
||||
|
||||
// XXX what is xtrack_err.past_end?
|
||||
if (distance_res == OK /*&& !xtrack_err.past_end*/) {
|
||||
|
||||
float delta_psi_c = pid_calculate(&offtrack_controller, 0, xtrack_err.distance, 0.0f, 0.0f); //p.xtrack_p * xtrack_err.distance
|
||||
|
||||
float psi_c = psi_track + delta_psi_c;
|
||||
float psi_e = psi_c - att.yaw;
|
||||
|
||||
/* wrap difference back onto -pi..pi range */
|
||||
psi_e = _wrap_pi(psi_e);
|
||||
|
||||
if (verbose) {
|
||||
printf("xtrack_err.distance %.4f ", (double)xtrack_err.distance);
|
||||
printf("delta_psi_c %.4f ", (double)delta_psi_c);
|
||||
printf("psi_c %.4f ", (double)psi_c);
|
||||
printf("att.yaw %.4f ", (double)att.yaw);
|
||||
printf("psi_e %.4f ", (double)psi_e);
|
||||
}
|
||||
|
||||
/* calculate roll setpoint, do this artificially around zero */
|
||||
float delta_psi_rate_c = pid_calculate(&heading_controller, psi_e, 0.0f, 0.0f, 0.0f);
|
||||
float psi_rate_track = 0; //=V_gr/r_track , this will be needed for implementation of arc following
|
||||
float psi_rate_c = delta_psi_rate_c + psi_rate_track;
|
||||
|
||||
/* limit turn rate */
|
||||
if (psi_rate_c > p.headingr_lim) {
|
||||
psi_rate_c = p.headingr_lim;
|
||||
|
||||
} else if (psi_rate_c < -p.headingr_lim) {
|
||||
psi_rate_c = -p.headingr_lim;
|
||||
}
|
||||
|
||||
float psi_rate_e = psi_rate_c - att.yawspeed;
|
||||
|
||||
// XXX sanity check: Assume 10 m/s stall speed and no stall condition
|
||||
float ground_speed = sqrtf(global_pos.vx * global_pos.vx + global_pos.vy * global_pos.vy);
|
||||
|
||||
if (ground_speed < 10.0f) {
|
||||
ground_speed = 10.0f;
|
||||
}
|
||||
|
||||
float psi_rate_e_scaled = psi_rate_e * ground_speed / 9.81f; //* V_gr / g
|
||||
|
||||
attitude_setpoint.roll_body = pid_calculate(&heading_rate_controller, psi_rate_e_scaled, 0.0f, 0.0f, deltaT);
|
||||
|
||||
if (verbose) {
|
||||
printf("psi_rate_c %.4f ", (double)psi_rate_c);
|
||||
printf("psi_rate_e_scaled %.4f ", (double)psi_rate_e_scaled);
|
||||
printf("rollbody %.4f\n", (double)attitude_setpoint.roll_body);
|
||||
}
|
||||
|
||||
if (verbose && counter % 100 == 0)
|
||||
printf("xtrack_err.distance: %0.4f, delta_psi_c: %0.4f\n", xtrack_err.distance, delta_psi_c);
|
||||
|
||||
} else {
|
||||
if (verbose && counter % 100 == 0)
|
||||
printf("distance_res: %d, past_end %d\n", distance_res, xtrack_err.past_end);
|
||||
}
|
||||
|
||||
/* Very simple Altitude Control */
|
||||
if (pos_updated) {
|
||||
|
||||
//TODO: take care of relative vs. ab. altitude
|
||||
attitude_setpoint.pitch_body = pid_calculate(&altitude_controller, global_setpoint.altitude, global_pos.alt, 0.0f, 0.0f);
|
||||
|
||||
}
|
||||
|
||||
// XXX need speed control
|
||||
attitude_setpoint.thrust = 0.7f;
|
||||
|
||||
/* publish the attitude setpoint */
|
||||
orb_publish(ORB_ID(vehicle_attitude_setpoint), attitude_setpoint_pub, &attitude_setpoint);
|
||||
|
||||
/* measure in what intervals the controller runs */
|
||||
perf_count(fw_interval_perf);
|
||||
|
||||
counter++;
|
||||
|
||||
} else {
|
||||
// XXX no setpoint, decent default needed (loiter?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[fixedwing_pos_control] exiting.\n");
|
||||
thread_running = false;
|
||||
|
||||
|
||||
close(attitude_setpoint_pub);
|
||||
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Startup Functions */
|
||||
|
||||
static void
|
||||
usage(const char *reason)
|
||||
{
|
||||
if (reason)
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
|
||||
fprintf(stderr, "usage: fixedwing_pos_control {start|stop|status}\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deamon app only briefly exists to start
|
||||
* the background job. The stack size assigned in the
|
||||
* Makefile does only apply to this management task.
|
||||
*
|
||||
* The actual stack size should be set in the call
|
||||
* to task_create().
|
||||
*/
|
||||
int fixedwing_pos_control_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
usage("missing command");
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
|
||||
if (thread_running) {
|
||||
printf("fixedwing_pos_control already running\n");
|
||||
/* this is not an error */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
deamon_task = task_spawn_cmd("fixedwing_pos_control",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX - 20,
|
||||
2048,
|
||||
fixedwing_pos_control_thread_main,
|
||||
(argv) ? (const char **)&argv[2] : (const char **)NULL);
|
||||
thread_running = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "stop")) {
|
||||
thread_should_exit = true;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "status")) {
|
||||
if (thread_running) {
|
||||
printf("\tfixedwing_pos_control is running\n");
|
||||
|
||||
} else {
|
||||
printf("\tfixedwing_pos_control not started\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage("unrecognized command");
|
||||
exit(1);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Fixedwing PositionControl application
|
||||
#
|
||||
|
||||
MODULE_COMMAND = fixedwing_pos_control
|
||||
|
||||
SRCS = fixedwing_pos_control_main.c
|
||||
@@ -1555,6 +1555,8 @@ Mavlink::mavlink_missionlib_send_gcs_string(const char *string)
|
||||
{
|
||||
const int len = MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN;
|
||||
mavlink_statustext_t statustext;
|
||||
statustext.severity = MAV_SEVERITY_INFO;
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (i < len - 1) {
|
||||
|
||||
@@ -820,11 +820,11 @@ protected:
|
||||
|
||||
void send(const hrt_abstime t)
|
||||
{
|
||||
bool updated = status_sub->update(t);
|
||||
updated |= pos_sp_triplet_sub->update(t);
|
||||
updated |= act_sub->update(t);
|
||||
bool updated = act_sub->update(t);
|
||||
(void)pos_sp_triplet_sub->update(t);
|
||||
(void)status_sub->update(t);
|
||||
|
||||
if (updated) {
|
||||
if (updated && (status->arming_state == ARMING_STATE_ARMED)) {
|
||||
/* translate the current syste state to mavlink state and mode */
|
||||
uint8_t mavlink_state;
|
||||
uint8_t mavlink_base_mode;
|
||||
@@ -1340,22 +1340,23 @@ protected:
|
||||
|
||||
void send(const hrt_abstime t)
|
||||
{
|
||||
(void)range_sub->update(t);
|
||||
if (range_sub->update(t)) {
|
||||
|
||||
uint8_t type;
|
||||
uint8_t type;
|
||||
|
||||
switch (range->type) {
|
||||
case RANGE_FINDER_TYPE_LASER:
|
||||
type = MAV_DISTANCE_SENSOR_LASER;
|
||||
break;
|
||||
switch (range->type) {
|
||||
case RANGE_FINDER_TYPE_LASER:
|
||||
type = MAV_DISTANCE_SENSOR_LASER;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t id = 0;
|
||||
uint8_t orientation = 0;
|
||||
uint8_t covariance = 20;
|
||||
|
||||
mavlink_msg_distance_sensor_send(_channel, range->timestamp / 1000, type, id, orientation,
|
||||
range->minimum_distance*100, range->maximum_distance*100, range->distance*100, covariance);
|
||||
}
|
||||
|
||||
uint8_t id = 0;
|
||||
uint8_t orientation = 0;
|
||||
uint8_t covariance = 20;
|
||||
|
||||
mavlink_msg_distance_sensor_send(_channel, range->timestamp / 1000, type, id, orientation,
|
||||
range->minimum_distance*100, range->maximum_distance*100, range->distance*100, covariance);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -217,6 +217,12 @@ MavlinkReceiver::handle_message_command_long(mavlink_message_t *msg)
|
||||
_mavlink->_task_should_exit = true;
|
||||
|
||||
} else {
|
||||
|
||||
if (msg->sysid == mavlink_system.sysid && msg->compid == mavlink_system.compid) {
|
||||
warnx("ignoring CMD spoofed with same SYS/COMP ID");
|
||||
return;
|
||||
}
|
||||
|
||||
struct vehicle_command_s vcmd;
|
||||
memset(&vcmd, 0, sizeof(vcmd));
|
||||
|
||||
@@ -432,8 +438,8 @@ MavlinkReceiver::handle_message_manual_control(mavlink_message_t *msg)
|
||||
memset(&manual, 0, sizeof(manual));
|
||||
|
||||
manual.timestamp = hrt_absolute_time();
|
||||
manual.roll = man.x / 1000.0f;
|
||||
manual.pitch = man.y / 1000.0f;
|
||||
manual.pitch = man.x / 1000.0f;
|
||||
manual.roll = man.y / 1000.0f;
|
||||
manual.yaw = man.r / 1000.0f;
|
||||
manual.throttle = man.z / 1000.0f;
|
||||
|
||||
|
||||
@@ -496,7 +496,8 @@ MulticopterAttitudeControl::control_attitude(float dt)
|
||||
//}
|
||||
} else {
|
||||
/* move yaw setpoint */
|
||||
_v_att_sp.yaw_body = _wrap_pi(_v_att_sp.yaw_body + _manual_control_sp.yaw * _params.man_yaw_max * dt);
|
||||
yaw_sp_move_rate = _manual_control_sp.yaw * _params.man_yaw_max;
|
||||
_v_att_sp.yaw_body = _wrap_pi(_v_att_sp.yaw_body + yaw_sp_move_rate * dt);
|
||||
_v_att_sp.R_valid = false;
|
||||
publish_att_sp = true;
|
||||
}
|
||||
|
||||
@@ -148,17 +148,17 @@ private:
|
||||
param_t xy_vel_d;
|
||||
param_t xy_vel_max;
|
||||
param_t xy_ff;
|
||||
param_t tilt_max;
|
||||
param_t tilt_max_air;
|
||||
param_t land_speed;
|
||||
param_t land_tilt_max;
|
||||
param_t tilt_max_land;
|
||||
} _params_handles; /**< handles for interesting parameters */
|
||||
|
||||
struct {
|
||||
float thr_min;
|
||||
float thr_max;
|
||||
float tilt_max;
|
||||
float tilt_max_air;
|
||||
float land_speed;
|
||||
float land_tilt_max;
|
||||
float tilt_max_land;
|
||||
|
||||
math::Vector<3> pos_p;
|
||||
math::Vector<3> vel_p;
|
||||
@@ -308,9 +308,9 @@ MulticopterPositionControl::MulticopterPositionControl() :
|
||||
_params_handles.xy_vel_d = param_find("MPC_XY_VEL_D");
|
||||
_params_handles.xy_vel_max = param_find("MPC_XY_VEL_MAX");
|
||||
_params_handles.xy_ff = param_find("MPC_XY_FF");
|
||||
_params_handles.tilt_max = param_find("MPC_TILT_MAX");
|
||||
_params_handles.tilt_max_air = param_find("MPC_TILTMAX_AIR");
|
||||
_params_handles.land_speed = param_find("MPC_LAND_SPEED");
|
||||
_params_handles.land_tilt_max = param_find("MPC_LAND_TILT");
|
||||
_params_handles.tilt_max_land = param_find("MPC_TILTMAX_LND");
|
||||
|
||||
/* fetch initial parameter values */
|
||||
parameters_update(true);
|
||||
@@ -355,11 +355,11 @@ MulticopterPositionControl::parameters_update(bool force)
|
||||
if (updated || force) {
|
||||
param_get(_params_handles.thr_min, &_params.thr_min);
|
||||
param_get(_params_handles.thr_max, &_params.thr_max);
|
||||
param_get(_params_handles.tilt_max, &_params.tilt_max);
|
||||
_params.tilt_max = math::radians(_params.tilt_max);
|
||||
param_get(_params_handles.tilt_max_air, &_params.tilt_max_air);
|
||||
_params.tilt_max_air = math::radians(_params.tilt_max_air);
|
||||
param_get(_params_handles.land_speed, &_params.land_speed);
|
||||
param_get(_params_handles.land_tilt_max, &_params.land_tilt_max);
|
||||
_params.land_tilt_max = math::radians(_params.land_tilt_max);
|
||||
param_get(_params_handles.tilt_max_land, &_params.tilt_max_land);
|
||||
_params.tilt_max_land = math::radians(_params.tilt_max_land);
|
||||
|
||||
float v;
|
||||
param_get(_params_handles.xy_p, &v);
|
||||
@@ -841,13 +841,13 @@ MulticopterPositionControl::task_main()
|
||||
thr_min = 0.0f;
|
||||
}
|
||||
|
||||
float tilt_max = _params.tilt_max;
|
||||
float tilt_max = _params.tilt_max_air;
|
||||
|
||||
/* adjust limits for landing mode */
|
||||
if (!_control_mode.flag_control_manual_enabled && _pos_sp_triplet.current.valid &&
|
||||
_pos_sp_triplet.current.type == SETPOINT_TYPE_LAND) {
|
||||
/* limit max tilt and min lift when landing */
|
||||
tilt_max = _params.land_tilt_max;
|
||||
tilt_max = _params.tilt_max_land;
|
||||
|
||||
if (thr_min < 0.0f) {
|
||||
thr_min = 0.0f;
|
||||
|
||||
@@ -174,16 +174,28 @@ PARAM_DEFINE_FLOAT(MPC_XY_VEL_MAX, 5.0f);
|
||||
PARAM_DEFINE_FLOAT(MPC_XY_FF, 0.5f);
|
||||
|
||||
/**
|
||||
* Maximum tilt
|
||||
* Maximum tilt angle in air
|
||||
*
|
||||
* Limits maximum tilt in AUTO and EASY modes.
|
||||
* Limits maximum tilt in AUTO and EASY modes during flight.
|
||||
*
|
||||
* @unit deg
|
||||
* @min 0.0
|
||||
* @max 90.0
|
||||
* @group Multicopter Position Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MPC_TILT_MAX, 45.0f);
|
||||
PARAM_DEFINE_FLOAT(MPC_TILTMAX_AIR, 45.0f);
|
||||
|
||||
/**
|
||||
* Maximum tilt during landing
|
||||
*
|
||||
* Limits maximum tilt angle on landing.
|
||||
*
|
||||
* @unit deg
|
||||
* @min 0.0
|
||||
* @max 90.0
|
||||
* @group Multicopter Position Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MPC_TILTMAX_LND, 15.0f);
|
||||
|
||||
/**
|
||||
* Landing descend rate
|
||||
@@ -194,14 +206,3 @@ PARAM_DEFINE_FLOAT(MPC_TILT_MAX, 45.0f);
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MPC_LAND_SPEED, 1.0f);
|
||||
|
||||
/**
|
||||
* Maximum landing tilt
|
||||
*
|
||||
* Limits maximum tilt on landing.
|
||||
*
|
||||
* @unit deg
|
||||
* @min 0.0
|
||||
* @max 90.0
|
||||
* @group Multicopter Position Control
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MPC_LAND_TILT, 15.0f);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Makefile to build the position estimator
|
||||
#
|
||||
|
||||
MODULE_COMMAND = position_estimator
|
||||
|
||||
# XXX this should be converted to a deamon, its a pretty bad example app
|
||||
MODULE_PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||
MODULE_STACKSIZE = 4096
|
||||
|
||||
SRCS = position_estimator_main.c
|
||||
@@ -1,423 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Tobias Naegeli <naegelit@student.ethz.ch>
|
||||
* Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file position_estimator_main.c
|
||||
* Model-identification based position estimator for multirotors
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <float.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_gps_position.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_local_position.h>
|
||||
#include <poll.h>
|
||||
|
||||
#define N_STATES 6
|
||||
#define ERROR_COVARIANCE_INIT 3
|
||||
#define R_EARTH 6371000.0
|
||||
|
||||
#define PROJECTION_INITIALIZE_COUNTER_LIMIT 5000
|
||||
#define REPROJECTION_COUNTER_LIMIT 125
|
||||
|
||||
__EXPORT int position_estimator_main(int argc, char *argv[]);
|
||||
|
||||
static uint16_t position_estimator_counter_position_information;
|
||||
|
||||
/* values for map projection */
|
||||
static double phi_1;
|
||||
static double sin_phi_1;
|
||||
static double cos_phi_1;
|
||||
static double lambda_0;
|
||||
static double scale;
|
||||
|
||||
/**
|
||||
* Initializes the map transformation.
|
||||
*
|
||||
* Initializes the transformation between the geographic coordinate system and the azimuthal equidistant plane
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
static void map_projection_init(double lat_0, double lon_0) //lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
|
||||
{
|
||||
/* notation and formulas according to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
phi_1 = lat_0 / 180.0 * M_PI;
|
||||
lambda_0 = lon_0 / 180.0 * M_PI;
|
||||
|
||||
sin_phi_1 = sin(phi_1);
|
||||
cos_phi_1 = cos(phi_1);
|
||||
|
||||
/* calculate local scale by using the relation of true distance and the distance on plane */ //TODO: this is a quick solution, there are probably easier ways to determine the scale
|
||||
|
||||
/* 1) calculate true distance d on sphere to a point: http://www.movable-type.co.uk/scripts/latlong.html */
|
||||
const double r_earth = 6371000;
|
||||
|
||||
double lat1 = phi_1;
|
||||
double lon1 = lambda_0;
|
||||
|
||||
double lat2 = phi_1 + 0.5 / 180 * M_PI;
|
||||
double lon2 = lambda_0 + 0.5 / 180 * M_PI;
|
||||
double sin_lat_2 = sin(lat2);
|
||||
double cos_lat_2 = cos(lat2);
|
||||
double d = acos(sin(lat1) * sin_lat_2 + cos(lat1) * cos_lat_2 * cos(lon2 - lon1)) * r_earth;
|
||||
|
||||
/* 2) calculate distance rho on plane */
|
||||
double k_bar = 0;
|
||||
double c = acos(sin_phi_1 * sin_lat_2 + cos_phi_1 * cos_lat_2 * cos(lon2 - lambda_0));
|
||||
|
||||
if (0 != c)
|
||||
k_bar = c / sin(c);
|
||||
|
||||
double x2 = k_bar * (cos_lat_2 * sin(lon2 - lambda_0)); //Projection of point 2 on plane
|
||||
double y2 = k_bar * ((cos_phi_1 * sin_lat_2 - sin_phi_1 * cos_lat_2 * cos(lon2 - lambda_0)));
|
||||
double rho = sqrt(pow(x2, 2) + pow(y2, 2));
|
||||
|
||||
scale = d / rho;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a point in the geographic coordinate system to the local azimuthal equidistant plane
|
||||
* @param x north
|
||||
* @param y east
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
static void map_projection_project(double lat, double lon, float *x, float *y)
|
||||
{
|
||||
/* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
double phi = lat / 180.0 * M_PI;
|
||||
double lambda = lon / 180.0 * M_PI;
|
||||
|
||||
double sin_phi = sin(phi);
|
||||
double cos_phi = cos(phi);
|
||||
|
||||
double k_bar = 0;
|
||||
/* using small angle approximation (formula in comment is without aproximation) */
|
||||
double c = acos(sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2)); //double c = acos( sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * cos(lambda - lambda_0) );
|
||||
|
||||
if (0 != c)
|
||||
k_bar = c / sin(c);
|
||||
|
||||
/* using small angle approximation (formula in comment is without aproximation) */
|
||||
*y = k_bar * (cos_phi * (lambda - lambda_0)) * scale;//*y = k_bar * (cos_phi * sin(lambda - lambda_0)) * scale;
|
||||
*x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2))) * scale; // *x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * cos(lambda - lambda_0))) * scale;
|
||||
|
||||
// printf("%phi_1=%.10f, lambda_0 =%.10f\n", phi_1, lambda_0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system
|
||||
*
|
||||
* @param x north
|
||||
* @param y east
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
static void map_projection_reproject(float x, float y, double *lat, double *lon)
|
||||
{
|
||||
/* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
|
||||
double x_descaled = x / scale;
|
||||
double y_descaled = y / scale;
|
||||
|
||||
double c = sqrt(pow(x_descaled, 2) + pow(y_descaled, 2));
|
||||
double sin_c = sin(c);
|
||||
double cos_c = cos(c);
|
||||
|
||||
double lat_sphere = 0;
|
||||
|
||||
if (c != 0)
|
||||
lat_sphere = asin(cos_c * sin_phi_1 + (x_descaled * sin_c * cos_phi_1) / c);
|
||||
else
|
||||
lat_sphere = asin(cos_c * sin_phi_1);
|
||||
|
||||
// printf("lat_sphere = %.10f\n",lat_sphere);
|
||||
|
||||
double lon_sphere = 0;
|
||||
|
||||
if (phi_1 == M_PI / 2) {
|
||||
//using small angle approximation (formula in comment is without aproximation)
|
||||
lon_sphere = (lambda_0 - y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(-y_descaled, x_descaled));
|
||||
|
||||
} else if (phi_1 == -M_PI / 2) {
|
||||
//using small angle approximation (formula in comment is without aproximation)
|
||||
lon_sphere = (lambda_0 + y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(y_descaled, x_descaled));
|
||||
|
||||
} else {
|
||||
|
||||
lon_sphere = (lambda_0 + atan2(y_descaled * sin_c , c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c));
|
||||
//using small angle approximation
|
||||
// double denominator = (c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c);
|
||||
// if(denominator != 0)
|
||||
// {
|
||||
// lon_sphere = (lambda_0 + (y_descaled * sin_c) / denominator);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
}
|
||||
|
||||
// printf("lon_sphere = %.10f\n",lon_sphere);
|
||||
|
||||
*lat = lat_sphere * 180.0 / M_PI;
|
||||
*lon = lon_sphere * 180.0 / M_PI;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* main
|
||||
****************************************************************************/
|
||||
|
||||
int position_estimator_main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
/* welcome user */
|
||||
printf("[multirotor position_estimator] started\n");
|
||||
|
||||
/* initialize values */
|
||||
static float u[2] = {0, 0};
|
||||
static float z[3] = {0, 0, 0};
|
||||
static float xapo[N_STATES] = {0, 0, 0, 0, 0, 0};
|
||||
static float Papo[N_STATES * N_STATES] = {ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0,
|
||||
ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0,
|
||||
ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0,
|
||||
ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0,
|
||||
ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0,
|
||||
ERROR_COVARIANCE_INIT, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static float xapo1[N_STATES];
|
||||
static float Papo1[36];
|
||||
|
||||
static float gps_covariance[3] = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
static uint16_t counter = 0;
|
||||
position_estimator_counter_position_information = 0;
|
||||
|
||||
uint8_t predict_only = 1;
|
||||
|
||||
bool gps_valid = false;
|
||||
|
||||
bool new_initialization = true;
|
||||
|
||||
static double lat_current = 0.0d;//[°]] --> 47.0
|
||||
static double lon_current = 0.0d; //[°]] -->8.5
|
||||
float alt_current = 0.0f;
|
||||
|
||||
|
||||
//TODO: handle flight without gps but with estimator
|
||||
|
||||
/* subscribe to vehicle status, attitude, gps */
|
||||
struct vehicle_gps_position_s gps;
|
||||
gps.fix_type = 0;
|
||||
struct vehicle_status_s vstatus;
|
||||
struct vehicle_attitude_s att;
|
||||
|
||||
int vehicle_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
|
||||
int vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
|
||||
/* subscribe to attitude at 100 Hz */
|
||||
int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
|
||||
/* wait until gps signal turns valid, only then can we initialize the projection */
|
||||
while (gps.fix_type < 3) {
|
||||
struct pollfd fds[1] = { {.fd = vehicle_gps_sub, .events = POLLIN} };
|
||||
|
||||
/* wait for GPS updates, BUT READ VEHICLE STATUS (!)
|
||||
* this choice is critical, since the vehicle status might not
|
||||
* actually change, if this app is started after GPS lock was
|
||||
* aquired.
|
||||
*/
|
||||
if (poll(fds, 1, 5000)) {
|
||||
/* Wait for the GPS update to propagate (we have some time) */
|
||||
usleep(5000);
|
||||
/* Read wether the vehicle status changed */
|
||||
orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_sub, &gps);
|
||||
gps_valid = (gps.fix_type > 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* get gps value for first initialization */
|
||||
orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_sub, &gps);
|
||||
lat_current = ((double)(gps.lat)) * 1e-7;
|
||||
lon_current = ((double)(gps.lon)) * 1e-7;
|
||||
alt_current = gps.alt * 1e-3;
|
||||
|
||||
/* initialize coordinates */
|
||||
map_projection_init(lat_current, lon_current);
|
||||
|
||||
/* publish global position messages only after first GPS message */
|
||||
struct vehicle_local_position_s local_pos = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.z = 0
|
||||
};
|
||||
orb_advert_t local_pos_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
|
||||
|
||||
printf("[multirotor position estimator] initialized projection with: lat: %.10f, lon:%.10f\n", lat_current, lon_current);
|
||||
|
||||
while (1) {
|
||||
|
||||
/*This runs at the rate of the sensors, if we have also a new gps update this is used in the position_estimator function */
|
||||
struct pollfd fds[1] = { {.fd = vehicle_attitude_sub, .events = POLLIN} };
|
||||
|
||||
if (poll(fds, 1, 5000) <= 0) {
|
||||
/* error / timeout */
|
||||
} else {
|
||||
|
||||
orb_copy(ORB_ID(vehicle_attitude), vehicle_attitude_sub, &att);
|
||||
/* got attitude, updating pos as well */
|
||||
orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_sub, &gps);
|
||||
orb_copy(ORB_ID(vehicle_status), vehicle_status_sub, &vstatus);
|
||||
|
||||
/*copy attitude */
|
||||
u[0] = att.roll;
|
||||
u[1] = att.pitch;
|
||||
|
||||
/* initialize map projection with the last estimate (not at full rate) */
|
||||
if (gps.fix_type > 2) {
|
||||
/* Project gps lat lon (Geographic coordinate system) to plane*/
|
||||
map_projection_project(((double)(gps.lat)) * 1e-7, ((double)(gps.lon)) * 1e-7, &(z[0]), &(z[1]));
|
||||
|
||||
local_pos.x = z[0];
|
||||
local_pos.y = z[1];
|
||||
/* negative offset from initialization altitude */
|
||||
local_pos.z = alt_current - (gps.alt) * 1e-3;
|
||||
|
||||
|
||||
orb_publish(ORB_ID(vehicle_local_position), local_pos_pub, &local_pos);
|
||||
}
|
||||
|
||||
|
||||
// gps_covariance[0] = gps.eph; //TODO: needs scaling
|
||||
// gps_covariance[1] = gps.eph;
|
||||
// gps_covariance[2] = gps.epv;
|
||||
|
||||
// } else {
|
||||
// /* we can not use the gps signal (it is of low quality) */
|
||||
// predict_only = 1;
|
||||
// }
|
||||
|
||||
// // predict_only = 0; //TODO: only for testing, removeme, XXX
|
||||
// // z[0] = sinf(((float)counter)/180.0f*3.14159265f); //TODO: only for testing, removeme, XXX
|
||||
// // usleep(100000); //TODO: only for testing, removeme, XXX
|
||||
|
||||
|
||||
// /*Get new estimation (this is calculated in the plane) */
|
||||
// //TODO: if new_initialization == true: use 0,0,0, else use xapo
|
||||
// if (true == new_initialization) { //TODO,XXX: uncomment!
|
||||
// xapo[0] = 0; //we have a new plane initialization. the current estimate is in the center of the plane
|
||||
// xapo[2] = 0;
|
||||
// xapo[4] = 0;
|
||||
// position_estimator(u, z, xapo, Papo, gps_covariance, predict_only, xapo1, Papo1);
|
||||
|
||||
// } else {
|
||||
// position_estimator(u, z, xapo, Papo, gps_covariance, predict_only, xapo1, Papo1);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// /* Copy values from xapo1 to xapo */
|
||||
// int i;
|
||||
|
||||
// for (i = 0; i < N_STATES; i++) {
|
||||
// xapo[i] = xapo1[i];
|
||||
// }
|
||||
|
||||
// if ((counter % REPROJECTION_COUNTER_LIMIT == 0) || (counter % (PROJECTION_INITIALIZE_COUNTER_LIMIT - 1) == 0)) {
|
||||
// /* Reproject from plane to geographic coordinate system */
|
||||
// // map_projection_reproject(xapo1[0], xapo1[2], map_scale, phi_1, lambda_0, &lat_current, &lon_current) //TODO,XXX: uncomment!
|
||||
// map_projection_reproject(z[0], z[1], &lat_current, &lon_current); //do not use estimator for projection testing, removeme
|
||||
// // //DEBUG
|
||||
// // if(counter%500 == 0)
|
||||
// // {
|
||||
// // printf("phi_1: %.10f\n", phi_1);
|
||||
// // printf("lambda_0: %.10f\n", lambda_0);
|
||||
// // printf("lat_estimated: %.10f\n", lat_current);
|
||||
// // printf("lon_estimated: %.10f\n", lon_current);
|
||||
// // printf("z[0]=%.10f, z[1]=%.10f, z[2]=%f\n", z[0], z[1], z[2]);
|
||||
// // fflush(stdout);
|
||||
// //
|
||||
// // }
|
||||
|
||||
// // if(!isnan(lat_current) && !isnan(lon_current))// && !isnan(xapo1[4]) && !isnan(xapo1[1]) && !isnan(xapo1[3]) && !isnan(xapo1[5]))
|
||||
// // {
|
||||
// /* send out */
|
||||
|
||||
// global_pos.lat = lat_current;
|
||||
// global_pos.lon = lon_current;
|
||||
// global_pos.alt = xapo1[4];
|
||||
// global_pos.vx = xapo1[1];
|
||||
// global_pos.vy = xapo1[3];
|
||||
// global_pos.vz = xapo1[5];
|
||||
|
||||
/* publish current estimate */
|
||||
// orb_publish(ORB_ID(vehicle_global_position), global_pos_pub, &global_pos);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printf("[position estimator] ERROR: nan values, lat_current=%.4f, lon_current=%.4f, z[0]=%.4f z[1]=%.4f\n", lat_current, lon_current, z[0], z[1]);
|
||||
// fflush(stdout);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe1.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe1(const real32_T A[9], const real32_T C[3], const real32_T K[3],
|
||||
const real32_T x_aposteriori_k[3], real32_T z, real32_T
|
||||
x_aposteriori[3])
|
||||
{
|
||||
printf("[dlqe input]: x_aposteriori_k %12.8f\t %12.8f\t %12.8f\t z:%12.8f\n", (double)(x_aposteriori_k[0]), (double)(x_aposteriori_k[1]), (double)(x_aposteriori_k[2]), (double)z);
|
||||
printf("[dlqe input]: C[0]: %12.8f\tC[1] %12.8f\tC[2] %12.8f\n", (double)(C[0]), (double)(C[1]), (double)(C[2]));
|
||||
real32_T y;
|
||||
int32_T i0;
|
||||
real32_T b_y[3];
|
||||
int32_T i1;
|
||||
real32_T f0;
|
||||
y = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
b_y[i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
b_y[i0] += C[i1] * A[i1 + 3 * i0];
|
||||
}
|
||||
|
||||
y += b_y[i0] * x_aposteriori_k[i0];
|
||||
}
|
||||
|
||||
y = z - y;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
f0 += A[i0 + 3 * i1] * x_aposteriori_k[i1];
|
||||
}
|
||||
|
||||
x_aposteriori[i0] = f0 + K[i0] * y;
|
||||
}
|
||||
//printf("[dlqe output]: x_aposteriori %12.8f\t %12.8f\t %12.8f\n", (double)(x_aposteriori[0]), (double)(x_aposteriori[1]), (double)(x_aposteriori[2]));
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe1.c) */
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE1_H__
|
||||
#define __KALMAN_DLQE1_H__
|
||||
/* Include files */
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe1_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe1(const real32_T A[9], const real32_T C[3], const real32_T K[3], const real32_T x_aposteriori_k[3], real32_T z, real32_T x_aposteriori[3]);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe1.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1_initialize.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1_initialize'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe1.h"
|
||||
#include "kalman_dlqe1_initialize.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe1_initialize(void)
|
||||
{
|
||||
rt_InitInfAndNaN(8U);
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe1_initialize.c) */
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1_initialize.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1_initialize'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE1_INITIALIZE_H__
|
||||
#define __KALMAN_DLQE1_INITIALIZE_H__
|
||||
/* Include files */
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe1_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe1_initialize(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe1_initialize.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1_terminate.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1_terminate'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe1.h"
|
||||
#include "kalman_dlqe1_terminate.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe1_terminate(void)
|
||||
{
|
||||
/* (no terminate code required) */
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe1_terminate.c) */
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1_terminate.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1_terminate'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE1_TERMINATE_H__
|
||||
#define __KALMAN_DLQE1_TERMINATE_H__
|
||||
/* Include files */
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe1_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe1_terminate(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe1_terminate.h) */
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe1_types.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe1'
|
||||
*
|
||||
* C source code generated on: Wed Feb 13 20:34:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE1_TYPES_H__
|
||||
#define __KALMAN_DLQE1_TYPES_H__
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe1_types.h) */
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe2.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
static real32_T rt_powf_snf(real32_T u0, real32_T u1);
|
||||
|
||||
/* Function Definitions */
|
||||
static real32_T rt_powf_snf(real32_T u0, real32_T u1)
|
||||
{
|
||||
real32_T y;
|
||||
real32_T f1;
|
||||
real32_T f2;
|
||||
if (rtIsNaNF(u0) || rtIsNaNF(u1)) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else {
|
||||
f1 = (real32_T)fabs(u0);
|
||||
f2 = (real32_T)fabs(u1);
|
||||
if (rtIsInfF(u1)) {
|
||||
if (f1 == 1.0F) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else if (f1 > 1.0F) {
|
||||
if (u1 > 0.0F) {
|
||||
y = ((real32_T)rtInf);
|
||||
} else {
|
||||
y = 0.0F;
|
||||
}
|
||||
} else if (u1 > 0.0F) {
|
||||
y = 0.0F;
|
||||
} else {
|
||||
y = ((real32_T)rtInf);
|
||||
}
|
||||
} else if (f2 == 0.0F) {
|
||||
y = 1.0F;
|
||||
} else if (f2 == 1.0F) {
|
||||
if (u1 > 0.0F) {
|
||||
y = u0;
|
||||
} else {
|
||||
y = 1.0F / u0;
|
||||
}
|
||||
} else if (u1 == 2.0F) {
|
||||
y = u0 * u0;
|
||||
} else if ((u1 == 0.5F) && (u0 >= 0.0F)) {
|
||||
y = (real32_T)sqrt(u0);
|
||||
} else if ((u0 < 0.0F) && (u1 > (real32_T)floor(u1))) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else {
|
||||
y = (real32_T)pow(u0, u1);
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
void kalman_dlqe2(real32_T dt, real32_T k1, real32_T k2, real32_T k3, const
|
||||
real32_T x_aposteriori_k[3], real32_T z, real32_T
|
||||
x_aposteriori[3])
|
||||
{
|
||||
//printf("[dqle2] dt: %12.8f\tvk1 %12.8f\tk2: %12.8f\tk3: %12.8f\n", (double)(dt), (double)(k1), (double)(k2), (double)(k3));
|
||||
//printf("[dqle2] dt: %8.4f\n", (double)(dt));//, (double)(k1), (double)(k2), (double)(k3));
|
||||
real32_T A[9];
|
||||
real32_T y;
|
||||
int32_T i0;
|
||||
static const int8_T iv0[3] = { 0, 0, 1 };
|
||||
|
||||
real32_T b_k1[3];
|
||||
int32_T i1;
|
||||
static const int8_T iv1[3] = { 1, 0, 0 };
|
||||
|
||||
real32_T f0;
|
||||
A[0] = 1.0F;
|
||||
A[3] = dt;
|
||||
A[6] = 0.5F * rt_powf_snf(dt, 2.0F);
|
||||
A[1] = 0.0F;
|
||||
A[4] = 1.0F;
|
||||
A[7] = dt;
|
||||
y = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
A[2 + 3 * i0] = (real32_T)iv0[i0];
|
||||
b_k1[i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
b_k1[i0] += (real32_T)iv1[i1] * A[i1 + 3 * i0];
|
||||
}
|
||||
|
||||
y += b_k1[i0] * x_aposteriori_k[i0];
|
||||
}
|
||||
|
||||
y = z - y;
|
||||
b_k1[0] = k1;
|
||||
b_k1[1] = k2;
|
||||
b_k1[2] = k3;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
f0 += A[i0 + 3 * i1] * x_aposteriori_k[i1];
|
||||
}
|
||||
|
||||
x_aposteriori[i0] = f0 + b_k1[i0] * y;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe2.c) */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:29 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE2_H__
|
||||
#define __KALMAN_DLQE2_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe2_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe2(real32_T dt, real32_T k1, real32_T k2, real32_T k3, const real32_T x_aposteriori_k[3], real32_T z, real32_T x_aposteriori[3]);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe2.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2_initialize.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2_initialize'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe2.h"
|
||||
#include "kalman_dlqe2_initialize.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe2_initialize(void)
|
||||
{
|
||||
rt_InitInfAndNaN(8U);
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe2_initialize.c) */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2_initialize.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2_initialize'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE2_INITIALIZE_H__
|
||||
#define __KALMAN_DLQE2_INITIALIZE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe2_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe2_initialize(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe2_initialize.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2_terminate.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2_terminate'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe2.h"
|
||||
#include "kalman_dlqe2_terminate.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe2_terminate(void)
|
||||
{
|
||||
/* (no terminate code required) */
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe2_terminate.c) */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2_terminate.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2_terminate'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE2_TERMINATE_H__
|
||||
#define __KALMAN_DLQE2_TERMINATE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe2_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe2_terminate(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe2_terminate.h) */
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe2_types.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:28 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE2_TYPES_H__
|
||||
#define __KALMAN_DLQE2_TYPES_H__
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe2_types.h) */
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe3.h"
|
||||
#include "randn.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
static real32_T rt_powf_snf(real32_T u0, real32_T u1);
|
||||
|
||||
/* Function Definitions */
|
||||
static real32_T rt_powf_snf(real32_T u0, real32_T u1)
|
||||
{
|
||||
real32_T y;
|
||||
real32_T f1;
|
||||
real32_T f2;
|
||||
if (rtIsNaNF(u0) || rtIsNaNF(u1)) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else {
|
||||
f1 = (real32_T)fabs(u0);
|
||||
f2 = (real32_T)fabs(u1);
|
||||
if (rtIsInfF(u1)) {
|
||||
if (f1 == 1.0F) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else if (f1 > 1.0F) {
|
||||
if (u1 > 0.0F) {
|
||||
y = ((real32_T)rtInf);
|
||||
} else {
|
||||
y = 0.0F;
|
||||
}
|
||||
} else if (u1 > 0.0F) {
|
||||
y = 0.0F;
|
||||
} else {
|
||||
y = ((real32_T)rtInf);
|
||||
}
|
||||
} else if (f2 == 0.0F) {
|
||||
y = 1.0F;
|
||||
} else if (f2 == 1.0F) {
|
||||
if (u1 > 0.0F) {
|
||||
y = u0;
|
||||
} else {
|
||||
y = 1.0F / u0;
|
||||
}
|
||||
} else if (u1 == 2.0F) {
|
||||
y = u0 * u0;
|
||||
} else if ((u1 == 0.5F) && (u0 >= 0.0F)) {
|
||||
y = (real32_T)sqrt(u0);
|
||||
} else if ((u0 < 0.0F) && (u1 > (real32_T)floor(u1))) {
|
||||
y = ((real32_T)rtNaN);
|
||||
} else {
|
||||
y = (real32_T)pow(u0, u1);
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
void kalman_dlqe3(real32_T dt, real32_T k1, real32_T k2, real32_T k3, const
|
||||
real32_T x_aposteriori_k[3], real32_T z, real32_T posUpdate,
|
||||
real32_T addNoise, real32_T sigma, real32_T x_aposteriori[3])
|
||||
{
|
||||
real32_T A[9];
|
||||
int32_T i0;
|
||||
static const int8_T iv0[3] = { 0, 0, 1 };
|
||||
|
||||
real_T b;
|
||||
real32_T y;
|
||||
real32_T b_y[3];
|
||||
int32_T i1;
|
||||
static const int8_T iv1[3] = { 1, 0, 0 };
|
||||
|
||||
real32_T b_k1[3];
|
||||
real32_T f0;
|
||||
A[0] = 1.0F;
|
||||
A[3] = dt;
|
||||
A[6] = 0.5F * rt_powf_snf(dt, 2.0F);
|
||||
A[1] = 0.0F;
|
||||
A[4] = 1.0F;
|
||||
A[7] = dt;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
A[2 + 3 * i0] = (real32_T)iv0[i0];
|
||||
}
|
||||
|
||||
if (addNoise == 1.0F) {
|
||||
b = randn();
|
||||
z += sigma * (real32_T)b;
|
||||
}
|
||||
|
||||
if (posUpdate != 0.0F) {
|
||||
y = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
b_y[i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
b_y[i0] += (real32_T)iv1[i1] * A[i1 + 3 * i0];
|
||||
}
|
||||
|
||||
y += b_y[i0] * x_aposteriori_k[i0];
|
||||
}
|
||||
|
||||
y = z - y;
|
||||
b_k1[0] = k1;
|
||||
b_k1[1] = k2;
|
||||
b_k1[2] = k3;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
f0 += A[i0 + 3 * i1] * x_aposteriori_k[i1];
|
||||
}
|
||||
|
||||
x_aposteriori[i0] = f0 + b_k1[i0] * y;
|
||||
}
|
||||
} else {
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
x_aposteriori[i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
x_aposteriori[i0] += A[i0 + 3 * i1] * x_aposteriori_k[i1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe3.c) */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE3_H__
|
||||
#define __KALMAN_DLQE3_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe3_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe3(real32_T dt, real32_T k1, real32_T k2, real32_T k3, const real32_T x_aposteriori_k[3], real32_T z, real32_T posUpdate, real32_T addNoise, real32_T sigma, real32_T x_aposteriori[3]);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe3.h) */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_data.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_data'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe3.h"
|
||||
#include "kalman_dlqe3_data.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
uint32_T method;
|
||||
uint32_T state[2];
|
||||
uint32_T b_method;
|
||||
uint32_T b_state;
|
||||
uint32_T c_state[2];
|
||||
boolean_T state_not_empty;
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
/* End of code generation (kalman_dlqe3_data.c) */
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_data.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_data'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE3_DATA_H__
|
||||
#define __KALMAN_DLQE3_DATA_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe3_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
extern uint32_T method;
|
||||
extern uint32_T state[2];
|
||||
extern uint32_T b_method;
|
||||
extern uint32_T b_state;
|
||||
extern uint32_T c_state[2];
|
||||
extern boolean_T state_not_empty;
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe3_data.h) */
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_initialize.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_initialize'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe3.h"
|
||||
#include "kalman_dlqe3_initialize.h"
|
||||
#include "kalman_dlqe3_data.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe3_initialize(void)
|
||||
{
|
||||
int32_T i;
|
||||
static const uint32_T uv0[2] = { 362436069U, 0U };
|
||||
|
||||
rt_InitInfAndNaN(8U);
|
||||
state_not_empty = FALSE;
|
||||
b_state = 1144108930U;
|
||||
b_method = 7U;
|
||||
method = 0U;
|
||||
for (i = 0; i < 2; i++) {
|
||||
c_state[i] = 362436069U + 158852560U * (uint32_T)i;
|
||||
state[i] = uv0[i];
|
||||
}
|
||||
|
||||
if (state[1] == 0U) {
|
||||
state[1] = 521288629U;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe3_initialize.c) */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_initialize.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_initialize'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE3_INITIALIZE_H__
|
||||
#define __KALMAN_DLQE3_INITIALIZE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe3_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe3_initialize(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe3_initialize.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_terminate.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_terminate'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe3.h"
|
||||
#include "kalman_dlqe3_terminate.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void kalman_dlqe3_terminate(void)
|
||||
{
|
||||
/* (no terminate code required) */
|
||||
}
|
||||
|
||||
/* End of code generation (kalman_dlqe3_terminate.c) */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_terminate.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3_terminate'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:31 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE3_TERMINATE_H__
|
||||
#define __KALMAN_DLQE3_TERMINATE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe3_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void kalman_dlqe3_terminate(void);
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe3_terminate.h) */
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* kalman_dlqe3_types.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe3'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:30 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __KALMAN_DLQE3_TYPES_H__
|
||||
#define __KALMAN_DLQE3_TYPES_H__
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
#endif
|
||||
/* End of code generation (kalman_dlqe3_types.h) */
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D(const real32_T A[9], const real32_T B[3], const
|
||||
real32_T C[3], const real32_T x_aposteriori_k[3], const real32_T
|
||||
P_aposteriori_k[9], real32_T u, real32_T z, uint8_T gps_update, const real32_T
|
||||
Q[9], real32_T R, real32_T thresh, real32_T decay, real32_T x_aposteriori[3],
|
||||
real32_T P_aposteriori[9])
|
||||
{
|
||||
int32_T i0;
|
||||
real32_T f0;
|
||||
int32_T k;
|
||||
real32_T b_A[9];
|
||||
int32_T i1;
|
||||
real32_T P_apriori[9];
|
||||
real32_T y;
|
||||
real32_T K[3];
|
||||
real32_T S;
|
||||
int8_T I[9];
|
||||
|
||||
/* prediction */
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (k = 0; k < 3; k++) {
|
||||
f0 += A[i0 + 3 * k] * x_aposteriori_k[k];
|
||||
}
|
||||
|
||||
x_aposteriori[i0] = f0 + B[i0] * u;
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
for (k = 0; k < 3; k++) {
|
||||
b_A[i0 + 3 * k] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
b_A[i0 + 3 * k] += A[i0 + 3 * i1] * P_aposteriori_k[i1 + 3 * k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
for (k = 0; k < 3; k++) {
|
||||
f0 = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
f0 += b_A[i0 + 3 * i1] * A[k + 3 * i1];
|
||||
}
|
||||
|
||||
P_apriori[i0 + 3 * k] = f0 + Q[i0 + 3 * k];
|
||||
}
|
||||
}
|
||||
|
||||
if ((real32_T)fabs(u) < thresh) {
|
||||
x_aposteriori[1] *= decay;
|
||||
}
|
||||
|
||||
/* update */
|
||||
if (gps_update == 1) {
|
||||
y = 0.0F;
|
||||
for (k = 0; k < 3; k++) {
|
||||
y += C[k] * x_aposteriori[k];
|
||||
K[k] = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
K[k] += C[i0] * P_apriori[i0 + 3 * k];
|
||||
}
|
||||
}
|
||||
|
||||
y = z - y;
|
||||
S = 0.0F;
|
||||
for (k = 0; k < 3; k++) {
|
||||
S += K[k] * C[k];
|
||||
}
|
||||
|
||||
S += R;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (k = 0; k < 3; k++) {
|
||||
f0 += P_apriori[i0 + 3 * k] * C[k];
|
||||
}
|
||||
|
||||
K[i0] = f0 / S;
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
x_aposteriori[i0] += K[i0] * y;
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 9; i0++) {
|
||||
I[i0] = 0;
|
||||
}
|
||||
|
||||
for (k = 0; k < 3; k++) {
|
||||
I[k + 3 * k] = 1;
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
for (k = 0; k < 3; k++) {
|
||||
b_A[k + 3 * i0] = (real32_T)I[k + 3 * i0] - K[k] * C[i0];
|
||||
}
|
||||
}
|
||||
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
for (k = 0; k < 3; k++) {
|
||||
P_aposteriori[i0 + 3 * k] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
P_aposteriori[i0 + 3 * k] += b_A[i0 + 3 * i1] * P_apriori[i1 + 3 * k];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i0 = 0; i0 < 9; i0++) {
|
||||
P_aposteriori[i0] = P_apriori[i0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_H__
|
||||
#define __POSITIONKALMANFILTER1D_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D(const real32_T A[9], const real32_T B[3], const real32_T C[3], const real32_T x_aposteriori_k[3], const real32_T P_aposteriori_k[9], real32_T u, real32_T z, uint8_T gps_update, const real32_T Q[9], real32_T R, real32_T thresh, real32_T decay, real32_T x_aposteriori[3], real32_T P_aposteriori[9]);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D.h) */
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D_dT.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D_dT(real32_T dT, const real32_T x_aposteriori_k[3],
|
||||
const real32_T P_aposteriori_k[9], real32_T u, real32_T z, uint8_T gps_update,
|
||||
const real32_T Q[9], real_T R, real32_T thresh, real32_T decay, real32_T
|
||||
x_aposteriori[3], real32_T P_aposteriori[9])
|
||||
{
|
||||
real32_T A[9];
|
||||
int32_T i;
|
||||
static const int8_T iv0[3] = { 0, 0, 1 };
|
||||
|
||||
real32_T K[3];
|
||||
real32_T f0;
|
||||
int32_T i0;
|
||||
real32_T b_A[9];
|
||||
int32_T i1;
|
||||
real32_T P_apriori[9];
|
||||
static const int8_T iv1[3] = { 1, 0, 0 };
|
||||
|
||||
real32_T fv0[3];
|
||||
real32_T y;
|
||||
static const int8_T iv2[3] = { 1, 0, 0 };
|
||||
|
||||
real32_T S;
|
||||
int8_T I[9];
|
||||
|
||||
/* dynamics */
|
||||
A[0] = 1.0F;
|
||||
A[3] = dT;
|
||||
A[6] = -0.5F * dT * dT;
|
||||
A[1] = 0.0F;
|
||||
A[4] = 1.0F;
|
||||
A[7] = -dT;
|
||||
for (i = 0; i < 3; i++) {
|
||||
A[2 + 3 * i] = (real32_T)iv0[i];
|
||||
}
|
||||
|
||||
/* prediction */
|
||||
K[0] = 0.5F * dT * dT;
|
||||
K[1] = dT;
|
||||
K[2] = 0.0F;
|
||||
for (i = 0; i < 3; i++) {
|
||||
f0 = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 += A[i + 3 * i0] * x_aposteriori_k[i0];
|
||||
}
|
||||
|
||||
x_aposteriori[i] = f0 + K[i] * u;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
b_A[i + 3 * i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
b_A[i + 3 * i0] += A[i + 3 * i1] * P_aposteriori_k[i1 + 3 * i0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
f0 += b_A[i + 3 * i1] * A[i0 + 3 * i1];
|
||||
}
|
||||
|
||||
P_apriori[i + 3 * i0] = f0 + Q[i + 3 * i0];
|
||||
}
|
||||
}
|
||||
|
||||
if ((real32_T)fabs(u) < thresh) {
|
||||
x_aposteriori[1] *= decay;
|
||||
}
|
||||
|
||||
/* update */
|
||||
if (gps_update == 1) {
|
||||
f0 = 0.0F;
|
||||
for (i = 0; i < 3; i++) {
|
||||
f0 += (real32_T)iv1[i] * x_aposteriori[i];
|
||||
fv0[i] = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
fv0[i] += (real32_T)iv1[i0] * P_apriori[i0 + 3 * i];
|
||||
}
|
||||
}
|
||||
|
||||
y = z - f0;
|
||||
f0 = 0.0F;
|
||||
for (i = 0; i < 3; i++) {
|
||||
f0 += fv0[i] * (real32_T)iv2[i];
|
||||
}
|
||||
|
||||
S = f0 + (real32_T)R;
|
||||
for (i = 0; i < 3; i++) {
|
||||
f0 = 0.0F;
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
f0 += P_apriori[i + 3 * i0] * (real32_T)iv2[i0];
|
||||
}
|
||||
|
||||
K[i] = f0 / S;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
x_aposteriori[i] += K[i] * y;
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
I[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
I[i + 3 * i] = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
A[i0 + 3 * i] = (real32_T)I[i0 + 3 * i] - K[i0] * (real32_T)iv1[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i0 = 0; i0 < 3; i0++) {
|
||||
P_aposteriori[i + 3 * i0] = 0.0F;
|
||||
for (i1 = 0; i1 < 3; i1++) {
|
||||
P_aposteriori[i + 3 * i0] += A[i + 3 * i1] * P_apriori[i1 + 3 * i0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 9; i++) {
|
||||
P_aposteriori[i] = P_apriori[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D_dT.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_DT_H__
|
||||
#define __POSITIONKALMANFILTER1D_DT_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_dT_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D_dT(real32_T dT, const real32_T x_aposteriori_k[3], const real32_T P_aposteriori_k[9], real32_T u, real32_T z, uint8_T gps_update, const real32_T Q[9], real_T R, real32_T thresh, real32_T decay, real32_T x_aposteriori[3], real32_T P_aposteriori[9]);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_dT.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT_initialize.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT_initialize'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D_dT.h"
|
||||
#include "positionKalmanFilter1D_dT_initialize.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D_dT_initialize(void)
|
||||
{
|
||||
rt_InitInfAndNaN(8U);
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D_dT_initialize.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT_initialize.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT_initialize'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_DT_INITIALIZE_H__
|
||||
#define __POSITIONKALMANFILTER1D_DT_INITIALIZE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_dT_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D_dT_initialize(void);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_dT_initialize.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT_terminate.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT_terminate'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D_dT.h"
|
||||
#include "positionKalmanFilter1D_dT_terminate.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D_dT_terminate(void)
|
||||
{
|
||||
/* (no terminate code required) */
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D_dT_terminate.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT_terminate.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT_terminate'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_DT_TERMINATE_H__
|
||||
#define __POSITIONKALMANFILTER1D_DT_TERMINATE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_dT_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D_dT_terminate(void);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_dT_terminate.h) */
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_dT_types.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_dT'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 17:37:33 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_DT_TYPES_H__
|
||||
#define __POSITIONKALMANFILTER1D_DT_TYPES_H__
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_dT_types.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_initialize.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_initialize'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D.h"
|
||||
#include "positionKalmanFilter1D_initialize.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D_initialize(void)
|
||||
{
|
||||
rt_InitInfAndNaN(8U);
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D_initialize.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_initialize.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_initialize'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_INITIALIZE_H__
|
||||
#define __POSITIONKALMANFILTER1D_INITIALIZE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D_initialize(void);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_initialize.h) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_terminate.c
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_terminate'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "positionKalmanFilter1D.h"
|
||||
#include "positionKalmanFilter1D_terminate.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
|
||||
/* Function Definitions */
|
||||
void positionKalmanFilter1D_terminate(void)
|
||||
{
|
||||
/* (no terminate code required) */
|
||||
}
|
||||
|
||||
/* End of code generation (positionKalmanFilter1D_terminate.c) */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_terminate.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D_terminate'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_TERMINATE_H__
|
||||
#define __POSITIONKALMANFILTER1D_TERMINATE_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "positionKalmanFilter1D_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern void positionKalmanFilter1D_terminate(void);
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_terminate.h) */
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* positionKalmanFilter1D_types.h
|
||||
*
|
||||
* Code generation for function 'positionKalmanFilter1D'
|
||||
*
|
||||
* C source code generated on: Fri Nov 30 14:26:11 2012
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POSITIONKALMANFILTER1D_TYPES_H__
|
||||
#define __POSITIONKALMANFILTER1D_TYPES_H__
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
#endif
|
||||
/* End of code generation (positionKalmanFilter1D_types.h) */
|
||||
@@ -1,524 +0,0 @@
|
||||
/*
|
||||
* randn.c
|
||||
*
|
||||
* Code generation for function 'randn'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/* Include files */
|
||||
#include "rt_nonfinite.h"
|
||||
#include "kalman_dlqe3.h"
|
||||
#include "randn.h"
|
||||
#include "kalman_dlqe3_data.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
static uint32_T d_state[625];
|
||||
|
||||
/* Function Declarations */
|
||||
static real_T b_genrandu(uint32_T mt[625]);
|
||||
static real_T eml_rand_mt19937ar(uint32_T e_state[625]);
|
||||
static real_T eml_rand_shr3cong(uint32_T e_state[2]);
|
||||
static void genrand_uint32_vector(uint32_T mt[625], uint32_T u[2]);
|
||||
static void genrandu(uint32_T s, uint32_T *e_state, real_T *r);
|
||||
static void twister_state_vector(uint32_T mt[625], real_T seed);
|
||||
|
||||
/* Function Definitions */
|
||||
static real_T b_genrandu(uint32_T mt[625])
|
||||
{
|
||||
real_T r;
|
||||
int32_T exitg1;
|
||||
uint32_T u[2];
|
||||
boolean_T isvalid;
|
||||
int32_T k;
|
||||
boolean_T exitg2;
|
||||
|
||||
/* <LEGAL> This is a uniform (0,1) pseudorandom number generator based on: */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> A C-program for MT19937, with initialization improved 2002/1/26. */
|
||||
/* <LEGAL> Coded by Takuji Nishimura and Makoto Matsumoto. */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, */
|
||||
/* <LEGAL> All rights reserved. */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> Redistribution and use in source and binary forms, with or without */
|
||||
/* <LEGAL> modification, are permitted provided that the following conditions */
|
||||
/* <LEGAL> are met: */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> 1. Redistributions of source code must retain the above copyright */
|
||||
/* <LEGAL> notice, this list of conditions and the following disclaimer. */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> 2. Redistributions in binary form must reproduce the above copyright */
|
||||
/* <LEGAL> notice, this list of conditions and the following disclaimer in the */
|
||||
/* <LEGAL> documentation and/or other materials provided with the distribution. */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> 3. The names of its contributors may not be used to endorse or promote */
|
||||
/* <LEGAL> products derived from this software without specific prior written */
|
||||
/* <LEGAL> permission. */
|
||||
/* <LEGAL> */
|
||||
/* <LEGAL> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
||||
/* <LEGAL> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
||||
/* <LEGAL> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
||||
/* <LEGAL> A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR */
|
||||
/* <LEGAL> CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
|
||||
/* <LEGAL> EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, */
|
||||
/* <LEGAL> PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */
|
||||
/* <LEGAL> PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
|
||||
/* <LEGAL> LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
|
||||
/* <LEGAL> NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
|
||||
/* <LEGAL> SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
do {
|
||||
exitg1 = 0;
|
||||
genrand_uint32_vector(mt, u);
|
||||
r = 1.1102230246251565E-16 * ((real_T)(u[0] >> 5U) * 6.7108864E+7 + (real_T)
|
||||
(u[1] >> 6U));
|
||||
if (r == 0.0) {
|
||||
if ((mt[624] >= 1U) && (mt[624] < 625U)) {
|
||||
isvalid = TRUE;
|
||||
} else {
|
||||
isvalid = FALSE;
|
||||
}
|
||||
|
||||
if (isvalid) {
|
||||
isvalid = FALSE;
|
||||
k = 1;
|
||||
exitg2 = FALSE;
|
||||
while ((exitg2 == FALSE) && (k < 625)) {
|
||||
if (mt[k - 1] == 0U) {
|
||||
k++;
|
||||
} else {
|
||||
isvalid = TRUE;
|
||||
exitg2 = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isvalid) {
|
||||
twister_state_vector(mt, 5489.0);
|
||||
}
|
||||
} else {
|
||||
exitg1 = 1;
|
||||
}
|
||||
} while (exitg1 == 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static real_T eml_rand_mt19937ar(uint32_T e_state[625])
|
||||
{
|
||||
real_T r;
|
||||
int32_T exitg1;
|
||||
uint32_T u32[2];
|
||||
int32_T i;
|
||||
static const real_T dv1[257] = { 0.0, 0.215241895984875, 0.286174591792068,
|
||||
0.335737519214422, 0.375121332878378, 0.408389134611989, 0.43751840220787,
|
||||
0.46363433679088, 0.487443966139235, 0.50942332960209, 0.529909720661557,
|
||||
0.549151702327164, 0.567338257053817, 0.584616766106378, 0.601104617755991,
|
||||
0.61689699000775, 0.63207223638606, 0.646695714894993, 0.660822574244419,
|
||||
0.674499822837293, 0.687767892795788, 0.700661841106814, 0.713212285190975,
|
||||
0.725446140909999, 0.737387211434295, 0.749056662017815, 0.760473406430107,
|
||||
0.771654424224568, 0.782615023307232, 0.793369058840623, 0.80392911698997,
|
||||
0.814306670135215, 0.824512208752291, 0.834555354086381, 0.844444954909153,
|
||||
0.854189171008163, 0.863795545553308, 0.87327106808886, 0.882622229585165,
|
||||
0.891855070732941, 0.900975224461221, 0.909987953496718, 0.91889818364959,
|
||||
0.927710533401999, 0.936429340286575, 0.945058684468165, 0.953602409881086,
|
||||
0.96206414322304, 0.970447311064224, 0.978755155294224, 0.986990747099062,
|
||||
0.99515699963509, 1.00325667954467, 1.01129241744, 1.01926671746548,
|
||||
1.02718196603564, 1.03504043983344, 1.04284431314415, 1.05059566459093,
|
||||
1.05829648333067, 1.06594867476212, 1.07355406579244, 1.0811144097034,
|
||||
1.08863139065398, 1.09610662785202, 1.10354167942464, 1.11093804601357,
|
||||
1.11829717411934, 1.12562045921553, 1.13290924865253, 1.14016484436815,
|
||||
1.14738850542085, 1.15458145035993, 1.16174485944561, 1.16887987673083,
|
||||
1.17598761201545, 1.18306914268269, 1.19012551542669, 1.19715774787944,
|
||||
1.20416683014438, 1.2111537262437, 1.21811937548548, 1.22506469375653,
|
||||
1.23199057474614, 1.23889789110569, 1.24578749554863, 1.2526602218949,
|
||||
1.25951688606371, 1.26635828701823, 1.27318520766536, 1.27999841571382,
|
||||
1.28679866449324, 1.29358669373695, 1.30036323033084, 1.30712898903073,
|
||||
1.31388467315022, 1.32063097522106, 1.32736857762793, 1.33409815321936,
|
||||
1.3408203658964, 1.34753587118059, 1.35424531676263, 1.36094934303328,
|
||||
1.36764858359748, 1.37434366577317, 1.38103521107586, 1.38772383568998,
|
||||
1.39441015092814, 1.40109476367925, 1.4077782768464, 1.41446128977547,
|
||||
1.42114439867531, 1.42782819703026, 1.43451327600589, 1.44120022484872,
|
||||
1.44788963128058, 1.45458208188841, 1.46127816251028, 1.46797845861808,
|
||||
1.47468355569786, 1.48139403962819, 1.48811049705745, 1.49483351578049,
|
||||
1.50156368511546, 1.50830159628131, 1.51504784277671, 1.521803020761,
|
||||
1.52856772943771, 1.53534257144151, 1.542128153229, 1.54892508547417,
|
||||
1.55573398346918, 1.56255546753104, 1.56939016341512, 1.57623870273591,
|
||||
1.58310172339603, 1.58997987002419, 1.59687379442279, 1.60378415602609,
|
||||
1.61071162236983, 1.61765686957301, 1.62462058283303, 1.63160345693487,
|
||||
1.63860619677555, 1.64562951790478, 1.65267414708306, 1.65974082285818,
|
||||
1.66683029616166, 1.67394333092612, 1.68108070472517, 1.68824320943719,
|
||||
1.69543165193456, 1.70264685479992, 1.7098896570713, 1.71716091501782,
|
||||
1.72446150294804, 1.73179231405296, 1.73915426128591, 1.74654827828172,
|
||||
1.75397532031767, 1.76143636531891, 1.76893241491127, 1.77646449552452,
|
||||
1.78403365954944, 1.79164098655216, 1.79928758454972, 1.80697459135082,
|
||||
1.81470317596628, 1.82247454009388, 1.83028991968276, 1.83815058658281,
|
||||
1.84605785028518, 1.8540130597602, 1.86201760539967, 1.87007292107127,
|
||||
1.878180486293, 1.88634182853678, 1.8945585256707, 1.90283220855043,
|
||||
1.91116456377125, 1.91955733659319, 1.92801233405266, 1.93653142827569,
|
||||
1.94511656000868, 1.95376974238465, 1.96249306494436, 1.97128869793366,
|
||||
1.98015889690048, 1.98910600761744, 1.99813247135842, 2.00724083056053,
|
||||
2.0164337349062, 2.02571394786385, 2.03508435372962, 2.04454796521753,
|
||||
2.05410793165065, 2.06376754781173, 2.07353026351874, 2.0833996939983,
|
||||
2.09337963113879, 2.10347405571488, 2.11368715068665, 2.12402331568952,
|
||||
2.13448718284602, 2.14508363404789, 2.15581781987674, 2.16669518035431,
|
||||
2.17772146774029, 2.18890277162636, 2.20024554661128, 2.21175664288416,
|
||||
2.22344334009251, 2.23531338492992, 2.24737503294739, 2.25963709517379,
|
||||
2.27210899022838, 2.28480080272449, 2.29772334890286, 2.31088825060137,
|
||||
2.32430801887113, 2.33799614879653, 2.35196722737914, 2.36623705671729,
|
||||
2.38082279517208, 2.39574311978193, 2.41101841390112, 2.42667098493715,
|
||||
2.44272531820036, 2.4592083743347, 2.47614993967052, 2.49358304127105,
|
||||
2.51154444162669, 2.53007523215985, 2.54922155032478, 2.56903545268184,
|
||||
2.58957598670829, 2.61091051848882, 2.63311639363158, 2.65628303757674,
|
||||
2.68051464328574, 2.70593365612306, 2.73268535904401, 2.76094400527999,
|
||||
2.79092117400193, 2.82287739682644, 2.85713873087322, 2.89412105361341,
|
||||
2.93436686720889, 2.97860327988184, 3.02783779176959, 3.08352613200214,
|
||||
3.147889289518, 3.2245750520478, 3.32024473383983, 3.44927829856143,
|
||||
3.65415288536101, 3.91075795952492 };
|
||||
|
||||
real_T u;
|
||||
static const real_T dv2[257] = { 1.0, 0.977101701267673, 0.959879091800108,
|
||||
0.9451989534423, 0.932060075959231, 0.919991505039348, 0.908726440052131,
|
||||
0.898095921898344, 0.887984660755834, 0.878309655808918, 0.869008688036857,
|
||||
0.860033621196332, 0.851346258458678, 0.842915653112205, 0.834716292986884,
|
||||
0.826726833946222, 0.818929191603703, 0.811307874312656, 0.803849483170964,
|
||||
0.796542330422959, 0.789376143566025, 0.782341832654803, 0.775431304981187,
|
||||
0.768637315798486, 0.761953346836795, 0.755373506507096, 0.748892447219157,
|
||||
0.742505296340151, 0.736207598126863, 0.729995264561476, 0.72386453346863,
|
||||
0.717811932630722, 0.711834248878248, 0.705928501332754, 0.700091918136512,
|
||||
0.694321916126117, 0.688616083004672, 0.682972161644995, 0.677388036218774,
|
||||
0.671861719897082, 0.66639134390875, 0.660975147776663, 0.655611470579697,
|
||||
0.650298743110817, 0.645035480820822, 0.639820277453057, 0.634651799287624,
|
||||
0.629528779924837, 0.624450015547027, 0.619414360605834, 0.614420723888914,
|
||||
0.609468064925773, 0.604555390697468, 0.599681752619125, 0.594846243767987,
|
||||
0.590047996332826, 0.585286179263371, 0.580559996100791, 0.575868682972354,
|
||||
0.571211506735253, 0.566587763256165, 0.561996775814525, 0.557437893618766,
|
||||
0.552910490425833, 0.548413963255266, 0.543947731190026, 0.539511234256952,
|
||||
0.535103932380458, 0.530725304403662, 0.526374847171684, 0.522052074672322,
|
||||
0.517756517229756, 0.513487720747327, 0.509245245995748, 0.505028667943468,
|
||||
0.500837575126149, 0.49667156905249, 0.492530263643869, 0.488413284705458,
|
||||
0.484320269426683, 0.480250865909047, 0.476204732719506, 0.47218153846773,
|
||||
0.468180961405694, 0.464202689048174, 0.460246417812843, 0.456311852678716,
|
||||
0.452398706861849, 0.448506701507203, 0.444635565395739, 0.440785034665804,
|
||||
0.436954852547985, 0.433144769112652, 0.429354541029442, 0.425583931338022,
|
||||
0.421832709229496, 0.418100649837848, 0.414387534040891, 0.410693148270188,
|
||||
0.407017284329473, 0.403359739221114, 0.399720314980197, 0.396098818515832,
|
||||
0.392495061459315, 0.388908860018789, 0.385340034840077, 0.381788410873393,
|
||||
0.378253817245619, 0.374736087137891, 0.371235057668239, 0.367750569779032,
|
||||
0.364282468129004, 0.360830600989648, 0.357394820145781, 0.353974980800077,
|
||||
0.350570941481406, 0.347182563956794, 0.343809713146851, 0.340452257044522,
|
||||
0.337110066637006, 0.333783015830718, 0.330470981379163, 0.327173842813601,
|
||||
0.323891482376391, 0.320623784956905, 0.317370638029914, 0.314131931596337,
|
||||
0.310907558126286, 0.307697412504292, 0.30450139197665, 0.301319396100803,
|
||||
0.298151326696685, 0.294997087799962, 0.291856585617095, 0.288729728482183,
|
||||
0.285616426815502, 0.282516593083708, 0.279430141761638, 0.276356989295668,
|
||||
0.273297054068577, 0.270250256365875, 0.267216518343561, 0.264195763997261,
|
||||
0.261187919132721, 0.258192911337619, 0.255210669954662, 0.252241126055942,
|
||||
0.249284212418529, 0.246339863501264, 0.24340801542275, 0.240488605940501,
|
||||
0.237581574431238, 0.23468686187233, 0.231804410824339, 0.228934165414681,
|
||||
0.226076071322381, 0.223230075763918, 0.220396127480152, 0.217574176724331,
|
||||
0.214764175251174, 0.211966076307031, 0.209179834621125, 0.206405406397881,
|
||||
0.203642749310335, 0.200891822494657, 0.198152586545776, 0.195425003514135,
|
||||
0.192709036903589, 0.190004651670465, 0.187311814223801, 0.1846304924268,
|
||||
0.181960655599523, 0.179302274522848, 0.176655321443735, 0.174019770081839,
|
||||
0.171395595637506, 0.168782774801212, 0.166181285764482, 0.163591108232366,
|
||||
0.161012223437511, 0.158444614155925, 0.15588826472448, 0.153343161060263,
|
||||
0.150809290681846, 0.148286642732575, 0.145775208005994, 0.143274978973514,
|
||||
0.140785949814445, 0.138308116448551, 0.135841476571254, 0.133386029691669,
|
||||
0.130941777173644, 0.12850872228, 0.126086870220186, 0.123676228201597,
|
||||
0.12127680548479, 0.11888861344291, 0.116511665625611, 0.114145977827839,
|
||||
0.111791568163838, 0.109448457146812, 0.107116667774684, 0.104796225622487,
|
||||
0.102487158941935, 0.10018949876881, 0.0979032790388625, 0.095628536713009,
|
||||
0.093365311912691, 0.0911136480663738, 0.0888735920682759,
|
||||
0.0866451944505581, 0.0844285095703535, 0.082223595813203,
|
||||
0.0800305158146631, 0.0778493367020961, 0.0756801303589272,
|
||||
0.0735229737139814, 0.0713779490588905, 0.0692451443970068,
|
||||
0.0671246538277886, 0.065016577971243, 0.0629210244377582, 0.06083810834954,
|
||||
0.0587679529209339, 0.0567106901062031, 0.0546664613248891,
|
||||
0.0526354182767924, 0.0506177238609479, 0.0486135532158687,
|
||||
0.0466230949019305, 0.0446465522512946, 0.0426841449164746,
|
||||
0.0407361106559411, 0.0388027074045262, 0.0368842156885674,
|
||||
0.0349809414617162, 0.0330932194585786, 0.0312214171919203,
|
||||
0.0293659397581334, 0.0275272356696031, 0.0257058040085489,
|
||||
0.0239022033057959, 0.0221170627073089, 0.0203510962300445,
|
||||
0.0186051212757247, 0.0168800831525432, 0.0151770883079353,
|
||||
0.0134974506017399, 0.0118427578579079, 0.0102149714397015,
|
||||
0.00861658276939875, 0.00705087547137324, 0.00552240329925101,
|
||||
0.00403797259336304, 0.00260907274610216, 0.0012602859304986,
|
||||
0.000477467764609386 };
|
||||
|
||||
real_T x;
|
||||
do {
|
||||
exitg1 = 0;
|
||||
genrand_uint32_vector(e_state, u32);
|
||||
i = (int32_T)((u32[1] >> 24U) + 1U);
|
||||
r = (((real_T)(u32[0] >> 3U) * 1.6777216E+7 + (real_T)((int32_T)u32[1] &
|
||||
16777215)) * 2.2204460492503131E-16 - 1.0) * dv1[i];
|
||||
if (fabs(r) <= dv1[i - 1]) {
|
||||
exitg1 = 1;
|
||||
} else if (i < 256) {
|
||||
u = b_genrandu(e_state);
|
||||
if (dv2[i] + u * (dv2[i - 1] - dv2[i]) < exp(-0.5 * r * r)) {
|
||||
exitg1 = 1;
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
u = b_genrandu(e_state);
|
||||
x = log(u) * 0.273661237329758;
|
||||
u = b_genrandu(e_state);
|
||||
} while (!(-2.0 * log(u) > x * x));
|
||||
|
||||
if (r < 0.0) {
|
||||
r = x - 3.65415288536101;
|
||||
} else {
|
||||
r = 3.65415288536101 - x;
|
||||
}
|
||||
|
||||
exitg1 = 1;
|
||||
}
|
||||
} while (exitg1 == 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static real_T eml_rand_shr3cong(uint32_T e_state[2])
|
||||
{
|
||||
real_T r;
|
||||
uint32_T icng;
|
||||
uint32_T jsr;
|
||||
uint32_T ui;
|
||||
int32_T j;
|
||||
static const real_T dv0[65] = { 0.340945, 0.4573146, 0.5397793, 0.6062427,
|
||||
0.6631691, 0.7136975, 0.7596125, 0.8020356, 0.8417227, 0.8792102, 0.9148948,
|
||||
0.9490791, 0.9820005, 1.0138492, 1.044781, 1.0749254, 1.1043917, 1.1332738,
|
||||
1.161653, 1.189601, 1.2171815, 1.2444516, 1.2714635, 1.298265, 1.3249008,
|
||||
1.3514125, 1.3778399, 1.4042211, 1.4305929, 1.4569915, 1.4834527, 1.5100122,
|
||||
1.5367061, 1.5635712, 1.5906454, 1.617968, 1.6455802, 1.6735255, 1.7018503,
|
||||
1.7306045, 1.7598422, 1.7896223, 1.8200099, 1.851077, 1.8829044, 1.9155831,
|
||||
1.9492166, 1.9839239, 2.0198431, 2.0571356, 2.095993, 2.136645, 2.1793713,
|
||||
2.2245175, 2.2725186, 2.3239338, 2.3795008, 2.4402218, 2.5075117, 2.5834658,
|
||||
2.6713916, 2.7769942, 2.7769942, 2.7769942, 2.7769942 };
|
||||
|
||||
real_T x;
|
||||
real_T y;
|
||||
real_T s;
|
||||
icng = 69069U * e_state[0] + 1234567U;
|
||||
jsr = e_state[1] ^ e_state[1] << 13U;
|
||||
jsr ^= jsr >> 17U;
|
||||
jsr ^= jsr << 5U;
|
||||
ui = icng + jsr;
|
||||
j = (int32_T)(ui & 63U);
|
||||
r = (real_T)(int32_T)ui * 4.6566128730773926E-10 * dv0[j + 1];
|
||||
if (fabs(r) <= dv0[j]) {
|
||||
} else {
|
||||
x = (fabs(r) - dv0[j]) / (dv0[j + 1] - dv0[j]);
|
||||
icng = 69069U * icng + 1234567U;
|
||||
jsr ^= jsr << 13U;
|
||||
jsr ^= jsr >> 17U;
|
||||
jsr ^= jsr << 5U;
|
||||
y = (real_T)(int32_T)(icng + jsr) * 2.328306436538696E-10;
|
||||
s = x + (0.5 + y);
|
||||
if (s > 1.301198) {
|
||||
if (r < 0.0) {
|
||||
r = 0.4878992 * x - 0.4878992;
|
||||
} else {
|
||||
r = 0.4878992 - 0.4878992 * x;
|
||||
}
|
||||
} else if (s <= 0.9689279) {
|
||||
} else {
|
||||
s = 0.4878992 * x;
|
||||
x = 0.4878992 - 0.4878992 * x;
|
||||
if (0.5 + y > 12.67706 - 12.37586 * exp(-0.5 * (0.4878992 - s) * x)) {
|
||||
if (r < 0.0) {
|
||||
r = -(0.4878992 - s);
|
||||
} else {
|
||||
r = 0.4878992 - s;
|
||||
}
|
||||
} else if (exp(-0.5 * dv0[j + 1] * dv0[j + 1]) + (0.5 + y) * 0.01958303 /
|
||||
dv0[j + 1] <= exp(-0.5 * r * r)) {
|
||||
} else {
|
||||
do {
|
||||
icng = 69069U * icng + 1234567U;
|
||||
jsr ^= jsr << 13U;
|
||||
jsr ^= jsr >> 17U;
|
||||
jsr ^= jsr << 5U;
|
||||
x = log(0.5 + (real_T)(int32_T)(icng + jsr) * 2.328306436538696E-10) /
|
||||
2.776994;
|
||||
icng = 69069U * icng + 1234567U;
|
||||
jsr ^= jsr << 13U;
|
||||
jsr ^= jsr >> 17U;
|
||||
jsr ^= jsr << 5U;
|
||||
} while (!(-2.0 * log(0.5 + (real_T)(int32_T)(icng + jsr) *
|
||||
2.328306436538696E-10) > x * x));
|
||||
|
||||
if (r < 0.0) {
|
||||
r = x - 2.776994;
|
||||
} else {
|
||||
r = 2.776994 - x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e_state[0] = icng;
|
||||
e_state[1] = jsr;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void genrand_uint32_vector(uint32_T mt[625], uint32_T u[2])
|
||||
{
|
||||
int32_T i;
|
||||
uint32_T mti;
|
||||
int32_T kk;
|
||||
uint32_T y;
|
||||
uint32_T b_y;
|
||||
uint32_T c_y;
|
||||
uint32_T d_y;
|
||||
for (i = 0; i < 2; i++) {
|
||||
u[i] = 0U;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
mti = mt[624] + 1U;
|
||||
if (mti >= 625U) {
|
||||
for (kk = 0; kk < 227; kk++) {
|
||||
y = (mt[kk] & 2147483648U) | (mt[1 + kk] & 2147483647U);
|
||||
if ((int32_T)(y & 1U) == 0) {
|
||||
b_y = y >> 1U;
|
||||
} else {
|
||||
b_y = y >> 1U ^ 2567483615U;
|
||||
}
|
||||
|
||||
mt[kk] = mt[397 + kk] ^ b_y;
|
||||
}
|
||||
|
||||
for (kk = 0; kk < 396; kk++) {
|
||||
y = (mt[227 + kk] & 2147483648U) | (mt[228 + kk] & 2147483647U);
|
||||
if ((int32_T)(y & 1U) == 0) {
|
||||
c_y = y >> 1U;
|
||||
} else {
|
||||
c_y = y >> 1U ^ 2567483615U;
|
||||
}
|
||||
|
||||
mt[227 + kk] = mt[kk] ^ c_y;
|
||||
}
|
||||
|
||||
y = (mt[623] & 2147483648U) | (mt[0] & 2147483647U);
|
||||
if ((int32_T)(y & 1U) == 0) {
|
||||
d_y = y >> 1U;
|
||||
} else {
|
||||
d_y = y >> 1U ^ 2567483615U;
|
||||
}
|
||||
|
||||
mt[623] = mt[396] ^ d_y;
|
||||
mti = 1U;
|
||||
}
|
||||
|
||||
y = mt[(int32_T)mti - 1];
|
||||
mt[624] = mti;
|
||||
y ^= y >> 11U;
|
||||
y ^= y << 7U & 2636928640U;
|
||||
y ^= y << 15U & 4022730752U;
|
||||
y ^= y >> 18U;
|
||||
u[i] = y;
|
||||
}
|
||||
}
|
||||
|
||||
static void genrandu(uint32_T s, uint32_T *e_state, real_T *r)
|
||||
{
|
||||
int32_T hi;
|
||||
uint32_T test1;
|
||||
uint32_T test2;
|
||||
hi = (int32_T)(s / 127773U);
|
||||
test1 = 16807U * (s - (uint32_T)hi * 127773U);
|
||||
test2 = 2836U * (uint32_T)hi;
|
||||
if (test1 < test2) {
|
||||
*e_state = (test1 - test2) + 2147483647U;
|
||||
} else {
|
||||
*e_state = test1 - test2;
|
||||
}
|
||||
|
||||
*r = (real_T)*e_state * 4.6566128752457969E-10;
|
||||
}
|
||||
|
||||
static void twister_state_vector(uint32_T mt[625], real_T seed)
|
||||
{
|
||||
uint32_T r;
|
||||
int32_T mti;
|
||||
if (seed < 4.294967296E+9) {
|
||||
if (seed >= 0.0) {
|
||||
r = (uint32_T)seed;
|
||||
} else {
|
||||
r = 0U;
|
||||
}
|
||||
} else if (seed >= 4.294967296E+9) {
|
||||
r = MAX_uint32_T;
|
||||
} else {
|
||||
r = 0U;
|
||||
}
|
||||
|
||||
mt[0] = r;
|
||||
for (mti = 0; mti < 623; mti++) {
|
||||
r = (r ^ r >> 30U) * 1812433253U + (uint32_T)(1 + mti);
|
||||
mt[1 + mti] = r;
|
||||
}
|
||||
|
||||
mt[624] = 624U;
|
||||
}
|
||||
|
||||
real_T randn(void)
|
||||
{
|
||||
real_T r;
|
||||
uint32_T e_state;
|
||||
real_T t;
|
||||
real_T b_r;
|
||||
uint32_T f_state;
|
||||
if (method == 0U) {
|
||||
if (b_method == 4U) {
|
||||
do {
|
||||
genrandu(b_state, &e_state, &r);
|
||||
genrandu(e_state, &b_state, &t);
|
||||
b_r = 2.0 * r - 1.0;
|
||||
t = 2.0 * t - 1.0;
|
||||
t = t * t + b_r * b_r;
|
||||
} while (!(t <= 1.0));
|
||||
|
||||
r = (2.0 * r - 1.0) * sqrt(-2.0 * log(t) / t);
|
||||
} else if (b_method == 5U) {
|
||||
r = eml_rand_shr3cong(c_state);
|
||||
} else {
|
||||
if (!state_not_empty) {
|
||||
memset(&d_state[0], 0, 625U * sizeof(uint32_T));
|
||||
twister_state_vector(d_state, 5489.0);
|
||||
state_not_empty = TRUE;
|
||||
}
|
||||
|
||||
r = eml_rand_mt19937ar(d_state);
|
||||
}
|
||||
} else if (method == 4U) {
|
||||
e_state = state[0];
|
||||
do {
|
||||
genrandu(e_state, &f_state, &r);
|
||||
genrandu(f_state, &e_state, &t);
|
||||
b_r = 2.0 * r - 1.0;
|
||||
t = 2.0 * t - 1.0;
|
||||
t = t * t + b_r * b_r;
|
||||
} while (!(t <= 1.0));
|
||||
|
||||
state[0] = e_state;
|
||||
r = (2.0 * r - 1.0) * sqrt(-2.0 * log(t) / t);
|
||||
} else {
|
||||
r = eml_rand_shr3cong(state);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* End of code generation (randn.c) */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* randn.h
|
||||
*
|
||||
* Code generation for function 'randn'
|
||||
*
|
||||
* C source code generated on: Tue Feb 19 15:26:32 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __RANDN_H__
|
||||
#define __RANDN_H__
|
||||
/* Include files */
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
#include "rtwtypes.h"
|
||||
#include "kalman_dlqe3_types.h"
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
extern real_T randn(void);
|
||||
#endif
|
||||
/* End of code generation (randn.h) */
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* rtGetInf.c
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:29 2013
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstract:
|
||||
* MATLAB for code generation function to initialize non-finite, Inf and MinusInf
|
||||
*/
|
||||
#include "rtGetInf.h"
|
||||
#define NumBitsPerChar 8U
|
||||
|
||||
/* Function: rtGetInf ==================================================
|
||||
* Abstract:
|
||||
* Initialize rtInf needed by the generated code.
|
||||
* Inf is initialized as non-signaling. Assumes IEEE.
|
||||
*/
|
||||
real_T rtGetInf(void)
|
||||
{
|
||||
size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar);
|
||||
real_T inf = 0.0;
|
||||
if (bitsPerReal == 32U) {
|
||||
inf = rtGetInfF();
|
||||
} else {
|
||||
uint16_T one = 1U;
|
||||
enum {
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
} machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian;
|
||||
switch (machByteOrder) {
|
||||
case LittleEndian:
|
||||
{
|
||||
union {
|
||||
LittleEndianIEEEDouble bitVal;
|
||||
real_T fltVal;
|
||||
} tmpVal;
|
||||
|
||||
tmpVal.bitVal.words.wordH = 0x7FF00000U;
|
||||
tmpVal.bitVal.words.wordL = 0x00000000U;
|
||||
inf = tmpVal.fltVal;
|
||||
break;
|
||||
}
|
||||
|
||||
case BigEndian:
|
||||
{
|
||||
union {
|
||||
BigEndianIEEEDouble bitVal;
|
||||
real_T fltVal;
|
||||
} tmpVal;
|
||||
|
||||
tmpVal.bitVal.words.wordH = 0x7FF00000U;
|
||||
tmpVal.bitVal.words.wordL = 0x00000000U;
|
||||
inf = tmpVal.fltVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inf;
|
||||
}
|
||||
|
||||
/* Function: rtGetInfF ==================================================
|
||||
* Abstract:
|
||||
* Initialize rtInfF needed by the generated code.
|
||||
* Inf is initialized as non-signaling. Assumes IEEE.
|
||||
*/
|
||||
real32_T rtGetInfF(void)
|
||||
{
|
||||
IEEESingle infF;
|
||||
infF.wordL.wordLuint = 0x7F800000U;
|
||||
return infF.wordL.wordLreal;
|
||||
}
|
||||
|
||||
/* Function: rtGetMinusInf ==================================================
|
||||
* Abstract:
|
||||
* Initialize rtMinusInf needed by the generated code.
|
||||
* Inf is initialized as non-signaling. Assumes IEEE.
|
||||
*/
|
||||
real_T rtGetMinusInf(void)
|
||||
{
|
||||
size_t bitsPerReal = sizeof(real_T) * (NumBitsPerChar);
|
||||
real_T minf = 0.0;
|
||||
if (bitsPerReal == 32U) {
|
||||
minf = rtGetMinusInfF();
|
||||
} else {
|
||||
uint16_T one = 1U;
|
||||
enum {
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
} machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian;
|
||||
switch (machByteOrder) {
|
||||
case LittleEndian:
|
||||
{
|
||||
union {
|
||||
LittleEndianIEEEDouble bitVal;
|
||||
real_T fltVal;
|
||||
} tmpVal;
|
||||
|
||||
tmpVal.bitVal.words.wordH = 0xFFF00000U;
|
||||
tmpVal.bitVal.words.wordL = 0x00000000U;
|
||||
minf = tmpVal.fltVal;
|
||||
break;
|
||||
}
|
||||
|
||||
case BigEndian:
|
||||
{
|
||||
union {
|
||||
BigEndianIEEEDouble bitVal;
|
||||
real_T fltVal;
|
||||
} tmpVal;
|
||||
|
||||
tmpVal.bitVal.words.wordH = 0xFFF00000U;
|
||||
tmpVal.bitVal.words.wordL = 0x00000000U;
|
||||
minf = tmpVal.fltVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return minf;
|
||||
}
|
||||
|
||||
/* Function: rtGetMinusInfF ==================================================
|
||||
* Abstract:
|
||||
* Initialize rtMinusInfF needed by the generated code.
|
||||
* Inf is initialized as non-signaling. Assumes IEEE.
|
||||
*/
|
||||
real32_T rtGetMinusInfF(void)
|
||||
{
|
||||
IEEESingle minfF;
|
||||
minfF.wordL.wordLuint = 0xFF800000U;
|
||||
return minfF.wordL.wordLreal;
|
||||
}
|
||||
|
||||
/* End of code generation (rtGetInf.c) */
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* rtGetInf.h
|
||||
*
|
||||
* Code generation for function 'kalman_dlqe2'
|
||||
*
|
||||
* C source code generated on: Thu Feb 14 12:52:29 2013
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __RTGETINF_H__
|
||||
#define __RTGETINF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "rtwtypes.h"
|
||||
#include "rt_nonfinite.h"
|
||||
|
||||
extern real_T rtGetInf(void);
|
||||
extern real32_T rtGetInfF(void);
|
||||
extern real_T rtGetMinusInf(void);
|
||||
extern real32_T rtGetMinusInfF(void);
|
||||
|
||||
#endif
|
||||
/* End of code generation (rtGetInf.h) */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user