Compare commits

...

42 Commits

Author SHA1 Message Date
e6bf1fea9b Revert "Merge pull request #20 from cthunter01/propagator"
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc-13, g++-13, ubuntu-latest) (push) Has been cancelled
This reverts commit 6280d9fb0184275843a8f4406c7293e41e65a639, reversing
changes made to 3c9c8b8c6a2b2e7430ff09efdc2cc0c1996b16ca.
2025-04-16 18:23:28 -06:00
152907beb2 Revert "adding testfile to test repo mirroring from gitea to github"
This reverts commit 8af70eef399a5a237c2c8c006f3f58e56fe15e47.
2025-04-16 18:22:05 -06:00
d2ac30118b Revert "second test of gitea push mirroring"
This reverts commit c14697eddf0a15a2b5938f66fde6c12ca5fe840f.
2025-04-16 18:21:48 -06:00
cc9ba15320 Revert "third test of gitea push mirroring"
This reverts commit 1e04c362ce24c44c400f2ab21fc6ed75239b080b.
2025-04-16 18:21:16 -06:00
9432848310 Revert "remove temporary test file"
This reverts commit 60610150e277710f6751b09ed8db6a7c090dab06.
2025-04-16 18:20:47 -06:00
60610150e2 remove temporary test file
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc-13, g++-13, ubuntu-latest) (push) Has been cancelled
2025-04-16 18:15:55 -06:00
1e04c362ce third test of gitea push mirroring
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc-13, g++-13, ubuntu-latest) (push) Has been cancelled
2025-04-05 19:19:41 -06:00
c14697eddf second test of gitea push mirroring
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc-13, g++-13, ubuntu-latest) (push) Has been cancelled
2025-04-05 19:18:47 -06:00
8af70eef39 adding testfile to test repo mirroring from gitea to github
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc-13, g++-13, ubuntu-latest) (push) Has been cancelled
2025-04-05 19:05:21 -06:00
7fd12b6e0c
Merge pull request #21 from cthunter01/propagator
Merge pull request #1 from qtrocket/development
2025-04-05 18:54:24 -06:00
ae72cf63a8
Merge pull request #1 from qtrocket/development
update
2025-04-05 18:53:20 -06:00
6280d9fb01
Merge pull request #20 from cthunter01/propagator
Propagator
2025-04-05 18:52:14 -06:00
6ddba41dd6 WIP 2024-08-16 18:18:49 -06:00
cb1a8c379b Initial commit of propagator test branch 2024-08-16 16:18:35 -06:00
3c9c8b8c6a
Merge pull request #19 from cthunter01/development
Fix build failures and add github CI actions. Automated builds on Ubuntu and Windows
2024-08-14 18:28:54 -06:00
ead8d1dc01
Merge branch 'qtrocket:development' into development 2024-08-14 18:27:26 -06:00
86587dc435
Update README.md 2024-08-14 18:25:52 -06:00
5a332ec060 Substantial refactor and cleanup of Propagator and Rocket class (now RocketModel class) 2024-03-17 10:19:39 -06:00
46eca1136f Remove model::Stage for now. It'll be good in the future, but makes initial development more complex. Prototype with single stage rocket for now while working out the physics engine 2024-03-17 08:13:24 -06:00
63a5b8995f Update CTest infrastructure to automatically run qtrocket unit tests 2024-03-15 15:17:26 -06:00
e0f3eb1c45 Exclude ubuntu-latest clang build since it's broken (not my breakage, Github's config of ubuntu-latest) 2024-03-15 13:29:30 -06:00
b72d6ff67f Add unit tests to workflow. Disable clang for now because it's broken in ubuntu-latest build container 2024-03-15 13:27:05 -06:00
1a29d0b04e Tweaking workflow. Trying to use gcc-13 on ubuntu 2024-03-15 12:58:37 -06:00
f938d5e21c fix typo in windows-latest.yml action 2024-03-15 12:41:12 -06:00
78bfecd8a3 Split github actions by OS 2024-03-15 12:39:40 -06:00
903b0ee8e6
Update cmake-multi-platform.yml 2024-03-15 12:08:08 -06:00
fb7e267bb4
Test gcc13 on ubuntu-latest: Update cmake-multi-platform.yml 2024-03-15 11:58:14 -06:00
17e87e2c40
Update cmake-multi-platform.yml 2024-03-15 11:20:38 -06:00
46c5caa1ab
Add "install Qt" to github actions: Update cmake-multi-platform.yml 2024-03-15 11:17:44 -06:00
bf83ffc9ec
Add github actions: Create cmake-multi-platform.yml 2024-03-15 11:01:15 -06:00
5db186e8da Fixed build on Fedora with boost. I'm not sure why it worked on FreeBSD but in Fedora 39 CMake didn't set boost up properly, or maybe the FetchContent(Boost) just never worked and it always found the installed boost library? But it fetches and sets up dynamically now... 2024-03-15 10:50:00 -06:00
e5c068ddf7 Remove external dependency on fmtlib in favor of std::format. Begin transition of model::Part into an interface 2024-03-14 18:06:05 -06:00
6a015d9797 Fix crash on motor load 2024-03-14 07:05:16 -06:00
f4e560fcd9 quick cleanup 2024-02-18 16:38:22 -07:00
5da279a8e6 Cleanup 2024-02-18 16:25:45 -07:00
d9cc4e4aec Remove CMakeLists.txt.user 2024-02-18 09:03:51 -07:00
9517b5b682 Added first model tests. Super basic Part test 2023-10-20 17:03:52 -06:00
41183b8397 WIP. Added Stage objects, and made Stage and Rocket a Propagatable. Changed Propagator to propagate a Propagatable instead of a Rocket. This is to allow for propagating dropped stages 2023-10-20 14:48:35 -06:00
9b807d53a4 Fixed US Standard Atmosphere class and tests 2023-10-19 10:58:01 -06:00
9391b85a07 WIP. Started building model/Part component 2023-10-19 08:33:34 -06:00
4da21707b6 Building and running again 2023-10-16 17:40:33 -06:00
505a66a1be WIP 2023-10-16 14:55:31 -06:00
46 changed files with 1167 additions and 908 deletions

