From b23f1151869fa715003eac50db927b906183e080 Mon Sep 17 00:00:00 2001 From: James Goppert <jgoppert@w7.hsl.dynalias.com> Date: Tue, 16 Aug 2011 21:19:21 -0400 Subject: [PATCH] Added gui. --- Makefile.am | 2 +- autotroll.m4 | 565 +++++++++++++++++++++++ autotroll.mk | 108 +++++ configure.in | 5 + gui/MainWindow.cpp | 467 +++++++++++++++++++ gui/MainWindow.hpp | 140 ++++++ gui/MainWindow.moc.cpp | 220 +++++++++ gui/MainWindow.ui | 917 ++++++++++++++++++++++++++++++++++++++ gui/MainWindow.ui.h | 915 +++++++++++++++++++++++++++++++++++++ gui/Makefile.am | 16 + gui/QOSGAdapterWidget.cpp | 194 ++++++++ gui/QOSGAdapterWidget.hpp | 147 ++++++ gui/Viewer.cpp | 76 ++++ gui/Viewer.hpp | 72 +++ gui/main.cc | 16 + gui/main.cpp | 14 + gui/osgUtils.cpp | 591 ++++++++++++++++++++++++ gui/osgUtils.hpp | 224 ++++++++++ gui/qt_main.cpp | 71 +++ gui/textures.qrc | 5 + 20 files changed, 4764 insertions(+), 1 deletion(-) create mode 100644 autotroll.m4 create mode 100644 autotroll.mk create mode 100644 gui/MainWindow.cpp create mode 100644 gui/MainWindow.hpp create mode 100644 gui/MainWindow.moc.cpp create mode 100644 gui/MainWindow.ui create mode 100644 gui/MainWindow.ui.h create mode 100644 gui/Makefile.am create mode 100644 gui/QOSGAdapterWidget.cpp create mode 100644 gui/QOSGAdapterWidget.hpp create mode 100644 gui/Viewer.cpp create mode 100644 gui/Viewer.hpp create mode 100644 gui/main.cc create mode 100644 gui/main.cpp create mode 100644 gui/osgUtils.cpp create mode 100644 gui/osgUtils.hpp create mode 100644 gui/qt_main.cpp create mode 100644 gui/textures.qrc diff --git a/Makefile.am b/Makefile.am index e9ccc70..7ea801f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src systems aircraft engine scripts data_output data_plot check_cases +SUBDIRS = src gui systems aircraft engine scripts data_output data_plot check_cases dist-hook: (cd $(top_srcdir)) diff --git a/autotroll.m4 b/autotroll.m4 new file mode 100644 index 0000000..5037197 --- /dev/null +++ b/autotroll.m4 @@ -0,0 +1,565 @@ +# Build Qt apps with the autotools (Autoconf/Automake). +# M4 macros. +# This file is part of AutoTroll. +# Copyright (C) 2006 Benoit Sigoure <benoit.sigoure@lrde.epita.fr> +# +# AutoTroll is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# In addition, as a special exception, the copyright holders of AutoTroll +# give you unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the macros of +# AutoTroll. You need not follow the terms of the GNU General Public License +# when using or distributing such scripts, even though portions of the text of +# AutoTroll appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes AutoTroll. +# +# This special exception to the GPL applies to versions of AutoTroll +# released by the copyright holders of AutoTroll. Note that people who make +# modified versions of AutoTroll are not obligated to grant this special +# exception for their modified versions; it is their choice whether to do so. +# The GNU General Public License gives permission to release a modified version +# without this exception; this exception also makes it possible to release a +# modified version which carries forward this exception. + + # ------------- # + # DOCUMENTATION # + # ------------- # + +# Disclaimer: Never tested with anything else than Qt 4.2! Feedback welcome. +# Simply invoke AT_WITH_QT in your configure.ac. AT_WITH_QT can take +# arguments which are documented in depth below. The default arguments are +# equivalent to the default .pro file generated by qmake. +# +# Invoking AT_WITH_QT will do the following: +# - Add a --with-qt option to your configure +# - Find qmake, moc and uic and save them in the make variables $(QMAKE), +# $(MOC), $(UIC). +# - Save the path to Qt in $(QT_PATH) +# - Find the flags to use Qt, that is: +# * $(QT_DEFINES): -D's defined by qmake. +# * $(QT_CFLAGS): CFLAGS as defined by qmake (C?!) +# * $(QT_CXXFLAGS): CXXFLAGS as defined by qmake. +# * $(QT_INCPATH): -I's defined by qmake. +# * $(QT_CPPFLAGS): Same as $(QT_DEFINES) + $(QT_INCPATH) +# * $(QT_LFLAGS): LFLAGS defined by qmake. +# * $(QT_LDFLAGS): Same thing as $(QT_LFLAGS). +# * $(QT_LIBS): LIBS defined by qmake. +# +# You *MUST* invoke $(MOC) and/or $(UIC) where necessary. AutoTroll provides +# you with Makerules to ease this, here is a sample Makefile.am to use with +# AutoTroll which builds the code given in the chapter 7 of the Qt Tutorial: +# http://doc.trolltech.com/4.2/tutorial-t7.html +# +# ------------------------------------------------------------------------- +# include $(top_srcdir)/build-aux/autotroll.mk +# +# ACLOCAL_AMFLAGS = -I build-aux +# +# bin_PROGRAMS = lcdrange +# lcdrange_SOURCES = $(BUILT_SOURCES) lcdrange.cpp lcdrange.h main.cpp +# lcdrange_CXXFLAGS = $(QT_CXXFLAGS) $(AM_CXXFLAGS) +# lcdrange_CPPFLAGS = $(QT_CPPFLAGS) $(AM_CPPFLAGS) +# lcdrange_LDFLAGS = $(QT_LDFLAGS) $(LDFLAGS) +# lcdrange_LDADD = $(QT_LIBS) $(LDADD) +# +# BUILT_SOURCES = lcdrange.moc.cpp +# ------------------------------------------------------------------------- +# +# Note that your MOC, UIC and QRC files *MUST* be listed manually in +# BUILT_SOURCES. If you name them properly (eg: .moc.cc, .qrc.cc, .ui.cc -- of +# course you can use .cpp or .cxx or .C rather than .cc) AutoTroll will build +# them automagically for you (using implicit rules defined in autotroll.mk). + +m4_define([_AUTOTROLL_SERIAL], [m4_translit([ +# serial 5 +], [# +], [])]) + + +m4_ifdef([AX_INSTEAD_IF], [], +[AC_DEFUN([AX_INSTEAD_IF], + [m4_ifval([$1], + [AC_MSG_WARN([$2]); [$1]], + [AC_MSG_ERROR([$2])])])]) + +m4_pattern_forbid([^AT_])dnl +m4_pattern_forbid([^_AT_])dnl + +# AT_WITH_QT([QT_modules], [QT_config], [QT_misc], [RUN-IF-FAILED], [RUN-IF-OK]) +# ------------------------------------------------------------------------------ +# Enable Qt support and add an option --with-qt to the configure script. +# +# The QT_modules argument is optional and defines extra modules to enable or +# disable (it's equivalent to the QT variable in .pro files). Modules can be +# specified as follows: +# +# AT_WITH_QT => No argument -> No QT value. +# Qmake sets it to "core gui" by default. +# AT_WITH_QT([xml]) => QT += xml +# AT_WITH_QT([+xml]) => QT += xml +# AT_WITH_QT([-gui]) => QT -= gui +# AT_WITH_QT([xml -gui +sql svg]) => QT += xml sql svg +# QT -= gui +# +# The QT_config argument is also optional and follows the same convention as +# QT_modules. Instead of changing the QT variable, it changes the CONFIG +# variable, which is used to tweak configuration and compiler options. +# +# The last argument, QT_misc (also optional) will be copied as-is the .pro +# file used to guess how to compile Qt apps. You may use it to further tweak +# the build process of Qt apps if tweaking the QT or CONFIG variables isn't +# enough for you. +# +# RUN-IF-FAILED is arbitrary code to execute if Qt cannot be found or if any +# problem happens. If this argument is omitted, then AC_MSG_ERROR will be +# called. RUN-IF-OK is arbitrary code to execute if Qt was successfully found. +AC_DEFUN([AT_WITH_QT], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CXX])dnl +echo "$as_me: this is autotroll.m4[]_AUTOTROLL_SERIAL" >&AS_MESSAGE_LOG_FD + + test x"$TROLL" != x && echo 'ViM rox emacs.' + +dnl Memo: AC_ARG_WITH(package, help-string, [if-given], [if-not-given]) + AC_ARG_WITH([qt], + [AS_HELP_STRING([--with-qt], + [Path to Qt @<:@Look in PATH and /usr/local/Trolltech@:>@])], + [QT_PATH=$withval]) + + # this is a hack to get decent flow control with 'break' + for _qt_ignored in once; do + + # Find Qt. + AC_ARG_VAR([QT_PATH], [Path to the Qt installation]) + if test -d /usr/local/Trolltech; then + # Try to find the latest version. + tmp_qt_paths=`echo /usr/local/Trolltech/*/bin | tr ' ' '\n' | sort -nr \ + | xargs | sed 's/ */:/g'` + fi + # Path to which recent MacPorts (~v1.7) install Qt4. + test -d /opt/local/libexec/qt4-mac/bin \ + && tmp_qt_paths="$tmp_qt_paths:/opt/local/libexec/qt4-mac/bin" + + # Find qmake. + AC_ARG_VAR([QMAKE], [Qt Makefile generator command]) + AC_PATH_PROGS([QMAKE], [qmake qmake-qt4 qmake-qt3], [missing], + [$QT_DIR:$QT_PATH:$PATH:$tmp_qt_paths]) + if test x"$QMAKE" = xmissing; then + AX_INSTEAD_IF([$4], [Cannot find qmake in your PATH. Try using --with-qt.]) + break + fi + + # Find moc (Meta Object Compiler). + AC_ARG_VAR([MOC], [Qt Meta Object Compiler command]) + AC_PATH_PROGS([MOC], [moc moc-qt4 moc-qt3], [missing], + [$QT_PATH:$PATH:$tmp_qt_paths]) + if test x"$MOC" = xmissing; then + AX_INSTEAD_IF([$4], + [Cannot find moc (Meta Object Compiler) in your PATH. Try using --with-qt.]) + break + fi + + # Find uic (User Interface Compiler). + AC_ARG_VAR([UIC], [Qt User Interface Compiler command]) + AC_PATH_PROGS([UIC], [uic uic-qt4 uic-qt3 uic3], [missing], + [$QT_PATH:$PATH:$tmp_qt_paths]) + if test x"$UIC" = xmissing; then + AX_INSTEAD_IF([$4], +[Cannot find uic (User Interface Compiler) in your PATH. Try using --with-qt.]) + break + fi + + # Find rcc (Qt Resource Compiler). + AC_ARG_VAR([RCC], [Qt Resource Compiler command]) + AC_PATH_PROGS([RCC], [rcc], [false], [$QT_PATH:$PATH:$tmp_qt_paths]) + if test x"$UIC" = xfalse; then + AC_MSG_WARN([Cannot find rcc (Qt Resource Compiler) in your PATH.\ + Try using --with-qt.]) + fi + + AC_MSG_CHECKING([whether host operating system is Darwin]) + at_darwin=no + at_qmake_args= + case $host_os in + darwin*) + at_darwin=yes + at_qmake_args='-spec macx-g++' + ;; + esac + AC_MSG_RESULT([$at_darwin]) + + # If we don't know the path to Qt, guess it from the path to qmake. + if test x"$QT_PATH" = x; then + QT_PATH=`dirname "$QMAKE"` + fi + if test x"$QT_PATH" = x; then + AX_INSTEAD_IF([$4], + [Cannot find the path to your Qt install. Use --with-qt.]) + break + fi + AC_SUBST([QT_PATH]) + + # Get ready to build a test-app with Qt. + if mkdir conftest.dir && cd conftest.dir; then :; else + AX_INSTEAD_IF([$4], [Cannot mkdir conftest.dir or cd to that directory.]) + break + fi + + cat >conftest.h <<_ASEOF +#include <QObject> + +class Foo: public QObject +{ + Q_OBJECT; +public: + Foo(); + ~Foo() {} +public Q_SLOTS: + void setValue(int value); +Q_SIGNALS: + void valueChanged(int newValue); +private: + int value_; +}; +_ASEOF + + cat >conftest.cpp <<_ASEOF +#include "conftest.h" +Foo::Foo() + : value_ (42) +{ + connect(this, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); +} + +void Foo::setValue(int value) +{ + value_ = value; +} + +int main() +{ + Foo f; +} +_ASEOF + if $QMAKE -project; then :; else + AX_INSTEAD_IF([$4], [Calling $QMAKE -project failed.]) + break + fi + + # Find the .pro file generated by qmake. + pro_file='conftest.dir.pro' + test -f $pro_file || pro_file=`echo *.pro` + if test -f "$pro_file"; then :; else + AX_INSTEAD_IF([$4], [Can't find the .pro file generated by Qmake.]) + break + fi + +dnl Tweak the value of QT in the .pro if have been the 1st arg. +m4_ifval([$1], [_AT_TWEAK_PRO_FILE([QT], [$1])]) + +dnl Tweak the value of CONFIG in the .pro if have been given a 2nd arg. +m4_ifval([$2], [_AT_TWEAK_PRO_FILE([CONFIG], [$2])]) + +m4_ifval([$3], +[ # Add the extra-settings the user wants to set in the .pro + echo "$3" >>"$pro_file" +]) + + echo "$as_me:$LINENO: Invoking $QMAKE on $pro_file" >&AS_MESSAGE_LOG_FD + sed 's/^/| /' "$pro_file" >&AS_MESSAGE_LOG_FD + + if $QMAKE $at_qmake_args; then :; else + AX_INSTEAD_IF([$4], [Calling $QMAKE $at_qmake_args failed.]) + break + fi + + # QMake has a very annoying misfeature: sometimes it generates Makefiles + # where all the references to the files from the Qt installation are + # relative. We can't use them as-is because if we take, say, a + # -I../../usr/include/Qt from that Makefile, the flag is invalid as soon + # as we use it in another (sub) directory. So what this perl pass does is + # that it rewrite all relative paths to absolute paths. Another problem + # when building on Cygwin is that QMake mixes paths with blackslashes and + # forward slashes and paths must be handled with extra care because of the + # stupid Windows drive letters. + echo "$as_me:$LINENO: fixing the Makefiles:" Makefile* >&AS_MESSAGE_LOG_FD + cat >fixmk.pl <<\EOF +[use strict; +use Cwd qw(cwd abs_path); +# This variable is useful on Cygwin for the following reason: Say that you are +# in `/' (that is, in fact you are in C:/cygwin, or something like that) if you +# `cd ..' then obviously you remain in `/' (that is in C:/cygwin). QMake +# generates paths that are relative to C:/ (or another driver letter, whatever) +# so the trick to get the `..' resolved properly is to prepend the absolute +# path of the current working directory in a Windows-style. C:/cygwin/../ will +# properly become C:/. +my $d = ""; +my $r2a = 0; +my $b2f = 0; + +my $cygwin = 0; +if ($^O eq "cygwin") { + $cygwin = 1; + $d = cwd(); + $d = `cygpath --mixed '$d'`; + chomp($d); + $d .= "/"; +} + +sub rel2abs($) +{ + my $p = $d . shift; + # print "r2a p=$p"; + -e $p || return $p; + if ($cygwin) { + $p = `cygpath --mixed '$p'`; + chomp($p); + } + else { + # Do not use abs_path on Cygwin: it incorrectly resolves the paths that are + # relative to C:/ rather than `/'. + $p = abs_path($p); + } + # print " -> $p\n"; + ++$r2a; + return $p; +} + +# Only useful on Cygwin. +sub back2forward($) +{ + my $p = shift; + # print "b2f p=$p"; + -e $p || return $p; + $p = `cygpath --mixed '$p'`; + chomp($p); + # print " -> $p\n"; + ++$b2f; + return $p; +} + +foreach my $mk (@ARGV) +{ + next if $mk =~ /~$/; + open(MK, $mk) or die("open $mk: $!"); + # print "mk=$mk\n"; + my $file = join("", <MK>); + close(MK) or die("close $mk: $!"); + rename $mk, $mk . "~" or die("rename $mk: $!"); + $file =~ s{(?:\.\.[\\/])+(?:[^"'\s:]+)}{rel2abs($&)}gse; + $file =~ s{(?:[a-zA-Z]:[\\/])?(?:[^"\s]+\\[^"\s:]+)+} + {back2forward($&)}gse if $cygwin; + open(MK, ">", $mk) or die("open >$mk: $!"); + print MK $file; + close(MK) or die("close >$mk: $!"); + print "$mk: updated $r2a relative paths and $b2f backslash-style paths\n"; + $r2a = 0; + $b2f = 0; +}] +EOF + + perl >&AS_MESSAGE_LOG_FD -w fixmk.pl Makefile* || + AC_MSG_WARN([failed to fix the Makefiles generated by $QMAKE]) + rm -f fixmk.pl + + # Try to compile a simple Qt app. + AC_CACHE_CHECK([whether we can build a simple Qt app], [at_cv_qt_build], + [at_cv_qt_build=ko + : ${MAKE=make} + + if $MAKE >&AS_MESSAGE_LOG_FD 2>&1; then + at_cv_qt_build='ok, looks like Qt 4' + else + echo "$as_me:$LINENO: Build failed, trying to #include <qobject.h> \ +instead" >&AS_MESSAGE_LOG_FD + sed 's/<QObject>/<qobject.h>/' conftest.h > tmp.h && mv tmp.h conftest.h + if $MAKE >&AS_MESSAGE_LOG_FD 2>&1; then + at_cv_qt_build='ok, looks like Qt 3' + else + # Sometimes (such as on Debian) build will fail because Qt hasn't been + # installed in debug mode and qmake tries (by default) to build apps in + # debug mode => Try again in release mode. + echo "$as_me:$LINENO: Build failed, trying to enforce release mode" \ + >&AS_MESSAGE_LOG_FD + + _AT_TWEAK_PRO_FILE([CONFIG], [+release]) + + sed 's/<qobject.h>/<QObject>/' conftest.h > tmp.h && mv tmp.h conftest.h + if $MAKE >&AS_MESSAGE_LOG_FD 2>&1; then + at_cv_qt_build='ok, looks like Qt 4, release mode forced' + else + echo "$as_me:$LINENO: Build failed, trying to #include <qobject.h> \ +instead" >&AS_MESSAGE_LOG_FD + sed 's/<QObject>/<qobject.h>/' conftest.h >tmp.h && mv tmp.h conftest.h + if $MAKE >&AS_MESSAGE_LOG_FD 2>&1; then + at_cv_qt_build='ok, looks like Qt 3, release mode forced' + else + at_cv_qt_build=ko + echo "$as_me:$LINENO: failed program was:" >&AS_MESSAGE_LOG_FD + sed 's/^/| /' conftest.h >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: failed program was:" >&AS_MESSAGE_LOG_FD + sed 's/^/| /' conftest.cpp >&AS_MESSAGE_LOG_FD + fi # if make with Qt3-style #include and release mode forced. + fi # if make with Qt4-style #include and release mode forced. + fi # if make with Qt3-style #include. + fi # if make with Qt4-style #include. + ])dnl end: AC_CACHE_CHECK(at_cv_qt_build) + + if test x"$at_cv_qt_build" = xko; then + AX_INSTEAD_IF([$4], [Cannot build a test Qt program]) + cd .. + break + fi + QT_VERSION_MAJOR=`echo "$at_cv_qt_build" | sed 's/[[^0-9]]*//g'` + AC_SUBST([QT_VERSION_MAJOR]) + + # This sed filter is applied after an expression of the form: /^FOO.*=/!d; + # It starts by removing the beginning of the line, removing references to + # SUBLIBS, removing unnecessary whitespaces at the beginning, and prefixes + # all variable uses by QT_. + qt_sed_filter='s///; + s/$(SUBLIBS)//g; + s/^ *//; + s/\$(\(@<:@A-Z_@:>@@<:@A-Z_@:>@*\))/$(QT_\1)/g' + + # Find the Makefile (qmake happens to generate a fake Makefile which invokes + # a Makefile.Debug or Makefile.Release). We we have both, we'll pick the + # Makefile.Release. The reason is that the main difference is that release + # uses -Os and debug -g. We can override -Os by passing another -O but we + # usually don't override -g. + if test -f Makefile.Release; then + at_mfile='Makefile.Release' + else + at_mfile='Makefile' + fi + if test -f $at_mfile; then :; else + AX_INSTEAD_IF([$4], [Cannot find the Makefile generated by qmake.]) + cd .. + break + fi + + # Find the DEFINES of Qt (should have been named CPPFLAGS). + AC_CACHE_CHECK([for the DEFINES to use with Qt], [at_cv_env_QT_DEFINES], + [at_cv_env_QT_DEFINES=`sed "/^DEFINES@<:@^A-Z=@:>@*=/!d;$qt_sed_filter" $at_mfile`]) + AC_SUBST([QT_DEFINES], [$at_cv_env_QT_DEFINES]) + + # Find the CFLAGS of Qt (We can use Qt in C?!) + AC_CACHE_CHECK([for the CFLAGS to use with Qt], [at_cv_env_QT_CFLAGS], + [at_cv_env_QT_CFLAGS=`sed "/^CFLAGS@<:@^A-Z=@:>@*=/!d;$qt_sed_filter" $at_mfile`]) + AC_SUBST([QT_CFLAGS], [$at_cv_env_QT_CFLAGS]) + + # Find the CXXFLAGS of Qt. + AC_CACHE_CHECK([for the CXXFLAGS to use with Qt], [at_cv_env_QT_CXXFLAGS], + [at_cv_env_QT_CXXFLAGS=`sed "/^CXXFLAGS@<:@^A-Z=@:>@*=/!d;$qt_sed_filter" $at_mfile`]) + AC_SUBST([QT_CXXFLAGS], [$at_cv_env_QT_CXXFLAGS]) + + # Find the INCPATH of Qt. + AC_CACHE_CHECK([for the INCPATH to use with Qt], [at_cv_env_QT_INCPATH], + [at_cv_env_QT_INCPATH=`sed "/^INCPATH@<:@^A-Z=@:>@*=/!d;$qt_sed_filter" $at_mfile`]) + AC_SUBST([QT_INCPATH], [$at_cv_env_QT_INCPATH]) + + AC_SUBST([QT_CPPFLAGS], ["$at_cv_env_QT_DEFINES $at_cv_env_QT_INCPATH"]) + + # Find the LFLAGS of Qt (Should have been named LDFLAGS) + AC_CACHE_CHECK([for the LDFLAGS to use with Qt], [at_cv_env_QT_LDFLAGS], + [at_cv_env_QT_LDFLAGS=`sed "/^LFLAGS@<:@^A-Z=@:>@*=/!d;$qt_sed_filter" $at_mfile`]) + AC_SUBST([QT_LFLAGS], [$at_cv_env_QT_LDFLAGS]) + AC_SUBST([QT_LDFLAGS], [$at_cv_env_QT_LDFLAGS]) + + # Find the LIBS of Qt. + AC_CACHE_CHECK([for the LIBS to use with Qt], [at_cv_env_QT_LIBS], + [at_cv_env_QT_LIBS=`sed "/^LIBS@<:@^A-Z@:>@*=/!d;$qt_sed_filter" $at_mfile` + if test x$at_darwin = xyes; then + # Fix QT_LIBS: as of today Libtool (GNU Libtool 1.5.23a) doesn't handle + # -F properly. The "bug" has been fixed on 22 October 2006 + # by Peter O'Gorman but we provide backward compatibility here. + at_cv_env_QT_LIBS=`echo "$at_cv_env_QT_LIBS" \ + | sed 's/^-F/-Wl,-F/;s/ -F/ -Wl,-F/g'` + fi + ]) + AC_SUBST([QT_LIBS], [$at_cv_env_QT_LIBS]) + + cd .. && rm -rf conftest.dir + + # Run the user code + $5 + + done # end hack (useless for to be able to use break) +]) + +# AT_REQUIRE_QT_VERSION(QT_version, RUN-IF-FAILED, RUN-IF-OK) +# ----------------------------------------------------------- +# Check (using qmake) that Qt's version "matches" QT_version. +# Must be run AFTER AT_WITH_QT. Requires autoconf 2.60. +# +# RUN-IF-FAILED is arbitrary code to execute if Qt cannot be found or if any +# problem happens. If this argument is omitted, then AC_MSG_ERROR will be +# called. RUN-IF-OK is arbitrary code to execute if Qt was successfully found. +AC_DEFUN([AT_REQUIRE_QT_VERSION], +[ AC_PREREQ([2.60]) + # this is a hack to get decent flow control with 'break' + for _qt_ignored in once; do + + if test x"$QMAKE" = x; then + AX_INSTEAD_IF([$2], + [\$QMAKE is empty.\ + Did you invoke AT@&t@_WITH_QT before AT@&t@_REQUIRE_QT_VERSION?]) + break + fi + AC_CACHE_CHECK([for Qt's version], [at_cv_QT_VERSION], + [echo "$as_me:$LINENO: Running $QMAKE --version:" >&AS_MESSAGE_LOG_FD + $QMAKE --version >&AS_MESSAGE_LOG_FD 2>&1 + qmake_version_sed=['/^.*\([0-9]\.[0-9]\.[0-9]\).*$/!d;s//\1/'] + at_cv_QT_VERSION=`$QMAKE --version 2>&1 | sed "$qmake_version_sed"`]) + if test x"$at_cv_QT_VERSION" = x; then + AX_INSTEAD_IF([$2], [Cannot detect Qt's version.]) + break + fi + AC_SUBST([QT_VERSION], [$at_cv_QT_VERSION]) + AS_VERSION_COMPARE([$QT_VERSION], [$1], + [AX_INSTEAD_IF([$2; break;], [This package requires Qt $1 or above.])]) + + # Run the user code + $3 + + done # end hack (useless for to be able to use break) +]) + +# _AT_TWEAK_PRO_FILE(QT_VAR, VALUE) +# --------------------------- +# @internal. Tweak the variable QT_VAR in the .pro. +# VALUE is an IFS-separated list of value and each value is rewritten +# as follows: +# +value => QT_VAR += value +# -value => QT_VAR -= value +# value => QT_VAR += value +AC_DEFUN([_AT_TWEAK_PRO_FILE], +[ # Tweak the value of $1 in the .pro file for $2. + + qt_conf='' + for at_mod in $2; do + at_mod=`echo "$at_mod" | sed 's/^-//; tough + s/^+//; beef + :ough + s/^/$1 -= /;n + :eef + s/^/$1 += /'` + qt_conf="$qt_conf +$at_mod" + done + echo "$qt_conf" | sed 1d >>"$pro_file" +]) diff --git a/autotroll.mk b/autotroll.mk new file mode 100644 index 0000000..45d6cf3 --- /dev/null +++ b/autotroll.mk @@ -0,0 +1,108 @@ +# Makerules. +# This file is part of AutoTroll. +# Copyright (C) 2006, 2007, 2009, 2010 Benoit Sigoure. +# +# AutoTroll is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# In addition, as a special exception, the copyright holders of AutoTroll +# give you unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the macros of +# AutoTroll. You need not follow the terms of the GNU General Public License +# when using or distributing such scripts, even though portions of the text of +# AutoTroll appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes AutoTroll. +# +# This special exception to the GPL applies to versions of AutoTroll +# released by the copyright holders of AutoTroll. Note that people who make +# modified versions of AutoTroll are not obligated to grant this special +# exception for their modified versions; it is their choice whether to do so. +# The GNU General Public License gives permission to release a modified version +# without this exception; this exception also makes it possible to release a +# modified version which carries forward this exception. + + # ------------- # + # DOCUMENTATION # + # ------------- # + +# See autotroll.m4 :) + + +SUFFIXES = .moc.cpp .moc.cc .moc.cxx .moc.C .h .hh .hpp \ + .ui .ui.h .ui.hh .ui.hpp \ + .qrc .qrc.cpp .qrc.cc .qrc.cxx .qrc.C + +# --- # +# MOC # +# --- # + +.hpp.moc.cpp: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.hh.moc.cpp: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.h.moc.cpp: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ + +.hpp.moc.cc: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.hh.moc.cc: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.h.moc.cc: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ + +.hpp.moc.cxx: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.hh.moc.cxx: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.h.moc.cxx: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ + +.hpp.moc.C: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.hh.moc.C: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ +.h.moc.C: + $(MOC) $(QT_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $@ + +# --- # +# UIC # +# --- # + +.ui.ui.hpp: + $(UIC) $< -o $@ + +.ui.ui.hh: + $(UIC) $< -o $@ + +.ui.ui.h: + $(UIC) $< -o $@ + +# --- # +# RCC # +# --- # + +.qrc.qrc.cpp: + $(RCC) -name `echo "$<" | sed 's|^.*/\(.*\)\.qrc$$|\1|'` $< -o $@ + +.qrc.qrc.cc: + $(RCC) -name `echo "$<" | sed 's|^.*/\(.*\)\.qrc$$|\1|'` $< -o $@ + +.qrc.qrc.cxx: + $(RCC) -name `echo "$<" | sed 's|^.*/\(.*\)\.qrc$$|\1|'` $< -o $@ + +.qrc.qrc.C: + $(RCC) -name `echo "$<" | sed 's|^.*/\(.*\)\.qrc$$|\1|'` $< -o $@ + +DISTCLEANFILES = $(BUILT_SOURCES) diff --git a/configure.in b/configure.in index 225fdd0..a6525da 100644 --- a/configure.in +++ b/configure.in @@ -4,6 +4,7 @@ AC_INIT(JSBSim.cpp, 1.0.rc3-advtrim-7, jon@jsbsim.org) dnl set the $host variable based on local machine/os AC_CANONICAL_TARGET +AC_CONFIG_AUX_DIR([m4]) AM_INIT_AUTOMAKE(jsbsim, 1.0.rc3-advtrim-7) AC_CONFIG_MACRO_DIR([m4]) @@ -105,6 +106,9 @@ AC_DEFINE(socklen_t,size_t)], [ AC_MSG_RESULT(int) AC_DEFINE(socklen_t,int)])]) +# AutoTroll with Qt +AT_WITH_QT([gui opengl]) + AC_OUTPUT( jsbsim.pc Makefile @@ -143,6 +147,7 @@ AC_OUTPUT( src/simgear/props/Makefile src/simgear/magvar/Makefile src/simgear/misc/Makefile + gui/Makefile engine/Makefile data_output/Makefile scripts/Makefile diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp new file mode 100644 index 0000000..eb43d9d --- /dev/null +++ b/gui/MainWindow.cpp @@ -0,0 +1,467 @@ +/* + * MainWindow.cpp + * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> + * + * MainWindow.cpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MainWindow.cpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "MainWindow.hpp" +#include <QFileDialog> +#include <QMessageBox> +#include <osg/Vec3d> + +#include <cstdlib> +#include <fstream> +#include <models/FGAircraft.h> +#include <models/propulsion/FGEngine.h> +#include <models/propulsion/FGTurbine.h> +#include <models/propulsion/FGTurboProp.h> + +MainWindow::MainWindow() : sceneRoot(new osg::Group), + callback(new SolverCallback(this)), trimThread(this), simThread(this), + ss(NULL), trimmer(NULL), fdm(NULL) +{ + setupUi(this); + viewer->setSceneData(sceneRoot); + viewer->setCameraManipulator(new osgGA::TrackballManipulator); + viewer->getCameraManipulator()->setHomePosition(osg::Vec3d(30,30,-30),osg::Vec3d(0,0,0),osg::Vec3d(0,0,-1),false); + viewer->getCameraManipulator()->home(0); + sceneRoot->addChild(new mavsim::visualization::Frame(20,"N","E","D")); + + // read initial settings + QCoreApplication::setOrganizationName("openmav"); + QCoreApplication::setOrganizationDomain("github.com/mavsim"); + QCoreApplication::setApplicationName("mavsim"); + + settings = new QSettings; + readSettings(); + writeSettings(); + + // load plane + try + { + plane = new mavsim::visualization::Plane; + plane->addChild(new mavsim::visualization::Frame(15,"X","Y","Z")); + sceneRoot->addChild(plane); + } + catch(const std::exception & e) + { + showMsg(e.what()); + } + + // connect signals and slots + connect(this,SIGNAL(showMsgBuffered(const QString &)), + this,SLOT(showMsg(const QString &)),Qt::QueuedConnection); +} + +MainWindow::~MainWindow() +{ + writeSettings(); + delete viewer; +} + +void MainWindow::writeSettings() +{ + settings->beginGroup("mainwindow"); + settings->setValue("enginePath",lineEdit_enginePath->text()); + settings->setValue("systemsPath",lineEdit_systemsPath->text()); + settings->setValue("aircraftPath",lineEdit_aircraftPath->text()); + settings->setValue("aircraft",lineEdit_aircraft->text()); + settings->setValue("initScript",lineEdit_initScript->text()); + settings->endGroup(); +} + +void MainWindow::readSettings() +{ + QString root(DATADIR); + settings->beginGroup("mainwindow"); + lineEdit_enginePath->setText(settings->value("enginePath",root+"/easystar/Engine").toString()); + lineEdit_systemsPath->setText(settings->value("systemsPath",root+"/easystar/Systems").toString()); + lineEdit_aircraftPath->setText(settings->value("aircraftPath",root+"/easystar").toString()); + lineEdit_aircraft->setText(settings->value("aircraft","easystar-windtunnel").toString()); + lineEdit_initScript->setText(settings->value("initScript","").toString()); + settings->endGroup(); +} + +void MainWindow::on_toolButton_enginePath_pressed() +{ + lineEdit_enginePath->setText(QFileDialog::getExistingDirectory( + this, tr("Select Engine Path"), + lineEdit_enginePath->text(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)); +} + +void MainWindow::on_toolButton_systemsPath_pressed() +{ + lineEdit_systemsPath->setText(QFileDialog::getExistingDirectory( + this, tr("Select Systems Path"), + lineEdit_systemsPath->text(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)); +} + +void MainWindow::on_toolButton_aircraftPath_pressed() +{ + lineEdit_aircraftPath->setText(QFileDialog::getExistingDirectory( + this, tr("Select Aircraft Path"), + lineEdit_aircraftPath->text(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)); +} + +void MainWindow::on_toolButton_aircraft_pressed() +{ + QString path(QFileDialog::getExistingDirectory( + this, tr("Select Aircraft Directory"), + lineEdit_aircraftPath->text(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)); + if (!path.isNull()) + { + QFileInfo pathInfo(path); + lineEdit_aircraft->setText(pathInfo.fileName()); + } +} + +void MainWindow::on_toolButton_initScript_pressed() +{ + lineEdit_initScript->setText(QFileDialog::getOpenFileName(this, + tr("Select Initialization Script"),lineEdit_initScript->text(), + tr("JSBSim Scripts (*.xml)"))); +} + +void MainWindow::on_pushButton_trim_pressed() +{ + on_pushButton_stop_pressed(); + writeSettings(); + try + { + trimThread.start(); + } + catch(const std::exception & e) + { + QMessageBox msgBox; + msgBox.setText(e.what()); + msgBox.exec(); + } + catch(...) + { + QMessageBox msgBox; + msgBox.setText("unknown trim exception"); + msgBox.exec(); + } +} + +void MainWindow::on_pushButton_linearize_pressed() +{ + QMutexLocker locker(&fdmMutex); + + on_pushButton_stop_pressed(); + writeSettings(); + using namespace JSBSim; + + if (!ss) + { + showMsg("trim the aircraft first"); + return; + } + + std::cout << "\nlinearization: " << std::endl; + + + std::vector< std::vector<double> > A,B,C,D; + std::vector<double> x0 = ss->x.get(), u0 = ss->u.get(); + std::vector<double> y0 = x0; // state feedback + std::cout << ss << std::endl; + + ss->linearize(x0,u0,y0,A,B,C,D); + for (int i = 0; i<A.size(); i++) + { + for (int j = 0; j<A[0].size(); j++) + { + std::cout << A[i][j]; + } + std::cout << "\n"; + } + int width=10; + std::cout.precision(3); + std::cout + << std::fixed + << std::right + << "\nA=\n" << std::setw(width) << A + << "\nB=\n" << std::setw(width) << B + << "\nC=\n" << std::setw(width) << C + << "\nD=\n" << std::setw(width) << D + << std::endl; + + // write scicoslab file + std::string aircraft = lineEdit_aircraft->text().toStdString(); + std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str()); + scicos.precision(10); + width=20; + scicos + << std::scientific + << "x0=..\n" << std::setw(width) << x0 << ";\n" + << "u0=..\n" << std::setw(width) << u0 << ";\n" + << "sys = syslin('c',..\n" + << std::setw(width) << A << ",..\n" + << std::setw(width) << B << ",..\n" + << std::setw(width) << C << ",..\n" + << std::setw(width) << D << ");\n" + << "tfm = ss2tf(sys);\n" + << std::endl; +} + +void MainWindow::on_pushButton_stop_pressed() +{ + stopSolver(); + simThread.quit(); + trimThread.quit(); +} + +void MainWindow::on_pushButton_simulate_pressed() +{ + on_pushButton_stop_pressed(); + simThread.start(); +} + +void MainWindow::stopSolver() +{ + stopRequested = true; +} + +void MainWindow::showMsg(const QString & str) +{ + QMessageBox msgBox; + msgBox.setText(str); + msgBox.exec(); +}; + +void MainWindow::trim() +{ + QMutexLocker locker(&fdmMutex); + using namespace JSBSim; + + // flight conditions + if (ss) + { + delete ss; + ss = NULL; + } + if (fdm) + { + delete fdm; + fdm = NULL; + } + if (trimmer) + { + delete trimmer; + trimmer = NULL; + } + if (!fdm) + fdm = new FGFDMExec; + double dt = 1./atof(lineEdit_modelSimRate->text().toAscii()); + FGTrimmer::Constraints constraints; + constraints.velocity = atof(lineEdit_velocity->text().toAscii()); + constraints.altitude= atof(lineEdit_altitude->text().toAscii()); + constraints.gamma= atof(lineEdit_gamma->text().toAscii())*M_PI/180.0; + constraints.rollRate= atof(lineEdit_rollRate->text().toAscii()); + constraints.pitchRate= atof(lineEdit_pitchRate->text().toAscii()); + constraints.yawRate= atof(lineEdit_yawRate->text().toAscii()); + bool stabAxisRoll = checkBox_stabAxisRoll->isChecked(); + bool variablePropPitch = checkBox_variablePropPitch->isChecked(); + + // paths + std::string aircraft=lineEdit_aircraft->text().toStdString(); + std::string aircraftPath=lineEdit_aircraftPath->text().toStdString(); + std::string enginePath=lineEdit_enginePath->text().toStdString(); + std::string systemsPath=lineEdit_systemsPath->text().toStdString(); + + // solver properties + bool showConvergeStatus = checkBox_showConvergence->isChecked(); + bool showSimplex = checkBox_showSimplex->isChecked(); + bool pause = checkBox_pause->isChecked(); + int debugLevel = atoi(comboBox_debugLevel->currentText().toAscii()); + double rtol = atof(lineEdit_rtol->text().toAscii()); + double abstol = atof(lineEdit_abstol->text().toAscii()); + double speed = atof(lineEdit_speed->text().toAscii()); + double random = atof(lineEdit_random->text().toAscii()); + int iterMax = atof(lineEdit_iterMax->text().toAscii()); + + // initial solver state + int n = 6; + std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n); + + lowerBound[0] = atof(lineEdit_throttleMin->text().toAscii())/100.0; + lowerBound[1] = atof(lineEdit_elevatorMin->text().toAscii())/100.0; + lowerBound[2] = atof(lineEdit_alphaMin->text().toAscii())*M_PI/180.0; + lowerBound[3] = atof(lineEdit_aileronMin->text().toAscii())/100.0; + lowerBound[4] = atof(lineEdit_rudderMin->text().toAscii())/100.0; + lowerBound[5] = atof(lineEdit_betaMin->text().toAscii())*M_PI/180.0; + + upperBound[0] = atof(lineEdit_throttleMax->text().toAscii())/100.0; + upperBound[1] = atof(lineEdit_elevatorMax->text().toAscii())/100.0; + upperBound[2] = atof(lineEdit_alphaMax->text().toAscii())*M_PI/180.0; + upperBound[3] = atof(lineEdit_aileronMax->text().toAscii())/100.0; + upperBound[4] = atof(lineEdit_rudderMax->text().toAscii())/100.0; + upperBound[5] = atof(lineEdit_betaMax->text().toAscii())*M_PI/180.0; + + initialGuess[0] = atof(lineEdit_throttleGuess->text().toAscii())/100.0; + initialGuess[1] = atof(lineEdit_elevatorGuess->text().toAscii())/100.0; + initialGuess[2] = atof(lineEdit_alphaGuess->text().toAscii())*M_PI/180.0; + initialGuess[3] = atof(lineEdit_aileronGuess->text().toAscii())/100.0; + initialGuess[4] = atof(lineEdit_rudderGuess->text().toAscii())/100.0; + initialGuess[5] = atof(lineEdit_betaGuess->text().toAscii())*M_PI/180.0; + + initialStepSize[0] = atof(lineEdit_throttleInitialStepSize->text().toAscii())/100.0; + initialStepSize[1] = atof(lineEdit_elevatorInitialStepSize->text().toAscii())/100.0; + initialStepSize[2] = atof(lineEdit_alphaInitialStepSize->text().toAscii())*M_PI/180.0; + initialStepSize[3] = atof(lineEdit_aileronInitialStepSize->text().toAscii())/100.0; + initialStepSize[4] = atof(lineEdit_rudderInitialStepSize->text().toAscii())/100.0; + initialStepSize[5] = atof(lineEdit_betaInitialStepSize->text().toAscii())*M_PI/180.0; + + // loading + std::cout << "\n==============================================\n"; + std::cout << "\tJSBSim Trimming Utility\n"; + std::cout << "==============================================\n" << std::endl; + + fdm->Setdt(dt); + + if (!fdm->LoadModel(aircraftPath,enginePath,systemsPath,aircraft,false)) + { + showMsgBuffered("model paths incorrect"); + return; + } + std::string aircraftName = fdm->GetAircraft()->GetAircraftName(); + std::cout << "\tsuccessfully loaded: " << aircraftName << std::endl; + + // Turn on propulsion system + fdm->GetPropulsion()->InitRunning(-1); + + // get propulsion pointer to determine type/ etc. + FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0); + FGThruster * thruster0 = engine0->GetThruster(); + + + // solve + trimmer = new FGTrimmer(*fdm,constraints); + FGNelderMead solver(*trimmer,initialGuess, lowerBound, upperBound, initialStepSize, + iterMax,rtol,abstol,speed, random, showConvergeStatus,showSimplex,pause,callback); + stopRequested = false; + while(!stopRequested && solver.status()==1) solver.update(); + + if (stopRequested) return; + else if (solver.status()!=0) + { + showMsgBuffered("solver failed"); + return; + } + + showMsgBuffered("solver converged"); + + // output + trimmer->printSolution(solver.getSolution()); // this also loads the solution into the fdm + + //std::cout << "\nsimulating flight to determine trim stability" << std::endl; + + //std::cout << "\nt = 5 seconds" << std::endl; + //for (int i=0;i<5*120;i++) fdm.Run(); + //trimmer->printState(); + + //std::cout << "\nt = 10 seconds" << std::endl; + //for (int i=0;i<5*120;i++) fdm.Run(); + //trimmer->printState(); + + ss = new FGStateSpace(*fdm); + + // longitudinal states + ss->x.add(new FGStateSpace::Vt); // 0 + ss->x.add(new FGStateSpace::Alpha); // 1 + ss->x.add(new FGStateSpace::Theta); // 2 + ss->x.add(new FGStateSpace::Q); // 3 + ss->x.add(new FGStateSpace::Alt); // 4 + + // lateral states + ss->x.add(new FGStateSpace::Beta); // 5 + ss->x.add(new FGStateSpace::Phi); // 6 + ss->x.add(new FGStateSpace::P); // 7 + ss->x.add(new FGStateSpace::R); // 8 + ss->x.add(new FGStateSpace::Psi); // 9 + + // nav states + ss->x.add(new FGStateSpace::Longitude); // 10 + ss->x.add(new FGStateSpace::Latitude); // 11 + + // propulsion states + if (thruster0->GetType()==FGThruster::ttPropeller) + { + ss->x.add(new FGStateSpace::Rpm0); + if (variablePropPitch) ss->x.add(new FGStateSpace::PropPitch); + int numEngines = fdm->GetPropulsion()->GetNumEngines(); + if (numEngines>1) ss->x.add(new FGStateSpace::Rpm1); + if (numEngines>2) ss->x.add(new FGStateSpace::Rpm2); + if (numEngines>3) ss->x.add(new FGStateSpace::Rpm3); + } + + // input + ss->u.add(new FGStateSpace::ThrottleCmd); // 0 + ss->u.add(new FGStateSpace::DaCmd); // 1 + ss->u.add(new FGStateSpace::DeCmd); // 2 + ss->u.add(new FGStateSpace::DrCmd); // 3 + + // state feedback + ss->y = ss->x; +} + +void MainWindow::simulate() +{ + if (!fdm) return; + QMutexLocker locker(&fdmMutex); + fdm->Run(); + double maxDeflection = 20.0*3.14/180.0; // TODO: this is rough + viewer->mutex.lock(); + plane->setEuler(ss->x.get(6),ss->x.get(2),ss->x.get(9)); + plane->setU(ss->u.get(0),ss->u.get(1)*maxDeflection, + ss->u.get(2)*maxDeflection,ss->u.get(3)*maxDeflection); + viewer->mutex.unlock(); +} + +SimulateThread::SimulateThread(MainWindow * window) : window(window), timer(this) +{ + connect(&timer, SIGNAL(timeout()), window, SLOT(simulate())); +} +void SimulateThread::run() +{ + using namespace JSBSim; + std::cout << "simulation started" << std::endl; + timer.start(1000/120); + exec(); +} + + +TrimThread::TrimThread(MainWindow * window) : window(window) +{ +} + +void TrimThread::run() +{ + try + { + window->trim(); + } + catch(std::exception & e) + { + std::cerr << "exception: " << e.what() << std::endl; + window->showMsgBuffered(e.what()); + } +} + +// vim:ts=4:sw=4 diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp new file mode 100644 index 0000000..45963d2 --- /dev/null +++ b/gui/MainWindow.hpp @@ -0,0 +1,140 @@ +/* + * MainWindow.hpp + * Copyright (C) James Goppert 2010 <james.goppert@gmail.com> + * + * MainWindow.hpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MainWindow.hpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MainWindow_HPP +#define MainWindow_HPP + +#include <QWidget> +#include "MainWindow.ui.h" +#include "osgUtils.hpp" +#include "math/FGNelderMead.h" +#include <iomanip> +#include <QThread> +#include <QSettings> +//#include "config.h" +#include <stdexcept> +#include <math/FGStateSpace.h> +#include <initialization/FGTrimmer.h> +#include <QMutex> + +class MainWindow; + +class SimulateThread : public QThread +{ + Q_OBJECT +public: + + SimulateThread(MainWindow * window); + void run(); + MainWindow * window; + QTimer timer; + void quit() + { + timer.stop(); + QThread::quit(); + } +}; + +class TrimThread : public QThread +{ + Q_OBJECT +public: + TrimThread(MainWindow * window); + void run(); + MainWindow * window; +}; + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ + Q_OBJECT + friend class SimulateThread; + friend class TrimThread; +public: + MainWindow(); + virtual ~MainWindow(); + QMutex fdmMutex; + +signals: + void showMsgBuffered(const QString & str); + +private slots: + void on_toolButton_enginePath_pressed(); + void on_toolButton_systemsPath_pressed(); + void on_toolButton_aircraftPath_pressed(); + void on_toolButton_aircraft_pressed(); + void on_toolButton_initScript_pressed(); + void on_pushButton_trim_pressed(); + void on_pushButton_stop_pressed(); + void on_pushButton_linearize_pressed(); + void on_pushButton_simulate_pressed(); + void showMsg(const QString & str); + void simulate(); + void trim(); + +private: + class SolverCallback : public JSBSim::FGNelderMead::Callback + { + public: + SolverCallback(MainWindow * window) : window(window) + { + } + void eval(const std::vector<double> & v) + { + double maxDeflection = 20.0*3.14/180.0; // TODO: this is rough + // should depend on aircraft, but currently no access + std::vector<double> data = window->trimmer->constrain(v); + window->viewer->mutex.lock(); + window->plane->setEuler(data[0],data[1],v[5]); + // phi, theta, beta to show orient, and side slip + window->plane->setU(v[0],v[3]*maxDeflection, + v[1]*maxDeflection,v[4]*maxDeflection); + window->viewer->mutex.unlock(); + } + MainWindow * window; + }; + SimulateThread simThread; + TrimThread trimThread; + SolverCallback * callback; + osg::ref_ptr<osg::Group> sceneRoot; + void loadModel(const std::string & name); + + void stopSolver(); + volatile bool stopRequested; + template <class varType> + void prompt(const std::string & str, varType & var) + { + std::cout << str + " [" << std::setw(10) << var << "]\t: "; + if (std::cin.peek() != '\n') + { + std::cin >> var; + std::cin.ignore(1000, '\n'); + } + else std::cin.get(); + } + QSettings * settings; + void writeSettings(); + void readSettings(); + mavsim::visualization::Plane * plane; + JSBSim::FGStateSpace * ss; + JSBSim::FGTrimmer * trimmer; + JSBSim::FGFDMExec * fdm; +}; + +#endif + +// vim:ts=4:sw=4 diff --git a/gui/MainWindow.moc.cpp b/gui/MainWindow.moc.cpp new file mode 100644 index 0000000..6ef6dc0 --- /dev/null +++ b/gui/MainWindow.moc.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'MainWindow.hpp' +** +** Created: Tue Aug 16 21:04:18 2011 +** by: The Qt Meta Object Compiler version 62 (Qt 4.7.3) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "MainWindow.hpp" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'MainWindow.hpp' doesn't include <QObject>." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.7.3. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_SimulateThread[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_SimulateThread[] = { + "SimulateThread\0" +}; + +const QMetaObject SimulateThread::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_SimulateThread, + qt_meta_data_SimulateThread, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &SimulateThread::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *SimulateThread::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *SimulateThread::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_SimulateThread)) + return static_cast<void*>(const_cast< SimulateThread*>(this)); + return QThread::qt_metacast(_clname); +} + +int SimulateThread::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +static const uint qt_meta_data_TrimThread[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_TrimThread[] = { + "TrimThread\0" +}; + +const QMetaObject TrimThread::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_TrimThread, + qt_meta_data_TrimThread, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &TrimThread::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *TrimThread::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *TrimThread::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_TrimThread)) + return static_cast<void*>(const_cast< TrimThread*>(this)); + return QThread::qt_metacast(_clname); +} + +int TrimThread::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +static const uint qt_meta_data_MainWindow[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 13, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 1, // signalCount + + // signals: signature, parameters, type, tag, flags + 16, 12, 11, 11, 0x05, + + // slots: signature, parameters, type, tag, flags + 41, 11, 11, 11, 0x08, + 76, 11, 11, 11, 0x08, + 112, 11, 11, 11, 0x08, + 149, 11, 11, 11, 0x08, + 182, 11, 11, 11, 0x08, + 217, 11, 11, 11, 0x08, + 246, 11, 11, 11, 0x08, + 275, 11, 11, 11, 0x08, + 309, 11, 11, 11, 0x08, + 342, 12, 11, 11, 0x08, + 359, 11, 11, 11, 0x08, + 370, 11, 11, 11, 0x08, + + 0 // eod +}; + +static const char qt_meta_stringdata_MainWindow[] = { + "MainWindow\0\0str\0showMsgBuffered(QString)\0" + "on_toolButton_enginePath_pressed()\0" + "on_toolButton_systemsPath_pressed()\0" + "on_toolButton_aircraftPath_pressed()\0" + "on_toolButton_aircraft_pressed()\0" + "on_toolButton_initScript_pressed()\0" + "on_pushButton_trim_pressed()\0" + "on_pushButton_stop_pressed()\0" + "on_pushButton_linearize_pressed()\0" + "on_pushButton_simulate_pressed()\0" + "showMsg(QString)\0simulate()\0trim()\0" +}; + +const QMetaObject MainWindow::staticMetaObject = { + { &QMainWindow::staticMetaObject, qt_meta_stringdata_MainWindow, + qt_meta_data_MainWindow, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MainWindow::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MainWindow::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MainWindow::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MainWindow)) + return static_cast<void*>(const_cast< MainWindow*>(this)); + return QMainWindow::qt_metacast(_clname); +} + +int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QMainWindow::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: showMsgBuffered((*reinterpret_cast< const QString(*)>(_a[1]))); break; + case 1: on_toolButton_enginePath_pressed(); break; + case 2: on_toolButton_systemsPath_pressed(); break; + case 3: on_toolButton_aircraftPath_pressed(); break; + case 4: on_toolButton_aircraft_pressed(); break; + case 5: on_toolButton_initScript_pressed(); break; + case 6: on_pushButton_trim_pressed(); break; + case 7: on_pushButton_stop_pressed(); break; + case 8: on_pushButton_linearize_pressed(); break; + case 9: on_pushButton_simulate_pressed(); break; + case 10: showMsg((*reinterpret_cast< const QString(*)>(_a[1]))); break; + case 11: simulate(); break; + case 12: trim(); break; + default: ; + } + _id -= 13; + } + return _id; +} + +// SIGNAL 0 +void MainWindow::showMsgBuffered(const QString & _t1) +{ + void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; + QMetaObject::activate(this, &staticMetaObject, 0, _a); +} +QT_END_MOC_NAMESPACE diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui new file mode 100644 index 0000000..5b96bbe --- /dev/null +++ b/gui/MainWindow.ui @@ -0,0 +1,917 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>825</width> + <height>862</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>mavsim Trim Program (for JSBSim models)</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="4"> + <widget class="ViewerQT" name="viewer" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="pushButton_trim"> + <property name="text"> + <string>Trim</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="pushButton_simulate"> + <property name="text"> + <string>Simulate</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButton_linearize"> + <property name="text"> + <string>Linearize</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButton_stop"> + <property name="text"> + <string>Stop</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <widget class="QDockWidget" name="guidanceDock"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>685</width> + <height>446</height> + </size> + </property> + <property name="windowTitle"> + <string>Trim Algorithm</string> + </property> + <attribute name="dockWidgetArea"> + <number>8</number> + </attribute> + <widget class="QWidget" name="dockWidgetContents_6"> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>5</number> + </property> + <widget class="QWidget" name="tab_3"> + <attribute name="title"> + <string>Aircraft</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="1" column="1"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Engine Path</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="lineEdit_enginePath"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Systems Path</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Aircraft Path</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLineEdit" name="lineEdit_systemsPath"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QToolButton" name="toolButton_enginePath"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QToolButton" name="toolButton_systemsPath"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="3" column="3"> + <widget class="QToolButton" name="toolButton_aircraftPath"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Aircraft</string> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="QLineEdit" name="lineEdit_aircraft"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="4" column="3"> + <widget class="QToolButton" name="toolButton_aircraft"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Initialization Script</string> + </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QLineEdit" name="lineEdit_initScript"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="5" column="3"> + <widget class="QToolButton" name="toolButton_initScript"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLineEdit" name="lineEdit_aircraftPath"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_38"> + <property name="text"> + <string>model sim rate</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLineEdit" name="lineEdit_modelSimRate"> + <property name="text"> + <string>120</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="label_39"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Trim Conditions</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>mode</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="6"> + <widget class="QComboBox" name="comboBox_mode"> + <item> + <property name="text"> + <string>Steady Level Flight</string> + </property> + </item> + <item> + <property name="text"> + <string>Coordinated Turn</string> + </property> + </item> + <item> + <property name="text"> + <string>Push Over</string> + </property> + </item> + <item> + <property name="text"> + <string>Pull Back</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>velocity</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_velocity"> + <property name="text"> + <string>500</string> + </property> + </widget> + </item> + <item row="1" column="6"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>ft/s</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>roll rate</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_rollRate"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="2" column="6"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>rad/s</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>pitch rate</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_pitchRate"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="3" column="6"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>rad/s</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>yaw rate</string> + </property> + </widget> + </item> + <item row="4" column="6"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>rad/s</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_yawRate"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QCheckBox" name="checkBox_stabAxisRoll"> + <property name="text"> + <string>stability axis roll</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_40"> + <property name="text"> + <string>altitude</string> + </property> + </widget> + </item> + <item row="5" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_altitude"> + <property name="text"> + <string>1000</string> + </property> + </widget> + </item> + <item row="5" column="6"> + <widget class="QLabel" name="label_41"> + <property name="text"> + <string>ft</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_42"> + <property name="text"> + <string>flight path angle</string> + </property> + </widget> + </item> + <item row="6" column="1" colspan="5"> + <widget class="QLineEdit" name="lineEdit_gamma"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QCheckBox" name="checkBox_variablePropPitch"> + <property name="text"> + <string>variable prop ptich</string> + </property> + </widget> + </item> + <item row="6" column="6"> + <widget class="QLabel" name="label_43"> + <property name="text"> + <string>deg</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Solver</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_6"> + <item row="0" column="0"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>relative tolerance</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_21"> + <property name="text"> + <string>absolute tolerance</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_22"> + <property name="text"> + <string>convergence relative step size</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_23"> + <property name="text"> + <string>max iterations</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_abstol"> + <property name="text"> + <string>1e-2</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_speed"> + <property name="text"> + <string>1.1</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_iterMax"> + <property name="text"> + <string>2000</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2"> + <widget class="QComboBox" name="comboBox_debugLevel"> + <item> + <property name="text"> + <string>0</string> + </property> + </item> + <item> + <property name="text"> + <string>1</string> + </property> + </item> + <item> + <property name="text"> + <string>2</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_34"> + <property name="text"> + <string>debug level</string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QCheckBox" name="checkBox_pause"> + <property name="text"> + <string>pause </string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_rtol"> + <property name="text"> + <string>1e-4</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QCheckBox" name="checkBox_showSimplex"> + <property name="text"> + <string>show simplex</string> + </property> + </widget> + </item> + <item row="7" column="2"> + <widget class="QCheckBox" name="checkBox_showConvergence"> + <property name="text"> + <string>show convergence</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_44"> + <property name="text"> + <string>randomization factor</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLineEdit" name="lineEdit_random"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_6"> + <attribute name="title"> + <string>Input</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_8"> + <item row="0" column="0"> + <widget class="QLabel" name="label_36"> + <property name="text"> + <string>joystick device</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEdit_joystick"> + <property name="text"> + <string>/dev/input/js0</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QToolButton" name="toolButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QCheckBox" name="checkBox_joystickEnabled"> + <property name="text"> + <string>joystick enabled</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_4"> + <attribute name="title"> + <string>Initial Guess</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_7"> + <item row="1" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Throttle</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Alpha</string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string>Beta</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lineEdit_throttleGuess"> + <property name="text"> + <string>50</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="lineEdit_aileronGuess"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="lineEdit_elevatorGuess"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLineEdit" name="lineEdit_alphaGuess"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLineEdit" name="lineEdit_betaGuess"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="1" column="5"> + <widget class="QLabel" name="label_24"> + <property name="text"> + <string>%</string> + </property> + </widget> + </item> + <item row="3" column="5"> + <widget class="QLabel" name="label_25"> + <property name="text"> + <string>%</string> + </property> + </widget> + </item> + <item row="5" column="5"> + <widget class="QLabel" name="label_26"> + <property name="text"> + <string>%</string> + </property> + </widget> + </item> + <item row="6" column="5"> + <widget class="QLabel" name="label_27"> + <property name="text"> + <string>deg</string> + </property> + </widget> + </item> + <item row="7" column="5"> + <widget class="QLabel" name="label_28"> + <property name="text"> + <string>deg</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="lineEdit_throttleMin"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLineEdit" name="lineEdit_aileronMin"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QLineEdit" name="lineEdit_elevatorMin"> + <property name="text"> + <string>-100</string> + </property> + </widget> + </item> + <item row="6" column="2"> + <widget class="QLineEdit" name="lineEdit_alphaMin"> + <property name="text"> + <string>-10</string> + </property> + </widget> + </item> + <item row="7" column="2"> + <widget class="QLineEdit" name="lineEdit_betaMin"> + <property name="text"> + <string>-10</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_29"> + <property name="text"> + <string>Guess</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_30"> + <property name="text"> + <string>Lower Bound</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="lineEdit_throttleMax"> + <property name="text"> + <string>100</string> + </property> + </widget> + </item> + <item row="3" column="3"> + <widget class="QLineEdit" name="lineEdit_aileronMax"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="5" column="3"> + <widget class="QLineEdit" name="lineEdit_elevatorMax"> + <property name="text"> + <string>100</string> + </property> + </widget> + </item> + <item row="6" column="3"> + <widget class="QLineEdit" name="lineEdit_alphaMax"> + <property name="text"> + <string>20</string> + </property> + </widget> + </item> + <item row="7" column="3"> + <widget class="QLineEdit" name="lineEdit_betaMax"> + <property name="text"> + <string>5</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="label_31"> + <property name="text"> + <string>Upper Bound</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Elevator</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Aileron</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_32"> + <property name="text"> + <string>Rudder</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="lineEdit_rudderGuess"> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="QLineEdit" name="lineEdit_rudderMin"> + <property name="text"> + <string>-100</string> + </property> + </widget> + </item> + <item row="4" column="3"> + <widget class="QLineEdit" name="lineEdit_rudderMax"> + <property name="text"> + <string>100</string> + </property> + </widget> + </item> + <item row="4" column="5"> + <widget class="QLabel" name="label_33"> + <property name="text"> + <string>%</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QLineEdit" name="lineEdit_throttleInitialStepSize"> + <property name="text"> + <string>20</string> + </property> + </widget> + </item> + <item row="3" column="4"> + <widget class="QLineEdit" name="lineEdit_aileronInitialStepSize"> + <property name="text"> + <string>10</string> + </property> + </widget> + </item> + <item row="4" column="4"> + <widget class="QLineEdit" name="lineEdit_rudderInitialStepSize"> + <property name="text"> + <string>10</string> + </property> + </widget> + </item> + <item row="5" column="4"> + <widget class="QLineEdit" name="lineEdit_elevatorInitialStepSize"> + <property name="text"> + <string>10</string> + </property> + </widget> + </item> + <item row="6" column="4"> + <widget class="QLineEdit" name="lineEdit_alphaInitialStepSize"> + <property name="text"> + <string>10</string> + </property> + </widget> + </item> + <item row="7" column="4"> + <widget class="QLineEdit" name="lineEdit_betaInitialStepSize"> + <property name="text"> + <string>5</string> + </property> + </widget> + </item> + <item row="0" column="4"> + <widget class="QLabel" name="label_37"> + <property name="text"> + <string>Initial Step Size</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_5"> + <attribute name="title"> + <string>Output</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="label_35"> + <property name="text"> + <string>Linearization File</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEdit_linearizationFile"/> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + <action name="actionQuit"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionLoad_Map"> + <property name="text"> + <string>Load Map</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>ViewerQT</class> + <extends>QWidget</extends> + <header>QOSGAdapterWidget.hpp</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>actionQuit</sender> + <signal>triggered()</signal> + <receiver>MainWindow</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>311</x> + <y>461</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/gui/MainWindow.ui.h b/gui/MainWindow.ui.h new file mode 100644 index 0000000..d051039 --- /dev/null +++ b/gui/MainWindow.ui.h @@ -0,0 +1,915 @@ +/******************************************************************************** +** Form generated from reading UI file 'MainWindow.ui' +** +** Created: Tue Aug 16 20:52:00 2011 +** by: Qt User Interface Compiler version 4.7.3 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QtCore/QVariant> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QButtonGroup> +#include <QtGui/QCheckBox> +#include <QtGui/QComboBox> +#include <QtGui/QDockWidget> +#include <QtGui/QGridLayout> +#include <QtGui/QHeaderView> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QMainWindow> +#include <QtGui/QPushButton> +#include <QtGui/QStatusBar> +#include <QtGui/QTabWidget> +#include <QtGui/QToolButton> +#include <QtGui/QWidget> +#include "QOSGAdapterWidget.hpp" + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QAction *actionQuit; + QAction *actionLoad_Map; + QWidget *centralwidget; + QGridLayout *gridLayout; + ViewerQT *viewer; + QPushButton *pushButton_trim; + QPushButton *pushButton_simulate; + QPushButton *pushButton_linearize; + QPushButton *pushButton_stop; + QStatusBar *statusbar; + QDockWidget *guidanceDock; + QWidget *dockWidgetContents_6; + QGridLayout *gridLayout_4; + QTabWidget *tabWidget; + QWidget *tab_3; + QGridLayout *gridLayout_5; + QLabel *label_2; + QLineEdit *lineEdit_enginePath; + QLabel *label_4; + QLabel *label_3; + QLineEdit *lineEdit_systemsPath; + QToolButton *toolButton_enginePath; + QToolButton *toolButton_systemsPath; + QToolButton *toolButton_aircraftPath; + QLabel *label_9; + QLineEdit *lineEdit_aircraft; + QToolButton *toolButton_aircraft; + QLabel *label_5; + QLineEdit *lineEdit_initScript; + QToolButton *toolButton_initScript; + QLineEdit *lineEdit_aircraftPath; + QLabel *label_38; + QLineEdit *lineEdit_modelSimRate; + QLabel *label_39; + QWidget *tab; + QGridLayout *gridLayout_2; + QLabel *label_10; + QComboBox *comboBox_mode; + QLabel *label; + QLineEdit *lineEdit_velocity; + QLabel *label_11; + QLabel *label_6; + QLineEdit *lineEdit_rollRate; + QLabel *label_12; + QLabel *label_7; + QLineEdit *lineEdit_pitchRate; + QLabel *label_13; + QLabel *label_8; + QLabel *label_14; + QLineEdit *lineEdit_yawRate; + QCheckBox *checkBox_stabAxisRoll; + QLabel *label_40; + QLineEdit *lineEdit_altitude; + QLabel *label_41; + QLabel *label_42; + QLineEdit *lineEdit_gamma; + QCheckBox *checkBox_variablePropPitch; + QLabel *label_43; + QWidget *tab_2; + QGridLayout *gridLayout_6; + QLabel *label_20; + QLabel *label_21; + QLabel *label_22; + QLabel *label_23; + QLineEdit *lineEdit_abstol; + QLineEdit *lineEdit_speed; + QLineEdit *lineEdit_iterMax; + QComboBox *comboBox_debugLevel; + QLabel *label_34; + QCheckBox *checkBox_pause; + QLineEdit *lineEdit_rtol; + QCheckBox *checkBox_showSimplex; + QCheckBox *checkBox_showConvergence; + QLabel *label_44; + QLineEdit *lineEdit_random; + QWidget *tab_6; + QGridLayout *gridLayout_8; + QLabel *label_36; + QLineEdit *lineEdit_joystick; + QToolButton *toolButton; + QCheckBox *checkBox_joystickEnabled; + QWidget *tab_4; + QGridLayout *gridLayout_7; + QLabel *label_15; + QLabel *label_17; + QLabel *label_19; + QLineEdit *lineEdit_throttleGuess; + QLineEdit *lineEdit_aileronGuess; + QLineEdit *lineEdit_elevatorGuess; + QLineEdit *lineEdit_alphaGuess; + QLineEdit *lineEdit_betaGuess; + QLabel *label_24; + QLabel *label_25; + QLabel *label_26; + QLabel *label_27; + QLabel *label_28; + QLineEdit *lineEdit_throttleMin; + QLineEdit *lineEdit_aileronMin; + QLineEdit *lineEdit_elevatorMin; + QLineEdit *lineEdit_alphaMin; + QLineEdit *lineEdit_betaMin; + QLabel *label_29; + QLabel *label_30; + QLineEdit *lineEdit_throttleMax; + QLineEdit *lineEdit_aileronMax; + QLineEdit *lineEdit_elevatorMax; + QLineEdit *lineEdit_alphaMax; + QLineEdit *lineEdit_betaMax; + QLabel *label_31; + QLabel *label_16; + QLabel *label_18; + QLabel *label_32; + QLineEdit *lineEdit_rudderGuess; + QLineEdit *lineEdit_rudderMin; + QLineEdit *lineEdit_rudderMax; + QLabel *label_33; + QLineEdit *lineEdit_throttleInitialStepSize; + QLineEdit *lineEdit_aileronInitialStepSize; + QLineEdit *lineEdit_rudderInitialStepSize; + QLineEdit *lineEdit_elevatorInitialStepSize; + QLineEdit *lineEdit_alphaInitialStepSize; + QLineEdit *lineEdit_betaInitialStepSize; + QLabel *label_37; + QWidget *tab_5; + QGridLayout *gridLayout_3; + QLabel *label_35; + QLineEdit *lineEdit_linearizationFile; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QString::fromUtf8("MainWindow")); + MainWindow->resize(825, 862); + QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(MainWindow->sizePolicy().hasHeightForWidth()); + MainWindow->setSizePolicy(sizePolicy); + actionQuit = new QAction(MainWindow); + actionQuit->setObjectName(QString::fromUtf8("actionQuit")); + actionLoad_Map = new QAction(MainWindow); + actionLoad_Map->setObjectName(QString::fromUtf8("actionLoad_Map")); + centralwidget = new QWidget(MainWindow); + centralwidget->setObjectName(QString::fromUtf8("centralwidget")); + gridLayout = new QGridLayout(centralwidget); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + viewer = new ViewerQT(centralwidget); + viewer->setObjectName(QString::fromUtf8("viewer")); + sizePolicy.setHeightForWidth(viewer->sizePolicy().hasHeightForWidth()); + viewer->setSizePolicy(sizePolicy); + + gridLayout->addWidget(viewer, 0, 0, 1, 4); + + pushButton_trim = new QPushButton(centralwidget); + pushButton_trim->setObjectName(QString::fromUtf8("pushButton_trim")); + + gridLayout->addWidget(pushButton_trim, 1, 0, 1, 1); + + pushButton_simulate = new QPushButton(centralwidget); + pushButton_simulate->setObjectName(QString::fromUtf8("pushButton_simulate")); + + gridLayout->addWidget(pushButton_simulate, 1, 3, 1, 1); + + pushButton_linearize = new QPushButton(centralwidget); + pushButton_linearize->setObjectName(QString::fromUtf8("pushButton_linearize")); + + gridLayout->addWidget(pushButton_linearize, 1, 2, 1, 1); + + pushButton_stop = new QPushButton(centralwidget); + pushButton_stop->setObjectName(QString::fromUtf8("pushButton_stop")); + + gridLayout->addWidget(pushButton_stop, 1, 1, 1, 1); + + MainWindow->setCentralWidget(centralwidget); + statusbar = new QStatusBar(MainWindow); + statusbar->setObjectName(QString::fromUtf8("statusbar")); + MainWindow->setStatusBar(statusbar); + guidanceDock = new QDockWidget(MainWindow); + guidanceDock->setObjectName(QString::fromUtf8("guidanceDock")); + sizePolicy.setHeightForWidth(guidanceDock->sizePolicy().hasHeightForWidth()); + guidanceDock->setSizePolicy(sizePolicy); + guidanceDock->setMinimumSize(QSize(685, 446)); + dockWidgetContents_6 = new QWidget(); + dockWidgetContents_6->setObjectName(QString::fromUtf8("dockWidgetContents_6")); + gridLayout_4 = new QGridLayout(dockWidgetContents_6); + gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4")); + tabWidget = new QTabWidget(dockWidgetContents_6); + tabWidget->setObjectName(QString::fromUtf8("tabWidget")); + tab_3 = new QWidget(); + tab_3->setObjectName(QString::fromUtf8("tab_3")); + gridLayout_5 = new QGridLayout(tab_3); + gridLayout_5->setObjectName(QString::fromUtf8("gridLayout_5")); + label_2 = new QLabel(tab_3); + label_2->setObjectName(QString::fromUtf8("label_2")); + + gridLayout_5->addWidget(label_2, 1, 1, 1, 1); + + lineEdit_enginePath = new QLineEdit(tab_3); + lineEdit_enginePath->setObjectName(QString::fromUtf8("lineEdit_enginePath")); + + gridLayout_5->addWidget(lineEdit_enginePath, 1, 2, 1, 1); + + label_4 = new QLabel(tab_3); + label_4->setObjectName(QString::fromUtf8("label_4")); + + gridLayout_5->addWidget(label_4, 2, 1, 1, 1); + + label_3 = new QLabel(tab_3); + label_3->setObjectName(QString::fromUtf8("label_3")); + + gridLayout_5->addWidget(label_3, 3, 1, 1, 1); + + lineEdit_systemsPath = new QLineEdit(tab_3); + lineEdit_systemsPath->setObjectName(QString::fromUtf8("lineEdit_systemsPath")); + + gridLayout_5->addWidget(lineEdit_systemsPath, 2, 2, 1, 1); + + toolButton_enginePath = new QToolButton(tab_3); + toolButton_enginePath->setObjectName(QString::fromUtf8("toolButton_enginePath")); + + gridLayout_5->addWidget(toolButton_enginePath, 1, 3, 1, 1); + + toolButton_systemsPath = new QToolButton(tab_3); + toolButton_systemsPath->setObjectName(QString::fromUtf8("toolButton_systemsPath")); + + gridLayout_5->addWidget(toolButton_systemsPath, 2, 3, 1, 1); + + toolButton_aircraftPath = new QToolButton(tab_3); + toolButton_aircraftPath->setObjectName(QString::fromUtf8("toolButton_aircraftPath")); + + gridLayout_5->addWidget(toolButton_aircraftPath, 3, 3, 1, 1); + + label_9 = new QLabel(tab_3); + label_9->setObjectName(QString::fromUtf8("label_9")); + + gridLayout_5->addWidget(label_9, 4, 1, 1, 1); + + lineEdit_aircraft = new QLineEdit(tab_3); + lineEdit_aircraft->setObjectName(QString::fromUtf8("lineEdit_aircraft")); + + gridLayout_5->addWidget(lineEdit_aircraft, 4, 2, 1, 1); + + toolButton_aircraft = new QToolButton(tab_3); + toolButton_aircraft->setObjectName(QString::fromUtf8("toolButton_aircraft")); + + gridLayout_5->addWidget(toolButton_aircraft, 4, 3, 1, 1); + + label_5 = new QLabel(tab_3); + label_5->setObjectName(QString::fromUtf8("label_5")); + + gridLayout_5->addWidget(label_5, 5, 1, 1, 1); + + lineEdit_initScript = new QLineEdit(tab_3); + lineEdit_initScript->setObjectName(QString::fromUtf8("lineEdit_initScript")); + + gridLayout_5->addWidget(lineEdit_initScript, 5, 2, 1, 1); + + toolButton_initScript = new QToolButton(tab_3); + toolButton_initScript->setObjectName(QString::fromUtf8("toolButton_initScript")); + + gridLayout_5->addWidget(toolButton_initScript, 5, 3, 1, 1); + + lineEdit_aircraftPath = new QLineEdit(tab_3); + lineEdit_aircraftPath->setObjectName(QString::fromUtf8("lineEdit_aircraftPath")); + + gridLayout_5->addWidget(lineEdit_aircraftPath, 3, 2, 1, 1); + + label_38 = new QLabel(tab_3); + label_38->setObjectName(QString::fromUtf8("label_38")); + + gridLayout_5->addWidget(label_38, 0, 1, 1, 1); + + lineEdit_modelSimRate = new QLineEdit(tab_3); + lineEdit_modelSimRate->setObjectName(QString::fromUtf8("lineEdit_modelSimRate")); + + gridLayout_5->addWidget(lineEdit_modelSimRate, 0, 2, 1, 1); + + label_39 = new QLabel(tab_3); + label_39->setObjectName(QString::fromUtf8("label_39")); + + gridLayout_5->addWidget(label_39, 0, 3, 1, 1); + + tabWidget->addTab(tab_3, QString()); + tab = new QWidget(); + tab->setObjectName(QString::fromUtf8("tab")); + gridLayout_2 = new QGridLayout(tab); + gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2")); + label_10 = new QLabel(tab); + label_10->setObjectName(QString::fromUtf8("label_10")); + + gridLayout_2->addWidget(label_10, 0, 0, 1, 1); + + comboBox_mode = new QComboBox(tab); + comboBox_mode->setObjectName(QString::fromUtf8("comboBox_mode")); + + gridLayout_2->addWidget(comboBox_mode, 0, 1, 1, 6); + + label = new QLabel(tab); + label->setObjectName(QString::fromUtf8("label")); + + gridLayout_2->addWidget(label, 1, 0, 1, 1); + + lineEdit_velocity = new QLineEdit(tab); + lineEdit_velocity->setObjectName(QString::fromUtf8("lineEdit_velocity")); + + gridLayout_2->addWidget(lineEdit_velocity, 1, 1, 1, 5); + + label_11 = new QLabel(tab); + label_11->setObjectName(QString::fromUtf8("label_11")); + + gridLayout_2->addWidget(label_11, 1, 6, 1, 1); + + label_6 = new QLabel(tab); + label_6->setObjectName(QString::fromUtf8("label_6")); + + gridLayout_2->addWidget(label_6, 2, 0, 1, 1); + + lineEdit_rollRate = new QLineEdit(tab); + lineEdit_rollRate->setObjectName(QString::fromUtf8("lineEdit_rollRate")); + + gridLayout_2->addWidget(lineEdit_rollRate, 2, 1, 1, 5); + + label_12 = new QLabel(tab); + label_12->setObjectName(QString::fromUtf8("label_12")); + + gridLayout_2->addWidget(label_12, 2, 6, 1, 1); + + label_7 = new QLabel(tab); + label_7->setObjectName(QString::fromUtf8("label_7")); + + gridLayout_2->addWidget(label_7, 3, 0, 1, 1); + + lineEdit_pitchRate = new QLineEdit(tab); + lineEdit_pitchRate->setObjectName(QString::fromUtf8("lineEdit_pitchRate")); + + gridLayout_2->addWidget(lineEdit_pitchRate, 3, 1, 1, 5); + + label_13 = new QLabel(tab); + label_13->setObjectName(QString::fromUtf8("label_13")); + + gridLayout_2->addWidget(label_13, 3, 6, 1, 1); + + label_8 = new QLabel(tab); + label_8->setObjectName(QString::fromUtf8("label_8")); + + gridLayout_2->addWidget(label_8, 4, 0, 1, 1); + + label_14 = new QLabel(tab); + label_14->setObjectName(QString::fromUtf8("label_14")); + + gridLayout_2->addWidget(label_14, 4, 6, 1, 1); + + lineEdit_yawRate = new QLineEdit(tab); + lineEdit_yawRate->setObjectName(QString::fromUtf8("lineEdit_yawRate")); + + gridLayout_2->addWidget(lineEdit_yawRate, 4, 1, 1, 5); + + checkBox_stabAxisRoll = new QCheckBox(tab); + checkBox_stabAxisRoll->setObjectName(QString::fromUtf8("checkBox_stabAxisRoll")); + checkBox_stabAxisRoll->setCheckable(true); + checkBox_stabAxisRoll->setChecked(true); + + gridLayout_2->addWidget(checkBox_stabAxisRoll, 8, 0, 1, 1); + + label_40 = new QLabel(tab); + label_40->setObjectName(QString::fromUtf8("label_40")); + + gridLayout_2->addWidget(label_40, 5, 0, 1, 1); + + lineEdit_altitude = new QLineEdit(tab); + lineEdit_altitude->setObjectName(QString::fromUtf8("lineEdit_altitude")); + + gridLayout_2->addWidget(lineEdit_altitude, 5, 1, 1, 5); + + label_41 = new QLabel(tab); + label_41->setObjectName(QString::fromUtf8("label_41")); + + gridLayout_2->addWidget(label_41, 5, 6, 1, 1); + + label_42 = new QLabel(tab); + label_42->setObjectName(QString::fromUtf8("label_42")); + + gridLayout_2->addWidget(label_42, 6, 0, 1, 1); + + lineEdit_gamma = new QLineEdit(tab); + lineEdit_gamma->setObjectName(QString::fromUtf8("lineEdit_gamma")); + + gridLayout_2->addWidget(lineEdit_gamma, 6, 1, 1, 5); + + checkBox_variablePropPitch = new QCheckBox(tab); + checkBox_variablePropPitch->setObjectName(QString::fromUtf8("checkBox_variablePropPitch")); + + gridLayout_2->addWidget(checkBox_variablePropPitch, 7, 0, 1, 1); + + label_43 = new QLabel(tab); + label_43->setObjectName(QString::fromUtf8("label_43")); + + gridLayout_2->addWidget(label_43, 6, 6, 1, 1); + + tabWidget->addTab(tab, QString()); + tab_2 = new QWidget(); + tab_2->setObjectName(QString::fromUtf8("tab_2")); + gridLayout_6 = new QGridLayout(tab_2); + gridLayout_6->setObjectName(QString::fromUtf8("gridLayout_6")); + label_20 = new QLabel(tab_2); + label_20->setObjectName(QString::fromUtf8("label_20")); + + gridLayout_6->addWidget(label_20, 0, 0, 1, 1); + + label_21 = new QLabel(tab_2); + label_21->setObjectName(QString::fromUtf8("label_21")); + + gridLayout_6->addWidget(label_21, 1, 0, 1, 1); + + label_22 = new QLabel(tab_2); + label_22->setObjectName(QString::fromUtf8("label_22")); + + gridLayout_6->addWidget(label_22, 2, 0, 1, 1); + + label_23 = new QLabel(tab_2); + label_23->setObjectName(QString::fromUtf8("label_23")); + + gridLayout_6->addWidget(label_23, 3, 0, 1, 1); + + lineEdit_abstol = new QLineEdit(tab_2); + lineEdit_abstol->setObjectName(QString::fromUtf8("lineEdit_abstol")); + + gridLayout_6->addWidget(lineEdit_abstol, 1, 1, 1, 2); + + lineEdit_speed = new QLineEdit(tab_2); + lineEdit_speed->setObjectName(QString::fromUtf8("lineEdit_speed")); + + gridLayout_6->addWidget(lineEdit_speed, 2, 1, 1, 2); + + lineEdit_iterMax = new QLineEdit(tab_2); + lineEdit_iterMax->setObjectName(QString::fromUtf8("lineEdit_iterMax")); + + gridLayout_6->addWidget(lineEdit_iterMax, 3, 1, 1, 2); + + comboBox_debugLevel = new QComboBox(tab_2); + comboBox_debugLevel->setObjectName(QString::fromUtf8("comboBox_debugLevel")); + + gridLayout_6->addWidget(comboBox_debugLevel, 4, 1, 1, 2); + + label_34 = new QLabel(tab_2); + label_34->setObjectName(QString::fromUtf8("label_34")); + + gridLayout_6->addWidget(label_34, 4, 0, 1, 1); + + checkBox_pause = new QCheckBox(tab_2); + checkBox_pause->setObjectName(QString::fromUtf8("checkBox_pause")); + + gridLayout_6->addWidget(checkBox_pause, 7, 0, 1, 1); + + lineEdit_rtol = new QLineEdit(tab_2); + lineEdit_rtol->setObjectName(QString::fromUtf8("lineEdit_rtol")); + + gridLayout_6->addWidget(lineEdit_rtol, 0, 1, 1, 2); + + checkBox_showSimplex = new QCheckBox(tab_2); + checkBox_showSimplex->setObjectName(QString::fromUtf8("checkBox_showSimplex")); + + gridLayout_6->addWidget(checkBox_showSimplex, 7, 1, 1, 1); + + checkBox_showConvergence = new QCheckBox(tab_2); + checkBox_showConvergence->setObjectName(QString::fromUtf8("checkBox_showConvergence")); + checkBox_showConvergence->setChecked(true); + + gridLayout_6->addWidget(checkBox_showConvergence, 7, 2, 1, 1); + + label_44 = new QLabel(tab_2); + label_44->setObjectName(QString::fromUtf8("label_44")); + + gridLayout_6->addWidget(label_44, 6, 0, 1, 1); + + lineEdit_random = new QLineEdit(tab_2); + lineEdit_random->setObjectName(QString::fromUtf8("lineEdit_random")); + + gridLayout_6->addWidget(lineEdit_random, 6, 1, 1, 1); + + tabWidget->addTab(tab_2, QString()); + tab_6 = new QWidget(); + tab_6->setObjectName(QString::fromUtf8("tab_6")); + gridLayout_8 = new QGridLayout(tab_6); + gridLayout_8->setObjectName(QString::fromUtf8("gridLayout_8")); + label_36 = new QLabel(tab_6); + label_36->setObjectName(QString::fromUtf8("label_36")); + + gridLayout_8->addWidget(label_36, 0, 0, 1, 1); + + lineEdit_joystick = new QLineEdit(tab_6); + lineEdit_joystick->setObjectName(QString::fromUtf8("lineEdit_joystick")); + + gridLayout_8->addWidget(lineEdit_joystick, 0, 1, 1, 1); + + toolButton = new QToolButton(tab_6); + toolButton->setObjectName(QString::fromUtf8("toolButton")); + + gridLayout_8->addWidget(toolButton, 0, 2, 1, 1); + + checkBox_joystickEnabled = new QCheckBox(tab_6); + checkBox_joystickEnabled->setObjectName(QString::fromUtf8("checkBox_joystickEnabled")); + + gridLayout_8->addWidget(checkBox_joystickEnabled, 1, 0, 1, 2); + + tabWidget->addTab(tab_6, QString()); + tab_4 = new QWidget(); + tab_4->setObjectName(QString::fromUtf8("tab_4")); + gridLayout_7 = new QGridLayout(tab_4); + gridLayout_7->setObjectName(QString::fromUtf8("gridLayout_7")); + label_15 = new QLabel(tab_4); + label_15->setObjectName(QString::fromUtf8("label_15")); + + gridLayout_7->addWidget(label_15, 1, 0, 1, 1); + + label_17 = new QLabel(tab_4); + label_17->setObjectName(QString::fromUtf8("label_17")); + + gridLayout_7->addWidget(label_17, 6, 0, 1, 1); + + label_19 = new QLabel(tab_4); + label_19->setObjectName(QString::fromUtf8("label_19")); + + gridLayout_7->addWidget(label_19, 7, 0, 1, 1); + + lineEdit_throttleGuess = new QLineEdit(tab_4); + lineEdit_throttleGuess->setObjectName(QString::fromUtf8("lineEdit_throttleGuess")); + + gridLayout_7->addWidget(lineEdit_throttleGuess, 1, 1, 1, 1); + + lineEdit_aileronGuess = new QLineEdit(tab_4); + lineEdit_aileronGuess->setObjectName(QString::fromUtf8("lineEdit_aileronGuess")); + + gridLayout_7->addWidget(lineEdit_aileronGuess, 3, 1, 1, 1); + + lineEdit_elevatorGuess = new QLineEdit(tab_4); + lineEdit_elevatorGuess->setObjectName(QString::fromUtf8("lineEdit_elevatorGuess")); + + gridLayout_7->addWidget(lineEdit_elevatorGuess, 5, 1, 1, 1); + + lineEdit_alphaGuess = new QLineEdit(tab_4); + lineEdit_alphaGuess->setObjectName(QString::fromUtf8("lineEdit_alphaGuess")); + + gridLayout_7->addWidget(lineEdit_alphaGuess, 6, 1, 1, 1); + + lineEdit_betaGuess = new QLineEdit(tab_4); + lineEdit_betaGuess->setObjectName(QString::fromUtf8("lineEdit_betaGuess")); + + gridLayout_7->addWidget(lineEdit_betaGuess, 7, 1, 1, 1); + + label_24 = new QLabel(tab_4); + label_24->setObjectName(QString::fromUtf8("label_24")); + + gridLayout_7->addWidget(label_24, 1, 5, 1, 1); + + label_25 = new QLabel(tab_4); + label_25->setObjectName(QString::fromUtf8("label_25")); + + gridLayout_7->addWidget(label_25, 3, 5, 1, 1); + + label_26 = new QLabel(tab_4); + label_26->setObjectName(QString::fromUtf8("label_26")); + + gridLayout_7->addWidget(label_26, 5, 5, 1, 1); + + label_27 = new QLabel(tab_4); + label_27->setObjectName(QString::fromUtf8("label_27")); + + gridLayout_7->addWidget(label_27, 6, 5, 1, 1); + + label_28 = new QLabel(tab_4); + label_28->setObjectName(QString::fromUtf8("label_28")); + + gridLayout_7->addWidget(label_28, 7, 5, 1, 1); + + lineEdit_throttleMin = new QLineEdit(tab_4); + lineEdit_throttleMin->setObjectName(QString::fromUtf8("lineEdit_throttleMin")); + + gridLayout_7->addWidget(lineEdit_throttleMin, 1, 2, 1, 1); + + lineEdit_aileronMin = new QLineEdit(tab_4); + lineEdit_aileronMin->setObjectName(QString::fromUtf8("lineEdit_aileronMin")); + + gridLayout_7->addWidget(lineEdit_aileronMin, 3, 2, 1, 1); + + lineEdit_elevatorMin = new QLineEdit(tab_4); + lineEdit_elevatorMin->setObjectName(QString::fromUtf8("lineEdit_elevatorMin")); + + gridLayout_7->addWidget(lineEdit_elevatorMin, 5, 2, 1, 1); + + lineEdit_alphaMin = new QLineEdit(tab_4); + lineEdit_alphaMin->setObjectName(QString::fromUtf8("lineEdit_alphaMin")); + + gridLayout_7->addWidget(lineEdit_alphaMin, 6, 2, 1, 1); + + lineEdit_betaMin = new QLineEdit(tab_4); + lineEdit_betaMin->setObjectName(QString::fromUtf8("lineEdit_betaMin")); + + gridLayout_7->addWidget(lineEdit_betaMin, 7, 2, 1, 1); + + label_29 = new QLabel(tab_4); + label_29->setObjectName(QString::fromUtf8("label_29")); + + gridLayout_7->addWidget(label_29, 0, 1, 1, 1); + + label_30 = new QLabel(tab_4); + label_30->setObjectName(QString::fromUtf8("label_30")); + + gridLayout_7->addWidget(label_30, 0, 2, 1, 1); + + lineEdit_throttleMax = new QLineEdit(tab_4); + lineEdit_throttleMax->setObjectName(QString::fromUtf8("lineEdit_throttleMax")); + + gridLayout_7->addWidget(lineEdit_throttleMax, 1, 3, 1, 1); + + lineEdit_aileronMax = new QLineEdit(tab_4); + lineEdit_aileronMax->setObjectName(QString::fromUtf8("lineEdit_aileronMax")); + + gridLayout_7->addWidget(lineEdit_aileronMax, 3, 3, 1, 1); + + lineEdit_elevatorMax = new QLineEdit(tab_4); + lineEdit_elevatorMax->setObjectName(QString::fromUtf8("lineEdit_elevatorMax")); + + gridLayout_7->addWidget(lineEdit_elevatorMax, 5, 3, 1, 1); + + lineEdit_alphaMax = new QLineEdit(tab_4); + lineEdit_alphaMax->setObjectName(QString::fromUtf8("lineEdit_alphaMax")); + + gridLayout_7->addWidget(lineEdit_alphaMax, 6, 3, 1, 1); + + lineEdit_betaMax = new QLineEdit(tab_4); + lineEdit_betaMax->setObjectName(QString::fromUtf8("lineEdit_betaMax")); + + gridLayout_7->addWidget(lineEdit_betaMax, 7, 3, 1, 1); + + label_31 = new QLabel(tab_4); + label_31->setObjectName(QString::fromUtf8("label_31")); + + gridLayout_7->addWidget(label_31, 0, 3, 1, 1); + + label_16 = new QLabel(tab_4); + label_16->setObjectName(QString::fromUtf8("label_16")); + + gridLayout_7->addWidget(label_16, 5, 0, 1, 1); + + label_18 = new QLabel(tab_4); + label_18->setObjectName(QString::fromUtf8("label_18")); + + gridLayout_7->addWidget(label_18, 3, 0, 1, 1); + + label_32 = new QLabel(tab_4); + label_32->setObjectName(QString::fromUtf8("label_32")); + + gridLayout_7->addWidget(label_32, 4, 0, 1, 1); + + lineEdit_rudderGuess = new QLineEdit(tab_4); + lineEdit_rudderGuess->setObjectName(QString::fromUtf8("lineEdit_rudderGuess")); + + gridLayout_7->addWidget(lineEdit_rudderGuess, 4, 1, 1, 1); + + lineEdit_rudderMin = new QLineEdit(tab_4); + lineEdit_rudderMin->setObjectName(QString::fromUtf8("lineEdit_rudderMin")); + + gridLayout_7->addWidget(lineEdit_rudderMin, 4, 2, 1, 1); + + lineEdit_rudderMax = new QLineEdit(tab_4); + lineEdit_rudderMax->setObjectName(QString::fromUtf8("lineEdit_rudderMax")); + + gridLayout_7->addWidget(lineEdit_rudderMax, 4, 3, 1, 1); + + label_33 = new QLabel(tab_4); + label_33->setObjectName(QString::fromUtf8("label_33")); + + gridLayout_7->addWidget(label_33, 4, 5, 1, 1); + + lineEdit_throttleInitialStepSize = new QLineEdit(tab_4); + lineEdit_throttleInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_throttleInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_throttleInitialStepSize, 1, 4, 1, 1); + + lineEdit_aileronInitialStepSize = new QLineEdit(tab_4); + lineEdit_aileronInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_aileronInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_aileronInitialStepSize, 3, 4, 1, 1); + + lineEdit_rudderInitialStepSize = new QLineEdit(tab_4); + lineEdit_rudderInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_rudderInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_rudderInitialStepSize, 4, 4, 1, 1); + + lineEdit_elevatorInitialStepSize = new QLineEdit(tab_4); + lineEdit_elevatorInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_elevatorInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_elevatorInitialStepSize, 5, 4, 1, 1); + + lineEdit_alphaInitialStepSize = new QLineEdit(tab_4); + lineEdit_alphaInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_alphaInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_alphaInitialStepSize, 6, 4, 1, 1); + + lineEdit_betaInitialStepSize = new QLineEdit(tab_4); + lineEdit_betaInitialStepSize->setObjectName(QString::fromUtf8("lineEdit_betaInitialStepSize")); + + gridLayout_7->addWidget(lineEdit_betaInitialStepSize, 7, 4, 1, 1); + + label_37 = new QLabel(tab_4); + label_37->setObjectName(QString::fromUtf8("label_37")); + + gridLayout_7->addWidget(label_37, 0, 4, 1, 1); + + tabWidget->addTab(tab_4, QString()); + tab_5 = new QWidget(); + tab_5->setObjectName(QString::fromUtf8("tab_5")); + gridLayout_3 = new QGridLayout(tab_5); + gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3")); + label_35 = new QLabel(tab_5); + label_35->setObjectName(QString::fromUtf8("label_35")); + + gridLayout_3->addWidget(label_35, 0, 0, 1, 1); + + lineEdit_linearizationFile = new QLineEdit(tab_5); + lineEdit_linearizationFile->setObjectName(QString::fromUtf8("lineEdit_linearizationFile")); + + gridLayout_3->addWidget(lineEdit_linearizationFile, 0, 1, 1, 1); + + tabWidget->addTab(tab_5, QString()); + + gridLayout_4->addWidget(tabWidget, 0, 0, 1, 1); + + guidanceDock->setWidget(dockWidgetContents_6); + MainWindow->addDockWidget(static_cast<Qt::DockWidgetArea>(8), guidanceDock); + + retranslateUi(MainWindow); + QObject::connect(actionQuit, SIGNAL(triggered()), MainWindow, SLOT(close())); + + tabWidget->setCurrentIndex(5); + + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "mavsim Trim Program (for JSBSim models)", 0, QApplication::UnicodeUTF8)); + actionQuit->setText(QApplication::translate("MainWindow", "Quit", 0, QApplication::UnicodeUTF8)); + actionLoad_Map->setText(QApplication::translate("MainWindow", "Load Map", 0, QApplication::UnicodeUTF8)); + pushButton_trim->setText(QApplication::translate("MainWindow", "Trim", 0, QApplication::UnicodeUTF8)); + pushButton_simulate->setText(QApplication::translate("MainWindow", "Simulate", 0, QApplication::UnicodeUTF8)); + pushButton_linearize->setText(QApplication::translate("MainWindow", "Linearize", 0, QApplication::UnicodeUTF8)); + pushButton_stop->setText(QApplication::translate("MainWindow", "Stop", 0, QApplication::UnicodeUTF8)); + guidanceDock->setWindowTitle(QApplication::translate("MainWindow", "Trim Algorithm", 0, QApplication::UnicodeUTF8)); + label_2->setText(QApplication::translate("MainWindow", "Engine Path", 0, QApplication::UnicodeUTF8)); + lineEdit_enginePath->setText(QString()); + label_4->setText(QApplication::translate("MainWindow", "Systems Path", 0, QApplication::UnicodeUTF8)); + label_3->setText(QApplication::translate("MainWindow", "Aircraft Path", 0, QApplication::UnicodeUTF8)); + lineEdit_systemsPath->setText(QString()); + toolButton_enginePath->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + toolButton_systemsPath->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + toolButton_aircraftPath->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + label_9->setText(QApplication::translate("MainWindow", "Aircraft", 0, QApplication::UnicodeUTF8)); + lineEdit_aircraft->setText(QString()); + toolButton_aircraft->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + label_5->setText(QApplication::translate("MainWindow", "Initialization Script", 0, QApplication::UnicodeUTF8)); + lineEdit_initScript->setText(QString()); + toolButton_initScript->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + lineEdit_aircraftPath->setText(QString()); + label_38->setText(QApplication::translate("MainWindow", "model sim rate", 0, QApplication::UnicodeUTF8)); + lineEdit_modelSimRate->setText(QApplication::translate("MainWindow", "120", 0, QApplication::UnicodeUTF8)); + label_39->setText(QApplication::translate("MainWindow", "Hz", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab_3), QApplication::translate("MainWindow", "Aircraft", 0, QApplication::UnicodeUTF8)); + label_10->setText(QApplication::translate("MainWindow", "mode", 0, QApplication::UnicodeUTF8)); + comboBox_mode->clear(); + comboBox_mode->insertItems(0, QStringList() + << QApplication::translate("MainWindow", "Steady Level Flight", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindow", "Coordinated Turn", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindow", "Push Over", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindow", "Pull Back", 0, QApplication::UnicodeUTF8) + ); + label->setText(QApplication::translate("MainWindow", "velocity", 0, QApplication::UnicodeUTF8)); + lineEdit_velocity->setText(QApplication::translate("MainWindow", "500", 0, QApplication::UnicodeUTF8)); + label_11->setText(QApplication::translate("MainWindow", "ft/s", 0, QApplication::UnicodeUTF8)); + label_6->setText(QApplication::translate("MainWindow", "roll rate", 0, QApplication::UnicodeUTF8)); + lineEdit_rollRate->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + label_12->setText(QApplication::translate("MainWindow", "rad/s", 0, QApplication::UnicodeUTF8)); + label_7->setText(QApplication::translate("MainWindow", "pitch rate", 0, QApplication::UnicodeUTF8)); + lineEdit_pitchRate->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + label_13->setText(QApplication::translate("MainWindow", "rad/s", 0, QApplication::UnicodeUTF8)); + label_8->setText(QApplication::translate("MainWindow", "yaw rate", 0, QApplication::UnicodeUTF8)); + label_14->setText(QApplication::translate("MainWindow", "rad/s", 0, QApplication::UnicodeUTF8)); + lineEdit_yawRate->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + checkBox_stabAxisRoll->setText(QApplication::translate("MainWindow", "stability axis roll", 0, QApplication::UnicodeUTF8)); + label_40->setText(QApplication::translate("MainWindow", "altitude", 0, QApplication::UnicodeUTF8)); + lineEdit_altitude->setText(QApplication::translate("MainWindow", "1000", 0, QApplication::UnicodeUTF8)); + label_41->setText(QApplication::translate("MainWindow", "ft", 0, QApplication::UnicodeUTF8)); + label_42->setText(QApplication::translate("MainWindow", "flight path angle", 0, QApplication::UnicodeUTF8)); + lineEdit_gamma->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + checkBox_variablePropPitch->setText(QApplication::translate("MainWindow", "variable prop ptich", 0, QApplication::UnicodeUTF8)); + label_43->setText(QApplication::translate("MainWindow", "deg", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab), QApplication::translate("MainWindow", "Trim Conditions", 0, QApplication::UnicodeUTF8)); + label_20->setText(QApplication::translate("MainWindow", "relative tolerance", 0, QApplication::UnicodeUTF8)); + label_21->setText(QApplication::translate("MainWindow", "absolute tolerance", 0, QApplication::UnicodeUTF8)); + label_22->setText(QApplication::translate("MainWindow", "convergence relative step size", 0, QApplication::UnicodeUTF8)); + label_23->setText(QApplication::translate("MainWindow", "max iterations", 0, QApplication::UnicodeUTF8)); + lineEdit_abstol->setText(QApplication::translate("MainWindow", "1e-2", 0, QApplication::UnicodeUTF8)); + lineEdit_speed->setText(QApplication::translate("MainWindow", "1.1", 0, QApplication::UnicodeUTF8)); + lineEdit_iterMax->setText(QApplication::translate("MainWindow", "2000", 0, QApplication::UnicodeUTF8)); + comboBox_debugLevel->clear(); + comboBox_debugLevel->insertItems(0, QStringList() + << QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindow", "1", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindow", "2", 0, QApplication::UnicodeUTF8) + ); + label_34->setText(QApplication::translate("MainWindow", "debug level", 0, QApplication::UnicodeUTF8)); + checkBox_pause->setText(QApplication::translate("MainWindow", "pause ", 0, QApplication::UnicodeUTF8)); + lineEdit_rtol->setText(QApplication::translate("MainWindow", "1e-4", 0, QApplication::UnicodeUTF8)); + checkBox_showSimplex->setText(QApplication::translate("MainWindow", "show simplex", 0, QApplication::UnicodeUTF8)); + checkBox_showConvergence->setText(QApplication::translate("MainWindow", "show convergence", 0, QApplication::UnicodeUTF8)); + label_44->setText(QApplication::translate("MainWindow", "randomization factor", 0, QApplication::UnicodeUTF8)); + lineEdit_random->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("MainWindow", "Solver", 0, QApplication::UnicodeUTF8)); + label_36->setText(QApplication::translate("MainWindow", "joystick device", 0, QApplication::UnicodeUTF8)); + lineEdit_joystick->setText(QApplication::translate("MainWindow", "/dev/input/js0", 0, QApplication::UnicodeUTF8)); + toolButton->setText(QApplication::translate("MainWindow", "...", 0, QApplication::UnicodeUTF8)); + checkBox_joystickEnabled->setText(QApplication::translate("MainWindow", "joystick enabled", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab_6), QApplication::translate("MainWindow", "Input", 0, QApplication::UnicodeUTF8)); + label_15->setText(QApplication::translate("MainWindow", "Throttle", 0, QApplication::UnicodeUTF8)); + label_17->setText(QApplication::translate("MainWindow", "Alpha", 0, QApplication::UnicodeUTF8)); + label_19->setText(QApplication::translate("MainWindow", "Beta", 0, QApplication::UnicodeUTF8)); + lineEdit_throttleGuess->setText(QApplication::translate("MainWindow", "50", 0, QApplication::UnicodeUTF8)); + lineEdit_aileronGuess->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_elevatorGuess->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_alphaGuess->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_betaGuess->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + label_24->setText(QApplication::translate("MainWindow", "%", 0, QApplication::UnicodeUTF8)); + label_25->setText(QApplication::translate("MainWindow", "%", 0, QApplication::UnicodeUTF8)); + label_26->setText(QApplication::translate("MainWindow", "%", 0, QApplication::UnicodeUTF8)); + label_27->setText(QApplication::translate("MainWindow", "deg", 0, QApplication::UnicodeUTF8)); + label_28->setText(QApplication::translate("MainWindow", "deg", 0, QApplication::UnicodeUTF8)); + lineEdit_throttleMin->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_aileronMin->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_elevatorMin->setText(QApplication::translate("MainWindow", "-100", 0, QApplication::UnicodeUTF8)); + lineEdit_alphaMin->setText(QApplication::translate("MainWindow", "-10", 0, QApplication::UnicodeUTF8)); + lineEdit_betaMin->setText(QApplication::translate("MainWindow", "-10", 0, QApplication::UnicodeUTF8)); + label_29->setText(QApplication::translate("MainWindow", "Guess", 0, QApplication::UnicodeUTF8)); + label_30->setText(QApplication::translate("MainWindow", "Lower Bound", 0, QApplication::UnicodeUTF8)); + lineEdit_throttleMax->setText(QApplication::translate("MainWindow", "100", 0, QApplication::UnicodeUTF8)); + lineEdit_aileronMax->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_elevatorMax->setText(QApplication::translate("MainWindow", "100", 0, QApplication::UnicodeUTF8)); + lineEdit_alphaMax->setText(QApplication::translate("MainWindow", "20", 0, QApplication::UnicodeUTF8)); + lineEdit_betaMax->setText(QApplication::translate("MainWindow", "5", 0, QApplication::UnicodeUTF8)); + label_31->setText(QApplication::translate("MainWindow", "Upper Bound", 0, QApplication::UnicodeUTF8)); + label_16->setText(QApplication::translate("MainWindow", "Elevator", 0, QApplication::UnicodeUTF8)); + label_18->setText(QApplication::translate("MainWindow", "Aileron", 0, QApplication::UnicodeUTF8)); + label_32->setText(QApplication::translate("MainWindow", "Rudder", 0, QApplication::UnicodeUTF8)); + lineEdit_rudderGuess->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8)); + lineEdit_rudderMin->setText(QApplication::translate("MainWindow", "-100", 0, QApplication::UnicodeUTF8)); + lineEdit_rudderMax->setText(QApplication::translate("MainWindow", "100", 0, QApplication::UnicodeUTF8)); + label_33->setText(QApplication::translate("MainWindow", "%", 0, QApplication::UnicodeUTF8)); + lineEdit_throttleInitialStepSize->setText(QApplication::translate("MainWindow", "20", 0, QApplication::UnicodeUTF8)); + lineEdit_aileronInitialStepSize->setText(QApplication::translate("MainWindow", "10", 0, QApplication::UnicodeUTF8)); + lineEdit_rudderInitialStepSize->setText(QApplication::translate("MainWindow", "10", 0, QApplication::UnicodeUTF8)); + lineEdit_elevatorInitialStepSize->setText(QApplication::translate("MainWindow", "10", 0, QApplication::UnicodeUTF8)); + lineEdit_alphaInitialStepSize->setText(QApplication::translate("MainWindow", "10", 0, QApplication::UnicodeUTF8)); + lineEdit_betaInitialStepSize->setText(QApplication::translate("MainWindow", "5", 0, QApplication::UnicodeUTF8)); + label_37->setText(QApplication::translate("MainWindow", "Initial Step Size", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab_4), QApplication::translate("MainWindow", "Initial Guess", 0, QApplication::UnicodeUTF8)); + label_35->setText(QApplication::translate("MainWindow", "Linearization File", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(tab_5), QApplication::translate("MainWindow", "Output", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // MAINWINDOW_H diff --git a/gui/Makefile.am b/gui/Makefile.am new file mode 100644 index 0000000..17a6511 --- /dev/null +++ b/gui/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/autotroll.mk + +# initiliaze to null +bin_PROGRAMS = +BUILT_SOURCES = + +bin_PROGRAMS += trim +trim_SOURCES = main.cpp MainWindow.cpp MainWindow.hpp MainWindow.ui MainWindow.ui.h \ + osgUtils.cpp osgUtils.hpp Viewer.cpp Viewer.hpp QOSGAdapterWidget.cpp \ + QOSGAdapterWidget.hpp \ + $(top_srcdir)/src/math/FGNelderMead.cpp +trim_CXXFLAGS = $(QT_CXXFLAGS) $(AM_CXXFLAGS) +trim_CPPFLAGS = $(QT_CPPFLAGS) $(AM_CPPFLAGS) -DUSE_QT4 -DDATADIR=\"$(top_srcdir)/data\" -I$(top_srcdir)/src +trim_LDFLAGS = $(QT_LDFLAGS) $(LDFLAGS) +trim_LDADD = $(QT_LIBS) $(LDADD) +BUILT_SOURCES += MainWindow.moc.cpp MainWindow.ui.h diff --git a/gui/QOSGAdapterWidget.cpp b/gui/QOSGAdapterWidget.cpp new file mode 100644 index 0000000..204997f --- /dev/null +++ b/gui/QOSGAdapterWidget.cpp @@ -0,0 +1,194 @@ +/* OpenSceneGraph adapter widget +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "QOSGAdapterWidget.hpp" + +QOSGAdapterWidget::QOSGAdapterWidget( QWidget * parent, const char * name, const QGLWidget * shareWidget, WindowFlags f): +#if USE_QT4 + QGLWidget(parent, shareWidget, f) +#else + QGLWidget(parent, name, shareWidget, f) +#endif +{ + _gw = new osgViewer::GraphicsWindowEmbedded(0,0,width(),height()); +#if USE_QT4 + setFocusPolicy(Qt::ClickFocus); +#else + setFocusPolicy(QWidget::ClickFocus); +#endif +} + +void QOSGAdapterWidget::resizeGL( int width, int height ) +{ + _gw->getEventQueue()->windowResize(0, 0, width, height ); + _gw->resized(0,0,width,height); +} + +void QOSGAdapterWidget::keyPressEvent( QKeyEvent* event ) +{ +#if USE_QT4 + _gw->getEventQueue()->keyPress( (osgGA::GUIEventAdapter::KeySymbol) *(event->text().toAscii().data() ) ); +#else + _gw->getEventQueue()->keyPress( (osgGA::GUIEventAdapter::KeySymbol) event->ascii() ); +#endif +} + +void QOSGAdapterWidget::keyReleaseEvent( QKeyEvent* event ) +{ +#if USE_QT4 + _gw->getEventQueue()->keyRelease( (osgGA::GUIEventAdapter::KeySymbol) *(event->text().toAscii().data() ) ); +#else + _gw->getEventQueue()->keyRelease( (osgGA::GUIEventAdapter::KeySymbol) event->ascii() ); +#endif +} + +void QOSGAdapterWidget::mousePressEvent( QMouseEvent* event ) +{ + int button = 0; + switch (event->button()) + { + case(Qt::LeftButton): + button = 1; + break; + case(Qt::MidButton): + button = 2; + break; + case(Qt::RightButton): + button = 3; + break; + case(Qt::NoButton): + button = 0; + break; + default: + button = 0; + break; + } + _gw->getEventQueue()->mouseButtonPress(event->x(), event->y(), button); +} + +void QOSGAdapterWidget::mouseReleaseEvent( QMouseEvent* event ) +{ + int button = 0; + switch (event->button()) + { + case(Qt::LeftButton): + button = 1; + break; + case(Qt::MidButton): + button = 2; + break; + case(Qt::RightButton): + button = 3; + break; + case(Qt::NoButton): + button = 0; + break; + default: + button = 0; + break; + } + _gw->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button); +} + +void QOSGAdapterWidget::mouseMoveEvent( QMouseEvent* event ) +{ + _gw->getEventQueue()->mouseMotion(event->x(), event->y()); +} + +int mainQOSGAdapterWidget(QApplication& a, osg::ArgumentParser& arguments) +{ + // load the scene. + osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); + if (!loadedModel) + { + std::cout << arguments[0] <<": No data loaded." << std::endl; + return 1; + } + + std::cout<<"Using QOSGAdapterWidget - QGLWidget subclassed to integrate with osgViewer using its embedded graphics window support."<<std::endl; + + if (arguments.read("--CompositeViewer")) + { + CompositeViewerQT* viewerWindow = new CompositeViewerQT; + + unsigned int width = viewerWindow->width(); + unsigned int height = viewerWindow->height(); + + { + osgViewer::View* view1 = new osgViewer::View; + view1->getCamera()->setGraphicsContext(viewerWindow->getGraphicsWindow()); + view1->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width)/static_cast<double>(height/2), 1.0, 1000.0); + view1->getCamera()->setViewport(new osg::Viewport(0,0,width,height/2)); + view1->setCameraManipulator(new osgGA::TrackballManipulator); + view1->setSceneData(loadedModel.get()); + + viewerWindow->addView(view1); + } + + { + osgViewer::View* view2 = new osgViewer::View; + view2->getCamera()->setGraphicsContext(viewerWindow->getGraphicsWindow()); + view2->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width)/static_cast<double>(height/2), 1.0, 1000.0); + view2->getCamera()->setViewport(new osg::Viewport(0,height/2,width,height/2)); + view2->setCameraManipulator(new osgGA::TrackballManipulator); + view2->setSceneData(loadedModel.get()); + + viewerWindow->addView(view2); + } + + viewerWindow->show(); +#if USE_QT4 + } + else if (arguments.read("--mdi")) + { + std::cout<<"Using ViewetQT MDI version"<<std::endl; + /* + Following problems are found here: + - miminize causes loaded model to disappear (some problem with Camera matrix? - clampProjectionMatrix is invalid) + */ + ViewerQT* viewerWindow = new ViewerQT; + viewerWindow->setCameraManipulator(new osgGA::TrackballManipulator); + viewerWindow->setSceneData(loadedModel.get()); + + QMainWindow* mw = new QMainWindow(); + QMdiArea* mdiArea = new QMdiArea(mw); + mw->setCentralWidget(mdiArea); + + QMdiSubWindow *subWindow = mdiArea->addSubWindow(viewerWindow); + subWindow->showMaximized(); + subWindow->setWindowTitle("New Window"); + mw->show(); +#endif // USE_QT4 + } + else + { + ViewerQT* viewerWindow = new ViewerQT; + + viewerWindow->setCameraManipulator(new osgGA::TrackballManipulator); + viewerWindow->setSceneData(loadedModel.get()); + + viewerWindow->show(); + } + + + a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); + + return a.exec(); +} + +/*EOF*/ diff --git a/gui/QOSGAdapterWidget.hpp b/gui/QOSGAdapterWidget.hpp new file mode 100644 index 0000000..9763610 --- /dev/null +++ b/gui/QOSGAdapterWidget.hpp @@ -0,0 +1,147 @@ +/* OpenSceneGraph example, osganimate. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#ifndef QOSGAdapterWidget_H +#define QOSGAdapterWidget_H + +#include <osgViewer/Viewer> +#include <osgViewer/CompositeViewer> +#include <osgViewer/ViewerEventHandlers> +#include <osgGA/TrackballManipulator> +#include <osgDB/ReadFile> +#include <QMutex> +//#include "config.h" + +#if USE_QT4 + +#include <QtCore/QString> +#include <QtCore/QTimer> +#include <QtGui/QKeyEvent> +#include <QtGui/QApplication> +#include <QtOpenGL/QGLWidget> +#include <QtGui/QMainWindow> +#include <QtGui/QMdiSubWindow> +#include <QtGui/QMdiArea> + +using Qt::WindowFlags; + +#else + +class QWidget; +#include <qtimer.h> +#include <qgl.h> +#include <qapplication.h> + +#define WindowFlags WFlags + +#endif + +#include <iostream> + +class QOSGAdapterWidget : public QGLWidget +{ +public: + + QOSGAdapterWidget( QWidget * parent = 0, const char * name = 0, const QGLWidget * shareWidget = 0, WindowFlags f = 0 ); + + virtual ~QOSGAdapterWidget() {} + + osgViewer::GraphicsWindow* getGraphicsWindow() + { + return _gw.get(); + } + const osgViewer::GraphicsWindow* getGraphicsWindow() const + { + return _gw.get(); + } + +protected: + + void init(); + + virtual void resizeGL( int width, int height ); + virtual void keyPressEvent( QKeyEvent* event ); + virtual void keyReleaseEvent( QKeyEvent* event ); + virtual void mousePressEvent( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent* event ); + virtual void mouseMoveEvent( QMouseEvent* event ); + + osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _gw; +}; + +class ViewerQT : public osgViewer::Viewer, public QOSGAdapterWidget +{ +public: + + QMutex mutex; + + ViewerQT(QWidget * parent = 0, const char * name = 0, const QGLWidget * shareWidget = 0, WindowFlags f = 0): + QOSGAdapterWidget( parent, name, shareWidget, f ) + { + getCamera()->setViewport(new osg::Viewport(0,0,width(),height())); + getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width())/static_cast<double>(height()), 1.0f, 10000.0f); + getCamera()->setGraphicsContext(getGraphicsWindow()); + + setThreadingModel(osgViewer::Viewer::SingleThreaded); + + connect(&_timer, SIGNAL(timeout()), this, SLOT(updateGL())); + _timer.start(100); + } + + virtual void paintGL() + { + mutex.lock(); + frame(); + mutex.unlock(); + } + +protected: + + QTimer _timer; +}; + +class CompositeViewerQT : public osgViewer::CompositeViewer, public QOSGAdapterWidget +{ +public: + + QMutex mutex; + + CompositeViewerQT(QWidget * parent = 0, const char * name = 0, const QGLWidget * shareWidget = 0, WindowFlags f = 0): + QOSGAdapterWidget( parent, name, shareWidget, f ) + { + setThreadingModel(osgViewer::CompositeViewer::SingleThreaded); + + connect(&_timer, SIGNAL(timeout()), this, SLOT(updateGL())); + _timer.start(100); + } + + virtual void paintGL() + { + mutex.lock(); + frame(); + mutex.unlock(); + } + +protected: + + QTimer _timer; +}; + +#endif + +/*EOF*/ diff --git a/gui/Viewer.cpp b/gui/Viewer.cpp new file mode 100644 index 0000000..d38641d --- /dev/null +++ b/gui/Viewer.cpp @@ -0,0 +1,76 @@ +/* + * Viewer.cpp + * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> + * + * Viewer.cpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Viewer.cpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Viewer.hpp" +#include <boost/bind.hpp> +#include <osgGA/TrackballManipulator> + +namespace mavsim +{ + +namespace visualization +{ + +Viewer::Viewer(int fps) : + myThread(), myMutex(), myFps(fps) +{ + using namespace osgViewer; + setThreadSafeReferenceCounting(true); + setThreadSafeRefUnref(true); + setCameraManipulator(new osgGA::TrackballManipulator); +} + +Viewer::~Viewer() +{ + if (myThread) myThread->join(); +} + +int Viewer::run() +{ + realize(); + myThread.reset(new boost::thread(boost::bind(&Viewer::loop,this))); + return 0; +} + +void Viewer::loop() +{ + while (!done()) + { + lock(); + frame(); + unlock(); + usleep(1e6/myFps); + } +} + +void Viewer::lock() +{ + myMutex.lock(); +} + +void Viewer::unlock() +{ + myMutex.unlock(); +} + +} // visualization + +} // mavsim + + +// vim:ts=4:sw=4 diff --git a/gui/Viewer.hpp b/gui/Viewer.hpp new file mode 100644 index 0000000..2cbc615 --- /dev/null +++ b/gui/Viewer.hpp @@ -0,0 +1,72 @@ +/* + * Viewer.hpp + * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> + * + * Viewer.hpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Viewer.hpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef mavsim_Viewer_HPP +#define mavsim_Viewer_HPP + +#include <osgViewer/Viewer> +#include <boost/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/scoped_ptr.hpp> + +namespace mavsim +{ + +namespace visualization +{ + +/** + * The purpose of this class is to create a viewer for simulation purposes. + */ +class Viewer : public osgViewer::Viewer +{ +public: + /** + * Constructor + */ + Viewer(int fps = 20); + virtual ~Viewer(); + /** + * Override default run to be mutex lockable + */ + int run(); + /** + * Function to frame viewer + */ + void loop(); + /** + * Unlock the mutex and allow the viewer to frame + */ + void unlock(); + /** + * Lock the mutex and prevent viewer from framing + */ + void lock(); +private: + boost::scoped_ptr<boost::thread> myThread; // viewer thread + boost::mutex myMutex; // mutex lock to protect data for multi-threading + int myFps; // Approxmiate frames per second, neglects framing time +}; + +} // visualization + +} // mavsim + +#endif + +// vim:ts=4:sw=4 diff --git a/gui/main.cc b/gui/main.cc new file mode 100644 index 0000000..0bb82d4 --- /dev/null +++ b/gui/main.cc @@ -0,0 +1,16 @@ +/* +** main.cc for autotroll-test in /tmp/autotroll/src +** +** Made by SIGOURE Benoit +** Mail <sigoure.benoit@lrde.epita.fr> +** +** Started on Mon Oct 16 11:04:14 2006 SIGOURE Benoit +** Last update Mon Oct 16 11:04:50 2006 SIGOURE Benoit +*/ + +int qt_main (int, char **); + +int main (int argc, char **argv) +{ + return qt_main (argc, argv); +} diff --git a/gui/main.cpp b/gui/main.cpp new file mode 100644 index 0000000..61683ce --- /dev/null +++ b/gui/main.cpp @@ -0,0 +1,14 @@ +#include <QApplication> +#include <QSplashScreen> +#include "MainWindow.hpp" +#include <X11/Xlib.h> + +int main (int argc, char * argv[]) +{ + XInitThreads(); + QApplication app(argc,argv); + app.processEvents(); + MainWindow w; + w.show(); + return app.exec(); +} diff --git a/gui/osgUtils.cpp b/gui/osgUtils.cpp new file mode 100644 index 0000000..c75bea2 --- /dev/null +++ b/gui/osgUtils.cpp @@ -0,0 +1,591 @@ +/* + * osgUtils.cpp + * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> + * + * osgUtils.cpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * osgUtils.cpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "osgUtils.hpp" +#include <osg/Group> +#include <iostream> +#include <osgText/Text> +#include <osg/Geode> +#include <osg/AutoTransform> +#include <osg/ShapeDrawable> +#include <osg/PositionAttitudeTransform> +#include <osg/Material> +#include <osg/Depth> +#include <osg/PointSprite> +#include <osg/Point> +#include <osgDB/ReadFile> +#include <stdexcept> +//#include "config.h" + +namespace mavsim +{ + +namespace visualization +{ + +std::vector<osg::Node*> findNamedNodes(const std::string& searchName, + osg::Node* currNode) +{ + osg::Group* currGroup; + std::vector<osg::Node*> foundNodes; + osg::Node *foundNode; + + // check to see if we have a valid (non-NULL) node. + // if we do have a null node, return NULL. + if ( !currNode) + { + return foundNodes; + } + + // We have a valid node, check to see if this is the node we + // are looking for. If so, return the current node. + if (currNode->getName() == searchName) + { + foundNodes.push_back(currNode); + } + + // We have a valid node, but not the one we are looking for. + // Check to see if it has children (non-leaf node). If the node + // has children, check each of the child nodes by recursive call. + // If one of the recursive calls returns a non-null value we have + // found the correct node, so return this node. + // If we check all of the children and have not found the node, + // return NULL + currGroup = currNode->asGroup(); // returns NULL if not a group. + if ( currGroup ) + { + for (unsigned int i = 0 ; i < currGroup->getNumChildren(); i ++) + { + std::vector<osg::Node*> subNodes = findNamedNodes(searchName, currGroup->getChild(i)); + if (subNodes.size()) + for(int j=0; j<subNodes.size(); j++) foundNodes.push_back(subNodes[j]); // found a match! + } + } + return foundNodes; +} + + +NodeFinder::NodeFinder(const std::string & name) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + myName(name), myNode(NULL) +{ +} + +void NodeFinder::apply(osg::Node& node) +{ + if (node.getName() == myName) + myNode = &node; + // traverse rest of graph + traverse(node); +} + +osg::Node* NodeFinder::getNode() +{ + return myNode.get(); +} + +NodeFinder::~NodeFinder() +{ +} + +void attachNode(const std::string & nodeName, + osg::Node * attachNode, + osg::Node * rootNode) +{ + NodeFinder nf(nodeName); + nf.apply(*rootNode); + osg::Node * node = nf.getNode(); + if (node != NULL) + { + osg::Group * group = node->asGroup(); + osg::Group * parent = group->getParent(0); + parent->removeChild(group); + parent->addChild(attachNode->asGroup()); + attachNode->asGroup()->addChild(group); + } + else + { + std::cerr << "node: " << nodeName << " not found." << std::endl; + } +} + +Label::Label( + const osg::Vec3& position, + const std::string& message, + float characterSize, + float minScale, + float maxScale) +{ + /* + osgText::Text* text = new osgText::Text; + text->setCharacterSize(characterSize); + text->setText(message); + text->setAlignment(osgText::Text::CENTER_CENTER); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + osg::AutoTransform* at = new osg::AutoTransform; + at->addChild(geode); + + at->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN); + at->setAutoScaleToScreen(true); + at->setMinimumScale(minScale); + at->setMaximumScale(maxScale); + at->setPosition(position); + addChild(at); + */ +} + +Frame::Frame( + float size, + const std::string & xLabel, + const std::string & yLabel, + const std::string & zLabel, + const osg::Vec4 & xColor, + const osg::Vec4 & yColor, + const osg::Vec4 & zColor) +{ + addChild(new Vector3(osg::Vec3(0,0,0), + osg::Vec3(size,0,0),xLabel,xColor)); + addChild(new Vector3(osg::Vec3(0,0,0), + osg::Vec3(0,size,0),yLabel,yColor)); + addChild(new Vector3(osg::Vec3(0,0,0), + osg::Vec3(0,0,size),zLabel,zColor)); +} + +Actuator::Actuator( + const std::string & name, + const osg::Vec3 & center, + osg::Node * root) : + myPat(new osg::PositionAttitudeTransform), + myCenter(center) +{ + attachNode(name,myPat,root); + myPat->setPosition(center); + myPat->setPivotPoint(center); +} + +void Actuator::setAttitude(osg::Quat quat) +{ + myPat->setAttitude(quat); +} + +void Actuator::setPosition(double x, double y, double z) +{ + myPat->setPosition(osg::Vec3(x,y,z)+myCenter); +} + +Vector3::Vector3(const osg::Vec3 & start, + const osg::Vec3 & end, + const std::string & name, + const osg::Vec4 & color) : + myPat(new osg::PositionAttitudeTransform) +{ + osg::Geode * geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable( + new osg::Cone(osg::Vec3(0,0,.9),.05,.1))); + geode->addDrawable(new osg::ShapeDrawable( + new osg::Cylinder(osg::Vec3(0,0,.45),.01,.9))); + osg::Material * material = new osg::Material; + material->setDiffuse(osg::Material::FRONT,color); + geode->getOrCreateStateSet()->setAttribute(material, osg::StateAttribute::OVERRIDE ); + myPat->addChild(new Label(osg::Vec3(0,0,1),name)); + myPat->addChild(geode); + myPat->getOrCreateStateSet()->setMode(GL_NORMALIZE, + osg::StateAttribute::ON); + set(start,end); + addChild(myPat); +} + + +void Vector3::set(const osg::Vec3 & start, + const osg::Vec3 & end) +{ + osg::Vec3 delta = end-start; + double length = delta.normalize(); + osg::Vec3 zAxis(0,0,1); + myPat->setAttitude(osg::Quat(acos(zAxis*delta),zAxis^delta)); + myPat->setPosition(start); + myPat->setPivotPoint(start); + myPat->setScale(osg::Vec3(1,1,1)*length); +} + +Ellipsoid::Ellipsoid(osg::Vec3d radii, osg::Vec3d center, osg::Vec4 color, int vBands, int hBands) : + myRadii(radii), + myCenter(center), + myVBands(vBands), + myHBands(hBands), + myGeom(new osg::Geometry), + myVertices(new osg::Vec3Array), + myNormals(new osg::Vec3Array), + myPrimitive(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP,0)) +{ + osg::Geode * geode = new osg::Geode; + osg::Vec4Array * colors = new osg::Vec4Array; + + myGeom->setVertexArray(myVertices); + + colors->push_back(color); + myGeom->setColorArray(colors); + myGeom->setColorBinding(osg::Geometry::BIND_OVERALL); + + myGeom->setNormalArray(myNormals); + myGeom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + + myGeom->addPrimitiveSet(myPrimitive); + geode->addDrawable(myGeom); + + addChild(geode); + + // transparency + if (color[3] != 1) + { + // Enable blending, select transparent bin. + osg::StateSet * stateSet = geode->getOrCreateStateSet(); + stateSet->setMode( GL_BLEND, osg::StateAttribute::ON ); + stateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); + + // Enable depth test so that an opaque polygon will occlude a transparent one behind it. + stateSet->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON ); + + // Conversely, disable writing to depth buffer so that + //a transparent polygon will allow polygons behind it to shine thru. + //OSG renders transparent polygons after opaque ones. + osg::Depth * depth = new osg::Depth; + depth->setWriteMask( false ); + stateSet->setAttributeAndModes( depth, osg::StateAttribute::ON ); + + // Disable lighting + stateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); + } + + draw(); +} + +Ellipsoid::~Ellipsoid() +{ +} + +void Ellipsoid::setParam(osg::Vec3d radii, osg::Vec3d center) +{ + myRadii = radii; + myCenter = center; + draw(); +} + +void Ellipsoid::addPoint(osg::Vec3 vert) +{ + osg::Vec3 norm = vert - myCenter; + norm.normalize(); + myNormals->push_back(norm); + myVertices->push_back(vert); + myPrimitive->push_back(myVertices->size()-1); +} + +void Ellipsoid::draw() +{ + myNormals->clear(); + myVertices->clear(); + myPrimitive->clear(); + + osg::Vec3 nadir = myCenter+osg::Vec3(0,0,myRadii.z()); + osg::Vec3 zenith = myCenter+osg::Vec3(0,0,-myRadii.z()); + + double hStep = 2*M_PI/myHBands, vStep = M_PI/myVBands; + for (double theta=0; theta<M_PI; theta+=hStep) + { + for (double phi=0; phi<2*M_PI; phi+=vStep) + { + if (phi != 0 && phi!= M_PI) + { + addPoint(osg::Vec3(myRadii.x()*sin(phi)*cos(theta)+myCenter.x(), + myRadii.y()*sin(phi)*sin(theta)+myCenter.y(), + myRadii.z()*cos(phi)+myCenter.z())); + addPoint(osg::Vec3(myRadii.x()*sin(phi)*cos(theta+hStep)+myCenter.x(), + myRadii.y()*sin(phi)*sin(theta+hStep)+myCenter.y(), + myRadii.z()*cos(phi)+myCenter.z())); + } + else if (phi == 0) + { + addPoint(nadir); + addPoint(nadir); + } + else if (phi == M_PI) + { + addPoint(zenith); + addPoint(zenith); + } + else std::cout<<"Error: Ellipsoid point not added"<<std::endl; + } + } + addPoint(nadir); //add last point of sphere + myGeom->dirtyDisplayList(); // force redraw +} + +PointCloud::PointCloud(int pointSize) : + myPoints(new osg::Vec3Array), + myColors(new osg::Vec4Array), + myGeom(new osg::Geometry), + myDrawArrays(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, myPoints->size())) +{ + osg::Geode * geode = new osg::Geode; + addChild(geode); + geode->setStateSet(makeStateSet(pointSize)); + geode->addDrawable(myGeom); + myGeom->setVertexArray(myPoints); + myGeom->setColorArray(myColors); + myGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); + myGeom->addPrimitiveSet(myDrawArrays); +} + +void PointCloud::addPoint(osg::Vec3 point, osg::Vec4 color) +{ + myPoints->push_back(point); + myColors->push_back(color); + updateSize(); +} + +void PointCloud::clear() +{ + myPoints->clear(); + myColors->clear(); + updateSize(); +} + +void PointCloud::updateSize() +{ + myDrawArrays->setCount(myPoints->size()); + myGeom->dirtyDisplayList(); +} + +osg::StateSet* PointCloud::makeStateSet(float size) +{ + osg::StateSet *set = new osg::StateSet(); + + /// Setup the point sprites + osg::PointSprite *sprite = new osg::PointSprite(); + set->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON); + + /// Give some size to the points to be able to see the sprite + osg::Point *point = new osg::Point(); + point->setSize(size); + set->setAttribute(point); + + /// Disable depth test to avoid sort problems and Lighting + set->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + set->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + return set; +} + +Jet::Jet() : + modelPat(), model(), myLeftAileron(), myRightAileron(), + myLeftElevator(), myRightElevator(), myRudder() +{ + std::string modelFile("DATADIR/models/jet.ac"); + model = osgDB::readNodeFile(modelFile); + if (!model) + { + throw(std::runtime_error("can't find model: " + modelFile)); + return; + } + modelPat = new PositionAttitudeTransform; + modelPat->setAttitude(osg::Quat(-M_PI/2,osg::Vec3(1,0,0))); + modelPat->addChild(model); + myLeftAileron.reset(new Actuator("leftAileron",osg::Vec3(-1.077,-0.319,2.652),model)); + myRightAileron.reset(new Actuator("rightAileron",osg::Vec3(-1.075,-0.319,-2.652),model)); + myLeftElevator.reset(new Actuator("leftElevator",osg::Vec3(-5.806,0.320,1.511),model)); + myRightElevator.reset(new Actuator("rightElevator",osg::Vec3(-5.806,0.320,-1.511),model)); + myRudder.reset(new Actuator("rudder",osg::Vec3(-6.485,2.114,0.000),model)); + myThrustPlume.reset(new Actuator("thrustPlume",osg::Vec3(0,0,0),model)); + addChild(modelPat); +} + +void Jet::setEuler(double roll, double pitch, double yaw) +{ + setAttitude(osg::Quat( + roll,osg::Vec3(1,0,0), + pitch,osg::Vec3(0,1,0), + yaw,osg::Vec3(0,0,1))); +} + +void Jet::setPositionScalars(double x, double y, double z) +{ + setPosition(osg::Vec3(x,y,z)); +} + +void Jet::setU(double throttle, double aileron, double elevator, double rudder) +{ + myLeftAileron->setAttitude(osg::Quat(aileron,osg::Vec3(0,0,1))); + myRightAileron->setAttitude(osg::Quat(-aileron,osg::Vec3(0,0,1))); + myLeftElevator->setAttitude(osg::Quat(elevator,osg::Vec3(0,0,1))); + myRightElevator->setAttitude(osg::Quat(elevator,osg::Vec3(0,0,1))); + myRudder->setAttitude(osg::Quat(rudder,osg::Vec3(0,1,0))); + myThrustPlume->setPosition(3-3*throttle,0,0); +} + +Plane::Plane() : + model(), myLeftAileron(), myRightAileron(), + myLeftElevator(), myRightElevator(), myRudder(), propAngle() +{ + std::string modelFile("DATADIR/models/plane.ac"); + model = osgDB::readNodeFile(modelFile); + if (!model) + { + throw(std::runtime_error("can't find model: " + modelFile)); + return; + } + modelPat = new PositionAttitudeTransform; + modelPat->setAttitude(osg::Quat(-M_PI/2,osg::Vec3(1,0,0))); + modelPat->addChild(model); + myLeftAileron.reset(new Actuator("leftAileron",osg::Vec3(-0.063,-0.559,3.514),model)); + myRightAileron.reset(new Actuator("rightAileron",osg::Vec3(-0.063,-0.559,-3.514),model)); + myLeftElevator.reset(new Actuator("leftElevator",osg::Vec3(-5.651,-0.019,-0.115),model)); + myRightElevator.reset(new Actuator("rightElevator",osg::Vec3(-5.651,0.019,-0.115),model)); + myRudder.reset(new Actuator("rudder",osg::Vec3(-5.638,0.234,0.000),model)); + myPropeller.reset(new Actuator("propeller",osg::Vec3(3.874,-0.353,0.003),model)); + addChild(modelPat); +} + +void Plane::setEuler(double roll, double pitch, double yaw) +{ + setAttitude(osg::Quat( + roll,osg::Vec3(1,0,0), + pitch,osg::Vec3(0,1,0), + yaw,osg::Vec3(0,0,1))); +} + +void Plane::setPositionScalars(double x, double y, double z) +{ + setPosition(osg::Vec3(x,y,z)); +} + +void Plane::setU(double throttle, double aileron, double elevator, double rudder) +{ + myLeftAileron->setAttitude(osg::Quat(aileron,osg::Vec3(0,0,1))); + myRightAileron->setAttitude(osg::Quat(-aileron,osg::Vec3(0,0,1))); + myLeftElevator->setAttitude(osg::Quat(elevator,osg::Vec3(0,0,1))); + myRightElevator->setAttitude(osg::Quat(elevator,osg::Vec3(0,0,1))); + myRudder->setAttitude(osg::Quat(rudder,osg::Vec3(0,1,0))); + myPropeller->setAttitude(osg::Quat(propAngle+=5*throttle,osg::Vec3(1,0,0))); +} + +Car::Car() : + model(), myWheelLF(), myWheelLB(), + myWheelRF(), myWheelRB(), + myTireAngleLF(), myTireAngleLB(), + myTireAngleRF(), myTireAngleRB() +{ + std::string modelFile("DATADIR/models/rcTruck.ac"); + std::cout << "model file: " << modelFile << std::endl; + model = osgDB::readNodeFile(modelFile); + if (!model) + { + throw(std::runtime_error("can't find model: " + modelFile)); + return; + } + modelPat = new PositionAttitudeTransform; + modelPat->setAttitude(osg::Quat(-M_PI/2,osg::Vec3(1,0,0))); + modelPat->addChild(model); + myWheelLF.reset(new Actuator("wheelLF",osg::Vec3(0.304,-0.087,-0.260),model)); + myWheelRF.reset(new Actuator("wheelRF",osg::Vec3(0.304,-0.087,0.260),model)); + myWheelLB.reset(new Actuator("wheelLB",osg::Vec3(-0.304,-0.087,-0.260),model)); + myWheelRB.reset(new Actuator("wheelRB",osg::Vec3(-0.304,-0.087,0.260),model)); + addChild(modelPat); +} + +void Car::setEuler(double roll, double pitch, double yaw) +{ + setAttitude(osg::Quat( + roll,osg::Vec3(1,0,0), + pitch,osg::Vec3(0,1,0), + yaw,osg::Vec3(0,0,1))); +} + +void Car::setPositionScalars(double x, double y, double z) +{ + setPosition(osg::Vec3(x,y,z)); +} + +void Car::setU(double throttle, double steering, double velocity) +{ + myWheelLF->setAttitude(osg::Quat( + myTireAngleLF-=0.5*throttle,osg::Vec3(0,0,1), + 0,osg::Vec3(1,0,0), + steering,osg::Vec3(0,-1,0))); + myWheelLB->setAttitude(osg::Quat(myTireAngleLB-=0.5*throttle,osg::Vec3(0,0,1))); + myWheelRF->setAttitude(osg::Quat( + myTireAngleRF-=0.5*throttle,osg::Vec3(0,0,1), + 0,osg::Vec3(1,0,0), + steering,osg::Vec3(0,-1,0))); + myWheelRB->setAttitude(osg::Quat(myTireAngleRB-=0.5*throttle,osg::Vec3(0,0,1))); +} + +Quad::Quad() : + model(), myPropF(), myPropB(),myPropL(), myPropR(), + myPropAngleF(), myPropAngleB(), myPropAngleL(), myPropAngleR() +{ + std::string modelFile("DATADIR/models/arducopter.ac"); + std::cout << "model file: " << modelFile << std::endl; + model = osgDB::readNodeFile(modelFile); + if (!model) + { + throw(std::runtime_error("can't find model: " + modelFile)); + return; + } + modelPat = new PositionAttitudeTransform; + modelPat->setAttitude(osg::Quat(-M_PI/2,osg::Vec3(1,0,0))); + modelPat->addChild(model); + myPropF.reset(new Actuator("propellerF",osg::Vec3(0.288,0.046,0),modelPat)); + myPropB.reset(new Actuator("propellerB",osg::Vec3(-0.288,0.046,0),modelPat)); + myPropL.reset(new Actuator("propellerL",osg::Vec3(0,0.046,-0.288),modelPat)); + myPropR.reset(new Actuator("propellerR",osg::Vec3(0,0.046,0.288),modelPat)); + addChild(modelPat); +} + +void Quad::setEuler(double roll, double pitch, double yaw) +{ + setAttitude(osg::Quat( + roll,osg::Vec3(1,0,0), + pitch,osg::Vec3(0,1,0), + yaw,osg::Vec3(0,0,1))); +} + +void Quad::setPositionScalars(double x, double y, double z) +{ + setPosition(osg::Vec3(x,y,z)); +} + +void Quad::setU(double throttleF, double throttleB, double throttleL, double throttleR) +{ + myPropF->setAttitude(osg::Quat(myPropAngleF-=-0.5*throttleF,osg::Vec3(0,1,0))); + myPropB->setAttitude(osg::Quat(myPropAngleB-=-0.5*throttleB,osg::Vec3(0,1,0))); + myPropL->setAttitude(osg::Quat(myPropAngleL-=0.5*throttleL,osg::Vec3(0,1,0))); + myPropR->setAttitude(osg::Quat(myPropAngleR-=0.5*throttleR,osg::Vec3(0,1,0))); +} + + + +} // visualization + +} // mavsim + + +// vim:ts=4:sw=4 diff --git a/gui/osgUtils.hpp b/gui/osgUtils.hpp new file mode 100644 index 0000000..56c8f67 --- /dev/null +++ b/gui/osgUtils.hpp @@ -0,0 +1,224 @@ +/* + * osgUtils.hpp + * Copyright (C) James Goppert 2010 <jgoppert@users.sourceforge.net> + * + * osgUtils.hpp is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * osgUtils.hpp is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef mavsim_osgUtils_HPP +#define mavsim_osgUtils_HPP + +#include <osg/NodeVisitor> +#include <osg/PositionAttitudeTransform> +#include <osg/Geometry> +#include <boost/scoped_ptr.hpp> + +#include <float.h> + +namespace mavsim +{ + +namespace visualization +{ + +static const osg::Vec4d white(1,1,1,1), red(1,0,0,1), green(0,1,0,1), blue(0,0,1,1), pink(1,0,1,1); + +std::vector<osg::Node*> findNamedNodes(const std::string& searchName, + osg::Node* currNode); + +class NodeFinder : public osg::NodeVisitor +{ +public: + NodeFinder(const std::string & name); + // This method gets called for every node in the scene + // graph. It checks each node to see if its name matches + // the target. If so, it saves the node's address. + virtual void apply(osg::Node& node); + osg::Node* getNode(); + virtual ~NodeFinder(); +protected: + std::string myName; + osg::ref_ptr<osg::Node> myNode; +}; + +void attachNode(const std::string & nodeName, + osg::Node * attachNode, + osg::Node * rootNode); + +class Label : public osg::Group +{ +public: + Label( + const osg::Vec3& position, + const std::string& message, + float characterSize=40, + float minScale=0, + float maxScale=FLT_MAX); +}; + +class Frame : public osg::PositionAttitudeTransform +{ +public: + Frame( + float size=10, + const std::string & xLabel="x", + const std::string & yLabel="y", + const std::string & zLabel="z", + const osg::Vec4 & xColor = osg::Vec4(1,0,0,1), + const osg::Vec4 & yColor = osg::Vec4(0,1,0,1), + const osg::Vec4 & zColor = osg::Vec4(0,0,1,1)); +}; + +class Actuator +{ +public: + Actuator( + const std::string & name, + const osg::Vec3 & center, + osg::Node * root); + void setAttitude(osg::Quat quat); + void setPosition(double x, double y, double z); +private: + osg::PositionAttitudeTransform * myPat; + osg::Vec3 myCenter; +}; + +class Vector3 : public osg::Group +{ +public: + Vector3(const osg::Vec3 & start, + const osg::Vec3 & end, + const std::string & name="", + const osg::Vec4 & color=osg::Vec4(1,0,0,1)); + void set(const osg::Vec3 & start, + const osg::Vec3 & end); +private: + osg::PositionAttitudeTransform * myPat; +}; + +class Ellipsoid : public osg::PositionAttitudeTransform +{ +public: + Ellipsoid(osg::Vec3d radii, osg::Vec3d center, osg::Vec4 color=osg::Vec4(1,0,0,1), + int vBands = 10, int hBands = 10); + void draw(); + virtual ~Ellipsoid(); + void setParam(osg::Vec3d radii, osg::Vec3d center); + void addPoint(osg::Vec3 vec); + +private: + osg::Vec3d myRadii, myCenter; + int myVBands, myHBands; + osg::ref_ptr<osg::Geometry> myGeom; + osg::ref_ptr<osg::Vec3Array> myVertices; + osg::ref_ptr<osg::Vec3Array> myNormals; + osg::ref_ptr<osg::DrawElementsUInt> myPrimitive; +}; + +class PointCloud : public osg::PositionAttitudeTransform +{ +public: + PointCloud(int pointSize); + void addPoint(osg::Vec3 point, osg::Vec4 color=osg::Vec4(1,1,1,0)); + void clear(); +private: + void updateSize(); + osg::ref_ptr<osg::Vec3Array> myPoints; + osg::ref_ptr<osg::Vec4Array> myColors; + osg::ref_ptr<osg::Geometry> myGeom; + osg::ref_ptr<osg::DrawArrays> myDrawArrays; + osg::StateSet* makeStateSet(float size); +}; + +class Jet : public osg::PositionAttitudeTransform +{ +public: + Jet(); + void setEuler(double roll, double pitch, double yaw); + void setPositionScalars(double x, double y, double z); + void setU(double throttle, double aileron, double elevator, double rudder); +private: + osg::ref_ptr<osg::Node> model; + osg::ref_ptr<osg::PositionAttitudeTransform> modelPat; + boost::scoped_ptr<Actuator> myLeftAileron; + boost::scoped_ptr<Actuator> myRightAileron; + boost::scoped_ptr<Actuator> myLeftElevator; + boost::scoped_ptr<Actuator> myRightElevator; + boost::scoped_ptr<Actuator> myRudder; + boost::scoped_ptr<Actuator> myThrustPlume; +}; + +class Plane : public osg::PositionAttitudeTransform +{ +public: + Plane(); + void setEuler(double roll, double pitch, double yaw); + void setPositionScalars(double x, double y, double z); + void setU(double throttle, double aileron, double elevator, double rudder); +private: + double propAngle; + osg::ref_ptr<osg::Node> model; + osg::ref_ptr<osg::PositionAttitudeTransform> modelPat; + boost::scoped_ptr<Actuator> myLeftAileron; + boost::scoped_ptr<Actuator> myRightAileron; + boost::scoped_ptr<Actuator> myLeftElevator; + boost::scoped_ptr<Actuator> myRightElevator; + boost::scoped_ptr<Actuator> myRudder; + boost::scoped_ptr<Actuator> myPropeller; +}; + +class Car : public osg::PositionAttitudeTransform +{ +public: + Car(); + void setEuler(double roll, double pitch, double yaw); + void setPositionScalars(double x, double y, double z); + void setU(double throttle, double steering, double velocity); +private: + osg::ref_ptr<osg::Node> model; + osg::ref_ptr<osg::PositionAttitudeTransform> modelPat; + double myTireAngleLF, myTireAngleLB, myTireAngleRF, myTireAngleRB; + boost::scoped_ptr<Actuator> myWheelLF; + boost::scoped_ptr<Actuator> myWheelLB; + boost::scoped_ptr<Actuator> myWheelRF; + boost::scoped_ptr<Actuator> myWheelRB; +}; + +class Quad : public osg::PositionAttitudeTransform +{ +public: + Quad(); + void setEuler(double roll, double pitch, double yaw); + void setPositionScalars(double x, double y, double z); + void setU(double throttleF, double throttleB, double throttleL, double throttleR); +private: + double myPropAngleF, myPropAngleB, myPropAngleL, myPropAngleR; + osg::ref_ptr<osg::Node> model; + osg::ref_ptr<osg::PositionAttitudeTransform> modelPat; + boost::scoped_ptr<Actuator> myPropF; + boost::scoped_ptr<Actuator> myPropB; + boost::scoped_ptr<Actuator> myPropL; + boost::scoped_ptr<Actuator> myPropR; +}; + + + + +} // visualization + +} // mavsim + +#endif + +// vim:ts=4:sw=4 diff --git a/gui/qt_main.cpp b/gui/qt_main.cpp new file mode 100644 index 0000000..5fc4ddc --- /dev/null +++ b/gui/qt_main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include <QApplication> +#include <QFont> +#include <QGridLayout> +#include <QPushButton> +#include <QWidget> + +#include "lcdrange.h" + +class MyWidget : public QWidget +{ +public: + MyWidget(QWidget *parent = 0); +}; + +MyWidget::MyWidget(QWidget *parent) + : QWidget(parent) +{ + QPushButton *quit = new QPushButton(tr("Quit")); + quit->setFont(QFont("Times", 18, QFont::Bold)); + + connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); + + QGridLayout *grid = new QGridLayout; + LCDRange *previousRange = 0; + + for (int row = 0; row < 3; ++row) { + for (int column = 0; column < 3; ++column) { + LCDRange *lcdRange = new LCDRange; + grid->addWidget(lcdRange, row, column); + if (previousRange) + connect(lcdRange, SIGNAL(valueChanged(int)), + previousRange, SLOT(setValue(int))); + previousRange = lcdRange; + } + } + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(quit); + layout->addLayout(grid); + setLayout(layout); +} + +int qt_main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MyWidget widget; + widget.show(); + return app.exec(); +} diff --git a/gui/textures.qrc b/gui/textures.qrc new file mode 100644 index 0000000..dfde5e1 --- /dev/null +++ b/gui/textures.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>data/some.txt</file> +</qresource> +</RCC> -- GitLab