Merge pull request #19 from cthunter01/development
Fix build failures and add github CI actions. Automated builds on Ubuntu and Windows
This commit is contained in:
commit
3c9c8b8c6a
86
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
86
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
# This starter workflow is for a CMake project running on multiple platforms. There is a different
|
||||
# starter workflow if you just want a single platform.
|
||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
|
||||
name: CMake on multiple platforms
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "development" ]
|
||||
pull_request:
|
||||
branches: [ "development" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
|
||||
# Consider changing this to true when your workflow is stable.
|
||||
fail-fast: false
|
||||
|
||||
# Set up a matrix to run the following 3 configurations:
|
||||
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator>
|
||||
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
|
||||
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
|
||||
#
|
||||
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
build_type: [Release]
|
||||
c_compiler: [gcc-13, clang, cl]
|
||||
include:
|
||||
- os: windows-latest
|
||||
c_compiler: cl
|
||||
cpp_compiler: cl
|
||||
- os: ubuntu-latest
|
||||
c_compiler: gcc-13
|
||||
cpp_compiler: g++-13
|
||||
#- os: ubuntu-latest
|
||||
#c_compiler: clang
|
||||
#cpp_compiler: clang++
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
c_compiler: gcc-13
|
||||
- os: windows-latest
|
||||
c_compiler: clang
|
||||
- os: ubuntu-latest
|
||||
c_compiler: cl
|
||||
# Clang is broken on ubuntu-latest. C++20 brings in inconsistent libraries
|
||||
- os: ubuntu-latest
|
||||
c_compiler: clang
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: 6.6.2
|
||||
target: desktop
|
||||
|
||||
- name: Set reusable strings
|
||||
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
|
||||
id: strings
|
||||
shell: bash
|
||||
run: |
|
||||
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: >
|
||||
cmake -B ${{ steps.strings.outputs.build-output-dir }}
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
-S ${{ github.workspace }}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ steps.strings.outputs.build-output-dir }}
|
||||
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest --build-config ${{ matrix.build_type }} -R 'qtrocket_*'
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -38,6 +38,8 @@ build/
|
||||
docs/doxygen/*
|
||||
|
||||
# IDE
|
||||
*.swp
|
||||
qtrocket.pro.user
|
||||
.qmake.stash
|
||||
CMakeLists.txt.user
|
||||
|
||||
|
115
CMakeLists.txt
115
CMakeLists.txt
@ -2,14 +2,27 @@ cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
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
|
||||
FetchContent_Declare(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest
|
||||
GIT_TAG v1.13.0)
|
||||
if(WIN32)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
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
|
||||
@ -36,18 +49,30 @@ if(WIN32)
|
||||
endif()
|
||||
FetchContent_MakeAvailable(CURL)
|
||||
|
||||
# eigen dependency
|
||||
FetchContent_Declare(Eigen
|
||||
GIT_REPOSITORY https://gitlab.com/libeigen/eigen
|
||||
GIT_TAG 3.4.0)
|
||||
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
|
||||
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 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()
|
||||
@ -84,61 +109,6 @@ set(PROJECT_SOURCES
|
||||
gui/ThrustCurveMotorSelector.ui
|
||||
gui/qcustomplot.cpp
|
||||
gui/qcustomplot.h
|
||||
model/MotorCase.cpp
|
||||
model/MotorCase.h
|
||||
model/MotorModel.cpp
|
||||
model/MotorModel.h
|
||||
model/MotorModelDatabase.cpp
|
||||
model/MotorModelDatabase.h
|
||||
model/Rocket.cpp
|
||||
model/Rocket.h
|
||||
model/ThrustCurve.cpp
|
||||
model/ThrustCurve.h
|
||||
sim/AtmosphericModel.h
|
||||
sim/ConstantAtmosphere.h
|
||||
sim/ConstantGravityModel.cpp
|
||||
sim/ConstantGravityModel.h
|
||||
sim/DESolver.h
|
||||
sim/Environment.h
|
||||
sim/GeoidModel.h
|
||||
sim/GravityModel.cpp
|
||||
sim/GravityModel.h
|
||||
sim/Propagator.cpp
|
||||
sim/Propagator.h
|
||||
sim/RK4Solver.h
|
||||
sim/SphericalGeoidModel.cpp
|
||||
sim/SphericalGeoidModel.h
|
||||
sim/SphericalGravityModel.cpp
|
||||
sim/SphericalGravityModel.h
|
||||
sim/StateData.cpp
|
||||
sim/StateData.h
|
||||
sim/USStandardAtmosphere.cpp
|
||||
sim/USStandardAtmosphere.h
|
||||
sim/WindModel.cpp
|
||||
sim/WindModel.h
|
||||
utils/BinMap.cpp
|
||||
utils/BinMap.h
|
||||
utils/CurlConnection.cpp
|
||||
utils/CurlConnection.h
|
||||
utils/Logger.cpp
|
||||
utils/Logger.h
|
||||
utils/MotorModelDatabase.cpp
|
||||
utils/MotorModelDatabase.h
|
||||
utils/RSEDatabaseLoader.cpp
|
||||
utils/RSEDatabaseLoader.h
|
||||
utils/ThreadPool.cpp
|
||||
utils/ThreadPool.h
|
||||
utils/ThrustCurveAPI.cpp
|
||||
utils/ThrustCurveAPI.h
|
||||
utils/Triplet.h
|
||||
utils/TSQueue.h
|
||||
utils/math/Constants.h
|
||||
utils/math/Quaternion.cpp
|
||||
utils/math/Quaternion.h
|
||||
utils/math/UtilityMathFunctions.cpp
|
||||
utils/math/UtilityMathFunctions.h
|
||||
utils/math/Vector3.cpp
|
||||
utils/math/Vector3.h
|
||||
${TS_FILES}
|
||||
)
|
||||
|
||||
@ -167,11 +137,26 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
#qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
||||
endif()
|
||||
|
||||
#target_link_libraries(qtrocket PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${Qt_VERSION_MAJOR}::PrintSupport libcurl jsoncpp_static fmt::fmt-header-only)
|
||||
target_link_libraries(qtrocket PRIVATE Qt6::Widgets Qt6::PrintSupport libcurl jsoncpp_static fmt::fmt-header-only)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(sim)
|
||||
add_subdirectory(model)
|
||||
|
||||
#target_link_libraries(qtrocket PRIVATE
|
||||
# Qt6::Widgets
|
||||
# Qt6::PrintSupport
|
||||
# libcurl
|
||||
# jsoncpp_static
|
||||
# fmt::fmt-header-only
|
||||
# eigen)
|
||||
|
||||
target_link_libraries(qtrocket PRIVATE
|
||||
Qt6::Widgets
|
||||
Qt6::PrintSupport
|
||||
utils
|
||||
sim
|
||||
model)
|
||||
|
||||
set_target_properties(qtrocket PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
|
@ -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>
|
36
QtRocket.cpp
36
QtRocket.cpp
@ -1,4 +1,3 @@
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
@ -45,7 +44,7 @@ void guiWorker(int argc, char* argv[], int& ret)
|
||||
|
||||
// Go!
|
||||
MainWindow w(QtRocket::getInstance());
|
||||
logger->info("Showing MainWindow");
|
||||
logger->debug("Showing MainWindow");
|
||||
w.show();
|
||||
ret = a.exec();
|
||||
|
||||
@ -65,7 +64,7 @@ void QtRocket::init()
|
||||
std::lock_guard<std::mutex> lck(mtx);
|
||||
if(!initialized)
|
||||
{
|
||||
utils::Logger::getInstance()->info("Instantiating new QtRocket");
|
||||
utils::Logger::getInstance()->debug("Instantiating new QtRocket");
|
||||
instance = new QtRocket();
|
||||
initialized = true;
|
||||
}
|
||||
@ -81,10 +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[])
|
||||
@ -101,12 +110,21 @@ int QtRocket::run(int argc, char* argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QtRocket::launchRocket()
|
||||
{
|
||||
// initialize the propagator
|
||||
rocket.first->clearStates();
|
||||
rocket.second->setCurrentTime(0.0);
|
||||
|
||||
// start the rocket motor
|
||||
rocket.first->launch();
|
||||
|
||||
// run the propagator until it terminates
|
||||
rocket.second->runUntilTerminate();
|
||||
}
|
||||
|
||||
void QtRocket::addMotorModels(std::vector<model::MotorModel>& m)
|
||||
{
|
||||
for(const auto& i : m)
|
||||
{
|
||||
motorModels.push_back(i);
|
||||
}
|
||||
motorDatabase->addMotorModels(motorModels);
|
||||
motorDatabase->addMotorModels(m);
|
||||
// TODO: Now clear any duplicates?
|
||||
}
|
||||
|
37
QtRocket.h
37
QtRocket.h
@ -14,13 +14,12 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "model/MotorModel.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "sim/AtmosphericModel.h"
|
||||
#include "sim/GravityModel.h"
|
||||
#include "model/RocketModel.h"
|
||||
#include "sim/Environment.h"
|
||||
#include "sim/Propagator.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/MotorModelDatabase.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
/**
|
||||
* @brief The QtRocket class is the master controller for the QtRocket application.
|
||||
@ -44,18 +43,29 @@ 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);
|
||||
|
||||
const std::vector<model::MotorModel>& getMotorModels() const { return motorModels; }
|
||||
|
||||
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; }
|
||||
|
||||
void launchRocket();
|
||||
/**
|
||||
* @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, 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 StateData& initState) { rocket.first->setInitialState(initState); }
|
||||
|
||||
private:
|
||||
QtRocket();
|
||||
|
||||
@ -66,16 +76,21 @@ private:
|
||||
static std::mutex mtx;
|
||||
static QtRocket* instance;
|
||||
|
||||
// Motor "database(s)"
|
||||
std::vector<model::MotorModel> motorModels;
|
||||
|
||||
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
|
||||
|
@ -35,8 +35,8 @@ AnalysisWindow::~AnalysisWindow()
|
||||
|
||||
void AnalysisWindow::onButton_plotAltitude_clicked()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
const std::vector<std::pair<double, std::vector<double>>>& res = rocket->getStates();
|
||||
QtRocket* qtRocket = QtRocket::getInstance();
|
||||
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();
|
||||
@ -62,8 +62,8 @@ void AnalysisWindow::onButton_plotAltitude_clicked()
|
||||
|
||||
void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
const std::vector<std::pair<double, std::vector<double>>>& res = rocket->getStates();
|
||||
QtRocket* qtRocket = QtRocket::getInstance();
|
||||
const std::vector<std::pair<double, StateData>>& res = qtRocket->getStates();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
@ -74,7 +74,7 @@ void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
for (int i = 0; i < tData.size(); ++i)
|
||||
{
|
||||
tData[i] = res[i].first;
|
||||
zData[i] = res[i].second[5];
|
||||
zData[i] = res[i].second.velocity[2];
|
||||
}
|
||||
// create graph and assign data to it:
|
||||
plot->addGraph();
|
||||
@ -91,8 +91,8 @@ void AnalysisWindow::onButton_plotVelocity_clicked()
|
||||
|
||||
void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
model::MotorModel motor = rocket->getCurrentMotorModel();
|
||||
std::shared_ptr<model::RocketModel> rocket = QtRocket::getInstance()->getRocket();
|
||||
model::MotorModel motor = rocket->getMotorModel();
|
||||
ThrustCurve tc = motor.getThrustCurve();
|
||||
|
||||
|
||||
@ -122,4 +122,4 @@ void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
||||
plot->yAxis->setRange(*std::min_element(std::begin(fData), std::end(fData)), *std::max_element(std::begin(fData), std::end(fData)));
|
||||
plot->replot();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "gui/MainWindow.h"
|
||||
#include "gui/ThrustCurveMotorSelector.h"
|
||||
#include "gui/SimOptionsWindow.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "model/RocketModel.h"
|
||||
#include "utils/RSEDatabaseLoader.h"
|
||||
|
||||
|
||||
@ -83,6 +83,7 @@ MainWindow::MainWindow(QtRocket* _qtRocket, QWidget *parent)
|
||||
this,
|
||||
SLOT(onButton_getTCMotorData_clicked()));
|
||||
|
||||
ui->calculateTrajectory_btn->setDisabled(true);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@ -122,12 +123,16 @@ 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->setInitialState(initialState);
|
||||
rocket->setMass(mass);
|
||||
rocket->setDragCoefficient(dragCoeff);
|
||||
rocket->launch();
|
||||
|
||||
qtRocket->setInitialState(initialState);
|
||||
qtRocket->launchRocket();
|
||||
|
||||
AnalysisWindow aWindow;
|
||||
aWindow.setModal(false);
|
||||
@ -186,7 +191,13 @@ void MainWindow::onButton_setMotor_clicked()
|
||||
QString motorName = ui->engineSelectorComboBox->currentText();
|
||||
model::MotorModel mm = rseDatabase->getMotorModelByName(motorName.toStdString());
|
||||
QtRocket::getInstance()->getRocket()->setMotorModel(mm);
|
||||
QtRocket::getInstance()->addMotorModels(rseDatabase->getMotors());
|
||||
|
||||
// Now that we have a motor selected, we can enable the calculateTrajectory button
|
||||
ui->calculateTrajectory_btn->setDisabled(false);
|
||||
|
||||
/// TODO: Figure out if this is the right place to populate the motor database
|
||||
/// or from RSEDatabaseLoader where it currently is populated.
|
||||
//QtRocket::getInstance()->addMotorModels(rseDatabase->getMotors());
|
||||
|
||||
}
|
||||
|
||||
|
48
main.cpp
48
main.cpp
@ -1,11 +1,9 @@
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
|
||||
#include "QtRocket.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
@ -14,54 +12,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Instantiate logger
|
||||
utils::Logger* logger = utils::Logger::getInstance();
|
||||
logger->setLogLevel(utils::Logger::DEBUG_);
|
||||
logger->setLogLevel(utils::Logger::PERF_);
|
||||
logger->info("Logger instantiated at PERF level");
|
||||
// instantiate QtRocket
|
||||
logger->debug("Starting QtRocket");
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
|
||||
// Run QtRocket. This'll start the GUI thread and block until the user
|
||||
// exits the program
|
||||
logger->debug("QtRocket->run()");
|
||||
int retVal = qtrocket->run(argc, argv);
|
||||
logger->debug("Returning");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This was the old main when it directly started the QtGui. It worked. The new way of
|
||||
* starting the gui through QtRocket->run() also seems to work, but I'm leaving this here for
|
||||
* now in case there are unforeseen issues with starting the gui in a separate thread via
|
||||
* QtRocket::run()
|
||||
*
|
||||
|
||||
#include "gui/MainWindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLocale>
|
||||
#include <QTranslator>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
a.setWindowIcon(QIcon(":/qtrocket.png"));
|
||||
|
||||
// Start translation component.
|
||||
// TODO: Only support US English at the moment. Anyone want to help translate?
|
||||
QTranslator translator;
|
||||
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||
for (const QString &locale : uiLanguages)
|
||||
{
|
||||
const QString baseName = "qtrocket_" + QLocale(locale).name();
|
||||
if (translator.load(":/i18n/" + baseName))
|
||||
{
|
||||
a.installTranslator(&translator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Go!
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
*/
|
||||
|
20
model/CMakeLists.txt
Normal file
20
model/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
add_library(model
|
||||
MotorModel.cpp
|
||||
MotorModel.h
|
||||
MotorModelDatabase.cpp
|
||||
MotorModelDatabase.h
|
||||
Part.cpp
|
||||
Part.h
|
||||
Propagatable.cpp
|
||||
Propagatable.h
|
||||
RocketModel.cpp
|
||||
RocketModel.h
|
||||
ThrustCurve.cpp
|
||||
ThrustCurve.h
|
||||
InertiaTensors.h)
|
||||
|
||||
target_link_libraries(model PRIVATE
|
||||
utils)
|
||||
|
||||
# Unit tests
|
||||
add_subdirectory(tests)
|
70
model/InertiaTensors.h
Normal file
70
model/InertiaTensors.h
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef INERTIATENSORS_H
|
||||
#define INERTIATENSORS_H
|
||||
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The InertiaTensors class provides a collection of methods to
|
||||
* deliver some common inertia tensors centered about the center of mass
|
||||
*/
|
||||
class InertiaTensors
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief SolidSphere
|
||||
* @param radius (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 SolidSphere(double radius)
|
||||
{
|
||||
double xx = 0.4*radius*radius;
|
||||
double yy = xx;
|
||||
double zz = xx;
|
||||
return Matrix3{{xx, 0, 0},
|
||||
{0, yy, 0},
|
||||
{0, 0, zz}};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HollowSphere
|
||||
* @param radius (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 HollowSphere(double radius)
|
||||
{
|
||||
double xx = (2.0/3.0)*radius*radius;
|
||||
double yy = xx;
|
||||
double zz = xx;
|
||||
return Matrix3{{xx, 0, 0},
|
||||
{0, yy, 0},
|
||||
{0, 0, zz}};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tube - The longitudinal axis is the z-axis. Can also be used for a solid cylinder
|
||||
* when innerRadius = 0.0
|
||||
* @param innerRadius (meters)
|
||||
* @param outerRadius (meters)
|
||||
* @param length (meters)
|
||||
* @return
|
||||
*/
|
||||
static Matrix3 Tube(double innerRadius, double outerRadius, double length)
|
||||
{
|
||||
double xx = (1.0/12.0)*(3.0*(innerRadius*innerRadius + outerRadius*outerRadius) + length*length);
|
||||
double yy = xx;
|
||||
double zz = (1.0/2.0)*(innerRadius*innerRadius + outerRadius*outerRadius);
|
||||
return Matrix3{{xx, 0.0, 0.0},
|
||||
{0.0, yy, 0.0},
|
||||
{0.0, 0.0, zz}};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // INERTIATENSORS_H
|
@ -1 +0,0 @@
|
||||
#include "MotorCase.h"
|
@ -1,17 +0,0 @@
|
||||
#ifndef MODEL_MOTORCASE_H
|
||||
#define MODEL_MOTORCASE_H
|
||||
|
||||
namespace model
|
||||
{
|
||||
class MotorCase
|
||||
{
|
||||
public:
|
||||
MotorCase();
|
||||
~MotorCase();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace model
|
||||
#endif // MODEL_MOTORCASE_H
|
@ -60,6 +60,7 @@ double MotorModel::getMass(double simTime) const
|
||||
double propMassEnd = i->second;
|
||||
double slope = (propMassEnd - propMassStart) / (tEnd - tStart);
|
||||
double currentMass = emptyMass + propMassStart + (thrustTime - tStart) * slope;
|
||||
utils::Logger::getInstance()->info("simTime: " + std::to_string(simTime) + ": motor mass: " + std::to_string(currentMass));
|
||||
return currentMass;
|
||||
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ public:
|
||||
MetaData data;
|
||||
private:
|
||||
bool ignitionOccurred{false};
|
||||
bool burnOutOccurred{false};
|
||||
bool burnOutOccurred{false};
|
||||
double emptyMass;
|
||||
double isp;
|
||||
double maxTime;
|
||||
|
109
model/Part.cpp
Normal file
109
model/Part.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "Part.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
Part::Part(const std::string& n,
|
||||
const Matrix3& I,
|
||||
double m,
|
||||
const Vector3& centerMass)
|
||||
: parent(nullptr),
|
||||
name(n),
|
||||
inertiaTensor(I),
|
||||
compositeInertiaTensor(I),
|
||||
mass(m),
|
||||
compositeMass(m),
|
||||
cm(centerMass),
|
||||
needsRecomputing(false),
|
||||
childParts()
|
||||
{ }
|
||||
|
||||
Part::~Part()
|
||||
{}
|
||||
|
||||
Part::Part(const Part& orig)
|
||||
: parent(orig.parent),
|
||||
name(orig.name),
|
||||
inertiaTensor(orig.inertiaTensor),
|
||||
compositeInertiaTensor(orig.compositeInertiaTensor),
|
||||
mass(orig.mass),
|
||||
compositeMass(orig.compositeMass),
|
||||
cm(orig.cm),
|
||||
needsRecomputing(orig.needsRecomputing),
|
||||
childParts()
|
||||
{
|
||||
|
||||
// We are copying the whole tree. If the part we're copying itself has child
|
||||
// parts, we are also copying all of them! This may be inefficient and not what
|
||||
// is desired, but it is less likely to lead to weird bugs with the same part
|
||||
// appearing in multiple locations of the rocket
|
||||
utils::Logger::getInstance()->debug("Calling model::Part copy constructor. Recursively copying all child parts. Check Part names for uniqueness");
|
||||
|
||||
|
||||
for(const auto& i : orig.childParts)
|
||||
{
|
||||
Part& x = *std::get<0>(i);
|
||||
std::shared_ptr<Part> tempPart = std::make_shared<Part>(x);
|
||||
childParts.emplace_back(tempPart, std::get<1>(i));;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double Part::getChildMasses(double t)
|
||||
{
|
||||
double childMasses{0.0};
|
||||
for(const auto& i : childParts)
|
||||
{
|
||||
childMasses += std::get<0>(i)->getMass(t);
|
||||
}
|
||||
return childMasses;
|
||||
|
||||
}
|
||||
|
||||
void Part::addChildPart(const Part& childPart, Vector3 position)
|
||||
{
|
||||
|
||||
double childMass = childPart.compositeMass;
|
||||
Matrix3 childInertiaTensor = childPart.compositeInertiaTensor;
|
||||
std::shared_ptr<Part> newChild = std::make_shared<Part>(childPart);
|
||||
// Set the parent pointer
|
||||
newChild->parent = this;
|
||||
|
||||
// Recompute inertia tensor
|
||||
|
||||
childInertiaTensor += childMass * ( position.dot(position) * Matrix3::Identity() - position*position.transpose());
|
||||
|
||||
compositeInertiaTensor += childInertiaTensor;
|
||||
compositeMass += childMass;
|
||||
|
||||
childParts.emplace_back(std::move(newChild), std::move(position));
|
||||
|
||||
if(parent)
|
||||
{
|
||||
parent->markAsNeedsRecomputing();
|
||||
parent->recomputeInertiaTensor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Part::recomputeInertiaTensor()
|
||||
{
|
||||
if(!needsRecomputing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// recompute the whole composite inertia tensor
|
||||
// Reset the composite inertia tensor
|
||||
compositeInertiaTensor = inertiaTensor;
|
||||
compositeMass = mass;
|
||||
for(auto& [child, pos] : childParts)
|
||||
{
|
||||
child->recomputeInertiaTensor();
|
||||
compositeInertiaTensor += child->compositeInertiaTensor + child->compositeMass * ( pos.dot(pos) * Matrix3::Identity() - pos*pos.transpose());
|
||||
compositeMass += child->compositeMass;
|
||||
}
|
||||
needsRecomputing = false;
|
||||
}
|
||||
|
||||
} // namespace model
|
136
model/Part.h
Normal file
136
model/Part.h
Normal file
@ -0,0 +1,136 @@
|
||||
#ifndef MODEL_PART_H
|
||||
#define MODEL_PART_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class Part
|
||||
{
|
||||
public:
|
||||
Part(const std::string& name,
|
||||
const Matrix3& I,
|
||||
double m,
|
||||
const Vector3& centerMass);
|
||||
|
||||
virtual ~Part();
|
||||
|
||||
Part(const Part&);
|
||||
|
||||
Part& operator=(Part other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
std::swap(parent, other.parent);
|
||||
std::swap(name, other.name);
|
||||
std::swap(inertiaTensor, other.inertiaTensor);
|
||||
std::swap(compositeInertiaTensor, other.compositeInertiaTensor);
|
||||
std::swap(mass, other.mass);
|
||||
std::swap(compositeMass, other.compositeMass);
|
||||
std::swap(cm, other.cm);
|
||||
std::swap(needsRecomputing, other.needsRecomputing);
|
||||
std::swap(childParts, other.childParts);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Part& operator=(Part&& other)
|
||||
{
|
||||
parent = std::move(other.parent);
|
||||
name = std::move(other.name);
|
||||
inertiaTensor = std::move(other.inertiaTensor);
|
||||
compositeInertiaTensor = std::move(other.compositeInertiaTensor);
|
||||
mass = std::move(other.mass);
|
||||
compositeMass = std::move(other.compositeMass);
|
||||
cm = std::move(other.cm);
|
||||
needsRecomputing = std::move(other.needsRecomputing);
|
||||
childParts = std::move(other.childParts);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setMass(double m) { mass = m; }
|
||||
|
||||
// Set the inertia tensor
|
||||
void setI(const Matrix3& I) { inertiaTensor = I; }
|
||||
Matrix3 getI() { return inertiaTensor; }
|
||||
Matrix3 getCompositeI() { return compositeInertiaTensor; }
|
||||
|
||||
void setCm(const Vector3& x) { cm = x; }
|
||||
// Special version of setCM that assumes the cm lies along the body x-axis
|
||||
void setCm(double x) { cm = {x, 0.0, 0.0}; }
|
||||
|
||||
double getMass(double t)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
double getCompositeMass(double t)
|
||||
{
|
||||
return compositeMass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a child part to this part.
|
||||
*
|
||||
* @param childPart Child part to add
|
||||
* @param position Relative position of the child part's center-of-mass w.r.t the
|
||||
* parent's center of mass
|
||||
*/
|
||||
void addChildPart(const Part& childPart, Vector3 position);
|
||||
|
||||
/**
|
||||
* @brief Recomputes the inertia tensor. If the change is due to the change in inertia
|
||||
* of a child part, an optional name of the child part can be given to
|
||||
* only recompute that change rather than recompute all child inertia
|
||||
* tensors
|
||||
*
|
||||
* @param name Optional name of the child part to recompute. If empty, it will
|
||||
* recompute all child inertia tensors
|
||||
*/
|
||||
//void recomputeInertiaTensor(std::string name = "");
|
||||
void recomputeInertiaTensor();
|
||||
private:
|
||||
|
||||
// This is a pointer to the parent Part, if it has one. Purpose is to be able to
|
||||
// tell the parent if it needs to recompute anything if this part changes. e.g.
|
||||
// if a change to this part's inertia tensor occurs, the parent needs to recompute
|
||||
// it's total inertia tensor.
|
||||
Part* parent{nullptr};
|
||||
|
||||
std::string name;
|
||||
|
||||
double getChildMasses(double t);
|
||||
void markAsNeedsRecomputing()
|
||||
{ needsRecomputing = true; if(parent) { parent->markAsNeedsRecomputing(); }}
|
||||
|
||||
// Because a part is both a simple part and the composite of itself with all of it's children,
|
||||
// we will keep track of this object's inertia tensor (without children), and the composite
|
||||
// one with all of it's children attached
|
||||
Matrix3 inertiaTensor; // moment of inertia tensor with respect to the part's center of mass and
|
||||
Matrix3 compositeInertiaTensor;
|
||||
double mass; // The moment of inertia tensor also has this, so don't double compute
|
||||
double compositeMass; // The mass of this part along with all attached parts
|
||||
|
||||
Vector3 cm; // center of mass wrt middle of component
|
||||
|
||||
bool needsRecomputing{false};
|
||||
|
||||
/// @brief child parts and the relative positions of their center of mass w.r.t.
|
||||
/// the center of mass of this part
|
||||
std::vector<std::tuple<std::shared_ptr<Part>, Vector3>> childParts;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MODEL_PART_H
|
0
model/Propagatable.cpp
Normal file
0
model/Propagatable.cpp
Normal file
58
model/Propagatable.h
Normal file
58
model/Propagatable.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef MODEL_PROPAGATABLE_H
|
||||
#define MODEL_PROPAGATABLE_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <utility>
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "sim/Aero.h"
|
||||
#include "sim/StateData.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class Propagatable
|
||||
{
|
||||
public:
|
||||
Propagatable() {}
|
||||
virtual ~Propagatable() {}
|
||||
|
||||
virtual Vector3 getForces(double t) = 0;
|
||||
virtual Vector3 getTorques(double t) = 0;
|
||||
|
||||
virtual double getMass(double t) = 0;
|
||||
virtual Matrix3 getInertiaTensor(double t) = 0;
|
||||
|
||||
virtual bool terminateCondition(double t) = 0;
|
||||
|
||||
void setCurrentState(const StateData& st) { currentState = st; }
|
||||
const StateData& getCurrentState() { return currentState; }
|
||||
|
||||
const StateData& getInitialState() { return initialState; }
|
||||
void setInitialState(const StateData& init) { initialState = init; }
|
||||
|
||||
void appendState(double t, const StateData& st) { states.emplace_back(t, st); }
|
||||
|
||||
const std::vector<std::pair<double, StateData>>& getStates() { return states; }
|
||||
|
||||
void clearStates() { states.clear(); }
|
||||
|
||||
protected:
|
||||
|
||||
sim::Aero aeroData;
|
||||
|
||||
StateData initialState;
|
||||
StateData currentState;
|
||||
StateData nextState;
|
||||
|
||||
std::vector<std::pair<double, StateData>> states;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MODEL_PROPAGATABLE_H
|
@ -1,34 +0,0 @@
|
||||
#include "Rocket.h"
|
||||
#include "QtRocket.h"
|
||||
|
||||
Rocket::Rocket() : propagator(this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Rocket::launch()
|
||||
{
|
||||
propagator.clearStates();
|
||||
propagator.setCurrentTime(0.0);
|
||||
mm.startMotor(0.0);
|
||||
propagator.runUntilTerminate();
|
||||
}
|
||||
|
||||
void Rocket::setMotorModel(const model::MotorModel& motor)
|
||||
{
|
||||
mm = motor;
|
||||
}
|
||||
|
||||
bool Rocket::terminateCondition(const std::pair<double, std::vector<double>>& 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);
|
||||
}
|
119
model/Rocket.h
119
model/Rocket.h
@ -1,119 +0,0 @@
|
||||
#ifndef ROCKET_H
|
||||
#define ROCKET_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "model/ThrustCurve.h"
|
||||
#include "model/MotorModel.h"
|
||||
#include "sim/Propagator.h"
|
||||
|
||||
/**
|
||||
* @brief The Rocket class holds all rocket components
|
||||
*
|
||||
*/
|
||||
class Rocket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Rocket class constructor
|
||||
*/
|
||||
Rocket();
|
||||
|
||||
/**
|
||||
* @brief launch Propagates the Rocket object until termination,
|
||||
* normally when altitude crosses from positive to negative
|
||||
*/
|
||||
void launch();
|
||||
|
||||
/**
|
||||
* @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, std::vector<double>>>& getStates() const { return propagator.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) { propagator.setInitialState(initState); }
|
||||
|
||||
/**
|
||||
* @brief getMass returns the current mass of the rocket. This is the sum of all components' masses
|
||||
* @return total current mass of the Rocket
|
||||
*/
|
||||
double getMass(double simTime) const { return mass + mm.getMass(simTime); }
|
||||
|
||||
/**
|
||||
* @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; }
|
||||
|
||||
/**
|
||||
* @brief getThrust returns current motor thrust
|
||||
* @param t current simulation time
|
||||
* @return thrust in Newtons
|
||||
*/
|
||||
double getThrust(double t);
|
||||
|
||||
/**
|
||||
* @brief setMotorModel
|
||||
* @param motor
|
||||
*/
|
||||
void setMotorModel(const model::MotorModel& motor);
|
||||
|
||||
/**
|
||||
* @brief Returns the current motor model.
|
||||
* @return The current motor model
|
||||
*/
|
||||
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, std::vector<double>>& cond);
|
||||
|
||||
/**
|
||||
* @brief setName sets the rocket name
|
||||
* @param n name to set the Rocket
|
||||
*/
|
||||
void setName(const std::string& n) { name = n; }
|
||||
private:
|
||||
|
||||
std::string name; /// Rocket name
|
||||
sim::Propagator propagator; /// propagator
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
#endif // ROCKET_H
|
79
model/RocketModel.cpp
Normal file
79
model/RocketModel.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "RocketModel.h"
|
||||
#include "QtRocket.h"
|
||||
#include "InertiaTensors.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
RocketModel::RocketModel()
|
||||
: topPart("NoseCone", InertiaTensors::SolidSphere(1.0), 1.0, {0.0, 0.0, 1.0})
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
double RocketModel::getMass(double t)
|
||||
{
|
||||
double mass = mm.getMass(t);
|
||||
mass += topPart.getCompositeMass(t);
|
||||
return mass;
|
||||
}
|
||||
|
||||
Matrix3 RocketModel::getInertiaTensor(double)
|
||||
{
|
||||
return topPart.getCompositeI();
|
||||
}
|
||||
|
||||
bool RocketModel::terminateCondition(double)
|
||||
{
|
||||
// Terminate propagation when the z coordinate drops below zero
|
||||
if(currentState.position[2] < 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 RocketModel::getForces(double t)
|
||||
{
|
||||
// Get thrust
|
||||
// Assume that thrust is always through the center of mass and in the rocket's Z-axis
|
||||
Vector3 forces{0.0, 0.0, mm.getThrust(t)};
|
||||
|
||||
|
||||
// Get gravity
|
||||
auto gravityModel = QtRocket::getInstance()->getEnvironment()->getGravityModel();
|
||||
|
||||
Vector3 gravity = gravityModel->getAccel(currentState.position)*getMass(t);
|
||||
|
||||
forces += gravity;
|
||||
|
||||
// Calculate aero forces
|
||||
|
||||
|
||||
return forces;
|
||||
}
|
||||
|
||||
Vector3 RocketModel::getTorques(double t)
|
||||
{
|
||||
return Vector3{0.0, 0.0, 0.0};
|
||||
|
||||
}
|
||||
|
||||
double RocketModel::getThrust(double t)
|
||||
{
|
||||
return mm.getThrust(t);
|
||||
}
|
||||
|
||||
void RocketModel::launch()
|
||||
{
|
||||
mm.startMotor(0.0);
|
||||
}
|
||||
|
||||
void RocketModel::setMotorModel(const model::MotorModel& motor)
|
||||
{
|
||||
mm = motor;
|
||||
}
|
||||
|
||||
} // namespace model
|
116
model/RocketModel.h
Normal file
116
model/RocketModel.h
Normal file
@ -0,0 +1,116 @@
|
||||
#ifndef ROCKETMODEL_H
|
||||
#define ROCKETMODEL_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "model/Part.h"
|
||||
#include "sim/Propagator.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 RocketModel : public Propagatable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Rocket class constructor
|
||||
*/
|
||||
RocketModel();
|
||||
|
||||
/**
|
||||
* @brief Rocket class destructor
|
||||
*
|
||||
*/
|
||||
virtual ~RocketModel() {}
|
||||
|
||||
/**
|
||||
* @brief launch Propagates the Rocket object until termination,
|
||||
* normally when altitude crosses from positive to negative
|
||||
*/
|
||||
void launch();
|
||||
|
||||
Vector3 getForces(double t) override;
|
||||
Vector3 getTorques(double t) override;
|
||||
/**
|
||||
* @brief getMass returns current rocket mass
|
||||
* @param t current simulation time
|
||||
* @return mass in kg
|
||||
*/
|
||||
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;
|
||||
|
||||
Matrix3 getInertiaTensor(double t) override;
|
||||
|
||||
/**
|
||||
* @brief getThrust returns current motor thrust
|
||||
* @param t current simulation time
|
||||
* @return thrust in Newtons
|
||||
*/
|
||||
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; }
|
||||
|
||||
|
||||
/**
|
||||
* @brief setName sets the rocket name
|
||||
* @param n name to set the Rocket
|
||||
*/
|
||||
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
|
||||
|
||||
model::MotorModel mm; /// Current Motor Model
|
||||
|
||||
model::Part topPart;
|
||||
|
||||
};
|
||||
|
||||
} // namespace model
|
||||
#endif // ROCKETMODEL_H
|
@ -8,8 +8,6 @@
|
||||
/// \endcond
|
||||
|
||||
#include "model/ThrustCurve.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
ThrustCurve::ThrustCurve(std::vector<std::pair<double, double>>& tc)
|
||||
: thrustCurve(tc),
|
||||
|
16
model/tests/CMakeLists.txt
Normal file
16
model/tests/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
add_executable(model_tests
|
||||
PartTests.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(model_tests PRIVATE
|
||||
model
|
||||
utils
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(model_tests)
|
||||
|
||||
add_test(NAME qtrocket_model_tests COMMAND model_tests)
|
||||
|
70
model/tests/PartTests.cpp
Normal file
70
model/tests/PartTests.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "model/Part.h"
|
||||
|
||||
class PartTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
// Per-test-suite set-up.
|
||||
// Called before the first test in this test suite.
|
||||
// Can be omitted if not needed.
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
//shared_resource_ = new ...;
|
||||
|
||||
// If `shared_resource_` is **not deleted** in `TearDownTestSuite()`,
|
||||
// reallocation should be prevented because `SetUpTestSuite()` may be called
|
||||
// in subclasses of FooTest and lead to memory leak.
|
||||
//
|
||||
// if (shared_resource_ == nullptr) {
|
||||
// shared_resource_ = new ...;
|
||||
// }
|
||||
}
|
||||
|
||||
// Per-test-suite tear-down.
|
||||
// Called after the last test in this test suite.
|
||||
// Can be omitted if not needed.
|
||||
static void TearDownTestSuite()
|
||||
{
|
||||
//delete shared_resource_;
|
||||
//shared_resource_ = nullptr;
|
||||
}
|
||||
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override { }
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override { }
|
||||
|
||||
// Some expensive resource shared by all tests.
|
||||
//static T* shared_resource_;
|
||||
};
|
||||
|
||||
//T* FooTest::shared_resource_ = nullptr;
|
||||
|
||||
TEST(PartTest, CreationTests)
|
||||
{
|
||||
Matrix3 inertia;
|
||||
inertia << 1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
Vector3 cm{1, 0, 0};
|
||||
model::Part testPart("testPart",
|
||||
inertia,
|
||||
1.0,
|
||||
cm);
|
||||
|
||||
Matrix3 inertia2;
|
||||
inertia2 << 1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
Vector3 cm2{1, 0, 0};
|
||||
model::Part testPart2("testPart2",
|
||||
inertia2,
|
||||
1.0,
|
||||
cm2);
|
||||
Vector3 R{2.0, 2.0, 2.0};
|
||||
testPart.addChildPart(testPart2, R);
|
||||
|
||||
|
||||
}
|
0
sim/Aero.cpp
Normal file
0
sim/Aero.cpp
Normal file
40
sim/Aero.h
Normal file
40
sim/Aero.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef SIM_AERO_H
|
||||
#define SIM_AERO_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
||||
class Aero
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
Vector3 cp; /// center of pressure
|
||||
|
||||
double Cx; /// longitudinal coefficient
|
||||
double Cy; /// These are probably the same for axial symmetric
|
||||
double Cz; /// rockets. The coeffients in the y and z body directions
|
||||
|
||||
double Cl; // roll moment coefficient
|
||||
double Cm; // pitch moment coefficient
|
||||
double Cn; // yaw moment coefficient
|
||||
|
||||
double baseCd; // coefficient of drag due to base drag
|
||||
double Cd; // total coeffient of drag
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SIM_AERO_H
|
@ -13,6 +13,10 @@ public:
|
||||
virtual double getDensity(double altitude) = 0;
|
||||
virtual double getPressure(double altitude) = 0;
|
||||
virtual double getTemperature(double altitude) = 0;
|
||||
|
||||
virtual double getSpeedOfSound(double altitude) = 0;
|
||||
virtual double getDynamicViscosity(double altitude) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
28
sim/CMakeLists.txt
Normal file
28
sim/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
add_library(sim
|
||||
Aero.cpp
|
||||
Aero.h
|
||||
AtmosphericModel.h
|
||||
ConstantAtmosphere.h
|
||||
ConstantGravityModel.h
|
||||
DESolver.h
|
||||
Environment.h
|
||||
GeoidModel.h
|
||||
GravityModel.h
|
||||
Propagator.cpp
|
||||
Propagator.h
|
||||
RK4Solver.h
|
||||
SphericalGeoidModel.cpp
|
||||
SphericalGeoidModel.h
|
||||
SphericalGravityModel.cpp
|
||||
SphericalGravityModel.h
|
||||
StateData.h
|
||||
USStandardAtmosphere.cpp
|
||||
USStandardAtmosphere.h
|
||||
WindModel.cpp
|
||||
WindModel.h)
|
||||
|
||||
target_link_libraries(sim PRIVATE
|
||||
utils)
|
||||
|
||||
# Unit tests
|
||||
add_subdirectory(tests)
|
@ -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
|
||||
|
@ -1,10 +0,0 @@
|
||||
#include "ConstantGravityModel.h"
|
||||
|
||||
namespace sim {
|
||||
|
||||
ConstantGravityModel::ConstantGravityModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace sim
|
@ -3,18 +3,21 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "sim/GravityModel.h"
|
||||
#include "utils/Triplet.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim {
|
||||
|
||||
class ConstantGravityModel : public GravityModel
|
||||
{
|
||||
public:
|
||||
ConstantGravityModel();
|
||||
ConstantGravityModel() {}
|
||||
|
||||
virtual ~ConstantGravityModel() {}
|
||||
virtual ~ConstantGravityModel() {}
|
||||
|
||||
TripletD getAccel(double, double, double) override { return TripletD(0.0, 0.0, -9.8); }
|
||||
Vector3 getAccel(double, double, double) override
|
||||
{
|
||||
return Vector3(0.0, 0.0, -9.8);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -4,14 +4,17 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class DESolver
|
||||
{
|
||||
public:
|
||||
@ -19,7 +22,17 @@ public:
|
||||
virtual ~DESolver() {}
|
||||
|
||||
virtual void setTimeStep(double ts) = 0;
|
||||
virtual void step(double t, const std::vector<double>& curVal, std::vector<double>& res ) = 0;
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param curVal
|
||||
* @param res
|
||||
* @param t Optional parameter, but not used in QtRocket. Some generic solvers take time as
|
||||
* a parameter to ODEs, but QtRocket's kinematic equations don't. Since I wrote
|
||||
* the RK4 solver independently as a general tool, this interface is needed
|
||||
* here unfortunately.
|
||||
*/
|
||||
virtual std::pair<T, T> step(T& state, T& rate) = 0;
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "sim/ConstantAtmosphere.h"
|
||||
#include "sim/USStandardAtmosphere.h"
|
||||
#include "sim/GeoidModel.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include "GravityModel.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
||||
GravityModel::GravityModel()
|
||||
{
|
||||
}
|
||||
|
||||
GravityModel::~GravityModel()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace sim
|
@ -2,7 +2,7 @@
|
||||
#define SIM_GRAVITYMODEL_H
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/Triplet.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
@ -10,11 +10,11 @@ namespace sim
|
||||
class GravityModel
|
||||
{
|
||||
public:
|
||||
GravityModel();
|
||||
virtual ~GravityModel();
|
||||
GravityModel() {}
|
||||
virtual ~GravityModel() {}
|
||||
|
||||
virtual TripletD getAccel(double x, double y, double z) = 0;
|
||||
TripletD getAccel(const TripletD& t) { return this->getAccel(t.x1, t.x2, t.x3); }
|
||||
virtual Vector3 getAccel(double x, double y, double z) = 0;
|
||||
Vector3 getAccel(const Vector3& t) { return this->getAccel(t.x(), t.y(), t.z()); }
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -2,7 +2,6 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -14,47 +13,36 @@
|
||||
// qtrocket headers
|
||||
#include "Propagator.h"
|
||||
|
||||
#include "QtRocket.h"
|
||||
#include "model/Rocket.h"
|
||||
#include "sim/RK4Solver.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
namespace sim {
|
||||
|
||||
Propagator::Propagator(Rocket* r)
|
||||
: integrator(),
|
||||
rocket(r)
|
||||
|
||||
namespace sim
|
||||
{
|
||||
|
||||
Propagator::Propagator(std::shared_ptr<model::Propagatable> r)
|
||||
: linearIntegrator(),
|
||||
object(r),
|
||||
saveStates(true),
|
||||
timeStep(0.01)
|
||||
{
|
||||
// Linear velocity and acceleration
|
||||
std::function<std::pair<Vector3, Vector3>(Vector3&, Vector3&)> linearODEs = [this](Vector3& state, Vector3& rate) -> std::pair<Vector3, Vector3>
|
||||
{
|
||||
Vector3 dPosition;
|
||||
Vector3 dVelocity;
|
||||
// dx/dt
|
||||
dPosition = rate;
|
||||
|
||||
// This is a little strange, but I have to populate the integrator unique_ptr
|
||||
// with reset. make_unique() doesn't work because the compiler can't seem to
|
||||
// deduce the template parameters correctly, and I don't want to specify them
|
||||
// manually either. RK4Solver constructor is perfectly capable of deducing it's
|
||||
// template types, and it derives from DESolver, so we can just reset the unique_ptr
|
||||
// and pass it a freshly allocated RK4Solver pointer
|
||||
// dvx/dt
|
||||
dVelocity = object->getForces(currentTime) / object->getMass(currentTime);
|
||||
|
||||
// The state vector has components of the form:
|
||||
// (x, y, z, xdot, ydot, zdot, pitch, yaw, roll, pitchRate, yawRate, rollRate)
|
||||
integrator.reset(new RK4Solver(
|
||||
/* dx/dt */ [](double, const std::vector<double>& s) -> double {return s[3]; },
|
||||
/* dy/dt */ [](double, const std::vector<double>& s) -> double {return s[4]; },
|
||||
/* dz/dt */ [](double, const std::vector<double>& s) -> double {return s[5]; },
|
||||
/* dvx/dt */ [this](double, const std::vector<double>& ) -> double { return getForceX() / getMass(); },
|
||||
/* dvy/dt */ [this](double, const std::vector<double>& ) -> double { return getForceY() / getMass(); },
|
||||
/* dvz/dt */ [this](double, const std::vector<double>& ) -> double { return getForceZ() / getMass(); },
|
||||
/* dpitch/dt */ [](double, const std::vector<double>& s) -> double { return s[9]; },
|
||||
/* dyaw/dt */ [](double, const std::vector<double>& s) -> double { return s[10]; },
|
||||
/* droll/dt */ [](double, const std::vector<double>& s) -> double { return s[11]; },
|
||||
/* dpitchRate/dt */ [this](double, const std::vector<double>& s) -> double { return (getTorqueP() - s[7] * s[8] * (getIroll() - getIyaw())) / getIpitch(); },
|
||||
/* dyawRate/dt */ [this](double, const std::vector<double>& s) -> double { return (getTorqueQ() - s[6] * s[9] * (getIpitch() - getIroll())) / getIyaw(); },
|
||||
/* drollRate/dt */ [this](double, const std::vector<double>& s) -> double { return (getTorqueR() - s[6] * s[7] * (getIyaw() - getIpitch())) / getIroll(); }));
|
||||
return std::make_pair(dPosition, dVelocity);
|
||||
};
|
||||
|
||||
linearIntegrator.reset(new RK4Solver<Vector3>(linearODEs));
|
||||
linearIntegrator->setTimeStep(timeStep);
|
||||
|
||||
integrator->setTimeStep(timeStep);
|
||||
saveStates = true;
|
||||
saveStates = true;
|
||||
}
|
||||
|
||||
Propagator::~Propagator()
|
||||
@ -63,61 +51,41 @@ Propagator::~Propagator()
|
||||
|
||||
void Propagator::runUntilTerminate()
|
||||
{
|
||||
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
||||
std::chrono::steady_clock::time_point endTime;
|
||||
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
||||
std::chrono::steady_clock::time_point endTime;
|
||||
|
||||
while(true)
|
||||
{
|
||||
// tempRes gets overwritten
|
||||
integrator->step(currentTime, currentState, tempRes);
|
||||
Vector3 currentPosition;
|
||||
Vector3 currentVelocity;
|
||||
Vector3 nextPosition;
|
||||
Vector3 nextVelocity;
|
||||
while(true)
|
||||
{
|
||||
currentPosition = object->getCurrentState().position;
|
||||
currentVelocity = object->getCurrentState().velocity;
|
||||
|
||||
std::swap(currentState, tempRes);
|
||||
if(saveStates)
|
||||
{
|
||||
states.push_back(std::make_pair(currentTime, currentState));
|
||||
}
|
||||
if(rocket->terminateCondition(std::make_pair(currentTime, currentState)))
|
||||
break;
|
||||
std::tie(nextPosition, nextVelocity) = linearIntegrator->step(currentPosition, currentVelocity);
|
||||
|
||||
currentTime += timeStep;
|
||||
}
|
||||
endTime = std::chrono::steady_clock::now();
|
||||
StateData nextState;
|
||||
nextState.position = nextPosition;
|
||||
nextState.velocity = nextVelocity;
|
||||
object->setCurrentState(nextState);
|
||||
|
||||
std::stringstream duration;
|
||||
duration << "runUntilTerminate time (microseconds): ";
|
||||
duration << std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
utils::Logger::getInstance()->debug(duration.str());
|
||||
if(saveStates)
|
||||
{
|
||||
object->appendState(currentTime, nextState);
|
||||
}
|
||||
if(object->terminateCondition(currentTime))
|
||||
break;
|
||||
|
||||
currentTime += timeStep;
|
||||
}
|
||||
endTime = std::chrono::steady_clock::now();
|
||||
|
||||
std::stringstream duration;
|
||||
duration << "runUntilTerminate time (microseconds): ";
|
||||
duration << std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
utils::Logger::getInstance()->debug(duration.str());
|
||||
|
||||
}
|
||||
|
||||
double Propagator::getMass()
|
||||
{
|
||||
return rocket->getMass(currentTime);
|
||||
}
|
||||
|
||||
double Propagator::getForceX()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
return (currentState[3] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState[2])/ 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState[3]* currentState[3];
|
||||
}
|
||||
|
||||
double Propagator::getForceY()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
return (currentState[4] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState[4]* currentState[4];
|
||||
}
|
||||
|
||||
double Propagator::getForceZ()
|
||||
{
|
||||
QtRocket* qtrocket = QtRocket::getInstance();
|
||||
double gravity = (qtrocket->getEnvironment()->getGravityModel()->getAccel(currentState[0], currentState[1], currentState[2])).x3;
|
||||
double airDrag = (currentState[5] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState[5]* currentState[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; }
|
||||
|
||||
} // namespace sim
|
||||
|
@ -5,17 +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
|
||||
@ -24,22 +29,17 @@ namespace sim
|
||||
class Propagator
|
||||
{
|
||||
public:
|
||||
Propagator(Rocket* r);
|
||||
Propagator(std::shared_ptr<model::Propagatable> o);
|
||||
~Propagator();
|
||||
|
||||
void setInitialState(const std::vector<double>& initialState)
|
||||
void setInitialState(const StateData& initialState)
|
||||
{
|
||||
currentState.resize(initialState.size());
|
||||
for(std::size_t i = 0; i < initialState.size(); ++i)
|
||||
{
|
||||
currentState[i] = initialState[i];
|
||||
}
|
||||
|
||||
object->setInitialState(initialState);
|
||||
}
|
||||
|
||||
const std::vector<double>& getCurrentState() const
|
||||
const StateData& getCurrentState() const
|
||||
{
|
||||
return currentState;
|
||||
return object->getCurrentState();
|
||||
}
|
||||
|
||||
void runUntilTerminate();
|
||||
@ -49,41 +49,21 @@ public:
|
||||
saveStates = s;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<double, std::vector<double>>>& 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();
|
||||
std::unique_ptr<sim::RK4Solver<Vector3>> linearIntegrator;
|
||||
// std::unique_ptr<sim::RK4Solver<Quaternion>> orientationIntegrator;
|
||||
|
||||
double getIpitch() { return 1.0; }
|
||||
double getIyaw() { return 1.0; }
|
||||
double getIroll() { return 1.0; }
|
||||
std::shared_ptr<model::Propagatable> object;
|
||||
|
||||
//private:
|
||||
|
||||
std::unique_ptr<sim::DESolver> integrator;
|
||||
|
||||
Rocket* rocket;
|
||||
|
||||
std::vector<double> currentState{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
std::vector<double> tempRes{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
bool saveStates{true};
|
||||
double currentTime{0.0};
|
||||
double timeStep{0.01};
|
||||
std::vector<std::pair<double, std::vector<double>>> states;
|
||||
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -4,10 +4,8 @@
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
// 3rd party headers
|
||||
|
||||
@ -16,84 +14,80 @@
|
||||
// qtrocket headers
|
||||
#include "sim/DESolver.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim {
|
||||
|
||||
template<typename... Ts>
|
||||
class RK4Solver : public DESolver
|
||||
/**
|
||||
* @brief Runge-Kutta 4th order coupled ODE solver.
|
||||
* @note This was written outside of the context of QtRocket, and it is very generic. There are
|
||||
* some features of this solver that are note used by QtRocket, for example, it can solve
|
||||
* and arbitrarily large system of coupled ODEs, but QtRocket only makes use of a system
|
||||
* of size 6 (x, y, z, xDot, yDot, zDot) at a time.
|
||||
*
|
||||
* @tparam Ts
|
||||
*/
|
||||
template<typename T>
|
||||
class RK4Solver : public DESolver<T>
|
||||
{
|
||||
public:
|
||||
|
||||
RK4Solver(Ts... funcs)
|
||||
RK4Solver(std::function<std::pair<T, T>(T&, T&)> func)
|
||||
{
|
||||
(odes.push_back(funcs), ...);
|
||||
temp.resize(sizeof...(Ts));
|
||||
|
||||
// This only works for Eigen Vector types.
|
||||
// TODO: Figure out how to make this slightly more generic, but for now
|
||||
// we're only using this for Vector3 and Quaternion types
|
||||
static_assert(std::is_same<T, Vector3>::value
|
||||
|| std::is_same<T, Quaternion>::value,
|
||||
"You can only use Vector3 or Quaternion valued functions in RK4Solver");
|
||||
|
||||
odes = func;
|
||||
}
|
||||
virtual ~RK4Solver() {}
|
||||
|
||||
void setTimeStep(double inTs) override { dt = inTs; halfDT = dt / 2.0; }
|
||||
|
||||
void step(double t, const std::vector<double>& curVal, std::vector<double>& res) override
|
||||
std::pair<T, T> step(T& state, T& rate) override
|
||||
{
|
||||
std::pair<T, T> res;
|
||||
if(dt == std::numeric_limits<double>::quiet_NaN())
|
||||
{
|
||||
utils::Logger::getInstance()->error("Calling RK4Solver without setting dt first is an error");
|
||||
res[0] = std::numeric_limits<double>::quiet_NaN();
|
||||
return res;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
k1[i] = odes[i](t, curVal);
|
||||
}
|
||||
std::tie(k1State, k1Rate) = odes(state, rate);
|
||||
// compute k2 values. This involves stepping the current values forward a half-step
|
||||
// based on k1, so we do the stepping first
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
temp[i] = curVal[i] + k1[i]*dt / 2.0;
|
||||
}
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
k2[i] = odes[i](t + halfDT, temp);
|
||||
}
|
||||
// repeat for k3
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
temp[i] = curVal[i] + k2[i]*dt / 2.0;
|
||||
}
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
k3[i] = odes[i](t + halfDT, temp);
|
||||
}
|
||||
std::tie(tempState, tempRate) = std::make_pair(state + k1State*halfDT, rate + k1Rate*halfDT);
|
||||
std::tie(k2State, k2Rate) = odes(tempState, tempRate);
|
||||
|
||||
// now k4
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
temp[i] = curVal[i] + k3[i]*dt;
|
||||
}
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
k4[i] = odes[i](t + dt, temp);
|
||||
}
|
||||
std::tie(tempState, tempRate) = std::make_pair(state + k2State*halfDT, rate + k2Rate*halfDT);
|
||||
std::tie(k3State, k3Rate) = odes(tempState, tempRate);
|
||||
|
||||
// now compute the result
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
res[i] = curVal[i] + (dt / 6.0)*(k1[i] + 2.0*k2[i] + 2.0*k3[i] + k4[i]);
|
||||
}
|
||||
std::tie(tempState, tempRate) = std::make_pair(state + k3State*dt, rate + k3Rate*dt);
|
||||
std::tie(k4State, k4Rate) = odes(tempState, tempRate);
|
||||
|
||||
res = std::make_pair(state + (dt / 6.0)*(k1State + 2.0*k2State + 2.0*k3State + k4State),
|
||||
rate + (dt / 6.0)*(k1Rate + 2.0*k2Rate + 2.0*k3Rate + k4Rate));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::function<double(double, const std::vector<double>&)>> odes;
|
||||
std::function<std::pair<T, T>(T&, T&)> odes;
|
||||
|
||||
static constexpr size_t len = sizeof...(Ts);
|
||||
double k1[len];
|
||||
double k2[len];
|
||||
double k3[len];
|
||||
double k4[len];
|
||||
T k1State;
|
||||
T k2State;
|
||||
T k3State;
|
||||
T k4State;
|
||||
T k1Rate;
|
||||
T k2Rate;
|
||||
T k3Rate;
|
||||
T k4Rate;
|
||||
|
||||
std::vector<double> temp;
|
||||
T tempState;
|
||||
T tempRate;
|
||||
|
||||
double dt = std::numeric_limits<double>::quiet_NaN();
|
||||
double halfDT = 0.0;
|
||||
|
@ -25,7 +25,7 @@ SphericalGravityModel::~SphericalGravityModel()
|
||||
|
||||
}
|
||||
|
||||
TripletD SphericalGravityModel::getAccel(double x, double y, double z)
|
||||
Vector3 SphericalGravityModel::getAccel(double x, double y, double z)
|
||||
{
|
||||
// Convert x, y, z from meters to km. This is to avoid potential precision losses
|
||||
// with using the earth's gravitation parameter in meters (14 digit number).
|
||||
@ -43,7 +43,7 @@ TripletD SphericalGravityModel::getAccel(double x, double y, double z)
|
||||
double ay = accelFactor * y_km * 1000.0;
|
||||
double az = accelFactor * z_km * 1000.0;
|
||||
|
||||
return TripletD(ax, ay, az);
|
||||
return Vector3(ax, ay, az);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define SIM_SPHERICALGRAVITYMODEL_H
|
||||
|
||||
// qtrocket headers
|
||||
#include "GravityModel.h"
|
||||
#include "sim/GravityModel.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
@ -13,7 +13,7 @@ public:
|
||||
SphericalGravityModel();
|
||||
virtual ~SphericalGravityModel();
|
||||
|
||||
TripletD getAccel(double x, double y, double z) override;
|
||||
Vector3 getAccel(double x, double y, double z) override;
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
@ -1,6 +0,0 @@
|
||||
#include "StateData.h"
|
||||
|
||||
StateData::StateData()
|
||||
{
|
||||
|
||||
}
|
@ -1,9 +1,15 @@
|
||||
#ifndef STATEDATA_H
|
||||
#define STATEDATA_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <vector>
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/Vector3.h"
|
||||
#include "utils/math/Quaternion.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
/**
|
||||
* @brief The StateData class holds physical state data. Things such as position, velocity,
|
||||
@ -13,20 +19,76 @@
|
||||
class StateData
|
||||
{
|
||||
public:
|
||||
StateData();
|
||||
StateData() {}
|
||||
~StateData() {}
|
||||
|
||||
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() const
|
||||
{
|
||||
return std::vector<double>{velocity[0], velocity[1], velocity[2]};
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
math::Vector3 position{0.0, 0.0, 0.0};
|
||||
math::Vector3 velocity{0.0, 0.0, 0.0};
|
||||
/// TODO: Put these behind an interface
|
||||
//Vector3 getPosition() const
|
||||
//{
|
||||
// return position;
|
||||
//}
|
||||
|
||||
math::Quaternion orientation{0.0, 0.0, 0.0, 0.0}; // roll, pitch, yaw
|
||||
math::Quaternion orientationRate{0.0, 0.0, 0.0, 0.0}; // roll-rate, pitch-rate, yaw-rate
|
||||
// Necessary?
|
||||
//math::Vector3 orientationAccel;
|
||||
//Vector3 getVelocity() const
|
||||
//{
|
||||
// return velocity;
|
||||
//}
|
||||
// private:
|
||||
|
||||
// This is an array because the integrator expects it
|
||||
double data[6];
|
||||
// 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)
|
||||
|
||||
Matrix3 dcm{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
|
||||
/// Euler angles are yaw-pitch-roll, and (3-2-1) order
|
||||
/// yaw - psi
|
||||
/// pitch - theta
|
||||
/// roll - phi
|
||||
Vector3 eulerAngles{0.0, 0.0, 0.0};
|
||||
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
// qtrocket headers
|
||||
#include "sim/USStandardAtmosphere.h"
|
||||
#include "utils/math/Constants.h"
|
||||
#include "utils/math/UtilityMathFunctions.h"
|
||||
|
||||
using namespace utils::math;
|
||||
|
||||
@ -17,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));
|
||||
@ -32,9 +33,9 @@ utils::BinMap initTemps()
|
||||
|
||||
}
|
||||
|
||||
utils::BinMap initLapseRates()
|
||||
utils::Bin initLapseRates()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 0.0065));
|
||||
map.insert(std::make_pair(11000.0, 0.0));
|
||||
map.insert(std::make_pair(20000.0, -0.001));
|
||||
@ -46,9 +47,9 @@ utils::BinMap initLapseRates()
|
||||
return map;
|
||||
}
|
||||
|
||||
utils::BinMap initDensities()
|
||||
utils::Bin initDensities()
|
||||
{
|
||||
utils::BinMap map;
|
||||
utils::Bin map;
|
||||
map.insert(std::make_pair(0.0, 1.225));
|
||||
map.insert(std::make_pair(11000.0, 0.36391));
|
||||
map.insert(std::make_pair(20000.0, 0.08803));
|
||||
@ -60,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()
|
||||
{
|
||||
@ -78,31 +92,64 @@ USStandardAtmosphere::~USStandardAtmosphere()
|
||||
|
||||
double USStandardAtmosphere::getDensity(double altitude)
|
||||
{
|
||||
if(temperatureLapseRate[altitude] == 0.0)
|
||||
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] /
|
||||
(standardTemperature[altitude] + temperatureLapseRate[altitude] * (altitude - standardDensity.getBinBase(altitude)));
|
||||
double base = (standardTemperature[altitude] - temperatureLapseRate[altitude] *
|
||||
(altitude - standardDensity.getBinBase(altitude))) / standardTemperature[altitude];
|
||||
|
||||
double exponent = 1 + (Constants::g0 * Constants::airMolarMass) /
|
||||
(Constants::Rstar * temperatureLapseRate[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
|
||||
|
@ -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;
|
||||
|
||||
|
||||
};
|
||||
|
@ -13,9 +13,9 @@ WindModel::~WindModel()
|
||||
{
|
||||
}
|
||||
|
||||
TripletD WindModel::getWindSpeed(double /* x */, double /* y */ , double /* z */)
|
||||
Vector3 WindModel::getWindSpeed(double /* x */, double /* y */ , double /* z */)
|
||||
{
|
||||
return TripletD(0.0, 0.0, 0.0);
|
||||
return Vector3(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
} // namespace sim
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define SIM_WINDMODEL_H
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/Triplet.h"
|
||||
#include "utils/math/MathTypes.h"
|
||||
|
||||
namespace sim
|
||||
{
|
||||
@ -13,7 +13,7 @@ public:
|
||||
WindModel();
|
||||
virtual ~WindModel();
|
||||
|
||||
virtual TripletD getWindSpeed(double x, double y, double z);
|
||||
virtual Vector3 getWindSpeed(double x, double y, double z);
|
||||
|
||||
};
|
||||
|
||||
|
15
sim/tests/CMakeLists.txt
Normal file
15
sim/tests/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
add_executable(sim_tests
|
||||
USStandardAtmosphereTests.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sim_tests
|
||||
sim
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(sim_tests)
|
||||
|
||||
add_test(NAME qtrocket_sim_tests COMMAND sim_tests)
|
||||
|
90
sim/tests/USStandardAtmosphereTests.cpp
Normal file
90
sim/tests/USStandardAtmosphereTests.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "sim/USStandardAtmosphere.h"
|
||||
|
||||
TEST(USStandardAtmosphereTests, DensityTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getDensity(0.0) / 1.225, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(1000.0) / 1.112, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(2000.0) / 1.007, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(3000.0) / 0.9093, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(4000.0) / 0.8194, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(5000.0) / 0.7364, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(6000.0) / 0.6601, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(7000.0) / 0.5900, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(15000.0) / 0.19367, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(20000.0) / 0.088035, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(25000.0) / 0.039466, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(30000.0) / 0.018012, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getDensity(40000.0) / 0.0038510, 1.0, 0.001);
|
||||
|
||||
// These are generally accurate to ~0.5%. Slight deviation of calculated
|
||||
// density from the given density in the report table
|
||||
EXPECT_NEAR(atmosphere.getDensity(8000.0) / 0.52579, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(9000.0) / 0.46706, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(10000.0) / 0.41351, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(50000.0) / 0.00097752, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(60000.0) / 0.00028832, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(70000.0) / 0.000074243, 1.0, 0.005);
|
||||
EXPECT_NEAR(atmosphere.getDensity(80000.0) / 0.000015701, 1.0, 0.005);
|
||||
|
||||
}
|
||||
|
||||
TEST(USStandardAtmosphereTests, PressureTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getPressure(0.0) / 101325.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(1000.0) / 89876.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(2000.0) / 79501.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(3000.0) / 70108.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(4000.0) / 61640.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(5000.0) / 54019.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(6000.0) / 47181.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(7000.0) / 41060.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(8000.0) / 35599.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(9000.0) / 30742.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(10000.0) / 26436.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(15000.0) / 12044.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(20000.0) / 5474.8, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(25000.0) / 2511.0, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(30000.0) / 1171.8, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(40000.0) / 277.52, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(50000.0) / 75.944, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(60000.0) / 20.314, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(70000.0) / 4.6342, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getPressure(80000.0) / 0.88627, 1.0, 0.001);
|
||||
|
||||
}
|
||||
|
||||
TEST(USStandardAtmosphereTests, TemperatureTests)
|
||||
{
|
||||
sim::USStandardAtmosphere atmosphere;
|
||||
|
||||
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||
EXPECT_NEAR(atmosphere.getTemperature(0.0) / 288.15, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(1000.0) / 281.651, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(2000.0) / 275.154, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(3000.0) / 268.659, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(4000.0) / 262.166, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(5000.0) / 255.676, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(6000.0) / 249.187, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(7000.0) / 242.7, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(8000.0) / 236.215, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(9000.0) / 229.733, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(10000.0) / 223.252, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(15000.0) / 216.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(20000.0) / 216.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(25000.0) / 221.552, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(30000.0) / 226.509, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(40000.0) / 251.05, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(50000.0) / 270.65, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(60000.0) / 245.45, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(70000.0) / 217.450, 1.0, 0.001);
|
||||
EXPECT_NEAR(atmosphere.getTemperature(80000.0) / 196.650, 1.0, 0.001);
|
||||
|
||||
}
|
@ -3,15 +3,14 @@
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
#include <stdexcept>
|
||||
|
||||
// 3rd party headers
|
||||
#include <fmt/core.h>
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "BinMap.h"
|
||||
#include "Bin.h"
|
||||
|
||||
// TODO: Check on the availability of this in Clang.
|
||||
// Replace libfmt with format when LLVM libc++ supports it
|
||||
@ -20,33 +19,33 @@
|
||||
namespace utils
|
||||
{
|
||||
|
||||
BinMap::BinMap()
|
||||
Bin::Bin()
|
||||
: bins()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BinMap::BinMap(BinMap&& o)
|
||||
Bin::Bin(Bin&& o)
|
||||
: bins(std::move(o.bins))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BinMap::~BinMap()
|
||||
Bin::~Bin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// TODO: Very low priority, but if anyone wants to make this more efficient it could be
|
||||
// interesting
|
||||
void BinMap::insert(const std::pair<double, double>& toInsert)
|
||||
void Bin::insert(const std::pair<double, double>& toInsert)
|
||||
{
|
||||
bins.push_back(toInsert);
|
||||
std::sort(bins.begin(), bins.end(),
|
||||
[](const auto& a, const auto& b){ return a.first < b.first; });
|
||||
}
|
||||
|
||||
double BinMap::operator[](double key)
|
||||
double Bin::operator[](double key)
|
||||
{
|
||||
auto iter = bins.begin();
|
||||
// If the key is less than the lowest bin value, then it is out of range
|
||||
@ -56,12 +55,12 @@ double BinMap::operator[](double key)
|
||||
if(key < iter->first)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
std::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
}
|
||||
// Increment it and start searching If we reach the end without finding an existing key
|
||||
// greater than our search term, then we've just hit the last bin and return that
|
||||
iter++;
|
||||
double retVal = bins.end()->second;
|
||||
double retVal = bins.back().second;
|
||||
while(iter != bins.end())
|
||||
{
|
||||
if(key < iter->first)
|
||||
@ -74,7 +73,7 @@ double BinMap::operator[](double key)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
double BinMap::getBinBase(double key)
|
||||
double Bin::getBinBase(double key)
|
||||
{
|
||||
auto iter = bins.begin();
|
||||
// If the key is less than the lowest bin value, then it is out of range
|
||||
@ -84,7 +83,7 @@ double BinMap::getBinBase(double key)
|
||||
if(key < iter->first)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
std::format("{} less than lower bound {} of BinMap", key, iter->first));
|
||||
}
|
||||
// Increment it and start searching If we reach the end without finding an existing key
|
||||
// greater than our search term, then we've just hit the last bin and return that
|
@ -1,5 +1,5 @@
|
||||
#ifndef UTILS_BINMAP_H
|
||||
#define UTILS_BINMAP_H
|
||||
#ifndef UTILS_BIN_H
|
||||
#define UTILS_BIN_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
@ -22,12 +22,12 @@ namespace utils {
|
||||
* @todo Make this class behave more like a proper STL container. Templetize it for one
|
||||
*
|
||||
*/
|
||||
class BinMap
|
||||
class Bin
|
||||
{
|
||||
public:
|
||||
BinMap();
|
||||
BinMap(BinMap&& o);
|
||||
~BinMap();
|
||||
Bin();
|
||||
Bin(Bin&& o);
|
||||
~Bin();
|
||||
|
||||
void insert(const std::pair<double, double>& toInsert);
|
||||
double operator[](double key);
|
||||
@ -40,4 +40,4 @@ private:
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // UTILS_BINMAP_H
|
||||
#endif // UTILS_BIN_H
|
30
utils/CMakeLists.txt
Normal file
30
utils/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
add_library(utils
|
||||
Bin.cpp
|
||||
Bin.h
|
||||
CurlConnection.cpp
|
||||
CurlConnection.h
|
||||
Logger.cpp
|
||||
Logger.h
|
||||
MotorModelDatabase.cpp
|
||||
MotorModelDatabase.h
|
||||
RSEDatabaseLoader.cpp
|
||||
RSEDatabaseLoader.h
|
||||
ThreadPool.cpp
|
||||
ThreadPool.h
|
||||
ThrustCurveAPI.cpp
|
||||
ThrustCurveAPI.h
|
||||
TSQueue.h
|
||||
math/Constants.h
|
||||
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
|
||||
eigen)
|
@ -40,6 +40,13 @@ void Logger::log(std::string_view msg, const LogLevel& lvl)
|
||||
// all levels at or lower than the current level.
|
||||
switch(currentLevel)
|
||||
{
|
||||
case PERF_:
|
||||
if(lvl == PERF_)
|
||||
{
|
||||
outFile << "[PERF] " << msg << std::endl;
|
||||
std::cout << "[PERF] " << msg << "\n";
|
||||
}
|
||||
[[fallthrough]];
|
||||
case DEBUG_:
|
||||
if(lvl == DEBUG_)
|
||||
{
|
||||
|
@ -25,7 +25,8 @@ public:
|
||||
ERROR_,
|
||||
WARN_,
|
||||
INFO_,
|
||||
DEBUG_
|
||||
DEBUG_,
|
||||
PERF_
|
||||
};
|
||||
|
||||
static Logger* getInstance();
|
||||
@ -38,16 +39,11 @@ public:
|
||||
|
||||
void setLogLevel(const LogLevel& lvl);
|
||||
|
||||
/*
|
||||
std::function<void(std::string_view)> error;
|
||||
std::function<void(std::string_view)> warn;
|
||||
std::function<void(std::string_view)> info;
|
||||
std::function<void(std::string_view)> debug;
|
||||
*/
|
||||
inline void error(std::string_view msg) { log(msg, ERROR_); }
|
||||
inline void warn(std::string_view msg) { log(msg, WARN_); }
|
||||
inline void info(std::string_view msg) { log(msg, INFO_); }
|
||||
inline void debug(std::string_view msg) { log(msg, DEBUG_); }
|
||||
inline void perf(std::string_view msg) { log(msg, PERF_); }
|
||||
|
||||
void log(std::ostream& o, const std::string& msg);
|
||||
|
||||
|
@ -68,20 +68,6 @@ std::optional<model::MotorModel> MotorModelDatabase::getMotorModel(const std::st
|
||||
void MotorModelDatabase::saveMotorDatabase(const std::string& filename)
|
||||
{
|
||||
|
||||
/*
|
||||
|
||||
<MotorDatabase>
|
||||
<version>1.0</version>
|
||||
<MotorModels>
|
||||
<model name="XYZ">
|
||||
<totalWeight>10.0</totalWeight>
|
||||
<totalImpulse>123.4</totalImpulse>
|
||||
</model>
|
||||
</MotorModels>
|
||||
</MotorDatabase>
|
||||
|
||||
*/
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
// top-level tree
|
||||
@ -112,6 +98,15 @@ void MotorModelDatabase::saveMotorDatabase(const std::string& filename)
|
||||
motor.put("type", m.data.type.str());
|
||||
motor.put("lastUpdated", m.data.lastUpdated);
|
||||
|
||||
// delays tag is in the form of a csv string
|
||||
std::stringstream delays;
|
||||
for (std::size_t i = 0; i < m.data.delays.size() - 1; ++i)
|
||||
{
|
||||
delays << std::to_string(m.data.delays[i]) << ",";
|
||||
}
|
||||
delays << std::to_string(m.data.delays[m.data.delays.size() - 1]);
|
||||
motor.put("delays", delays.str());
|
||||
|
||||
// thrust data
|
||||
{
|
||||
pt::ptree tc;
|
||||
|
@ -74,4 +74,4 @@ private:
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // UTILS_MOTORMODELDATABASE_H
|
||||
#endif // UTILS_MOTORMODELDATABASE_H
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
// 3rd party headers
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
@ -58,6 +59,16 @@ void RSEDatabaseLoader::buildAndAppendMotorModel(boost::property_tree::ptree& v)
|
||||
mm.commonName = v.get<std::string>("<xmlattr>.code", "");
|
||||
|
||||
// mm.delays = extract vector from csv list
|
||||
std::string delays = v.get<std::string>("<xmlattr>.delays", "1000");
|
||||
std::size_t pos{0};
|
||||
std::string tok;
|
||||
while ((pos = delays.find(",")) != std::string::npos)
|
||||
{
|
||||
tok = delays.substr(0, pos);
|
||||
mm.delays.push_back(std::atoi(tok.c_str()));
|
||||
delays.erase(0, pos + 1);
|
||||
}
|
||||
mm.delays.push_back(std::atoi(delays.c_str()));
|
||||
|
||||
// mm.designation = What is this?
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
// C++ headers
|
||||
// 3rd party headers
|
||||
#include <json/json.h>
|
||||
#include <optional>
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
@ -25,6 +26,58 @@ ThrustCurveAPI::~ThrustCurveAPI()
|
||||
|
||||
}
|
||||
|
||||
std::optional<ThrustCurve> ThrustCurveAPI::getThrustCurve(const std::string& id)
|
||||
{
|
||||
std::stringstream endpoint;
|
||||
endpoint << hostname << "api/v1/download.json?motorId=" << id << "&data=samples";
|
||||
std::vector<std::string> extraHeaders = {};
|
||||
|
||||
std::string res = curlConnection.get(endpoint.str(), extraHeaders);
|
||||
model::MotorModel mm;
|
||||
|
||||
if(!res.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
Json::Reader reader;
|
||||
Json::Value jsonResult;
|
||||
reader.parse(res, jsonResult);
|
||||
|
||||
std::vector<std::pair<double, double>> samples;
|
||||
for(Json::ValueConstIterator iter = jsonResult["results"].begin();
|
||||
iter != jsonResult["results"].end();
|
||||
++iter)
|
||||
{
|
||||
// if there are more than 1 items in the results list, we only want the RASP data
|
||||
// Otherwise just take whatever is there
|
||||
if(std::next(iter) != jsonResult["results"].end())
|
||||
{
|
||||
if( (*iter)["format"].asString() != "RASP")
|
||||
continue;
|
||||
}
|
||||
for(Json::ValueConstIterator samplesIter = (*iter)["samples"].begin();
|
||||
samplesIter != (*iter)["samples"].end();
|
||||
++samplesIter)
|
||||
{
|
||||
samples.push_back(std::make_pair((*samplesIter)["time"].asDouble(),
|
||||
(*samplesIter)["thrust"].asDouble()));
|
||||
|
||||
}
|
||||
}
|
||||
return ThrustCurve(samples);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::string err("Unable to parse JSON from Thrustcurve motor data request. Error: ");
|
||||
err += e.what();
|
||||
|
||||
Logger::getInstance()->error(err);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
|
||||
}
|
||||
|
||||
model::MotorModel ThrustCurveAPI::getMotorData(const std::string& motorId)
|
||||
{
|
||||
@ -182,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();
|
||||
@ -191,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")
|
||||
@ -200,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();
|
||||
@ -226,7 +283,14 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
else
|
||||
mm.type = model::MotorModel::MotorType(model::MotorModel::MOTORTYPE::HYBRID);
|
||||
|
||||
Logger::getInstance()->debug("5");
|
||||
auto tc = getThrustCurve(mm.motorIdTC);
|
||||
motorModel.moveMetaData(std::move(mm));
|
||||
Logger::getInstance()->debug("6");
|
||||
if(tc)
|
||||
{
|
||||
motorModel.addThrustCurve(*tc);
|
||||
}
|
||||
retVal.push_back(motorModel);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
// C++ headers
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
@ -91,6 +92,8 @@ private:
|
||||
const std::string hostname;
|
||||
CurlConnection curlConnection;
|
||||
|
||||
std::optional<ThrustCurve> getThrustCurve(const std::string& id);
|
||||
|
||||
// no extra headers, but CurlConnection library wants them
|
||||
const std::vector<std::string> extraHeaders{};
|
||||
};
|
||||
|
@ -1,21 +0,0 @@
|
||||
#ifndef TRIPLET_H
|
||||
#define TRIPLET_H
|
||||
|
||||
/**
|
||||
* The purpose of this class is to get rid of using std::tuple for coordinate triplets.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
struct Triplet
|
||||
{
|
||||
Triplet(const T& a, const T& b, const T& c)
|
||||
: x1(a), x2(b), x3(c)
|
||||
{}
|
||||
T x1;
|
||||
T x2;
|
||||
T x3;
|
||||
};
|
||||
|
||||
using TripletD = Triplet<double>;
|
||||
|
||||
#endif // TRIPLET_H
|
@ -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;
|
||||
|
74
utils/math/MathTypes.h
Normal file
74
utils/math/MathTypes.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef UTILS_MATH_MATHTYPES_H
|
||||
#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.
|
||||
|
||||
template <int Size>
|
||||
using MyMatrix = Eigen::Matrix<double, Size, Size>;
|
||||
|
||||
template <int Size>
|
||||
using MyVector = Eigen::Matrix<double, Size, 1>;
|
||||
|
||||
typedef Eigen::Quaterniond Quaternion;
|
||||
|
||||
using Matrix3 = MyMatrix<3>;
|
||||
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
|
@ -1,25 +0,0 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/Quaternion.h"
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
Quaternion::Quaternion()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Quaternion::Quaternion(double r, const Vector3& i)
|
||||
: real(r),
|
||||
imag(i)
|
||||
{
|
||||
}
|
||||
|
||||
Quaternion::Quaternion(double r, double i1, double i2, double i3)
|
||||
: real(r),
|
||||
imag(i1, i2, i3)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace math
|
@ -1,63 +0,0 @@
|
||||
#ifndef MATH_QUATERNION_H
|
||||
#define MATH_QUATERNION_H
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
#include <utility>
|
||||
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
// qtrocket headers
|
||||
#include "Vector3.h"
|
||||
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
class Quaternion
|
||||
{
|
||||
public:
|
||||
Quaternion();
|
||||
~Quaternion() {}
|
||||
|
||||
Quaternion(double r, const Vector3& i);
|
||||
Quaternion(double r, double i1, double i2, double i3);
|
||||
|
||||
Quaternion(const Quaternion&) = default;
|
||||
Quaternion(Quaternion&&) = default;
|
||||
|
||||
Quaternion& operator=(const Quaternion& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
return *this;
|
||||
real = rhs.real;
|
||||
imag = rhs.imag;
|
||||
return *this;
|
||||
}
|
||||
Quaternion& operator=(Quaternion&& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
return *this;
|
||||
real = std::move(rhs.real);
|
||||
imag = std::move(rhs.imag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
Quaternion operator-() {}
|
||||
Quaternion operator-(const Quaternion& ) {}
|
||||
Quaternion operator+(const Quaternion& ) {}
|
||||
Quaternion operator*(double ) {}
|
||||
Quaternion operator*(const Quaternion& ) {}
|
||||
*/
|
||||
|
||||
private:
|
||||
double real;
|
||||
Vector3 imag;
|
||||
};
|
||||
|
||||
} // namespace math
|
||||
|
||||
#endif // MATH_QUATERNION_H
|
@ -1,15 +0,0 @@
|
||||
|
||||
/// \cond
|
||||
// C headers
|
||||
// C++ headers
|
||||
// 3rd party headers
|
||||
/// \endcond
|
||||
|
||||
|
||||
namespace utils
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
} // namespace math
|
||||
} // namespace utils
|
@ -1,68 +0,0 @@
|
||||
|
||||
// qtrocket headers
|
||||
#include "utils/math/Vector3.h"
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
Vector3::Vector3()
|
||||
: x1(0.0),
|
||||
x2(0.0),
|
||||
x3(0.0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Vector3::Vector3(const double& inX1,
|
||||
const double& inX2,
|
||||
const double& inX3)
|
||||
: x1(inX1),
|
||||
x2(inX2),
|
||||
x3(inX3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Vector3::Vector3(const Vector3& o)
|
||||
: x1(o.x1),
|
||||
x2(o.x2),
|
||||
x3(o.x3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Vector3::~Vector3()
|
||||
{}
|
||||
|
||||
Vector3 Vector3::operator=(const Vector3& rhs)
|
||||
{
|
||||
return Vector3(rhs.x1, rhs.x2, rhs.x3);
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-()
|
||||
{
|
||||
return Vector3(-x1, -x2, -x3);
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-(const Vector3& rhs)
|
||||
{
|
||||
return Vector3(x1 - rhs.x1,
|
||||
x2 - rhs.x2,
|
||||
x3 - rhs.x3);
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator+(const Vector3& rhs)
|
||||
{
|
||||
return Vector3(x1 + rhs.x1,
|
||||
x2 + rhs.x2,
|
||||
x3 + rhs.x3);
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator*(const double& s)
|
||||
{
|
||||
return Vector3(x1 * s,
|
||||
x2 * s,
|
||||
x3 * s);
|
||||
}
|
||||
|
||||
} // namespace math
|
@ -1,40 +0,0 @@
|
||||
#ifndef MATH_VECTOR3_H
|
||||
#define MATH_VECTOR3_H
|
||||
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
Vector3();
|
||||
Vector3(const double& inX1,
|
||||
const double& inX2,
|
||||
const double& inX3);
|
||||
|
||||
Vector3(const Vector3& o);
|
||||
|
||||
~Vector3();
|
||||
|
||||
Vector3 operator=(const Vector3& rhs);
|
||||
|
||||
Vector3 operator-();
|
||||
Vector3 operator-(const Vector3& rhs);
|
||||
Vector3 operator+(const Vector3& rhs);
|
||||
Vector3 operator*(const double& s);
|
||||
|
||||
double getX1() { return x1; }
|
||||
double getX2() { return x2; }
|
||||
double getX3() { return x3; }
|
||||
|
||||
|
||||
//private:
|
||||
double x1;
|
||||
double x2;
|
||||
double x3;
|
||||
};
|
||||
|
||||
} // namespace math
|
||||
|
||||
#endif // MATH_VECTOR3_H
|
Loading…
x
Reference in New Issue
Block a user