Compare commits
42 Commits
questionab
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
e6bf1fea9b | |||
152907beb2 | |||
d2ac30118b | |||
cc9ba15320 | |||
9432848310 | |||
60610150e2 | |||
1e04c362ce | |||
c14697eddf | |||
8af70eef39 | |||
7fd12b6e0c | |||
ae72cf63a8 | |||
6280d9fb01 | |||
6ddba41dd6 | |||
cb1a8c379b | |||
3c9c8b8c6a | |||
ead8d1dc01 | |||
86587dc435 | |||
5a332ec060 | |||
46eca1136f | |||
63a5b8995f | |||
e0f3eb1c45 | |||
b72d6ff67f | |||
1a29d0b04e | |||
f938d5e21c | |||
78bfecd8a3 | |||
903b0ee8e6 | |||
fb7e267bb4 | |||
17e87e2c40 | |||
46c5caa1ab | |||
bf83ffc9ec | |||
5db186e8da | |||
e5c068ddf7 | |||
6a015d9797 | |||
f4e560fcd9 | |||
5da279a8e6 | |||
d9cc4e4aec | |||
9517b5b682 | |||
41183b8397 | |||
9b807d53a4 | |||
9391b85a07 | |||
4da21707b6 | |||
505a66a1be |
86
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
86
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
# This starter workflow is for a CMake project running on multiple platforms. There is a different
|
||||
# starter workflow if you just want a single platform.
|
||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
|
||||
name: CMake on multiple platforms
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "development" ]
|
||||
pull_request:
|
||||
branches: [ "development" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
|
||||
# Consider changing this to true when your workflow is stable.
|
||||
fail-fast: false
|
||||
|
||||
# Set up a matrix to run the following 3 configurations:
|
||||
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator>
|
||||
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
|
||||
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
|
||||
#
|
||||
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
build_type: [Release]
|
||||
c_compiler: [gcc-13, clang, cl]
|
||||
include:
|
||||
- os: windows-latest
|
||||
c_compiler: cl
|
||||
cpp_compiler: cl
|
||||
- os: ubuntu-latest
|
||||
c_compiler: gcc-13
|
||||
cpp_compiler: g++-13
|
||||
#- os: ubuntu-latest
|
||||
#c_compiler: clang
|
||||
#cpp_compiler: clang++
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
c_compiler: gcc-13
|
||||
- os: windows-latest
|
||||
c_compiler: clang
|
||||
- os: ubuntu-latest
|
||||
c_compiler: cl
|
||||
# Clang is broken on ubuntu-latest. C++20 brings in inconsistent libraries
|
||||
- os: ubuntu-latest
|
||||
c_compiler: clang
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: 6.6.2
|
||||
target: desktop
|
||||
|
||||
- name: Set reusable strings
|
||||
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
|
||||
id: strings
|
||||
shell: bash
|
||||
run: |
|
||||
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: >
|
||||
cmake -B ${{ steps.strings.outputs.build-output-dir }}
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
-S ${{ github.workspace }}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ steps.strings.outputs.build-output-dir }}
|
||||
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest --build-config ${{ matrix.build_type }} -R 'qtrocket_*'
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -38,6 +38,8 @@ build/
|
||||
docs/doxygen/*
|
||||
|
||||
# IDE
|
||||
*.swp
|
||||
qtrocket.pro.user
|
||||
.qmake.stash
|
||||
CMakeLists.txt.user
|
||||
|
||||
|
@ -5,6 +5,8 @@ project(qtrocket VERSION 0.1 LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
enable_testing()
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Google Test framework
|
||||
@ -17,10 +19,10 @@ endif()
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# fmtlib dependency
|
||||
FetchContent_Declare(fmt
|
||||
GIT_REPOSITORY https://github.com/fmtlib/fmt
|
||||
GIT_TAG 9.1.0)
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
#FetchContent_Declare(fmt
|
||||
# GIT_REPOSITORY https://github.com/fmtlib/fmt
|
||||
# GIT_TAG 9.1.0)
|
||||
#FetchContent_MakeAvailable(fmt)
|
||||
|
||||
# jsoncpp dependency
|
||||
FetchContent_Declare(jsoncpp
|
||||
@ -48,11 +50,18 @@ endif()
|
||||
FetchContent_MakeAvailable(CURL)
|
||||
|
||||
# eigen dependency
|
||||
FetchContent_Declare(eigen
|
||||
FetchContent_Declare(Eigen
|
||||
GIT_REPOSITORY https://gitlab.com/libeigen/eigen
|
||||
GIT_TAG 3.4.0)
|
||||
FetchContent_MakeAvailable(eigen)
|
||||
FetchContent_MakeAvailable(Eigen)
|
||||
|
||||
# boost dependency
|
||||
|
||||
FetchContent_Declare(Boost
|
||||
GIT_REPOSITORY https://github.com/boostorg/boost
|
||||
GIT_TAG boost-1.84.0)
|
||||
set(BOOST_INCLUDE_LIBRARIES property_tree)
|
||||
FetchContent_MakeAvailable(Boost)
|
||||
# Add qtrocket subdirectories. These are components that will be linked in
|
||||
|
||||
|
||||
@ -63,7 +72,7 @@ set(CMAKE_AUTORCC ON)
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_PREFIX_PATH $ENV{QTDIR})
|
||||
include_directories("C:\\boost\\boost_1_82_0\\")
|
||||
# include_directories("C:\\boost\\boost_1_82_0\\")
|
||||
# find_package(Qt6Core REQUIRED)
|
||||
# find_package(Qt6Widgets REQUIRED)
|
||||
endif()
|
||||
|
@ -1,416 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 10.0.0, 2023-04-26T18:22:10. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{126c64d7-12e8-468a-ad3f-06f0fbdaeca1}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">6</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt6</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt6</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{834bc66d-170a-454c-a2b0-c17798dc7b12}</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
||||
-DCMAKE_BUILD_TYPE:STRING=Debug
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{buildDir}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/travis/build-qtrocket-Desktop_Qt6-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="CMake.Build.Type">Release</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{buildDir}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/travis/build-qtrocket-Desktop_Qt6-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{buildDir}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/travis/build-qtrocket-Desktop_Qt6-RelWithDebInfo</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
|
||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{buildDir}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/travis/build-qtrocket-Desktop_Qt6-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
|
||||
<value type="QString" key="CMake.Build.Type">MinSizeRel</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
||||
-DCMAKE_BUILD_TYPE:STRING=MinSizeRel
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{buildDir}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/travis/build-qtrocket-Desktop_Qt6-MinSizeRel</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Minimum Size Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">5</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">qtrocket</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.qtrocket</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">qtrocket</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/travis/build-qtrocket-Desktop_Qt6-Debug</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
16
QtRocket.cpp
16
QtRocket.cpp
@ -1,4 +1,3 @@
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
@ -45,7 +44,7 @@ void guiWorker(int argc, char* argv[], int& ret)
|
||||
|
||||
// Go!
|
||||
MainWindow w(QtRocket::getInstance());
|
||||
logger->info("Showing MainWindow");
|
||||
logger->debug("Showing MainWindow");
|
||||
w.show();
|
||||
ret = a.exec();
|
||||
|
||||
@ -65,7 +64,7 @@ void QtRocket::init()
|
||||
std::lock_guard<std::mutex> lck(mtx);
|
||||
if(!initialized)
|
||||
{
|
||||
utils::Logger::getInstance()->info("Instantiating new QtRocket");
|
||||
utils::Logger::getInstance()->debug("Instantiating new QtRocket");
|
||||
instance = new QtRocket();
|
||||
initialized = true;
|
||||
}
|
||||
@ -81,13 +80,20 @@ QtRocket::QtRocket()
|
||||
setEnvironment(std::make_shared<sim::Environment>());
|
||||
|
||||
rocket.first =
|
||||
std::make_shared<Rocket>();
|
||||
std::make_shared<model::RocketModel>();
|
||||
|
||||
rocket.second =
|
||||
std::make_shared<sim::Propagator>(rocket.first);
|
||||
|
||||
motorDatabase = std::make_shared<utils::MotorModelDatabase>();
|
||||
|
||||
logger->debug("Initial states vector size: " + std::to_string(states.capacity()) );
|
||||
// Reserve at least 1024 spaces for StateData
|
||||
if(states.capacity() < 1024)
|
||||
{
|
||||
states.reserve(1024);
|
||||
}
|
||||
logger->debug("New states vector size: " + std::to_string(states.capacity()) );
|
||||
}
|
||||
|
||||
int QtRocket::run(int argc, char* argv[])
|
||||
@ -107,7 +113,7 @@ int QtRocket::run(int argc, char* argv[])
|
||||
void QtRocket::launchRocket()
|
||||
{
|
||||
// initialize the propagator
|
||||
rocket.second->clearStates();
|
||||
rocket.first->clearStates();
|
||||
rocket.second->setCurrentTime(0.0);
|
||||
|
||||
// start the rocket motor
|
||||
|
28
QtRocket.h
28
QtRocket.h
@ -14,13 +14,12 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "model/MotorModel.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "sim/AtmosphericModel.h"
|
||||
#include "sim/GravityModel.h"
|
||||
#include "model/RocketModel.h"
|
||||
#include "sim/Environment.h"
|
||||
#include "sim/Propagator.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/MotorModelDatabase.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
/**
|
||||
* @brief The QtRocket class is the master controller for the QtRocket application.
|
||||
@ -44,13 +43,13 @@ public:
|
||||
|
||||
std::shared_ptr<sim::Environment> getEnvironment() { return environment; }
|
||||
void setTimeStep(double t) { rocket.second->setTimeStep(t); }
|
||||
std::shared_ptr<Rocket> getRocket() { return rocket.first; }
|
||||
std::shared_ptr<model::RocketModel> getRocket() { return rocket.first; }
|
||||
|
||||
std::shared_ptr<utils::MotorModelDatabase> getMotorDatabase() { return motorDatabase; }
|
||||
|
||||
void addMotorModels(std::vector<model::MotorModel>& m);
|
||||
|
||||
void addRocket(std::shared_ptr<Rocket> r) { rocket.first = r; }
|
||||
void addRocket(std::shared_ptr<model::RocketModel> r) { rocket.first = r; rocket.second = std::make_shared<sim::Propagator>(r); }
|
||||
|
||||
void setEnvironment(std::shared_ptr<sim::Environment> e) { environment = e; }
|
||||
|
||||
@ -59,18 +58,13 @@ public:
|
||||
* @brief getStates returns a vector of time/state pairs generated during launch()
|
||||
* @return vector of pairs of doubles, where the first value is a time and the second a state vector
|
||||
*/
|
||||
const std::vector<std::pair<double, Vector6>>& getStates() const { return rocket.second->getStates(); }
|
||||
const std::vector<std::pair<double, StateData>>& getStates() const { return rocket.first->getStates(); }
|
||||
|
||||
/**
|
||||
* @brief setInitialState sets the initial state of the Rocket.
|
||||
* @param initState initial state vector (x, y, z, xDot, yDot, zDot, pitch, yaw, roll, pitchDot, yawDot, rollDot)
|
||||
*/
|
||||
void setInitialState(const std::vector<double>& initialPos,
|
||||
const std::vector<double>& initialVel,
|
||||
const std::vector<double>& initialOri,
|
||||
const std::vector<double>& initialOriRate)
|
||||
|
||||
{ rocket.second->setInitialState(initialPos, initialVel, initialOri, initialOriRate); }
|
||||
void setInitialState(const StateData& initState) { rocket.first->setInitialState(initState); }
|
||||
|
||||
private:
|
||||
QtRocket();
|
||||
@ -84,11 +78,19 @@ private:
|
||||
|
||||
utils::Logger* logger;
|
||||
|
||||
std::pair<std::shared_ptr<Rocket>, std::shared_ptr<sim::Propagator>> rocket;
|
||||
using Rocket = std::pair<std::shared_ptr<model::RocketModel>, std::shared_ptr<sim::Propagator>>;
|
||||
Rocket rocket;
|
||||
|
||||
std::shared_ptr<sim::Environment> environment;
|
||||
std::shared_ptr<utils::MotorModelDatabase> motorDatabase;
|
||||
|
||||
// Launch site
|
||||
// ECEF coordinates
|
||||
Vector3 launchSitePosition{0.0, 0.0, 0.0};
|
||||
|
||||
// Table of state data
|
||||
std::vector<StateData> states;
|
||||
|
||||
};
|
||||
|
||||
#endif // QTROCKET_H
|
||||
|
71
README.md
71
README.md
@ -1,71 +1,2 @@
|
||||
# qtrocket
|
||||
An open source model Rocket Simulator written in C++ and Qt Toolkit, coming soon!
|
||||
|
||||
## Why?
|
||||
Because it's fun! Model and High Power rocketry are enjoyable hobbies that teach model building
|
||||
and inspire people to keep learning. For me, part of that learning process includes learning more
|
||||
about the aerodynamics of rocket flight, and what better way to learn than write a simulator?
|
||||
|
||||
There are already open source rocket simulators out there (e.g. OpenRocket), but this is another
|
||||
take on that idea. For one, this is written in C++ and OpenRocket is written in Java, but more
|
||||
importantly, I hope to engineer this in a way that is as modular as possible from the standpoint
|
||||
of the parts, components, and concepts involved in modeling a rocket. That way, this can serve not
|
||||
only as a model rocket design program, but a platform for people to learn about how rockets fly by
|
||||
building and integrating their own test parts and models easily. This way QtRocket may serve as a
|
||||
learning platform not just for me, but for others as well.
|
||||
|
||||
### Why Release An Unfinished Product?
|
||||
Well, first of all it isn't actually *released* yet. But it is public because I'm always interested in getting any feedback others may have. I'm doing this to learn as well, and if you have any
|
||||
pointers, I'd love to hear them! And if you want to contribute, well, please do! Let's talk :)
|
||||
|
||||
## External Build Dependencies
|
||||
* Boost libraries. On Windows this is hardcoded to v1.82.0, but only because I'm not sure how dependencies work on Windows
|
||||
* Qt6 (You can download it for free for Open Source use here: https://www.qt.io/download)
|
||||
* Other dependencies are handled within the CMake build system
|
||||
* Maybe something else I'm forgetting about? If you find something not listed that isn't a standard install, let me know
|
||||
|
||||
## How To Use It
|
||||
First, it's still in the very early stages of development, but it *can* propagate objects through
|
||||
an atomosphere with a given coefficient of drag, mass, and motor.
|
||||
|
||||
When you first open qtrocket, you're presented with the main window:
|
||||

|
||||
|
||||
The main window thus far has been centered around testing the core physics engin. As you can see,
|
||||
there are several fields that you can edit:
|
||||
* Initial Velocity - This is an initial vertical velocity off the launch rod or rail
|
||||
* Angle - Currently disabled. If the rocket launches at an angle, this would be it. Currently
|
||||
it is disabled and set at 90 degrees from horizontal, aka vertical.
|
||||
* mass - The mass of the rocket in kilograms (not including the motor)
|
||||
* Cd - The coefficient of drag of the rocket
|
||||
* Time Step - The time step used by the simulator, in seconds. Defaults to 0.01 seconds.
|
||||
|
||||
Once you fill out these fields (or just accept their defaults), you are ready to load a motor. The
|
||||
"Load RSE Database File" button will open a file browser to allow you to select a RockSim
|
||||
engine database file. One is included in the data/ directory of qtrocket that holds some AeroTech
|
||||
motors. After selecting a motor, you can click on the "Set Motor" button. This will add the selected
|
||||
motor to the rocket, and use it to launch the rocket.
|
||||
|
||||
Once you have selected and added the rocket motor, click "Calculate Trajectory". A new dialog will
|
||||
appear (if the plot is empty, just click the "Plot Altitude" button):
|
||||

|
||||
From here you can also plot velocity by clicking "Plot Velocity":
|
||||

|
||||
|
||||
And, plot the thrust curve of the motor you selected.
|
||||
|
||||
## Thrustcurve.org integration
|
||||
There is another feature, in that qtrocket integrates with the excellent online motor database thrustcurve.org. From the main window, click "Get Thrustcurve Motor Data". A new window will open:
|
||||
|
||||

|
||||
|
||||
In order to use it, you first must click "Get Metadata". Then you can select the manufacturer, motor diameter, and impulse class.
|
||||
|
||||
After filling out those combo boxes, click "Search". From there, you can search all available
|
||||
motors with those criteria. After choosing one in the combo box, click "setMotor", and that
|
||||
motor's thrust curve will be displayed in the plot.
|
||||
|
||||
|
||||
## Known Issues
|
||||
* It doesn't do much
|
||||
* I know, but it's just a little fella and it's still growing ;)
|
||||
An open source model Rocket Simulator written in C++ and Qt Toolkit, coming soon
|
||||
|
@ -36,7 +36,7 @@ AnalysisWindow::~AnalysisWindow()
|
||||
void AnalysisWindow::onButton_plotAltitude_clicked()
|
||||
{
|
||||
QtRocket* qtRocket = QtRocket::getInstance();
|
||||
const std::vector<std::pair<double, Vector6>>& res = qtRocket->getStates();
|
||||
const std::vector<std::pair<double, StateData>>& res = qtRocket->getStates();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
@ -46,7 +46,7 @@ void AnalysisWindow::onButton_plotAltitude_clicked()
|
||||
for (int i = 0; i < tData.size(); ++i)
|
||||
{
|
||||
tData[i] = res[i].first;
|
||||
zData[i] = res[i].second[2];
|
||||
zData[i] = res[i].second.position[2];
|
||||
}
|
||||
// create graph and assign data to it:
|
||||
plot->addGraph();
|
||||
@ -63,7 +63,7 @@ void AnalysisWindow::onButton_plotAltitude_clicked()
|
||||
void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
{
|
||||
QtRocket* qtRocket = QtRocket::getInstance();
|
||||
const std::vector<std::pair<double, Vector6>>& res = qtRocket->getStates();
|
||||
const std::vector<std::pair<double, StateData>>& res = qtRocket->getStates();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
@ -74,7 +74,7 @@ void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
for (int i = 0; i < tData.size(); ++i)
|
||||
{
|
||||
tData[i] = res[i].first;
|
||||
zData[i] = res[i].second[5];
|
||||
zData[i] = res[i].second.velocity[2];
|
||||
}
|
||||
// create graph and assign data to it:
|
||||
plot->addGraph();
|
||||
@ -91,8 +91,8 @@ void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
|
||||
void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
model::MotorModel motor = rocket->getCurrentMotorModel();
|
||||
std::shared_ptr<model::RocketModel> rocket = QtRocket::getInstance()->getRocket();
|
||||
model::MotorModel motor = rocket->getMotorModel();
|
||||
ThrustCurve tc = motor.getThrustCurve();
|
||||
|
||||
|
||||
@ -122,4 +122,4 @@ void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
||||
plot->yAxis->setRange(*std::min_element(std::begin(fData), std::end(fData)), *std::max_element(std::begin(fData), std::end(fData)));
|
||||
plot->replot();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "gui/MainWindow.h"
|
||||
#include "gui/ThrustCurveMotorSelector.h"
|
||||
#include "gui/SimOptionsWindow.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "model/RocketModel.h"
|
||||
#include "utils/RSEDatabaseLoader.h"
|
||||
|
||||
|
||||
@ -123,15 +123,15 @@ void MainWindow::onButton_calculateTrajectory_clicked()
|
||||
|
||||
double initialVelocityX = initialVelocity * std::cos(initialAngle / 57.2958);
|
||||
double initialVelocityZ = initialVelocity * std::sin(initialAngle / 57.2958);
|
||||
std::vector<double> initialPos = {0.0, 0.0, 0.0};
|
||||
std::vector<double> initialVel = {initialVelocityX, 0.0, initialVelocityZ};
|
||||
std::vector<double> initialOri = {0.0, 0.0, 0.0};
|
||||
std::vector<double> initialOriRate = {0.0, 0.0, 0.0};
|
||||
//std::vector<double> initialState = {0.0, 0.0, 0.0, initialVelocityX, 0.0, initialVelocityZ, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
StateData initialState;
|
||||
initialState.position = {0.0, 0.0, 0.0};
|
||||
initialState.velocity = {initialVelocityX, 0.0, initialVelocityZ};
|
||||
auto rocket = QtRocket::getInstance()->getRocket();
|
||||
rocket->setMass(mass);
|
||||
rocket->setDragCoefficient(dragCoeff);
|
||||
|
||||
qtRocket->setInitialState(initialPos, initialVel, initialOri, initialOriRate);
|
||||
qtRocket->setInitialState(initialState);
|
||||
qtRocket->launchRocket();
|
||||
|
||||
AnalysisWindow aWindow;
|
||||
@ -204,4 +204,4 @@ void MainWindow::onButton_setMotor_clicked()
|
||||
void MainWindow::onMenu_File_Quit_triggered()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
}
|
9
main.cpp
9
main.cpp
@ -1,11 +1,9 @@
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
|
||||
#include "QtRocket.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
@ -14,13 +12,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Instantiate logger
|
||||
utils::Logger* logger = utils::Logger::getInstance();
|
||||
logger->setLogLevel(utils::Logger::DEBUG_);
|
||||
logger->setLogLevel(utils::Logger::PERF_);
|
||||
logger->info("Logger instantiated at PERF level");
|
||||
// instantiate QtRocket
|
||||
logger->debug("Starting QtRocket");
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
|
||||
// Run QtRocket. This'll start the GUI thread and block until the user
|
||||
// exits the program
|
||||
logger->debug("QtRocket->run()");
|
||||
int retVal = qtrocket->run(argc, argv);
|
||||
logger->debug("Returning");
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,18 @@ add_library(model
|
||||
MotorModel.h
|
||||
MotorModelDatabase.cpp
|
||||
MotorModelDatabase.h
|
||||
Rocket.cpp
|
||||
Rocket.h
|
||||
Part.cpp
|
||||
Part.h
|
||||
Propagatable.cpp
|
||||
Propagatable.h
|
||||
RocketModel.cpp
|
||||
RocketModel.h
|
||||
ThrustCurve.cpp
|
||||
ThrustCurve.h)
|
||||
ThrustCurve.h
|
||||
InertiaTensors.h)
|
||||
|
||||
target_link_libraries(model PRIVATE
|
||||
utils)
|
||||
|
||||
# Unit tests
|
||||
add_subdirectory(tests)
|
||||
|
70
model/InertiaTensors.h
Normal file
70
model/InertiaTensors.h
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef INERTIATENSORS_H
|
||||
#define INERTIATENSORS_H
|
||||
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The InertiaTensors class provides a collection of methods to
|
||||
* deliver some common inertia tensors centered about the center of mass
|
||||
*/
|
||||
class InertiaTensors
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief SolidSphere
|
||||
* @param radius (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 SolidSphere(double radius)
|
||||
{
|
||||
double xx = 0.4*radius*radius;
|
||||
double yy = xx;
|
||||
double zz = xx;
|
||||
return Matrix3{{xx, 0, 0},
|
||||
{0, yy, 0},
|
||||
{0, 0, zz}};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HollowSphere
|
||||
* @param radius (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 HollowSphere(double radius)
|
||||
{
|
||||
double xx = (2.0/3.0)*radius*radius;
|
||||
double yy = xx;
|
||||
double zz = xx;
|
||||
return Matrix3{{xx, 0, 0},
|
||||
{0, yy, 0},
|
||||
{0, 0, zz}};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tube - The longitudinal axis is the z-axis. Can also be used for a solid cylinder
|
||||
* when innerRadius = 0.0
|
||||
* @param innerRadius (meters)
|
||||
* @param outerRadius (meters)
|
||||
* @param length (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 Tube(double innerRadius, double outerRadius, double length)
|
||||
{
|
||||
double xx = (1.0/12.0)*(3.0*(innerRadius*innerRadius + outerRadius*outerRadius) + length*length);
|
||||
double yy = xx;
|
||||
double zz = (1.0/2.0)*(innerRadius*innerRadius + outerRadius*outerRadius);
|
||||
return Matrix3{{xx, 0.0, 0.0},
|
||||
{0.0, yy, 0.0},
|
||||
{0.0, 0.0, zz}};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // INERTIATENSORS_H
|
@ -60,6 +60,7 @@ double MotorModel::getMass(double simTime) const
|
||||
double propMassEnd = i->second;
|
||||
double slope = (propMassEnd - propMassStart) / (tEnd - tStart);
|
||||
double currentMass = emptyMass + propMassStart + (thrustTime - tStart) * slope;
|
||||
utils::Logger::getInstance()->info("simTime: " + std::to_string(simTime) + ": motor mass: " + std::to_string(currentMass));
|
||||
return currentMass;
|
||||
|
||||
}
|
||||
|
109
model/Part.cpp
Normal file
109
model/Part.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "Part.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
Part::Part(const std::string& n,
|
||||
const Matrix3& I,
|
||||
double m,
|
||||
const Vector3& centerMass)
|
||||
: parent(nullptr),
|
||||
name(n),
|
||||
inertiaTensor(I),
|
||||
compositeInertiaTensor(I),
|
||||
mass(m),
|
||||
compositeMass(m),
|
||||
cm(centerMass),
|
||||
needsRecomputing(false),
|
||||
childParts()
|
||||
{ }
|
||||
|
||||
Part::~Part()
|
||||
{}
|
||||
|
||||
Part::Part(const Part& orig)
|
||||
: parent(orig.parent),
|
||||
name(orig.name),
|
||||
inertiaTensor(orig.inertiaTensor),
|
||||
compositeInertiaTensor(orig.compositeInertiaTensor),
|
||||
mass(orig.mass),
|
||||
compositeMass(orig.compositeMass),
|
||||
cm(orig.cm),
|
||||
needsRecomputing(orig.needsRecomputing),
|
||||
childParts()
|
||||
{
|
||||
|
||||
// We are copying the whole tree. If the part we're copying itself has child
|
||||
// parts, we are also copying all of them! This may be inefficient and not what
|
||||
// is desired, but it is less likely to lead to weird bugs with the same part
|
||||
// appearing in multiple locations of the rocket
|
||||
utils::Logger::getInstance()->debug("Calling model::Part copy constructor. Recursively copying all child parts. Check Part names for uniqueness");
|
||||
|
||||
|
||||
for(const auto& i : orig.childParts)
|
||||
{
|
||||
Part& x = *std::get<0>(i);
|
||||
std::shared_ptr<Part> tempPart = std::make_shared<Part>(x);
|
||||
childParts.emplace_back(tempPart, std::get<1>(i));;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double Part::getChildMasses(double t)
|
||||
{
|
||||
double childMasses{0.0};
|
||||
for(const auto& i : childParts)
|
||||
{
|
||||
childMasses += std::get<0>(i)->getMass(t);
|
||||
}
|
||||
return childMasses;
|
||||
|
||||
}
|
||||
|
||||
void Part::addChildPart(const Part& childPart, Vector3 position)
|
||||
{
|
||||
|
||||
double childMass = childPart.compositeMass;
|
||||
Matrix3 childInertiaTensor = childPart.compositeInertiaTensor;
|
||||
std::shared_ptr<Part> newChild = std::make_shared<Part>(childPart);
|
||||
// Set the parent pointer
|
||||
newChild->parent = this;
|
||||
|
||||
// Recompute inertia tensor
|
||||
|
||||
childInertiaTensor += childMass * ( position.dot(position) * Matrix3::Identity() - position*position.transpose());
|
||||
|
||||
compositeInertiaTensor += childInertiaTensor;
|
||||
compositeMass += childMass;
|
||||
|
||||
childParts.emplace_back(std::move(newChild), std::move(position));
|
||||
|
||||
if(parent)
|
||||
{
|
||||
parent->markAsNeedsRecomputing();
|
||||
parent->recomputeInertiaTensor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Part::recomputeInertiaTensor()
|
||||
{
|
||||
if(!needsRecomputing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// recompute the whole composite inertia tensor
|
||||
// Reset the composite inertia tensor
|
||||
compositeInertiaTensor = inertiaTensor;
|
||||
compositeMass = mass;
|
||||
for(auto& [child, pos] : childParts)
|
||||
{
|
||||
child->recomputeInertiaTensor();
|
||||
compositeInertiaTensor += child->compositeInertiaTensor + child->compositeMass * ( pos.dot(pos) * Matrix3::Identity() - pos*pos.transpose());
|
||||
compositeMass += child->compositeMass;
|
||||
}
|
||||
needsRecomputing = false;
|
||||
}
|
||||
|
||||
} // namespace model
|
136
model/Part.h
Normal file
136
model/Part.h
Normal file
@ -0,0 +1,136 @@
|
||||
#ifndef MODEL_PART_H
|
||||
#define MODEL_PART_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class Part
|
||||
{
|
||||
public:
|
||||
Part(const std::string& name,
|
||||
const Matrix3& I,
|
||||
double m,
|
||||
const Vector3& centerMass);
|
||||
|
||||
virtual ~Part();
|
||||
|
||||
Part(const Part&);
|
||||
|
||||
Part& operator=(Part other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
std::swap(parent, other.parent);
|
||||
std::swap(name, other.name);
|
||||
std::swap(inertiaTensor, other.inertiaTensor);
|
||||
std::swap(compositeInertiaTensor, other.compositeInertiaTensor);
|
||||
std::swap(mass, other.mass);
|
||||
std::swap(compositeMass, other.compositeMass);
|
||||
std::swap(cm, other.cm);
|
||||
std::swap(needsRecomputing, other.needsRecomputing);
|
||||
std::swap(childParts, other.childParts);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Part& operator=(Part&& other)
|
||||
{
|
||||
parent = std::move(other.parent);
|
||||
name = std::move(other.name);
|
||||
inertiaTensor = std::move(other.inertiaTensor);
|
||||
compositeInertiaTensor = std::move(other.compositeInertiaTensor);
|
||||
mass = std::move(other.mass);
|
||||
compositeMass = std::move(other.compositeMass);
|
||||
cm = std::move(other.cm);
|
||||
needsRecomputing = std::move(other.needsRecomputing);
|
||||
childParts = std::move(other.childParts);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setMass(double m) { mass = m; }
|
||||
|
||||
// Set the inertia tensor
|
||||
void setI(const Matrix3& I) { inertiaTensor = I; }
|
||||
Matrix3 getI() { return inertiaTensor; }
|
||||
Matrix3 getCompositeI() { return compositeInertiaTensor; }
|
||||
|
||||
void setCm(const Vector3& x) { cm = x; }
|
||||
// Special version of setCM that assumes the cm lies along the body x-axis
|
||||
void setCm(double x) { cm = {x, 0.0, 0.0}; }
|
||||
|
||||
double getMass(double t)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
double getCompositeMass(double t)
|
||||
{
|
||||
return compositeMass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a child part to this part.
|
||||
*
|
||||
* @param childPart Child part to add
|
||||
* @param position Relative position of the child part's center-of-mass w.r.t the
|
||||
* parent's center of mass
|
||||
*/
|
||||
void addChildPart(const Part& childPart, Vector3 position);
|
||||
|
||||
/**
|
||||
* @brief Recomputes the inertia tensor. If the change is due to the change in inertia
|
||||
* of a child part, an optional name of the child part can be given to
|
||||
* only recompute that change rather than recompute all child inertia
|
||||
* tensors
|
||||
*
|
||||
* @param name Optional name of the child part to recompute. If empty, it will
|
||||
* recompute all child inertia tensors
|
||||
*/
|
||||
//void recomputeInertiaTensor(std::string name = "");
|
||||
void recomputeInertiaTensor();
|
||||
private:
|
||||
|
||||
// This is a pointer to the parent Part, if it has one. Purpose is to be able to
|
||||
// tell the parent if it needs to recompute anything if this part changes. e.g.
|
||||
// if a change to this part's inertia tensor occurs, the parent needs to recompute
|
||||
// it's total inertia tensor.
|
||||
Part* parent{nullptr};
|
||||
|
||||
std::string name;
|
||||
|
||||
double getChildMasses(double t);
|
||||
void markAsNeedsRecomputing()
|
||||
{ needsRecomputing = true; if(parent) { parent->markAsNeedsRecomputing(); }}
|
||||
|
||||
// Because a part is both a simple part and the composite of itself with all of it's children,
|
||||
// we will keep track of this object's inertia tensor (without children), and the composite
|
||||
// one with all of it's children attached
|
||||
Matrix3 inertiaTensor; // moment of inertia tensor with respect to the part's center of mass and
|
||||
Matrix3 compositeInertiaTensor;
|
||||
double mass; // The moment of inertia tensor also has this, so don't double compute
|
||||
double compositeMass; // The mass of this part along with all attached parts
|
||||
|
||||
Vector3 cm; // center of mass wrt middle of component
|
||||
|
||||
bool needsRecomputing{false};
|
||||
|
||||
/// @brief child parts and the relative positions of their center of mass w.r.t.
|
||||
/// the center of mass of this part
|
||||
std::vector<std::tuple<std::shared_ptr<Part>, Vector3>> childParts;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MODEL_PART_H
|
0
model/Propagatable.cpp
Normal file
0
model/Propagatable.cpp
Normal file
58
model/Propagatable.h
Normal file
58
model/Propagatable.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef MODEL_PROPAGATABLE_H
|
||||
#define MODEL_PROPAGATABLE_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <utility>
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "sim/Aero.h"
|
||||
#include "sim/StateData.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class Propagatable
|
||||
{
|
||||
public:
|
||||
Propagatable() {}
|
||||
virtual ~Propagatable() {}
|
||||
|
||||
virtual Vector3 getForces(double t) = 0;
|
||||
virtual Vector3 getTorques(double t) = 0;
|
||||
|
||||
virtual double getMass(double t) = 0;
|
||||
virtual Matrix3 getInertiaTensor(double t) = 0;
|
||||
|
||||
virtual bool terminateCondition(double t) = 0;
|
||||
|
||||
void setCurrentState(const StateData& st) { currentState = st; }
|
||||
const StateData& getCurrentState() { return currentState; }
|
||||
|
||||
const StateData& getInitialState() { return initialState; }
|
||||
void setInitialState(const StateData& init) { initialState = init; }
|
||||
|
||||
void appendState(double t, const StateData& st) { states.emplace_back(t, st); }
|
||||
|
||||
const std::vector<std::pair<double, StateData>>& getStates() { return states; }
|
||||
|
||||
void clearStates() { states.clear(); }
|
||||
|
||||
protected:
|
||||
|
||||
sim::Aero aeroData;
|
||||
|
||||
StateData initialState;
|
||||
StateData currentState;
|
||||
StateData nextState;
|
||||
|
||||
std::vector<std::pair<double, StateData>> states;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MODEL_PROPAGATABLE_H
|
@ -1,33 +0,0 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "Rocket.h"
|
||||
#include "QtRocket.h"
|
||||
|
||||
Rocket::Rocket()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Rocket::launch()
|
||||
{
|
||||
mm.startMotor(0.0);
|
||||
}
|
||||
|
||||
void Rocket::setMotorModel(const model::MotorModel& motor)
|
||||
{
|
||||
mm = motor;
|
||||
}
|
||||
|
||||
bool Rocket::terminateCondition(const std::pair<double, Vector6>& cond)
|
||||
{
|
||||
// Terminate propagation when the z coordinate drops below zero
|
||||
if(cond.second[2] < 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
double Rocket::getThrust(double t)
|
||||
{
|
||||
return mm.getThrust(t);
|
||||
}
|
79
model/RocketModel.cpp
Normal file
79
model/RocketModel.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "RocketModel.h"
|
||||
#include "QtRocket.h"
|
||||
#include "InertiaTensors.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
RocketModel::RocketModel()
|
||||
: topPart("NoseCone", InertiaTensors::SolidSphere(1.0), 1.0, {0.0, 0.0, 1.0})
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
double RocketModel::getMass(double t)
|
||||
{
|
||||
double mass = mm.getMass(t);
|
||||
mass += topPart.getCompositeMass(t);
|
||||
return mass;
|
||||
}
|
||||
|
||||
Matrix3 RocketModel::getInertiaTensor(double)
|
||||
{
|
||||
return topPart.getCompositeI();
|
||||
}
|
||||
|
||||
bool RocketModel::terminateCondition(double)
|
||||
{
|
||||
// Terminate propagation when the z coordinate drops below zero
|
||||
if(currentState.position[2] < 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 RocketModel::getForces(double t)
|
||||
{
|
||||
// Get thrust
|
||||
// Assume that thrust is always through the center of mass and in the rocket's Z-axis
|
||||
Vector3 forces{0.0, 0.0, mm.getThrust(t)};
|
||||
|
||||
|
||||
// Get gravity
|
||||
auto gravityModel = QtRocket::getInstance()->getEnvironment()->getGravityModel();
|
||||
|
||||
Vector3 gravity = gravityModel->getAccel(currentState.position)*getMass(t);
|
||||
|
||||
forces += gravity;
|
||||
|
||||
// Calculate aero forces
|
||||
|
||||
|
||||
return forces;
|
||||
}
|
||||
|
||||
Vector3 RocketModel::getTorques(double t)
|
||||
{
|
||||
return Vector3{0.0, 0.0, 0.0};
|
||||
|
||||
}
|
||||
|
||||
double RocketModel::getThrust(double t)
|
||||
{
|
||||
return mm.getThrust(t);
|
||||
}
|
||||
|
||||
void RocketModel::launch()
|
||||
{
|
||||
mm.startMotor(0.0);
|
||||
}
|
||||
|
||||
void RocketModel::setMotorModel(const model::MotorModel& motor)
|
||||
{
|
||||
mm = motor;
|
||||
}
|
||||
|
||||
} // namespace model
|
@ -1,9 +1,10 @@
|
||||
#ifndef ROCKET_H
|
||||
#define ROCKET_H
|
||||
#ifndef ROCKETMODEL_H
|
||||
#define ROCKETMODEL_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
@ -12,22 +13,34 @@
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "model/ThrustCurve.h"
|
||||
#include "model/MotorModel.h"
|
||||
#include "model/Part.h"
|
||||
#include "sim/Propagator.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
#include "model/MotorModel.h"
|
||||
|
||||
#include "model/Propagatable.h"
|
||||
// Not yet
|
||||
//#include "model/Stage.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The Rocket class holds all rocket components
|
||||
*
|
||||
*/
|
||||
class Rocket
|
||||
class RocketModel : public Propagatable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Rocket class constructor
|
||||
*/
|
||||
Rocket();
|
||||
RocketModel();
|
||||
|
||||
/**
|
||||
* @brief Rocket class destructor
|
||||
*
|
||||
*/
|
||||
virtual ~RocketModel() {}
|
||||
|
||||
/**
|
||||
* @brief launch Propagates the Rocket object until termination,
|
||||
@ -35,33 +48,22 @@ public:
|
||||
*/
|
||||
void launch();
|
||||
|
||||
Vector3 getForces(double t) override;
|
||||
Vector3 getTorques(double t) override;
|
||||
/**
|
||||
* @brief getMass returns the current mass of the rocket. This is the sum of all components' masses
|
||||
* @return total current mass of the Rocket
|
||||
* @brief getMass returns current rocket mass
|
||||
* @param t current simulation time
|
||||
* @return mass in kg
|
||||
*/
|
||||
double getMass(double simTime) const { return mass + mm.getMass(simTime); }
|
||||
double getMass(double t) override;
|
||||
/**
|
||||
* @brief terminateCondition returns true or false, whether the passed-in time/state matches the terminate condition
|
||||
* @param cond time/state pair
|
||||
* @return true if the passed-in time/state satisfies the terminate condition
|
||||
*/
|
||||
bool terminateCondition(double t) override;
|
||||
|
||||
/**
|
||||
* @brief setMass sets the current total mass of the Rocket
|
||||
* @param m total Rocket mass
|
||||
* @todo This should be dynamically computed, not set. Fix this
|
||||
*/
|
||||
void setMass(double m) { mass = m;}
|
||||
|
||||
/**
|
||||
* @brief setDragCoefficient sets the current total drag coefficient of the Rocket
|
||||
* @param d drag coefficient
|
||||
* @todo This should be dynamically computed, not set. Fix this
|
||||
*/
|
||||
void setDragCoefficient(double d) { dragCoeff = d; }
|
||||
|
||||
/**
|
||||
* @brief getDragCoefficient returns the current drag coefficient
|
||||
*
|
||||
* This is intended to be called by the propagator during propagation.
|
||||
* @return the coefficient of drag
|
||||
*/
|
||||
double getDragCoefficient() const { return dragCoeff; }
|
||||
Matrix3 getInertiaTensor(double t) override;
|
||||
|
||||
/**
|
||||
* @brief getThrust returns current motor thrust
|
||||
@ -70,24 +72,25 @@ public:
|
||||
*/
|
||||
double getThrust(double t);
|
||||
|
||||
|
||||
/**
|
||||
* @brief setMotorModel
|
||||
* @param motor
|
||||
*/
|
||||
void setMotorModel(const model::MotorModel& motor);
|
||||
|
||||
|
||||
/**
|
||||
* @brief getMotorModel
|
||||
*/
|
||||
MotorModel getMotorModel() { return mm; }
|
||||
|
||||
/**
|
||||
* @brief Returns the current motor model.
|
||||
* @return The current motor model
|
||||
*/
|
||||
const model::MotorModel& getCurrentMotorModel() const { return mm; }
|
||||
//const model::MotorModel& getCurrentMotorModel() const { return mm; }
|
||||
|
||||
/**
|
||||
* @brief terminateCondition returns true or false, whether the passed-in time/state matches the terminate condition
|
||||
* @param cond time/state pair
|
||||
* @return true if the passed-in time/state satisfies the terminate condition
|
||||
*/
|
||||
bool terminateCondition(const std::pair<double, Vector6>& cond);
|
||||
|
||||
/**
|
||||
* @brief setName sets the rocket name
|
||||
@ -95,16 +98,19 @@ public:
|
||||
*/
|
||||
void setName(const std::string& n) { name = n; }
|
||||
|
||||
|
||||
double getDragCoefficient() { return 1.0; }
|
||||
void setDragCoefficient(double d) { }
|
||||
void setMass(double m) { }
|
||||
|
||||
private:
|
||||
|
||||
std::string name; /// Rocket name
|
||||
double dragCoeff; /// @todo get rid of this, should be dynamically calculated
|
||||
double mass; /// @todo get rid of this, should be dynamically computed, but is the current rocket mass
|
||||
|
||||
model::MotorModel mm; /// Current Motor Model
|
||||
|
||||
model::Part topPart;
|
||||
|
||||
};
|
||||
|
||||
#endif // ROCKET_H
|
||||
} // namespace model
|
||||
#endif // ROCKETMODEL_H
|
@ -8,8 +8,6 @@
|
||||
/// \endcond
|
||||
|
||||
#include "model/ThrustCurve.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
ThrustCurve::ThrustCurve(std::vector<std::pair<double, double>>& tc)
|
||||
: thrustCurve(tc),
|
||||
|
16
model/tests/CMakeLists.txt
Normal file
16
model/tests/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
add_executable(model_tests
|
||||
PartTests.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(model_tests PRIVATE
|
||||
model
|
||||
utils
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(model_tests)
|
||||
|
||||
add_test(NAME qtrocket_model_tests COMMAND model_tests)
|
||||
|
70
model/tests/PartTests.cpp
Normal file
70
model/tests/PartTests.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "model/Part.h"
|
||||
|
||||
class PartTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
// Per-test-suite set-up.
|
||||
// Called before the first test in this test suite.
|
||||
// Can be omitted if not needed.
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
//shared_resource_ = new ...;
|
||||
|
||||
// If `shared_resource_` is **not deleted** in `TearDownTestSuite()`,
|
||||
// reallocation should be prevented because `SetUpTestSuite()` may be called
|
||||
// in subclasses of FooTest and lead to memory leak.
|
||||
//
|
||||
// if (shared_resource_ == nullptr) {
|
||||
// shared_resource_ = new ...;
|
||||
// }
|
||||
}
|
||||
|
||||
// Per-test-suite tear-down.
|
||||
// Called after the last test in this test suite.
|
||||
// Can be omitted if not needed.
|
||||
static void TearDownTestSuite()
|
||||
{
|
||||
//delete shared_resource_;
|
||||
//shared_resource_ = nullptr;
|
||||
}
|
||||
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override { }
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override { }
|
||||
|
||||
// Some expensive resource shared by all tests.
|
||||
//static T* shared_resource_;
|
||||
};
|
||||
|
||||
//T* FooTest::shared_resource_ = nullptr;
|
||||
|
||||
TEST(PartTest, CreationTests)
|
||||
{
|
||||
Matrix3 inertia;
|
||||
inertia << 1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
Vector3 cm{1, 0, 0};
|
||||
model::Part testPart("testPart",
|
||||
inertia,
|
||||
1.0,
|
||||
cm);
|
||||
|
||||
Matrix3 inertia2;
|
||||
inertia2 << 1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
Vector3 cm2{1, 0, 0};
|
||||
model::Part testPart2("testPart2",
|
||||
inertia2,
|
||||
1.0,
|
||||
cm2);
|
||||
Vector3 R{2.0, 2.0, 2.0};
|
||||
testPart.addChildPart(testPart2, R);
|
||||
|
||||
|
||||
}
|
0
sim/Aero.cpp
Normal file
0
sim/Aero.cpp
Normal file
40
sim/Aero.h
Normal file
40
sim/Aero.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef SIM_AERO_H
|
||||
#define SIM_AERO_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
||||
class Aero
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
Vector3 cp; /// center of pressure
|
||||
|
||||
double Cx; /// longitudinal coefficient
|
||||
double Cy; /// These are probably the same for axial symmetric
|
||||
double Cz; /// rockets. The coeffients in the y and z body directions
|
||||
|
||||
double Cl; // roll moment coefficient
|
||||
double Cm; // pitch moment coefficient
|
||||
double Cn; // yaw moment coefficient
|
||||
|
||||
double baseCd; // coefficient of drag due to base drag
|
||||
double Cd; // total coeffient of drag
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SIM_AERO_H
|
@ -13,6 +13,10 @@ public:
|
||||
virtual double getDensity(double altitude) = 0;
|
||||
virtual double getPressure(double altitude) = 0;
|
||||
virtual double getTemperature(double altitude) = 0;
|
||||
|
||||
virtual double getSpeedOfSound(double altitude) = 0;
|
||||
virtual double getDynamicViscosity(double altitude) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -1,4 +1,6 @@
|
||||
add_library(sim
|
||||
Aero.cpp
|
||||
Aero.h
|
||||
AtmosphericModel.h
|
||||
ConstantAtmosphere.h
|
||||
ConstantGravityModel.h
|
||||
|
@ -15,6 +15,10 @@ public:
|
||||
double getDensity(double) override { return 1.225; }
|
||||
double getPressure(double) override { return 101325.0; }
|
||||
double getTemperature(double) override { return 288.15; }
|
||||
|
||||
double getSpeedOfSound(double) override { return 340.294; }
|
||||
|
||||
double getDynamicViscosity(double) override { return 1.78938e-5; }
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -4,13 +4,12 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "sim/ConstantAtmosphere.h"
|
||||
#include "sim/USStandardAtmosphere.h"
|
||||
#include "sim/GeoidModel.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -14,106 +13,36 @@
|
||||
// qtrocket headers
|
||||
#include "Propagator.h"
|
||||
|
||||
#include "QtRocket.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "sim/RK4Solver.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
namespace sim {
|
||||
|
||||
Propagator::Propagator(std::shared_ptr<Rocket> r)
|
||||
: linearIntegrator(),
|
||||
orientationIntegrator(),
|
||||
rocket(r),
|
||||
currentBodyState(),
|
||||
worldFrameState()
|
||||
namespace sim
|
||||
{
|
||||
|
||||
Propagator::Propagator(std::shared_ptr<model::Propagatable> r)
|
||||
: linearIntegrator(),
|
||||
object(r),
|
||||
saveStates(true),
|
||||
timeStep(0.01)
|
||||
{
|
||||
// Linear velocity and acceleration
|
||||
std::function<std::pair<Vector3, Vector3>(Vector3&, Vector3&)> linearODEs = [this](Vector3& state, Vector3& rate) -> std::pair<Vector3, Vector3>
|
||||
{
|
||||
Vector3 dPosition;
|
||||
Vector3 dVelocity;
|
||||
// dx/dt
|
||||
dPosition = rate;
|
||||
|
||||
// This is a little strange, but I have to populate the integrator unique_ptr
|
||||
// with reset. make_unique() doesn't work because the compiler can't seem to
|
||||
// deduce the template parameters correctly, and I don't want to specify them
|
||||
// manually either. RK4Solver constructor is perfectly capable of deducing it's
|
||||
// template types, and it derives from DESolver, so we can just reset the unique_ptr
|
||||
// and pass it a freshly allocated RK4Solver pointer
|
||||
// dvx/dt
|
||||
dVelocity = object->getForces(currentTime) / object->getMass(currentTime);
|
||||
|
||||
// The state vector has components of the form:
|
||||
return std::make_pair(dPosition, dVelocity);
|
||||
};
|
||||
|
||||
// Linear velocity and acceleration
|
||||
std::function<std::pair<Vector3, Vector3>(Vector3&, Vector3&)> linearODE = [this](Vector3& state, Vector3& rate) -> std::pair<Vector3, Vector3>
|
||||
{
|
||||
Vector3 dPosition;
|
||||
Vector3 dVelocity;
|
||||
// dx/dt
|
||||
dPosition[0] = rate[0];
|
||||
linearIntegrator.reset(new RK4Solver<Vector3>(linearODEs));
|
||||
linearIntegrator->setTimeStep(timeStep);
|
||||
|
||||
// dy/dt
|
||||
dPosition[1] = rate[1];
|
||||
|
||||
// dz/dt
|
||||
dPosition[2] = rate[2];
|
||||
|
||||
// dvx/dt
|
||||
dVelocity[0] = getForceX() / getMass();
|
||||
|
||||
// dvy/dt
|
||||
dVelocity[1] = getForceY() / getMass();
|
||||
|
||||
// dvz/dt
|
||||
dVelocity[2] = getForceZ() / getMass();
|
||||
|
||||
return std::make_pair(dPosition, dVelocity);
|
||||
|
||||
};
|
||||
|
||||
linearIntegrator.reset(new RK4Solver<Vector6>(linearODE));
|
||||
linearIntegrator->setTimeStep(timeStep);
|
||||
|
||||
// This is pure quaternion
|
||||
// This formula is taken from https://www.vectornav.com/resources/inertial-navigation-primer/math-fundamentals/math-attitudetran
|
||||
//
|
||||
// Convention for the quaternions is (vector, scalar). So q4 is scalar term
|
||||
//
|
||||
// q1Dot = 1/2 * [(q4*omega1) - (q3*omega2) + (q2*omega3)]
|
||||
// q2Dot = 1/2 * [(q3*omega1) + (q4*omega2) - (q1*omega3)]
|
||||
// q3Dot = 1/2 * [(-q2*omega1) + (q1*omega2) + (q4*omega3)]
|
||||
// q4Dot = -1/2 *[(q1*omega1) + (q2*omega2) + (q3*omega3)]
|
||||
//
|
||||
// omega1 = yawRate
|
||||
// omega2 = pitchRate
|
||||
// omega3 = rollRate
|
||||
//
|
||||
// orientationIntegrator.reset(new RK4Solver(
|
||||
// /* dyawRate/dt */ [this](const std::vector<double>& s, double) -> double
|
||||
// { return getTorqueP() / getIyaw(); },
|
||||
// /* dpitchRate/dt */ [this](const std::vector<double>& s, double) -> double
|
||||
// { return getTorqueQ() / getIpitch(); },
|
||||
// /* drollRate/dt */ [this](const std::vector<double>& s, double) -> double
|
||||
// { return getTorqueR() / getIroll(); },
|
||||
// /* q1Dot */ [](const std::vector<double>& s, double) -> double
|
||||
// {
|
||||
// double retVal = s[6]*s[0] - s[5]*s[1] + s[4]*s[2];
|
||||
// return 0.5 * retVal;
|
||||
// },
|
||||
// /* q2Dot */ [](const std::vector<double>& s, double) -> double
|
||||
// {
|
||||
// double retVal = s[5]*s[0] + s[6]*s[1] - s[3]*s[2];
|
||||
// return 0.5 * retVal;
|
||||
// },
|
||||
// /* q3Dot */ [](const std::vector<double>& s, double) -> double
|
||||
// {
|
||||
// double retVal = -s[4]*s[0] + s[3]*s[1] + s[6]*s[2];
|
||||
// return 0.5 * retVal;
|
||||
// },
|
||||
// /* q4Dot */ [](const std::vector<double>& s, double) -> double
|
||||
// {
|
||||
// double retVal = s[3]*s[0] + s[4]*s[1] + s[5]*s[2];
|
||||
// return -0.5 * retVal;
|
||||
// }));
|
||||
// orientationIntegrator->setTimeStep(timeStep);
|
||||
|
||||
saveStates = true;
|
||||
saveStates = true;
|
||||
}
|
||||
|
||||
Propagator::~Propagator()
|
||||
@ -122,91 +51,40 @@ Propagator::~Propagator()
|
||||
|
||||
void Propagator::runUntilTerminate()
|
||||
{
|
||||
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
||||
std::chrono::steady_clock::time_point endTime;
|
||||
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
||||
std::chrono::steady_clock::time_point endTime;
|
||||
|
||||
while(true)
|
||||
{
|
||||
Vector3 currentPosition;
|
||||
Vector3 currentVelocity;
|
||||
Vector3 nextPosition;
|
||||
Vector3 nextVelocity;
|
||||
while(true)
|
||||
{
|
||||
currentPosition = object->getCurrentState().position;
|
||||
currentVelocity = object->getCurrentState().velocity;
|
||||
|
||||
// Reset the body frame positions to zero since the origin of the body frame is the CM
|
||||
currentBodyState[0] = 0.0;
|
||||
currentBodyState[1] = 0.0;
|
||||
currentBodyState[2] = 0.0;
|
||||
std::tie(nextPosition, nextVelocity) = linearIntegrator->step(currentPosition, currentVelocity);
|
||||
|
||||
// tempRes gets overwritten
|
||||
tempRes = linearIntegrator->step(currentBodyState);
|
||||
StateData nextState;
|
||||
nextState.position = nextPosition;
|
||||
nextState.velocity = nextVelocity;
|
||||
object->setCurrentState(nextState);
|
||||
|
||||
std::swap(currentBodyState, tempRes);
|
||||
|
||||
if(saveStates)
|
||||
{
|
||||
states.push_back(std::make_pair(currentTime, currentBodyState));
|
||||
}
|
||||
if(rocket->terminateCondition(std::make_pair(currentTime, currentBodyState)))
|
||||
break;
|
||||
if(saveStates)
|
||||
{
|
||||
object->appendState(currentTime, nextState);
|
||||
}
|
||||
if(object->terminateCondition(currentTime))
|
||||
break;
|
||||
|
||||
currentTime += timeStep;
|
||||
}
|
||||
endTime = std::chrono::steady_clock::now();
|
||||
|
||||
std::stringstream duration;
|
||||
duration << "runUntilTerminate time (microseconds): ";
|
||||
duration << std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
utils::Logger::getInstance()->debug(duration.str());
|
||||
|
||||
}
|
||||
|
||||
double Propagator::getMass()
|
||||
{
|
||||
return rocket->getMass(currentTime);
|
||||
}
|
||||
|
||||
double Propagator::getForceX()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
return (currentBodyState[3] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentBodyState[2])/ 2.0 * 0.008107 * rocket->getDragCoefficient() * currentBodyState[3]* currentBodyState[3];
|
||||
}
|
||||
|
||||
double Propagator::getForceY()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
return (currentBodyState[4] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentBodyState[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentBodyState[4]* currentBodyState[4];
|
||||
}
|
||||
|
||||
double Propagator::getForceZ()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
double gravity = (qtrocket->getEnvironment()->getGravityModel()->getAccel(currentBodyState[0], currentBodyState[1], currentBodyState[2]))[2];
|
||||
double airDrag = (currentBodyState[5] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentBodyState[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentBodyState[5]* currentBodyState[5];
|
||||
double thrust = rocket->getThrust(currentTime);
|
||||
return gravity + airDrag + thrust;
|
||||
}
|
||||
|
||||
double Propagator::getTorqueP() { return 0.0; }
|
||||
double Propagator::getTorqueQ() { return 0.0; }
|
||||
double Propagator::getTorqueR() { return 0.0; }
|
||||
|
||||
Vector3 Propagator::getCurrentGravity()
|
||||
{
|
||||
auto gravityModel = QtRocket::getInstance()->getEnvironment()->getGravityModel();
|
||||
auto gravityAccel = gravityModel->getAccel(currentBodyState[0],
|
||||
currentBodyState[1],
|
||||
currentBodyState[2]);
|
||||
Vector3 gravityVector{gravityAccel[0],
|
||||
gravityAccel[1],
|
||||
gravityAccel[2]};
|
||||
|
||||
|
||||
Quaternion q{currentOrientation[3],
|
||||
currentOrientation[4],
|
||||
currentOrientation[5],
|
||||
currentOrientation[6]};
|
||||
|
||||
Vector3 res = q * gravityVector;
|
||||
|
||||
|
||||
return Vector3{0.0, 0.0, 0.0};
|
||||
currentTime += timeStep;
|
||||
}
|
||||
endTime = std::chrono::steady_clock::now();
|
||||
|
||||
std::stringstream duration;
|
||||
duration << "runUntilTerminate time (microseconds): ";
|
||||
duration << std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
utils::Logger::getInstance()->debug(duration.str());
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,20 +5,22 @@
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "sim/DESolver.h"
|
||||
#include "sim/RK4Solver.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
#include "sim/StateData.h"
|
||||
#include "model/Propagatable.h"
|
||||
|
||||
|
||||
// Forward declare
|
||||
namespace model
|
||||
{
|
||||
class Rocket;
|
||||
}
|
||||
class QtRocket;
|
||||
|
||||
namespace sim
|
||||
@ -27,43 +29,17 @@ namespace sim
|
||||
class Propagator
|
||||
{
|
||||
public:
|
||||
Propagator(std::shared_ptr<Rocket> r);
|
||||
Propagator(std::shared_ptr<model::Propagatable> o);
|
||||
~Propagator();
|
||||
|
||||
void setInitialState(const std::vector<double>& initialState,
|
||||
const std::vector<double>& initialVelocity,
|
||||
const std::vector<double>& initialOrientation,
|
||||
const std::vector<double>& initalOriRate)
|
||||
void setInitialState(const StateData& initialState)
|
||||
{
|
||||
for(std::size_t i = 0; i < initialState.size(); ++i)
|
||||
{
|
||||
currentBodyPosition[i] = initialState[i];
|
||||
}
|
||||
for(std::size_t i = 0; i < initialVelocity.size(); ++i)
|
||||
{
|
||||
currentBodyVelocity[i] = initialVelocity[i];
|
||||
}
|
||||
/*
|
||||
for(std::size_t i = 0; i < initialOrientation.size(); ++i)
|
||||
{
|
||||
currentOrientation[i] = initialOrientation[i];
|
||||
}
|
||||
for(std::size_t i = 0; i < initialOriRate.size(); ++i)
|
||||
{
|
||||
currentOrientationRate[i] = initialOriRate[i];
|
||||
}
|
||||
*/
|
||||
|
||||
object->setInitialState(initialState);
|
||||
}
|
||||
|
||||
const Vector6& getCurrentState() const
|
||||
const StateData& getCurrentState() const
|
||||
{
|
||||
std::vector<double> retVal{currentBodyPosition.begin(), currentBodyPosition.end()};
|
||||
for(auto& i : currentBodyVelocity)
|
||||
{
|
||||
retVal.push_back(i);
|
||||
}
|
||||
return retVal;
|
||||
return object->getCurrentState();
|
||||
}
|
||||
|
||||
void runUntilTerminate();
|
||||
@ -73,56 +49,21 @@ public:
|
||||
saveStates = s;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<double, Vector6>>& getStates() const { return states; }
|
||||
|
||||
void clearStates() { states.clear(); }
|
||||
void setCurrentTime(double t) { currentTime = t; }
|
||||
void setTimeStep(double ts) { timeStep = ts; }
|
||||
void setSaveStats(bool s) { saveStates = s; }
|
||||
|
||||
private:
|
||||
double getMass();
|
||||
double getForceX();
|
||||
double getForceY();
|
||||
double getForceZ();
|
||||
|
||||
double getTorqueP();
|
||||
double getTorqueQ();
|
||||
double getTorqueR();
|
||||
|
||||
double getIpitch() { return 1.0; }
|
||||
double getIyaw() { return 1.0; }
|
||||
double getIroll() { return 1.0; }
|
||||
|
||||
std::unique_ptr<sim::RK4Solver<Vector3>> linearIntegrator;
|
||||
// std::unique_ptr<sim::RK4Solver<Quaternion>> orientationIntegrator;
|
||||
|
||||
std::shared_ptr<Rocket> rocket;
|
||||
std::shared_ptr<model::Propagatable> object;
|
||||
|
||||
StateData worldFrameState;
|
||||
StateData bodyFrameState
|
||||
Vector3 currentBodyPosition{0.0, 0.0, 0.0};
|
||||
Vector3 currentBodyVelocity{0.0, 0.0, 0.0};
|
||||
Vector3 nextBodyPosition{0.0, 0.0, 0.0};
|
||||
Vector3 nextBodyVelocity{0.0, 0.0, 0.0};
|
||||
|
||||
std::vector<double> currentWorldState{0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
|
||||
Vector3 currentGravity{0.0, 0.0, 0.0};
|
||||
Vector3 currentWindSpeed{0.0, 0.0, 0.0};
|
||||
|
||||
|
||||
// orientation vectors in the form (yawDot, pitchDot, rollDot, q1, q2, q3, q4)
|
||||
Quaternion currentOrientation{0.0, 0.0, 0.0, 0.0};
|
||||
Quaternion currentOrientationRate{0.0, 0.0, 0.0, 0.0};
|
||||
Quaternion nextOrientation{0.0, 0.0, 0.0, 0.0};
|
||||
Quaternion nextOrientationRate{0.0, 0.0, 0.0, 0.0};
|
||||
bool saveStates{true};
|
||||
double currentTime{0.0};
|
||||
double timeStep{0.01};
|
||||
std::vector<std::pair<double, Vector6>> states;
|
||||
|
||||
Vector3 getCurrentGravity();
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -4,10 +4,8 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
// 3rd party headers
|
||||
|
||||
|
@ -22,24 +22,63 @@ public:
|
||||
StateData() {}
|
||||
~StateData() {}
|
||||
|
||||
std::vector<double> getPosStdVector()
|
||||
StateData(const StateData&) = default;
|
||||
StateData(StateData&&) = default;
|
||||
|
||||
StateData& operator=(const StateData& rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
position = rhs.position;
|
||||
velocity = rhs.velocity;
|
||||
orientation = rhs.orientation;
|
||||
orientationRate = rhs.orientationRate;
|
||||
dcm = rhs.dcm;
|
||||
eulerAngles = rhs.eulerAngles;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
StateData& operator=(StateData&& rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
position = std::move(rhs.position);
|
||||
velocity = std::move(rhs.velocity);
|
||||
orientation = std::move(rhs.orientation);
|
||||
orientationRate = std::move(rhs.orientationRate);
|
||||
dcm = std::move(rhs.dcm);
|
||||
eulerAngles = std::move(rhs.eulerAngles);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<double> getPosStdVector() const
|
||||
{
|
||||
return std::vector<double>{position[0], position[1], position[2]};
|
||||
}
|
||||
std::vector<double> getVelStdVector()
|
||||
std::vector<double> getVelStdVector() const
|
||||
{
|
||||
return std::vector<double>{velocity[0], velocity[1], velocity[2]};
|
||||
}
|
||||
|
||||
|
||||
/// TODO: Put these behind an interface
|
||||
//Vector3 getPosition() const
|
||||
//{
|
||||
// return position;
|
||||
//}
|
||||
|
||||
//Vector3 getVelocity() const
|
||||
//{
|
||||
// return velocity;
|
||||
//}
|
||||
// private:
|
||||
|
||||
// These are 4-vectors so quaternion multiplication works out. The last term (scalar) is always
|
||||
// zero. I could just use quaternions here, but I want to make it clear that these aren't
|
||||
// rotations, they're vectors
|
||||
// Intended to be used as world state data
|
||||
Vector3 position{0.0, 0.0, 0.0};
|
||||
Vector3 velocity{0.0, 0.0, 0.0};
|
||||
|
||||
// Orientation of body coordinates w.r.t. world coordinates
|
||||
Quaternion orientation{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
||||
Quaternion orientationRate{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
||||
|
||||
@ -51,9 +90,6 @@ public:
|
||||
/// roll - phi
|
||||
Vector3 eulerAngles{0.0, 0.0, 0.0};
|
||||
|
||||
// This is an array because the integrator expects it
|
||||
double data[6];
|
||||
|
||||
};
|
||||
|
||||
#endif // STATEDATA_H
|
||||
|
@ -18,9 +18,9 @@ namespace sim
|
||||
{
|
||||
|
||||
// Populate static data
|
||||
utils::BinMap initTemps()
|
||||
utils::Bin initTemps()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 288.15));
|
||||
map.insert(std::make_pair(11000.0, 216.65));
|
||||
map.insert(std::make_pair(20000.0, 216.65));
|
||||
@ -33,10 +33,9 @@ utils::BinMap initTemps()
|
||||
|
||||
}
|
||||
|
||||
/// TODO: These are inverted. They should be of the opposite sign
|
||||
utils::BinMap initLapseRates()
|
||||
utils::Bin initLapseRates()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 0.0065));
|
||||
map.insert(std::make_pair(11000.0, 0.0));
|
||||
map.insert(std::make_pair(20000.0, -0.001));
|
||||
@ -48,9 +47,9 @@ utils::BinMap initLapseRates()
|
||||
return map;
|
||||
}
|
||||
|
||||
utils::BinMap initDensities()
|
||||
utils::Bin initDensities()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 1.225));
|
||||
map.insert(std::make_pair(11000.0, 0.36391));
|
||||
map.insert(std::make_pair(20000.0, 0.08803));
|
||||
@ -62,9 +61,9 @@ utils::BinMap initDensities()
|
||||
return map;
|
||||
}
|
||||
|
||||
utils::BinMap initPressures()
|
||||
utils::Bin initPressures()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 101325));
|
||||
map.insert(std::make_pair(11000.0, 22632.1));
|
||||
map.insert(std::make_pair(20000.0, 5474.89));
|
||||
@ -76,12 +75,10 @@ utils::BinMap initPressures()
|
||||
return map;
|
||||
}
|
||||
|
||||
utils::BinMap USStandardAtmosphere::temperatureLapseRate(initLapseRates());
|
||||
utils::BinMap USStandardAtmosphere::standardTemperature(initTemps());
|
||||
utils::BinMap USStandardAtmosphere::standardDensity(initDensities());
|
||||
utils::BinMap USStandardAtmosphere::standardPressure(initPressures());
|
||||
|
||||
|
||||
utils::Bin USStandardAtmosphere::temperatureLapseRate(initLapseRates());
|
||||
utils::Bin USStandardAtmosphere::standardTemperature(initTemps());
|
||||
utils::Bin USStandardAtmosphere::standardDensity(initDensities());
|
||||
utils::Bin USStandardAtmosphere::standardPressure(initPressures());
|
||||
|
||||
USStandardAtmosphere::USStandardAtmosphere()
|
||||
{
|
||||
@ -120,7 +117,6 @@ double USStandardAtmosphere::getTemperature(double altitude)
|
||||
double baseAltitude = standardTemperature.getBinBase(altitude);
|
||||
return baseTemp - (altitude - baseAltitude) * temperatureLapseRate[altitude];
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
double USStandardAtmosphere::getPressure(double altitude)
|
||||
{
|
||||
@ -128,13 +124,13 @@ double USStandardAtmosphere::getPressure(double altitude)
|
||||
{
|
||||
return standardPressure[altitude] * std::exp(
|
||||
(-Constants::g0 * Constants::airMolarMass * (altitude - standardPressure.getBinBase(altitude)))
|
||||
/ (Constants::Rstar * standardPressure[altitude]));
|
||||
/ (Constants::Rstar * standardTemperature[altitude]));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
double base = (standardPressure[altitude] - temperatureLapseRate[altitude] *
|
||||
(altitude - standardPressure.getBinBase(altitude))) / standardPressure[altitude];
|
||||
double base = (standardTemperature[altitude] - temperatureLapseRate[altitude] *
|
||||
(altitude - standardPressure.getBinBase(altitude))) / standardTemperature[altitude];
|
||||
|
||||
double exponent = (Constants::g0 * Constants::airMolarMass) /
|
||||
(Constants::Rstar * temperatureLapseRate[altitude]);
|
||||
@ -143,4 +139,17 @@ double USStandardAtmosphere::getPressure(double altitude)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double USStandardAtmosphere::getSpeedOfSound(double altitude)
|
||||
{
|
||||
return std::sqrt( (Constants::gamma * Constants::Rstar * getTemperature(altitude))
|
||||
/
|
||||
Constants::airMolarMass);
|
||||
}
|
||||
|
||||
double USStandardAtmosphere::getDynamicViscosity(double altitude)
|
||||
{
|
||||
double temperature = getTemperature(altitude);
|
||||
return (Constants::beta * std::pow(temperature, 1.5)) / ( temperature + Constants::S);
|
||||
}
|
||||
} // namespace sim
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "sim/AtmosphericModel.h"
|
||||
#include "utils/BinMap.h"
|
||||
#include "utils/Bin.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
@ -28,11 +28,15 @@ public:
|
||||
double getPressure(double altitude) override;
|
||||
double getTemperature(double altitude) override;
|
||||
|
||||
double getSpeedOfSound(double altitude) override;
|
||||
|
||||
double getDynamicViscosity(double altitude) override;
|
||||
|
||||
private:
|
||||
static utils::BinMap temperatureLapseRate;
|
||||
static utils::BinMap standardTemperature;
|
||||
static utils::BinMap standardDensity;
|
||||
static utils::BinMap standardPressure;
|
||||
static utils::Bin temperatureLapseRate;
|
||||
static utils::Bin standardTemperature;
|
||||
static utils::Bin standardDensity;
|
||||
static utils::Bin standardPressure;
|
||||
|
||||
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
enable_testing()
|
||||
|
||||
add_executable(sim_tests
|
||||
USStandardAtmosphereTests.cpp
|
||||
@ -12,3 +11,5 @@ target_link_libraries(sim_tests
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(sim_tests)
|
||||
|
||||
add_test(NAME qtrocket_sim_tests COMMAND sim_tests)
|
||||
|
||||
|
@ -6,27 +6,85 @@ TEST(USStandardAtmosphereTests, DensityTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getDensity(0.0) / 1.225, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(1000.0) / 1.112, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(2000.0) / 1.007, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(3000.0) / 0.9093, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(4000.0) / 0.8194, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(5000.0) / 0.7364, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(6000.0) / 0.6601, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(7000.0) / 0.5900, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(8000.0) / 0.5258, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(9000.0) / 0.4647, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(10000.0) / 0.4135, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(15000.0) / 0.1948, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(20000.0) / 0.08891, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(25000.0) / 0.039466, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(30000.0) / 0.018012, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(40000.0) / 0.0038510, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(60000.0) / 0.00028832, 1.0, 0.01);
|
||||
EXPECT_NEAR(atmosphere.getDensity(70000.0) / 0.000074243, 1.0, 0.01);
|
||||
// These two fail. Commenting out for now, the 50k meters is off by 5%, the 80k by 100%
|
||||
// TODO: Why?
|
||||
//EXPECT_NEAR(atmosphere.getDensity(50000.0) / 0.0010269, 1.0, 0.01);
|
||||
//EXPECT_NEAR(atmosphere.getDensity(80000.0) / 0.000015701, 1.0, 0.01);
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getDensity(0.0) / 1.225, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(1000.0) / 1.112, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(2000.0) / 1.007, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(3000.0) / 0.9093, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(4000.0) / 0.8194, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(5000.0) / 0.7364, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(6000.0) / 0.6601, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(7000.0) / 0.5900, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(15000.0) / 0.19367, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(20000.0) / 0.088035, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(25000.0) / 0.039466, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(30000.0) / 0.018012, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(40000.0) / 0.0038510, 1.0, 0.001);
|
||||
|
||||
// These are generally accurate to ~0.5%. Slight deviation of calculated
|
||||
// density from the given density in the report table
|
||||
EXPECT_NEAR(atmosphere.getDensity(8000.0) / 0.52579, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(9000.0) / 0.46706, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(10000.0) / 0.41351, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(50000.0) / 0.00097752, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(60000.0) / 0.00028832, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(70000.0) / 0.000074243, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(80000.0) / 0.000015701, 1.0, 0.005);
|
||||
|
||||
}
|
||||
|
||||
TEST(USStandardAtmosphereTests, PressureTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getPressure(0.0) / 101325.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(1000.0) / 89876.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(2000.0) / 79501.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(3000.0) / 70108.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(4000.0) / 61640.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(5000.0) / 54019.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(6000.0) / 47181.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(7000.0) / 41060.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(8000.0) / 35599.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(9000.0) / 30742.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(10000.0) / 26436.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(15000.0) / 12044.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(20000.0) / 5474.8, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(25000.0) / 2511.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(30000.0) / 1171.8, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(40000.0) / 277.52, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(50000.0) / 75.944, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(60000.0) / 20.314, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(70000.0) / 4.6342, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(80000.0) / 0.88627, 1.0, 0.001);
|
||||
|
||||
}
|
||||
|
||||
TEST(USStandardAtmosphereTests, TemperatureTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getTemperature(0.0) / 288.15, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(1000.0) / 281.651, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(2000.0) / 275.154, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(3000.0) / 268.659, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(4000.0) / 262.166, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(5000.0) / 255.676, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(6000.0) / 249.187, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(7000.0) / 242.7, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(8000.0) / 236.215, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(9000.0) / 229.733, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(10000.0) / 223.252, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(15000.0) / 216.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(20000.0) / 216.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(25000.0) / 221.552, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(30000.0) / 226.509, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(40000.0) / 251.05, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(50000.0) / 270.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(60000.0) / 245.45, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(70000.0) / 217.450, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(80000.0) / 196.650, 1.0, 0.001);
|
||||
|
||||
}
|
@ -3,15 +3,14 @@
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
#include <stdexcept>
|
||||
|
||||
// 3rd party headers
|
||||
#include <fmt/core.h>
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "BinMap.h"
|
||||
#include "Bin.h"
|
||||
|
||||
// TODO: Check on the availability of this in Clang.
|
||||
// Replace libfmt with format when LLVM libc++ supports it
|
||||
@ -20,33 +19,33 @@
|
||||
namespace utils
|
||||
{
|
||||
|
||||
BinMap::BinMap()
|
||||
Bin::Bin()
|
||||
: bins()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BinMap::BinMap(BinMap&& o)
|
||||
Bin::Bin(Bin&& o)
|
||||
: bins(std::move(o.bins))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BinMap::~BinMap()
|
||||
Bin::~Bin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// TODO: Very low priority, but if anyone wants to make this more efficient it could be
|
||||
// interesting
|
||||
void BinMap::insert(const std::pair<double, double>& toInsert)
|
||||
void Bin::insert(const std::pair<double, double>& toInsert)
|
||||
{
|
||||
bins.push_back(toInsert);
|
||||
std::sort(bins.begin(), bins.end(),
|
||||
[](const auto& a, const auto& b){ return a.first < b.first; });
|
||||
}
|
||||
|
||||
double BinMap::operator[](double key)
|
||||
double Bin::operator[](double key)
|
||||
{
|
||||
auto iter = bins.begin();
|
||||
// If the key is less than the lowest bin value, then it is out of range
|
||||
@ -56,12 +55,12 @@ double BinMap::operator[](double key)
|
||||
if(key < iter->first)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
std::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
}
|
||||
// Increment it and start searching If we reach the end without finding an existing key
|
||||
// greater than our search term, then we've just hit the last bin and return that
|
||||
iter++;
|
||||
double retVal = bins.end()->second;
|
||||
double retVal = bins.back().second;
|
||||
while(iter != bins.end())
|
||||
{
|
||||
if(key < iter->first)
|
||||
@ -74,7 +73,7 @@ double BinMap::operator[](double key)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
double BinMap::getBinBase(double key)
|
||||
double Bin::getBinBase(double key)
|
||||
{
|
||||
auto iter = bins.begin();
|
||||
// If the key is less than the lowest bin value, then it is out of range
|
||||
@ -84,7 +83,7 @@ double BinMap::getBinBase(double key)
|
||||
if(key < iter->first)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
std::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
}
|
||||
// Increment it and start searching If we reach the end without finding an existing key
|
||||
// greater than our search term, then we've just hit the last bin and return that
|
@ -1,5 +1,5 @@
|
||||
#ifndef UTILS_BINMAP_H
|
||||
#define UTILS_BINMAP_H
|
||||
#ifndef UTILS_BIN_H
|
||||
#define UTILS_BIN_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
@ -22,12 +22,12 @@ namespace utils {
|
||||
* @todo Make this class behave more like a proper STL container. Templetize it for one
|
||||
*
|
||||
*/
|
||||
class BinMap
|
||||
class Bin
|
||||
{
|
||||
public:
|
||||
BinMap();
|
||||
BinMap(BinMap&& o);
|
||||
~BinMap();
|
||||
Bin();
|
||||
Bin(Bin&& o);
|
||||
~Bin();
|
||||
|
||||
void insert(const std::pair<double, double>& toInsert);
|
||||
double operator[](double key);
|
||||
@ -40,4 +40,4 @@ private:
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // UTILS_BINMAP_H
|
||||
#endif // UTILS_BIN_H
|
@ -1,6 +1,6 @@
|
||||
add_library(utils
|
||||
BinMap.cpp
|
||||
BinMap.h
|
||||
Bin.cpp
|
||||
Bin.h
|
||||
CurlConnection.cpp
|
||||
CurlConnection.h
|
||||
Logger.cpp
|
||||
@ -18,8 +18,13 @@ add_library(utils
|
||||
math/MathTypes.h
|
||||
math/UtilityMathFunctions.h)
|
||||
|
||||
|
||||
#target_include_directories(utils PRIVATE
|
||||
# ${Boost_INCLUDE_DIRS})
|
||||
|
||||
|
||||
target_link_libraries(utils PUBLIC
|
||||
libcurl
|
||||
Boost::property_tree
|
||||
jsoncpp_static
|
||||
fmt::fmt-header-only
|
||||
eigen)
|
||||
|
@ -40,6 +40,13 @@ void Logger::log(std::string_view msg, const LogLevel& lvl)
|
||||
// all levels at or lower than the current level.
|
||||
switch(currentLevel)
|
||||
{
|
||||
case PERF_:
|
||||
if(lvl == PERF_)
|
||||
{
|
||||
outFile << "[PERF] " << msg << std::endl;
|
||||
std::cout << "[PERF] " << msg << "\n";
|
||||
}
|
||||
[[fallthrough]];
|
||||
case DEBUG_:
|
||||
if(lvl == DEBUG_)
|
||||
{
|
||||
|
@ -25,7 +25,8 @@ public:
|
||||
ERROR_,
|
||||
WARN_,
|
||||
INFO_,
|
||||
DEBUG_
|
||||
DEBUG_,
|
||||
PERF_
|
||||
};
|
||||
|
||||
static Logger* getInstance();
|
||||
@ -38,16 +39,11 @@ public:
|
||||
|
||||
void setLogLevel(const LogLevel& lvl);
|
||||
|
||||
/*
|
||||
std::function<void(std::string_view)> error;
|
||||
std::function<void(std::string_view)> warn;
|
||||
std::function<void(std::string_view)> info;
|
||||
std::function<void(std::string_view)> debug;
|
||||
*/
|
||||
inline void error(std::string_view msg) { log(msg, ERROR_); }
|
||||
inline void warn(std::string_view msg) { log(msg, WARN_); }
|
||||
inline void info(std::string_view msg) { log(msg, INFO_); }
|
||||
inline void debug(std::string_view msg) { log(msg, DEBUG_); }
|
||||
inline void perf(std::string_view msg) { log(msg, PERF_); }
|
||||
|
||||
void log(std::ostream& o, const std::string& msg);
|
||||
|
||||
|
@ -235,7 +235,9 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
{
|
||||
Json::Reader reader;
|
||||
Json::Value jsonResult;
|
||||
Logger::getInstance()->debug("1");
|
||||
reader.parse(result, jsonResult);
|
||||
Logger::getInstance()->debug("2");
|
||||
|
||||
for(Json::ValueConstIterator iter = jsonResult["results"].begin();
|
||||
iter != jsonResult["results"].end();
|
||||
@ -244,6 +246,7 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
model::MotorModel motorModel;
|
||||
model::MotorModel::MetaData mm;
|
||||
mm.commonName = (*iter)["commonName"].asString();
|
||||
Logger::getInstance()->debug("3");
|
||||
|
||||
std::string availability = (*iter)["availability"].asString();
|
||||
if(availability == "regular")
|
||||
@ -253,6 +256,7 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
|
||||
mm.avgThrust = (*iter)["avgThrustN"].asDouble();
|
||||
mm.burnTime = (*iter)["burnTimeS"].asDouble();
|
||||
Logger::getInstance()->debug("4");
|
||||
// TODO fill in certOrg
|
||||
// TODO fill in delays
|
||||
mm.designation = (*iter)["designation"].asString();
|
||||
@ -279,8 +283,10 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
else
|
||||
mm.type = model::MotorModel::MotorType(model::MotorModel::MOTORTYPE::HYBRID);
|
||||
|
||||
motorModel.moveMetaData(std::move(mm));
|
||||
Logger::getInstance()->debug("5");
|
||||
auto tc = getThrustCurve(mm.motorIdTC);
|
||||
motorModel.moveMetaData(std::move(mm));
|
||||
Logger::getInstance()->debug("6");
|
||||
if(tc)
|
||||
{
|
||||
motorModel.addThrustCurve(*tc);
|
||||
|
@ -6,9 +6,19 @@ namespace utils::math
|
||||
|
||||
namespace Constants
|
||||
{
|
||||
constexpr double Rstar = 8.3144598;
|
||||
constexpr double Rstar = 8.31432;
|
||||
constexpr const double g0 = 9.80665;
|
||||
constexpr const double airMolarMass = 0.0289644;
|
||||
|
||||
// gamma is the ratio of the specific heat of air at constant pressure to that at
|
||||
// constant volume. Used in computing the speed of sound
|
||||
constexpr const double gamma = 1.4;
|
||||
|
||||
// beta is used in calculating the dynamic viscosity of air. Based on the 1976 US Standard
|
||||
// Atmosphere report, it is empirically measured to be:
|
||||
constexpr const double beta = 1.458e-6;
|
||||
// Sutherland's constant
|
||||
constexpr const double S = 110.4;
|
||||
constexpr const double standardTemperature = 288.15;
|
||||
constexpr const double standardDensity = 1.2250;
|
||||
constexpr const double meanEarthRadiusWGS84 = 6371008.8;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define UTILS_MATH_MATHTYPES_H
|
||||
|
||||
#include <Eigen/Dense>
|
||||
#include <vector>
|
||||
|
||||
/// This is not in any namespace. These typedefs are intended to be used throughout QtRocket,
|
||||
/// so keeping them in the global namespace seems to make sense.
|
||||
@ -20,4 +21,54 @@ using Matrix4 = MyMatrix<4>;
|
||||
using Vector3 = MyVector<3>;
|
||||
using Vector6 = MyVector<6>;
|
||||
|
||||
/*
|
||||
namespace utils
|
||||
{
|
||||
std::vector<double> myVectorToStdVector(const Vector3& x)
|
||||
{
|
||||
return std::vector<double>{x.coeff(0), x.coeff(1), x.coeff(2)};
|
||||
}
|
||||
|
||||
std::vector<double> myVectorToStdVector(const Vector6& x)
|
||||
{
|
||||
return std::vector<double>{x.coeff(0),
|
||||
x.coeff(1),
|
||||
x.coeff(2),
|
||||
x.coeff(3),
|
||||
x.coeff(4),
|
||||
x.coeff(5)};
|
||||
}
|
||||
}
|
||||
|
||||
class Vector3 : public MyVector<3>
|
||||
{
|
||||
public:
|
||||
template<typename... Args>
|
||||
Vector3(Args&&... args) : MyVector<3>(std::forward<Args>(args)...)
|
||||
{}
|
||||
operator std::vector<double>()
|
||||
{
|
||||
return std::vector<double>{this->coeff(0), this->coeff(1), this->coeff(2)};
|
||||
}
|
||||
};
|
||||
|
||||
class Vector6 : public MyVector<6>
|
||||
{
|
||||
public:
|
||||
template<typename... Args>
|
||||
Vector6(Args&&... args) : MyVector<6>(std::forward<Args>(args)...)
|
||||
{}
|
||||
operator std::vector<double>()
|
||||
{
|
||||
return std::vector<double>{this->coeff(0),
|
||||
this->coeff(1),
|
||||
this->coeff(2),
|
||||
this->coeff(3),
|
||||
this->coeff(4),
|
||||
this->coeff(5)};
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
#endif // UTILS_MATH_MATHTYPES_H
|
Loading…
x
Reference in New Issue
Block a user