View 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
View File

@ -38,6 +38,8 @@ build/
docs/doxygen/*
# IDE
*.swp
qtrocket.pro.user
.qmake.stash
CMakeLists.txt.user

View File

@ -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()

View File

@ -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>

View File

@ -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

View File

@ -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,13 +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>& initState) { rocket.second->setInitialState(initState); }
void setInitialState(const StateData& initState) { rocket.first->setInitialState(initState); }
private:
QtRocket();
@ -79,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

View File

@ -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:
![Main Window](resources/screenshots/MainWindow.png)
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):
![Alt text](resources/screenshots/Altitude.png)
From here you can also plot velocity by clicking "Plot Velocity":
![Alt text](resources/screenshots/Velocity.png)
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:
![Alt text](resources/screenshots/ThrustCurveWindow.png)
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

View File

@ -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();

View File

@ -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,7 +123,10 @@ void MainWindow::onButton_calculateTrajectory_clicked()
double initialVelocityX = initialVelocity * std::cos(initialAngle / 57.2958);
double initialVelocityZ = initialVelocity * std::sin(initialAngle / 57.2958);
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};
//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);

View File

@ -1,11 +1,9 @@
/// \cond
// C headers
// C++ headers
// 3rd party headers
/// \endcond
#include "QtRocket.h"
#include "utils/Logger.h"
@ -14,12 +12,15 @@ 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;

View File

@ -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
View 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

View File

@ -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
View 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
View 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
View File

58
model/Propagatable.h Normal file
View 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

View File

@ -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
View 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

View File

@ -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

View File

@ -8,8 +8,6 @@
/// \endcond
#include "model/ThrustCurve.h"
#include "utils/Logger.h"
ThrustCurve::ThrustCurve(std::vector<std::pair<double, double>>& tc)
: thrustCurve(tc),

View 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
View 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
View File

40
sim/Aero.h Normal file
View 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

View File

@ -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

View File

@ -1,4 +1,6 @@
add_library(sim
Aero.cpp
Aero.h
AtmosphericModel.h
ConstantAtmosphere.h
ConstantGravityModel.h

View File

@ -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

View File

@ -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
{

View File

@ -17,7 +17,6 @@
#include "sim/ConstantAtmosphere.h"
#include "sim/USStandardAtmosphere.h"
#include "sim/GeoidModel.h"
namespace sim
{

View File

@ -2,7 +2,6 @@
/// \cond
// C headers
// C++ headers
#include <cmath>
#include <chrono>
#include <iostream>
#include <sstream>
@ -14,105 +13,35 @@
// 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
{
// 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
// The state vector has components of the form:
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&)> linearODE = [this](Vector3& state, Vector3& rate) -> std::pair<Vector3, Vector3>
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[0] = rate[0];
// dy/dt
dPosition[1] = rate[1];
// dz/dt
dPosition[2] = rate[2];
dPosition = rate;
// dvx/dt
dVelocity[0] = getForceX() / getMass();
// dvy/dt
dVelocity[1] = getForceY() / getMass();
// dvz/dt
dVelocity[2] = getForceZ() / getMass();
dVelocity = object->getForces(currentTime) / object->getMass(currentTime);
return std::make_pair(dPosition, dVelocity);
};
linearIntegrator.reset(new RK4Solver<Vector6>(linearODE));
linearIntegrator.reset(new RK4Solver<Vector3>(linearODEs));
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;
}
@ -125,24 +54,27 @@ void Propagator::runUntilTerminate()
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point endTime;
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);
std::swap(currentBodyState, tempRes);
StateData nextState;
nextState.position = nextPosition;
nextState.velocity = nextVelocity;
object->setCurrentState(nextState);
if(saveStates)
{
states.push_back(std::make_pair(currentTime, currentBodyState));
object->appendState(currentTime, nextState);
}
if(rocket->terminateCondition(std::make_pair(currentTime, currentBodyState)))
if(object->terminateCondition(currentTime))
break;
currentTime += timeStep;
@ -156,58 +88,4 @@ void Propagator::runUntilTerminate()
}
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};
}
} // namespace sim

View File

@ -5,19 +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
@ -26,21 +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)
void setInitialState(const StateData& initialState)
{
for(std::size_t i = 0; i < initialState.size(); ++i)
{
currentBodyState[i] = initialState[i];
object->setInitialState(initialState);
}
}
const Vector6& getCurrentState() const
const StateData& getCurrentState() const
{
return currentBodyState;
return object->getCurrentState();
}
void runUntilTerminate();
@ -50,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::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

View File

@ -4,10 +4,8 @@
/// \cond
// C headers
// C++ headers
#include <cmath>
#include <functional>
#include <limits>
#include <vector>
// 3rd party headers

View File

@ -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

View File

@ -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,23 +33,23 @@ utils::BinMap initTemps()
}
utils::BinMap initLapseRates()
utils::Bin initLapseRates()
{
utils::BinMap map;
map.insert(std::make_pair(0.0, -0.0065));
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));
map.insert(std::make_pair(32000.0, 0.0028));
map.insert(std::make_pair(20000.0, -0.001));
map.insert(std::make_pair(32000.0, -0.0028));
map.insert(std::make_pair(47000.0, 0.0));
map.insert(std::make_pair(51000.0, -0.0028));
map.insert(std::make_pair(71000.0, -0.002));
map.insert(std::make_pair(51000.0, 0.0028));
map.insert(std::make_pair(71000.0, 0.002));
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));
@ -61,11 +61,24 @@ utils::BinMap initDensities()
return map;
}
utils::BinMap USStandardAtmosphere::temperatureLapseRate(initLapseRates());
utils::BinMap USStandardAtmosphere::standardTemperature(initTemps());
utils::BinMap USStandardAtmosphere::standardDensity(initDensities());
utils::Bin initPressures()
{
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));
map.insert(std::make_pair(32000.0, 868.02));
map.insert(std::make_pair(47000.0, 110.91));
map.insert(std::make_pair(51000.0, 66.94));
map.insert(std::make_pair(71000.0, 3.96));
return map;
}
utils::Bin USStandardAtmosphere::temperatureLapseRate(initLapseRates());
utils::Bin USStandardAtmosphere::standardTemperature(initTemps());
utils::Bin USStandardAtmosphere::standardDensity(initDensities());
utils::Bin USStandardAtmosphere::standardPressure(initPressures());
USStandardAtmosphere::USStandardAtmosphere()
{
@ -81,28 +94,62 @@ double USStandardAtmosphere::getDensity(double altitude)
{
if(utils::math::floatingPointEqual(temperatureLapseRate[altitude], 0.0))
{
return standardDensity[altitude] * std::exp((-Constants::g0 * Constants::airMolarMass * (altitude - standardDensity.getBinBase(altitude)))
return standardDensity[altitude] * std::exp(
(-Constants::g0 * Constants::airMolarMass * (altitude - standardDensity.getBinBase(altitude)))
/ (Constants::Rstar * standardTemperature[altitude]));
}
else
{
double base = (standardTemperature[altitude] - temperatureLapseRate[altitude] * (altitude - standardDensity.getBinBase(altitude))) / standardTemperature[altitude];
double base = (standardTemperature[altitude] - temperatureLapseRate[altitude] *
(altitude - standardDensity.getBinBase(altitude))) / standardTemperature[altitude];
double exponent = (Constants::g0 * Constants::airMolarMass) /
(Constants::Rstar * temperatureLapseRate[altitude]) - 1.0;
return standardDensity[altitude] * std::pow(base, exponent);
}
}
double USStandardAtmosphere::getTemperature(double /*altitude*/)
double USStandardAtmosphere::getTemperature(double altitude)
{
return 0.0;
double baseTemp = standardTemperature[altitude];
double baseAltitude = standardTemperature.getBinBase(altitude);
return baseTemp - (altitude - baseAltitude) * temperatureLapseRate[altitude];
}
double USStandardAtmosphere::getPressure(double /* altitude */)
double USStandardAtmosphere::getPressure(double altitude)
{
return 0.0;
if(utils::math::floatingPointEqual(temperatureLapseRate[altitude], 0.0))
{
return standardPressure[altitude] * std::exp(
(-Constants::g0 * Constants::airMolarMass * (altitude - standardPressure.getBinBase(altitude)))
/ (Constants::Rstar * standardTemperature[altitude]));
}
else
{
double base = (standardTemperature[altitude] - temperatureLapseRate[altitude] *
(altitude - standardPressure.getBinBase(altitude))) / standardTemperature[altitude];
double exponent = (Constants::g0 * Constants::airMolarMass) /
(Constants::Rstar * temperatureLapseRate[altitude]);
return standardPressure[altitude] * std::pow(base, exponent);
}
}
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

View File

@ -3,7 +3,7 @@
// qtrocket headers
#include "sim/AtmosphericModel.h"
#include "utils/BinMap.h"
#include "utils/Bin.h"
namespace sim
{
@ -28,10 +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::Bin temperatureLapseRate;
static utils::Bin standardTemperature;
static utils::Bin standardDensity;
static utils::Bin standardPressure;
};

View File

@ -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)

View File

@ -6,24 +6,85 @@ TEST(USStandardAtmosphereTests, DensityTests)
{
sim::USStandardAtmosphere atmosphere;
EXPECT_DOUBLE_EQ(atmosphere.getDensity(0.0), 1.225);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(1000.0), 1.112);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(2000.0), 1.007);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(3000.0), 0.9093);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(4000.0), 0.8194);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(5000.0), 0.7364);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(6000.0), 0.6601);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(7000.0), 0.5900);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(8000.0), 0.5258);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(9000.0), 0.4647);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(10000.0), 0.4135);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(15000.0), 0.1948);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(20000.0), 0.08891);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(25000.0), 0.04008);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(30000.0), 0.01841);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(40000.0), 0.003996);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(50000.0), 0.001027);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(60000.0), 0.0003097);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(70000.0), 0.00008283);
EXPECT_DOUBLE_EQ(atmosphere.getDensity(80000.0), 0.00001846);
// 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);
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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_)
{

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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