diff --git a/.gitignore b/.gitignore index d2d63ed98612b69e0bb748cd74a300734f41e1a2..9df3b454f410d9279fb0a25c11ee4fbb2d9e752c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,9 @@ build *.sublime-project .vscode/* - store.json scripts/event_header_generator/generated/ scripts/event_header_generator/venv/ + +**/generated +**/scxmls diff --git a/sbs.conf b/sbs.conf index 93083ca47a0bcc7ee5188a6a62033f37168ff467..135d4404230432a6fc796fc2fda69c0c925f4c9c 100644 --- a/sbs.conf +++ b/sbs.conf @@ -80,6 +80,7 @@ PROJECT_INCLUDES: -Isrc/boards -Isrc/boards/DeathStack -Iskyward-boardcore/src/shared -Iskyward-boardcore + -Iskyward-boardcore/src/shared -Iskyward-boardcore/libs/mavlink_skyward_lib -Iskyward-boardcore/libs/eigen PROJECT_SUBDIRS: @@ -188,7 +189,7 @@ Files: src/boards/DeathStack/events/EventStrings.cpp Type: board BoardId: stm32f429zi_skyward_death_stack BinName: death-stack-entry -Include: %shared %deathstack %logger %pwm %spi %xbee %piksi %servo +Include: %shared %deathstack %logger %pwm %spi %xbee %piksi %servo Defines: -DDEATH_STACK_1 Main: death-stack-entry @@ -411,10 +412,35 @@ Main: catch/ada/ada_kalman_p/test-ada-simulation # Defines: -DSTANDALONE_CATCH1_TEST # Main: catch/fsm/test-fmm # + [test-ada] Type: test BoardId: stm32f429zi_skyward_death_stack BinName: test-ada Include: %shared %ada %test-utils %ada-test-sources %mock-sensors-data %logger %logservice %logger-hermes Defines: -DSTANDALONE_CATCH1_TEST -DSDRAM_ISSI -DDEBUG -Main: catch/fsm/test-ada \ No newline at end of file +Main: catch/fsm/test-ada + +[test-aerobrakes] +Type: test +BoardId: stm32f429zi_skyward_death_stack +BinName: test-aerobrakes +Include: %shared %test-utils %pwm %servo +Defines: -DSTANDALONE_CATCH1_TEST +Main: catch/fsm/test-aerobrakes + +[test-aerobrakes-interactive] +Type: test +BoardId: stm32f429zi_skyward_death_stack +BinName: test-aerobrakes-interactive +Include: %shared %test-utils %pwm %servo +Defines: -DDEBUG +Main: aerobrakes/test-aerobrakes-interactive + +[test-aerobrakes-algorithm] +Type: test +BoardId: stm32f429zi_skyward_death_stack +BinName: test-aerobrakes-algorithm +Include: %shared %servo %pwm +Defines: -DDEBUG +Main: aerobrakes/test-aerobrakes-algorithm diff --git a/scripts/event_header_generator/README.md b/scripts/event_header_generator/README.md deleted file mode 100644 index f87e46c67ebcec406b02c58e10dbe91b00a0c8d3..0000000000000000000000000000000000000000 --- a/scripts/event_header_generator/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Events Generator Script - -This script generates the Events.h and Topics.h heander file from a GoogleSheets document on Google Drive. - -To execute the script: - -``` -pip install --upgrade google-api-python-client -pip install oauth2client -python scripts/homeone/event_header_generator/event_generator.py -``` - -The first time a browser window should open asking for your credentials (use the Skyward ones). -If it doesn't and only gives you an error, try executing it by clicking on the icon. \ No newline at end of file diff --git a/scripts/event_header_generator/credentials.json b/scripts/event_header_generator/credentials.json deleted file mode 100644 index dae318afc5661116b82fe75f80f4316e538e670a..0000000000000000000000000000000000000000 --- a/scripts/event_header_generator/credentials.json +++ /dev/null @@ -1 +0,0 @@ -{"installed":{"client_id":"1025168905991-tv31etsgm3lecodc5c798shqciekad40.apps.googleusercontent.com","project_id":"homeone-event-ge-1540834105298","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"Yhaf67HuHR4DyXZKNXWu2lre","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} \ No newline at end of file diff --git a/scripts/event_header_generator/event_generator.py b/scripts/event_header_generator/event_generator.py deleted file mode 100644 index 048a2ba7f8fe2725e46533b6877e974bf75e8cfc..0000000000000000000000000000000000000000 --- a/scripts/event_header_generator/event_generator.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/python3 - -# Copyright (c) 2018 Skyward Experimental Rocketry -# Authors: Luca Erbetta -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -from googleapiclient.discovery import build -from httplib2 import Http -from oauth2client import file, client, tools - -import re -import datetime -import sys -from os.path import join -import os - -OUTPUT_FOLDER = "generated" -SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly' - -service = None - -# Spreadsheet file used to generate the events. The can be found in the link -# to the spreadsheet, for example: -# https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0/ -# --> -# 184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 -SPREADSHEET_ID = '184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0' -EVENTS_RANGE_NAME = 'EventList!A2:A' -TOPICS_RANGE_NAME = 'Topics!B3:B' - - -def auth(): - try: - store = file.Storage('store.json') - creds = store.get() - if not creds or creds.invalid: - flow = client.flow_from_clientsecrets('credentials.json', SCOPES) - creds = tools.run_flow(flow, store) - - global service - service = build('sheets', 'v4', http=creds.authorize(Http())) - return True - except: - print("Authentication error:", sys.exc_info()[0]) - return False - - -def load_events(): - result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, - range=EVENTS_RANGE_NAME).execute() - lines = result.get('values', []) - - # Event names start with EV_ and contains only uppercase letters or underscores - re_event = re.compile(r'(?P<ev>^EV_([A-Z_]+)+)') - - # Only return lines with valid events, remove additional data - events = [] - for l in lines: - m = re_event.match(l[0]) - if m is not None: - events.append(m.group('ev')) - else: - print("Skipped line containing invalid event: {}".format(l)) - - return events - - -def load_topics(): - result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, - range=TOPICS_RANGE_NAME).execute() - lines = result.get('values', []) - re_topics = re.compile(r'(?P<topic>^TOPIC_([A-Z_]+)+)') - - # Only return lines with valid topics, remove additional data - topics = [] - for l in lines: - m = re_topics.match(l[0]) - if m is not None: - topics.append(m.group('topic')) - else: - print("Skipped line containing invalid topics: {}".format(l)) - - return topics - - -def has_duplicates(lst): - if len(lst) != len(set(lst)): - return True - return False - - - -print("Skyward on-board software event header generator v0.2") -print("Google sheets API auth in progress...") - -if auth(): - print("Auth successfull.") -else: - exit() - -#directory = os.path.dirname(OUTPUT_FOLDER) -if not os.path.exists(OUTPUT_FOLDER): - os.mkdir(OUTPUT_FOLDER) - -print("Reading from: https://docs.google.com/spreadsheets/d/" + SPREADSHEET_ID) - -events = load_events() -topics = load_topics() - -# Check duplicates -if has_duplicates(events): - print("Duplicate events found! Terminating.") - exit() - -if has_duplicates(topics): - print("Duplicate topics found! Terminating.") - exit() - -events.sort() -topics.sort() - -print("{} events loaded.".format(len(events))) -print("{} topics loaded.".format(len(topics))) - -enum_str = "" -event_map_str = "" -event_list_str = "" - -date = datetime.datetime.now() -link = "https://docs.google.com/spreadsheets/d/{id}".format(id=SPREADSHEET_ID) - - -# Events.h generation - -print("Generating Events.h...") - -for e in events: - endl = ",\n" if e != events[-1] else "" - enum_str += " " + e + \ - (" = EV_FIRST_SIGNAL" if e == events[0] else "") + endl - event_map_str += " {{ {event}, {string} }}{endl}".format( - event=e, string='"' + e + '"', endl=endl) - event_list_str += e + (", " if e != events[-1] else "") - -with open('Events.h.template', 'r') as template_file: - template = template_file.read() - -template = template.format(sheet_link=link, date=date, - enum_data=enum_str,event_list=event_list_str) - -with open(join(OUTPUT_FOLDER, 'Events.h'), 'w') as header_file: - header_file.write(template) - -print("Events.h successfully generated.") -# Topics.h generation - -print("Generating Topics.h...") -enum_str = "" -topic_map_str = "" -topic_list_str = "" - -for t in topics: - endl = ",\n" if t != topics[-1] else "" - enum_str += " " + t + endl - topic_map_str += " {{ {topics}, {string} }}{endl}".format( - topics=t, string='"' + t + '"', endl=endl) - topic_list_str += t + (", " if t != topics[-1] else "") - -with open('Topics.h.template', 'r') as template_file: - template = template_file.read() - -template = template.format(sheet_link=link, date=date, - enum_data=enum_str, topic_list=topic_list_str) - -with open(join(OUTPUT_FOLDER, 'Topics.h'), 'w') as header_file: - header_file.write(template) - -with open('EventStrings.cpp.template', 'r') as cpp_template_file: - cpp = cpp_template_file.read() - -cpp = cpp.format(sheet_link=link, date=date, - event_map_data=event_map_str, topic_map_data=topic_map_str) - -with open(join(OUTPUT_FOLDER, 'EventStrings.cpp'), 'w') as cpp_file: - cpp_file.write(cpp) - -print("Topics.h successfully generated.") - -print() -print("All files successfully generated. Please move Events.h, Topics.h, EventStrings.cpp into your project sources.") -print(".... Done.") diff --git a/scripts/event_header_generator/requirements.txt b/scripts/event_header_generator/requirements.txt deleted file mode 100644 index b4e01569861fa5001ba712bfb61688ed45a3f451..0000000000000000000000000000000000000000 --- a/scripts/event_header_generator/requirements.txt +++ /dev/null @@ -1,20 +0,0 @@ -cachetools==3.1.0 -certifi==2019.3.9 -chardet==3.0.4 -google-api-python-client==1.7.8 -google-auth==1.6.3 -google-auth-httplib2==0.0.3 -google-auth-oauthlib==0.3.0 -httplib2==0.12.3 -idna==2.8 -oauth2client==4.1.3 -oauthlib==3.0.1 -pkg-resources==0.0.0 -pyasn1==0.4.5 -pyasn1-modules==0.2.5 -requests==2.21.0 -requests-oauthlib==1.2.0 -rsa==4.0 -six==1.12.0 -uritemplate==3.0.0 -urllib3==1.24.2 diff --git a/scripts/eventgen.sh b/scripts/eventgen.sh new file mode 100755 index 0000000000000000000000000000000000000000..6763addd5072948bc8e191ff4e61e4c31c20494a --- /dev/null +++ b/scripts/eventgen.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (c) 2021 Skyward Experimental Rocketry +# Authors: Alberto Nidasio +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DIRNAME="$(dirname $0)" +$DIRNAME/../skyward-boardcore/scripts/generators/eventgen.py $@ diff --git a/scripts/fsmgen.sh b/scripts/fsmgen.sh new file mode 100755 index 0000000000000000000000000000000000000000..2bae83d7f938ec78624784bfbb93aaa0f17e4431 --- /dev/null +++ b/scripts/fsmgen.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (c) 2021 Skyward Experimental Rocketry +# Authors: Alberto Nidasio +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DIRNAME="$(dirname $0)" +$DIRNAME/../skyward-boardcore/scripts/generators/fsmgen.py $@ diff --git a/scripts/linter.sh b/scripts/linter.sh new file mode 100755 index 0000000000000000000000000000000000000000..f0b2eac4f3a6e8628c1abe05506886fe2b7fc572 --- /dev/null +++ b/scripts/linter.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +DIRNAME="$(dirname $0)" +$DIRNAME/../skyward-boardcore/scripts/linter.sh $DIRNAME/../src/boards \ No newline at end of file diff --git a/scripts/scxml2plant.sh b/scripts/scxml2plant.sh new file mode 100755 index 0000000000000000000000000000000000000000..7a4d5a9cd20a8837ae09f940ff8b382d171ffee0 --- /dev/null +++ b/scripts/scxml2plant.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +DIRNAME="$(dirname $0)" +$DIRNAME/../skyward-boardcore/scripts/scxml2plant/scxml2plant.sh $DIRNAME/../src/boards \ No newline at end of file diff --git a/src/boards/DeathStack/AeroBrakesController/AeroBrakes.scxml b/src/boards/DeathStack/AeroBrakesController/AeroBrakes.scxml new file mode 100644 index 0000000000000000000000000000000000000000..4eb7408f8e44f84d1bab3bc797c9c0d992b5a8f2 --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/AeroBrakes.scxml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="initialization" version="1.0"> + <state id="initialization"> + <onentry>initServo()</onentry> + <onentry>transition(idle)</onentry> + </state> + <state id="idle"> + <transition event="FLIGHT_EVENTS.EV_LIFTOFF" target="shadowMode" /> + <transition event="ABK.EV_WIGGLE_SERVO" target="idle"> + wiggleServo() + </transition> + <transition event="ABK.EV_RESET_SERVO" target="idle"> + resetServo() + </transition> + <transition event="ABK.EV_TEST_ABK" target="testAirbrakes" /> + </state> + <state id="shadowMode"> + <onentry>postD(EV_SHADOW_MODE_TIMEOUT)</onentry> + <transition event="ABK.EV_SHADOW_MODE_TIMEOUT" target="enabled" /> + <transition event="ABK.EV_DISABLE_ABK" target="disabled" /> + </state> + <state id="enabled"> + <onentry>enableAirbrakes()</onentry> + <transition event="FLIGHT_EVENTS.EV_APOGEE" target="end" /> + <transition event="ABK.EV_DISABLE_ABK" target="disabled" /> + </state> + <state id="end"> + <onentry>setFullyClosed()</onentry> + </state> + <state id="disabled"> + <onentry>setFullyClosed()</onentry> + </state> + <state id="testAirbrakes"> + <onentry>enableAirbrakes()</onentry> + <onentry>incrementallyOpen()</onentry> + <onentry>postD(ABK.EV_TEST_TIMEOUT)</onentry> + <onexit>incrementallyClose()</onexit> + <onexit>disableAirbrakes()</onexit> + <transition event="ABK.EV_TEST_TIMEOUT" target="idle" /> + </state> +</scxml> diff --git a/src/boards/DeathStack/AeroBrakesController/AeroBrakesControlAlgorithm.h b/src/boards/DeathStack/AeroBrakesController/AeroBrakesControlAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..2339050e0460840d5c6a083ed70fa40d1035055b --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/AeroBrakesControlAlgorithm.h @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <algorithm> +#include <type_traits> + +#include "../Algorithm.h" +#include "../ServoInterface.h" +#include "AeroBrakesData.h" +#include "Pid.h" +#include "configs/AeroBrakesConfig.h" +#include "sensors/Sensor.h" +#include "trajectories/Trajectory.h" +#include "TimestampTimer.h" + +/* + Error and timing benchmark results: + + | float | double + ========================================================== + Max setpoint error: | 0.000122 | 0.000001 + Max u error: | 0.001045 | 0.000052 + Max deltas error: | 0.000000 | 0.000000 + Max alpha error: | 0 | 0 + Init time: | 0.179810 ms | 2.037333 ms + Avg iter time: | 0.151057 | 1.065261 ms + Total computation time: | 25.557320 ms | 181.001143 ms + +*/ + +using namespace DeathStackBoard::AeroBrakesConfigs; + +namespace DeathStackBoard +{ + +template <class T> +class AeroBrakesControlAlgorithm : public Algorithm +{ +private: + uint32_t indexMinVal = 0; + float alpha = 0; + uint64_t ts = 0; + Trajectory chosenTrajectory; + ServoInterface* actuator; + Sensor<T>& sensor; + Pid pid; + AeroBrakesData data; + + std::is_same<float, decltype(std::declval<T>().z)> checkz; + std::is_same<float, decltype(std::declval<T>().vz)> checkvz; + std::is_same<float, decltype(std::declval<T>().vMod)> checkvMod; + std::is_same<uint16_t, decltype(std::declval<T>().timestamp)> + checktimestamp; + +public: + AeroBrakesControlAlgorithm(Sensor<T>& sensor, + ServoInterface* actuator); + + bool init() override { return true; } + + /** + * @brief This method starts the algorithm and chooses the trajectory the + * rocket will follow for reaching apogee. + * */ + void begin(); + + /** + * @brief This method looks for nearest point in the current chosen + * trajectory and sends to the servoInterface the aerobrakes degree + * according to the current rocket speed and the one in the prediction. + * */ + void step() override; + + /** + * @brief Computes the alpha degree (in radiants) to be sent to the + * servoInterface in order to follow the choosen trajectory. If + * firstIteration is true then the nearest trajectory to the current + * rocket's coordinates is chosen. + * + * @param firstIteration The flag indicating wheter the trajectory has + * already been choosen or not. + * + * @returns The alpha in radiants to be sent to the servoInterface + * */ + float computeAlpha(bool firstIteration); + + /** + * @brief Chooses the nearest point on the trajectory, considering all the + * trajectories. Given the rocket initial input, stores the nearest + * trajectory. + * + * @param z The altitude of the rocket + * @param vz The z component of the rocket's speed + * */ + TrajectoryPoint chooseTrajectory(float z, float vz); + + /** + * @brief Starting from the second iteration selects the nearest point on + * the choosen trajectory. This method does not consider the Euclidean + * distance, but only the altitude (z) distance. + * + * @param z The altitude of the rocket + * @param vz The z component of the rocket's speed + * */ + TrajectoryPoint getSetpoint(float z, float vz); + + /** + * @brief Update Pid internal input. The Pid output represents represents + * the drag force of the wind. + * + * @param vz The z component of the rocket's speed + * @param vMod Modulo of the rocket's speed + * @param rho The density of the air + * @param setpoint Nearest point to the current rocket input in the chosen + * trajectory + * */ + float pidStep(float vz, float vMod, float rho, TrajectoryPoint setpoint); + + /** + * @brief Compute the necessary aerobrakes surface to match the + * given the drag force from the Pid. The possible deltaS values are + * discretized in (DELTA_S_AVAILABLE_MIN, DELTA_S_AVAILABLE_MAX) with a + * step of DELTA_S_AVAILABLE_STEP. For every possible deltaS the + * correspondig drag force is computed with @see getDrag method and the one + * that gives lowest error with respect to Pid output is returned. + * + * @param z The current altitude of the rocket + * @param vz The z component of the rocket's speed + * @param vMod Modulo of the rocket's speed + * @param rho The density of the air + * @param u The current pid value + * */ + float getDeltaS(float z, float vz, float vMod, float rho, float u); + + /** + * @brief Maps the exposed aerobrakes surface to servoInterface angle in + * radiants. + * + * @param deltas Total variation of the aerobrakes surface + * */ + float getAlpha(float deltaS); + + /** + * @param h The current altitude + * @return The density of air according to current altitude. + * */ + float getRho(float h); + + /** + * @param v_mod Modulo of the current rocket speed. + * @param z The z component of the rocket's speed + * @return The speed in Mach unit. + * */ + float getMach(float v_mod, float z); + + /** + * @param deltaS The total variation of the aerobrakes surface + * @return The radial distance of the current aerobrakes extension. + * */ + float getExtension(float deltaS); + + /** + * @param h The current altitude of the rocket + * @param s + * @param powMach Array containing precomputed powers of the mach + * @return The drag force coefficient + * */ + float getDrag(float h, float s, float* powMach); + + /** + * @brief Log algorithm data structure + * + */ + void logData(); +}; + +template <class T> +AeroBrakesControlAlgorithm<T>::AeroBrakesControlAlgorithm( + Sensor<T>& sensor, ServoInterface* actuator) + : actuator(actuator), sensor(sensor), pid(Kp, Ki) +{ +} + +template <class T> +void AeroBrakesControlAlgorithm<T>::begin() +{ + if (running) + { + return; + } + + running = true; + + ts = (sensor.getLastSample()).timestamp; + + alpha = computeAlpha(true); + actuator->set(alpha); +} + +template <class T> +void AeroBrakesControlAlgorithm<T>::step() +{ + if ((sensor.getLastSample()).timestamp > ts) + { + ts = (sensor.getLastSample()).timestamp; + alpha = computeAlpha(false); + } + + actuator->set(alpha); + + logData(); +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::computeAlpha(bool firstIteration) +{ + T input = sensor.getLastSample(); + float z = input.z; + float vz = input.vz; + float vMod = input.vMod; + float rho = getRho(z); + + TrajectoryPoint setpoint; + + if (firstIteration) + { + setpoint = chooseTrajectory(z, vz); + } + else + { + setpoint = getSetpoint(z, vz); + } + + float u = pidStep(vz, vMod, rho, setpoint); + float deltaS = getDeltaS(z, vz, vMod, rho, u); + float alpha = getAlpha(deltaS); + + return alpha; +} + +template <class T> +TrajectoryPoint AeroBrakesControlAlgorithm<T>::chooseTrajectory(float z, + float vz) +{ + TrajectoryPoint currentPoint(z, vz); + + float bestMin = INFINITY; + + for (unsigned trajectoryIndex = 0; trajectoryIndex < TOT_TRAJECTORIES; + trajectoryIndex++) + { + + Trajectory trajectory = Trajectory(trajectoryIndex); + + for (uint32_t pointIndex = 0; pointIndex < LOOKS; pointIndex++) + { + TrajectoryPoint ref = trajectory.get(pointIndex); + float distancesFromCurrentinput = + TrajectoryPoint::distance(ref, currentPoint); + + if (distancesFromCurrentinput < bestMin) + { + bestMin = distancesFromCurrentinput; + indexMinVal = pointIndex; + chosenTrajectory = trajectory; + } + } + } + + TrajectoryPoint setpoint = chosenTrajectory.get(indexMinVal); + + return setpoint; +} + +template <class T> +TrajectoryPoint AeroBrakesControlAlgorithm<T>::getSetpoint(float z, float vz) +{ + TrajectoryPoint currentPoint(z, vz); + float minDistance = INFINITY; + + uint32_t start = std::max(indexMinVal + START_INDEX_OFFSET, (uint32_t)0); + uint32_t end = chosenTrajectory.length(); + + for (uint32_t pointIndex = start; pointIndex < end; pointIndex++) + { + TrajectoryPoint ref = chosenTrajectory.get(pointIndex); + float DistanceFromCurrentinput = + TrajectoryPoint::zDistance(ref, currentPoint); + if (DistanceFromCurrentinput < minDistance) + { + minDistance = DistanceFromCurrentinput; + indexMinVal = pointIndex; + } + } + + TrajectoryPoint setpoint = chosenTrajectory.get(indexMinVal); + + return setpoint; +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::pidStep(float vz, float vMod, float rho, + TrajectoryPoint setpoint) +{ + float umin = 0; + // The *1 factor replaces the cd variable. This variable will be later + // calculated in the getDeltaS method. + float umax = 0.5 * rho * S0 * 1 * vz * vMod; + float error = (vz - setpoint.getVz()); + + float u = pid.step(umin, umax, error); + + return u; +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getDeltaS(float z, float vz, float vMod, + float rho, float u) +{ + float deltaS = 0; + float bestValue = INFINITY; + + float mach = getMach(vMod, z); + // Precomputes all the powers of mach (from 0 to 6) in order to reuse it + // at avery iteration of the deltaSAvailable loop. + // See getDrag method. + float powMach[7] = {1, + mach, + powf(mach, 2), + powf(mach, 3), + powf(mach, 4), + powf(mach, 5), + powf(mach, 6)}; + + for (float deltaSAvailable = DELTA_S_AVAILABLE_MIN; + deltaSAvailable < DELTA_S_AVAILABLE_MAX + DELTA_S_AVAILABLE_STEP; + deltaSAvailable += DELTA_S_AVAILABLE_STEP) + { + float cdAvaliable = getDrag(z, deltaSAvailable, powMach); + float temp = abs(u - 0.5 * rho * S0 * cdAvaliable * vz * vMod); + if (temp < bestValue) + { + bestValue = temp; + deltaS = deltaSAvailable; + } + } + + return deltaS; +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getAlpha(float deltaS) +{ + float alphaRadiants = + (-B_DELTAS + sqrt(powf(B_DELTAS, 2) + 4 * A_DELTAS * deltaS)) / + (2 * A_DELTAS); + float alphaDegrees = alphaRadiants * 180.0f / PI; + + return alphaDegrees; +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getRho(float h) +{ + return RHO * expf(-h / Hn); +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getMach(float v_mod, float z) +{ + float c = Co + ALPHA * z; + return v_mod / c; +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getExtension(float deltaS) +{ + return (-B + sqrtf(powf(B, 2) + 4 * A * deltaS)) / (2 * A); +} + +template <class T> +float AeroBrakesControlAlgorithm<T>::getDrag(float h, float s, float* powMach) +{ + float x = getExtension(s); + + return coeffs.n000 + coeffs.n100 * powMach[1] + coeffs.n200 * powMach[2] + + coeffs.n300 * powMach[3] + coeffs.n400 * powMach[4] + + coeffs.n500 * powMach[5] + coeffs.n600 * powMach[6] + + coeffs.n010 * x + coeffs.n020 * powf(x, 2) + + coeffs.n110 * x * powMach[1] + + coeffs.n120 * powf(x, 2) * powMach[1] + + coeffs.n210 * x * powMach[2] + + coeffs.n220 * powf(x, 2) * powMach[2] + + coeffs.n310 * x * powMach[3] + + coeffs.n320 * powf(x, 2) * powMach[3] + + coeffs.n410 * x * powMach[4] + + coeffs.n420 * powf(x, 2) * powMach[4] + + coeffs.n510 * x * powMach[5] + + coeffs.n520 * powf(x, 2) * powMach[5] + coeffs.n001 * h; +} + +template <class T> +void AeroBrakesControlAlgorithm<T>::logData() +{ + data.timestamp = TimestampTimer::getTimestamp(); + data.running = running; + data.servo_position = actuator->getCurrentPosition(); + + // logger.log(data); +} + +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/AeroBrakesController/AeroBrakesController.h b/src/boards/DeathStack/AeroBrakesController/AeroBrakesController.h new file mode 100644 index 0000000000000000000000000000000000000000..53d7b05668060baf9bd0070c43cb5ad5c72e9111 --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/AeroBrakesController.h @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <miosix.h> + +#include "AeroBrakesController/AeroBrakesControlAlgorithm.h" +#include "AeroBrakesController/AeroBrakesServo.h" +#include "AeroBrakesData.h" +#include "TimestampTimer.h" +#include "configs/AeroBrakesConfig.h" +#include "events/EventBroker.h" +#include "events/Events.h" +#include "events/FSM.h" + +namespace DeathStackBoard +{ + +/** + * @brief AeroBrakes state machine + */ +template <class T> +class AeroBrakesController : public FSM<AeroBrakesController<T>> +{ +public: + AeroBrakesController(Sensor<T>& sensor, + ServoInterface* servo = new AeroBrakesServo()); + ~AeroBrakesController(); + + // Aerobrakes FSM states + void state_initialization(const Event& ev); + void state_idle(const Event& ev); + void state_shadowMode(const Event& ev); + void state_enabled(const Event& ev); + void state_end(const Event& ev); + void state_disabled(const Event& ev); + void state_testAerobrakes(const Event& ev); + + /** + * @brief Update the aerobrakes control algorithm + */ + void update(); + +private: + AeroBrakesControllerStatus status; + ServoInterface* servo; + AeroBrakesControlAlgorithm<T> algorithm; + + uint16_t ev_shadow_mode_timeout_id; + + /** + * @brief Incrementally opens the servo with steps of 10° + */ + void incrementallyOpen(); + + /** + * @brief Incrementally closes the servo with steps of 10° + */ + void incrementallyClose(); + + void logStatus(AeroBrakesControllerState state); +}; + +template <class T> +AeroBrakesController<T>::AeroBrakesController(Sensor<T>& sensor, + ServoInterface* servo) + : FSM<AeroBrakesController<T>>( + &AeroBrakesController<T>::state_initialization), + servo(servo), algorithm(sensor, servo) +{ + memset(&status, 0, sizeof(AeroBrakesControllerStatus)); + sEventBroker->subscribe(this, TOPIC_FLIGHT_EVENTS); + sEventBroker->subscribe(this, TOPIC_ABK); +} + +template <class T> +AeroBrakesController<T>::~AeroBrakesController() +{ + sEventBroker->unsubscribe(this); +} + +template <class T> +void AeroBrakesController<T>::logStatus(AeroBrakesControllerState state) +{ + status.timestamp = TimestampTimer::getTimestamp(); + status.state = state; + + // logger.log(status); + + // StackLogger::getInstance()->updateStack(THID_ABK_FSM); +} + +template <class T> +void AeroBrakesController<T>::update() +{ + algorithm.update(); +} + +template <class T> +void AeroBrakesController<T>::state_initialization(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + servo->enable(); + servo->reset(); + + this->transition(&AeroBrakesController<T>::state_idle); + break; + } + case EV_EXIT: + { + break; + } + + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_idle(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + logStatus(AeroBrakesControllerState::IDLE); + + TRACE("[AeroBrakes] entering state idle\n"); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state idle\n"); + break; + } + case EV_LIFTOFF: + { + this->transition(&AeroBrakesController<T>::state_shadowMode); + break; + } + case EV_WIGGLE_SERVO: + { + servo->selfTest(); + break; + } + case EV_RESET_SERVO: + { + servo->reset(); + break; + } + case EV_TEST_ABK: + { + this->transition(&AeroBrakesController<T>::state_testAerobrakes); + break; + } + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_shadowMode(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + ev_shadow_mode_timeout_id = + sEventBroker->postDelayed<SHADOW_MODE_DURATION>( + Event{EV_SHADOW_MODE_TIMEOUT}, TOPIC_FLIGHT_EVENTS); + + logStatus(AeroBrakesControllerState::SHADOW_MODE); + + TRACE("[AeroBrakes] entering state shadow_mode\n"); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state shadow_mode\n"); + break; + } + case EV_SHADOW_MODE_TIMEOUT: + { + this->transition(&AeroBrakesController<T>::state_enabled); + break; + } + case EV_DISABLE_ABK: + { + this->transition(&AeroBrakesController<T>::state_disabled); + break; + } + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_enabled(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + algorithm.begin(); + + logStatus(AeroBrakesControllerState::ENABLED); + + TRACE("[AeroBrakes] entering state enabled\n"); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state enabled\n"); + break; + } + case EV_APOGEE: + { + this->transition(&AeroBrakesController<T>::state_end); + break; + } + case EV_DISABLE_ABK: + { + this->transition(&AeroBrakesController<T>::state_disabled); + break; + } + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_end(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + algorithm.end(); + servo->reset(); + + logStatus(AeroBrakesControllerState::END); + + TRACE("[AeroBrakes] entering state end\n"); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state end\n"); + break; + } + + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_disabled(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + algorithm.end(); + servo->reset(); + + logStatus(AeroBrakesControllerState::DISABLED); + + TRACE("[AeroBrakes] entering state disabled\n"); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state disabled\n"); + break; + } + + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::state_testAerobrakes(const Event& ev) +{ + switch (ev.sig) + { + case EV_ENTRY: + { + TRACE("[AeroBrakes] entering state test_aerobrakes\n"); + + incrementallyOpen(); + miosix::Thread::sleep(1000); + incrementallyClose(); + miosix::Thread::sleep(1000); + servo->reset(); + + logStatus(AeroBrakesControllerState::TEST_AEROBRAKES); + + sEventBroker->post(Event{EV_TEST_TIMEOUT}, TOPIC_ABK); + break; + } + case EV_EXIT: + { + TRACE("[AeroBrakes] exiting state test_aerobrakes\n"); + break; + } + case EV_TEST_TIMEOUT: + { + this->transition(&AeroBrakesController<T>::state_idle); + break; + } + default: + { + break; + } + } +} + +template <class T> +void AeroBrakesController<T>::incrementallyOpen() +{ + // Equal steps of about 5° + const int STEPS_NUM = (servo->MAX_POS - servo->MIN_POS) / 10.0f; + const float INCREMENT_STEP = (servo->MAX_POS - servo->MIN_POS) / STEPS_NUM; + + float currentStep = servo->MIN_POS; + + for (auto i = 0; i < STEPS_NUM; i++) + { + TRACE("Servo position : %.2f\n", currentStep); + servo->set(currentStep); + currentStep += INCREMENT_STEP; + miosix::Thread::sleep(1000); + } + + servo->set(servo->MAX_POS); +} + +template <class T> +void AeroBrakesController<T>::incrementallyClose() +{ + // Equal steps of about 5° + const int STEPS_NUM = (servo->MAX_POS - servo->MIN_POS) / 10.0f; + const float INCREMENT_STEP = (servo->MAX_POS - servo->MIN_POS) / STEPS_NUM; + + float currentStep = servo->MAX_POS; + + for (auto i = 0; i < STEPS_NUM; i++) + { + TRACE("Servo position : %.2f\n", currentStep); + servo->set(currentStep); + currentStep -= INCREMENT_STEP; + miosix::Thread::sleep(1000); + } + + servo->set(servo->MIN_POS); +} + +} // namespace DeathStackBoard \ No newline at end of file diff --git a/src/boards/DeathStack/AeroBrakesController/AeroBrakesData.h b/src/boards/DeathStack/AeroBrakesController/AeroBrakesData.h new file mode 100644 index 0000000000000000000000000000000000000000..b96ff70f7c596e3341ba8e9e2d2ce7566959d0bf --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/AeroBrakesData.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <stdint.h> + +#include <iostream> +#include <string> + +namespace DeathStackBoard +{ + +/** + * Enum defining the possibile FSM states. + */ +enum AeroBrakesControllerState : uint8_t +{ + IDLE = 0, + SHADOW_MODE, + ENABLED, + END, + DISABLED, + TEST_AEROBRAKES, +}; + +/** + * Structure defining the overall controller status. + */ +struct AeroBrakesControllerStatus +{ + long long timestamp; + AeroBrakesControllerState state; + + static std::string header() { return "timestamp,state\n"; } + + void print(std::ostream& os) const + { + os << timestamp << "," << (int)state << "\n"; + } +}; + +/** + * Structure defining the output of the control algorithm. + */ +struct AeroBrakesData +{ + long long timestamp; + float running; + float servo_position; + + static std::string header() { return "timestamp,running,servo_position\n"; } + + void print(std::ostream& os) const + { + os << timestamp << "," << (int)running << "," << servo_position << "\n"; + } +}; + +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/AeroBrakesController/AeroBrakesServo.h b/src/boards/DeathStack/AeroBrakesController/AeroBrakesServo.h new file mode 100644 index 0000000000000000000000000000000000000000..d6a4475c84562d545e31fec606010ca115f960d9 --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/AeroBrakesServo.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "../ServoInterface.h" +#include "../configs/AeroBrakesConfig.h" +#include "drivers/servo/servo.h" +#include "miosix.h" + +using namespace DeathStackBoard::AeroBrakesConfigs; + +namespace DeathStackBoard +{ +class AeroBrakesServo : public ServoInterface +{ +public: + AeroBrakesServo() : ServoInterface(SERVO_MIN_POS, SERVO_MAX_POS) {} + AeroBrakesServo(float minPosition, float maxPosition) + : ServoInterface(minPosition, maxPosition) + { + } + AeroBrakesServo(float minPosition, float maxPosition, float resetPosition) + : ServoInterface(minPosition, maxPosition, resetPosition) + { + } + + void enable() override + { + servo.enable(SERVO_PWM_CH); + servo.start(); + } + + void disable() override + { + servo.stop(); + servo.disable(SERVO_PWM_CH); + } + + /** + * @brief Perform wiggle around the middle point. + */ + void selfTest() override + { + float base = (MAX_POS + RESET_POS) / 2; + float maxpos = base + SERVO_WIGGLE_AMPLITUDE / 2; + float minpos = base - SERVO_WIGGLE_AMPLITUDE / 2; + + set(base); + + for (int i = 0; i < 3; i++) + { + miosix::Thread::sleep(UPDATE_TIME + 100); + set(maxpos); + miosix::Thread::sleep(UPDATE_TIME + 100); + set(minpos); + } + + miosix::Thread::sleep(UPDATE_TIME); + } + +private: + Servo servo{SERVO_TIMER}; + +protected: + /** + * @brief Set servo position. + * + * @param angle servo position (in degrees) + */ + void setPosition(float angle) override + { + currentPosition = angle; + // map position to [0;1] interval for the servo driver + servo.setPosition(AeroBrakesConfigs::SERVO_PWM_CH, angle / 180.0f); + } + + float preprocessPosition(float angle) override + { + angle = ServoInterface::preprocessPosition(angle); + + float rate = (angle - currentPosition) / UPDATE_TIME; + + if (rate > SERVO_MAX_RATE) + { + angle = UPDATE_TIME * SERVO_MAX_RATE + currentPosition; + } + else if (rate < SERVO_MIN_RATE) + { + angle = UPDATE_TIME * SERVO_MIN_RATE + currentPosition; + } + + return angle; + } +}; +} // namespace DeathStackBoard \ No newline at end of file diff --git a/scripts/event_header_generator/EventStrings.cpp.template b/src/boards/DeathStack/AeroBrakesController/Coeffs.h similarity index 54% rename from scripts/event_header_generator/EventStrings.cpp.template rename to src/boards/DeathStack/AeroBrakesController/Coeffs.h index d11c60bbcd8c6f9896aa2e36f18cd173e3f4eb31..53b95075b53505504c40578c915641bd906ba85f 100644 --- a/scripts/event_header_generator/EventStrings.cpp.template +++ b/src/boards/DeathStack/AeroBrakesController/Coeffs.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,41 +21,33 @@ * THE SOFTWARE. */ -/* - ****************************************************************************** - * THIS FILE IS AUTOGENERATED. DO NOT EDIT. * - ****************************************************************************** - */ - -// Generated from: {sheet_link} -// Autogen date: {date} - - -#include "Events.h" -#include "Topics.h" - -#include <map> -using std::map; +#pragma once namespace DeathStackBoard -{{ - -string getEventString(uint8_t event) -{{ - static const map<uint8_t, string> event_string_map {{ -{event_map_data} - }}; - auto it = event_string_map.find(event); - return it == event_string_map.end() ? "EV_UNKNOWN" : it->second; -}} - -string getTopicString(uint8_t topic) -{{ - static const map<uint8_t, string> topic_string_map{{ -{topic_map_data} - }}; - auto it = topic_string_map.find(topic); - return it == topic_string_map.end() ? "TOPIC_UNKNOWN" : it->second; -}} - -}} \ No newline at end of file +{ +typedef struct +{ + float n000 = 0.496878; + float n100 = -1.405038; + float n200 = 6.502618; + float n300 = -18.314261; + float n400 = 30.152448; + float n500 = -26.715700; + float n600 = 9.711730; + float n010 = 8.486901; + float n020 = 141.050398; + float n110 = 1.233043; + float n120 = -152.610100; + float n210 = 81.980768; + float n220 = 1072.170007; + float n310 = -309.620754; + float n320 = -3618.989164; + float n410 = 455.524477; + float n420 = 5190.202262; + float n510 = -212.545170; + float n520 = -2402.939515; + float n001 = 0.000003; +} coeffs_t; + +const coeffs_t coeffs; +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/AeroBrakesController/Pid.h b/src/boards/DeathStack/AeroBrakesController/Pid.h new file mode 100644 index 0000000000000000000000000000000000000000..2d85e2a3d0a990a47e25fff3784f50cd34d91a20 --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/Pid.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "Coeffs.h" + +namespace DeathStackBoard +{ +/** + * @brief Pid proportional and integral controller with saturation + * */ +class Pid +{ +private: + const float Kp; + const float Ki; + + float i = 0; + bool saturation = false; + +public: + Pid(float Kp, float Ki) : Kp(Kp), Ki(Ki) {} + ~Pid() {} + + /** + * @brief Update the Pid internal state + * */ + float step(float umin, float umax, float error) + { + + float p = Kp * error; + + if (!saturation) + { + i = i + Ki * error; + } + + float u = p + i; + + if (u < umin) + { + u = umin; + saturation = true; + } + else if (u > umax) + { + u = umax; + saturation = true; + } + else + { + saturation = false; + } + + return u; + } +}; + +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/AeroBrakesController/readme.md b/src/boards/DeathStack/AeroBrakesController/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..ef63c80a1a898154e6d6b7e618b677c581064c7f --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/readme.md @@ -0,0 +1,12 @@ +```mermaid +stateDiagram-v2 + [*] --> initialization + initialization --> idle + idle --> shadow_mode : EV_LIFTOFF + idle --> test_airbrakes : EV_TEST_ABK + shadow_mode --> enabled : EV_SHADOW_MODE_TIMEOUT + shadow_mode --> disabled : EV_DISABLE_ABK + enabled --> end : EV_APOGEE + enabled --> disabled : EV_DISABLE_ABK + test_airbrakes --> idle : EV_TEST_TIMEOUT +``` \ No newline at end of file diff --git a/src/boards/DeathStack/AeroBrakesController/trajectories/Trajectories_data.h b/src/boards/DeathStack/AeroBrakesController/trajectories/Trajectories_data.h new file mode 100644 index 0000000000000000000000000000000000000000..055934ac9d0ca2669b891fd0ca05169dbf4c787d --- /dev/null +++ b/src/boards/DeathStack/AeroBrakesController/trajectories/Trajectories_data.h @@ -0,0 +1,1727 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +namespace DeathStackBoard +{ + +static const unsigned int TOT_TRAJECTORIES = 9; +static const unsigned int TRAJECTORY_MAX_LENGTH = 500; + +struct point_t +{ + float z; + float vz; +}; + +struct trajectory_t +{ + unsigned int length; + point_t data[TRAJECTORY_MAX_LENGTH]; +}; + +const trajectory_t TRAJECTORIES_DATA[TOT_TRAJECTORIES] = { + {404, + { + {822.834116, 250.000000}, {822.834116, 250.000000}, + {825.748986, 249.760711}, {838.211504, 248.739999}, + {850.623108, 247.724175}, {862.984042, 246.713176}, + {875.294545, 245.706939}, {887.554854, 244.705404}, + {899.765202, 243.708514}, {911.925820, 242.716212}, + {924.036936, 241.728443}, {936.098776, 240.745154}, + {948.111562, 239.766291}, {960.075515, 238.791806}, + {971.990851, 237.821647}, {983.857786, 236.855768}, + {995.676534, 235.894120}, {1007.447303, 234.936658}, + {1019.170303, 233.983337}, {1030.845739, 233.034114}, + {1042.473816, 232.088944}, {1054.054734, 231.147786}, + {1065.588693, 230.210598}, {1077.075892, 229.277341}, + {1088.516525, 228.347974}, {1099.910786, 227.422460}, + {1111.258866, 226.500758}, {1122.560956, 225.582833}, + {1133.817243, 224.668648}, {1145.027913, 223.758166}, + {1156.193151, 222.851351}, {1167.313139, 221.948170}, + {1178.388058, 221.048587}, {1189.418087, 220.152568}, + {1200.403403, 219.260081}, {1211.344183, 218.371092}, + {1222.240599, 217.485570}, {1233.092825, 216.603481}, + {1243.901032, 215.724796}, {1254.665389, 214.849483}, + {1265.386064, 213.977511}, {1276.063223, 213.108851}, + {1286.697031, 212.243472}, {1297.287652, 211.381346}, + {1307.835246, 210.522443}, {1318.339976, 209.666734}, + {1328.801999, 208.814192}, {1339.221474, 207.964789}, + {1349.598556, 207.118496}, {1359.933400, 206.275288}, + {1370.226161, 205.435136}, {1380.476990, 204.598014}, + {1390.686037, 203.763896}, {1400.853454, 202.932756}, + {1410.979387, 202.104569}, {1421.063984, 201.279308}, + {1431.107390, 200.456948}, {1441.109750, 199.637465}, + {1451.071208, 198.820835}, {1460.991905, 198.007031}, + {1470.871981, 197.196032}, {1480.711577, 196.387812}, + {1490.510831, 195.582347}, {1500.269880, 194.779616}, + {1509.988861, 193.979594}, {1519.667907, 193.182259}, + {1529.307153, 192.387588}, {1538.906732, 191.595558}, + {1548.466774, 190.806148}, {1557.987411, 190.019334}, + {1567.468772, 189.235097}, {1576.910985, 188.453413}, + {1586.314177, 187.674262}, {1595.678474, 186.897622}, + {1605.004001, 186.123472}, {1614.290883, 185.351793}, + {1623.539242, 184.582562}, {1632.749200, 183.815761}, + {1641.920878, 183.051368}, {1651.054396, 182.289363}, + {1660.149874, 181.529728}, {1669.207428, 180.772442}, + {1678.227176, 180.017486}, {1687.209234, 179.264841}, + {1696.153717, 178.514488}, {1705.060740, 177.766407}, + {1713.930415, 177.020581}, {1722.762854, 176.276990}, + {1731.558169, 175.535617}, {1740.316470, 174.796443}, + {1749.037868, 174.059450}, {1757.722470, 173.324621}, + {1766.370384, 172.591937}, {1774.981716, 171.861382}, + {1783.556574, 171.132938}, {1792.095063, 170.406588}, + {1800.597285, 169.682314}, {1809.063346, 168.960101}, + {1817.493346, 168.239931}, {1825.887389, 167.521788}, + {1834.245575, 166.805655}, {1842.568005, 166.091516}, + {1850.854776, 165.379356}, {1859.105989, 164.669158}, + {1867.321741, 163.960906}, {1875.502128, 163.254585}, + {1883.647247, 162.550180}, {1891.757194, 161.847674}, + {1899.832062, 161.147054}, {1907.871946, 160.448303}, + {1915.876939, 159.751406}, {1923.847132, 159.056350}, + {1931.782619, 158.363120}, {1939.683490, 157.671700}, + {1947.549834, 156.982076}, {1955.381742, 156.294235}, + {1963.179302, 155.608162}, {1970.942602, 154.923843}, + {1978.671730, 154.241265}, {1986.366772, 153.560412}, + {1994.027814, 152.881273}, {2001.654941, 152.203833}, + {2009.248239, 151.528079}, {2016.807791, 150.853998}, + {2024.333681, 150.181577}, {2031.825990, 149.510802}, + {2039.284802, 148.841661}, {2046.710197, 148.174141}, + {2054.102256, 147.508229}, {2061.461059, 146.843913}, + {2068.786687, 146.181181}, {2076.079217, 145.520019}, + {2083.338728, 144.860416}, {2090.565297, 144.202360}, + {2097.759002, 143.545838}, {2104.919919, 142.890839}, + {2112.048124, 142.237351}, {2119.143691, 141.585362}, + {2126.206697, 140.934861}, {2133.237215, 140.285836}, + {2140.235317, 139.638276}, {2147.201078, 138.992170}, + {2154.134570, 138.347506}, {2161.035865, 137.704273}, + {2167.905033, 137.062460}, {2174.742146, 136.422056}, + {2181.547274, 135.783051}, {2188.320486, 135.145434}, + {2195.061852, 134.509195}, {2201.771439, 133.874321}, + {2208.449318, 133.240804}, {2215.095554, 132.608633}, + {2221.710214, 131.977797}, {2228.293366, 131.348287}, + {2234.845076, 130.720092}, {2241.365408, 130.093203}, + {2247.854429, 129.467608}, {2254.312201, 128.843300}, + {2260.738790, 128.220267}, {2267.134260, 127.598500}, + {2273.498672, 126.977989}, {2279.832090, 126.358726}, + {2286.134575, 125.740700}, {2292.406190, 125.123902}, + {2298.646996, 124.508322}, {2304.857053, 123.893953}, + {2311.036421, 123.280784}, {2317.185161, 122.668806}, + {2323.303331, 122.058010}, {2329.390991, 121.448388}, + {2335.448199, 120.839930}, {2341.475013, 120.232629}, + {2347.471491, 119.626474}, {2353.437689, 119.021458}, + {2359.373665, 118.417571}, {2365.279474, 117.814806}, + {2371.155173, 117.213153}, {2377.000817, 116.612605}, + {2382.816461, 116.013153}, {2388.602160, 115.414789}, + {2394.357967, 114.817504}, {2400.083937, 114.221291}, + {2405.780123, 113.626142}, {2411.446577, 113.032047}, + {2417.083354, 112.439000}, {2422.690503, 111.846993}, + {2428.268079, 111.256018}, {2433.816131, 110.666066}, + {2439.334711, 110.077130}, {2444.823869, 109.489203}, + {2450.283656, 108.902277}, {2455.714122, 108.316344}, + {2461.115315, 107.731397}, {2466.487286, 107.147428}, + {2471.830082, 106.564431}, {2477.143753, 105.982397}, + {2482.428346, 105.401319}, {2487.683909, 104.821190}, + {2492.910488, 104.242003}, {2498.108132, 103.663751}, + {2503.276887, 103.086426}, {2508.416798, 102.510023}, + {2513.527912, 101.934532}, {2518.610274, 101.359948}, + {2523.663929, 100.786264}, {2528.688923, 100.213473}, + {2533.685299, 99.641568}, {2538.653101, 99.070542}, + {2543.592375, 98.500389}, {2548.503162, 97.931102}, + {2553.385506, 97.362673}, {2558.239451, 96.795098}, + {2563.065037, 96.228368}, {2567.862308, 95.662479}, + {2572.631306, 95.097422}, {2577.372071, 94.533192}, + {2582.084646, 93.969782}, {2586.769070, 93.407186}, + {2591.425384, 92.845398}, {2596.053630, 92.284412}, + {2600.653845, 91.724220}, {2605.226071, 91.164818}, + {2609.770347, 90.606198}, {2614.286711, 90.048355}, + {2618.775202, 89.491283}, {2623.235858, 88.934976}, + {2627.668718, 88.379427}, {2632.073820, 87.824631}, + {2636.451200, 87.270581}, {2640.800896, 86.717273}, + {2645.122946, 86.164699}, {2649.417384, 85.612855}, + {2653.684249, 85.061734}, {2657.923576, 84.511331}, + {2662.135400, 83.961639}, {2666.319757, 83.412654}, + {2670.476683, 82.864370}, {2674.606212, 82.316780}, + {2678.708378, 81.769880}, {2682.783217, 81.223664}, + {2686.830762, 80.678126}, {2690.851046, 80.133261}, + {2694.844104, 79.589063}, {2698.809969, 79.045527}, + {2702.748673, 78.502648}, {2706.660250, 77.960420}, + {2710.544732, 77.418838}, {2714.402150, 76.877896}, + {2718.232537, 76.337589}, {2722.035925, 75.797913}, + {2725.812344, 75.258861}, {2729.561826, 74.720429}, + {2733.284402, 74.182611}, {2736.980103, 73.645403}, + {2740.648958, 73.108799}, {2744.290997, 72.572793}, + {2747.906252, 72.037382}, {2751.494750, 71.502560}, + {2755.056522, 70.968322}, {2758.591597, 70.434663}, + {2762.100003, 69.901578}, {2765.581769, 69.369062}, + {2769.036923, 68.837111}, {2772.465494, 68.305719}, + {2775.867509, 67.774881}, {2779.242996, 67.244594}, + {2782.591982, 66.714851}, {2785.914495, 66.185648}, + {2789.210560, 65.656981}, {2792.480206, 65.128845}, + {2795.723458, 64.601234}, {2798.940342, 64.074145}, + {2802.130885, 63.547573}, {2805.295112, 63.021513}, + {2808.433049, 62.495960}, {2811.544721, 61.970911}, + {2814.630153, 61.446359}, {2817.689369, 60.922302}, + {2820.722395, 60.398734}, {2823.729255, 59.875651}, + {2826.709972, 59.353048}, {2829.664572, 58.830921}, + {2832.593076, 58.309266}, {2835.495510, 57.788078}, + {2838.371896, 57.267353}, {2841.222257, 56.747087}, + {2844.046616, 56.227274}, {2846.844995, 55.707912}, + {2849.617418, 55.188995}, {2852.363906, 54.670519}, + {2855.084481, 54.152480}, {2857.779165, 53.634875}, + {2860.447979, 53.117698}, {2863.090945, 52.600945}, + {2865.708084, 52.084613}, {2868.299417, 51.568697}, + {2870.864964, 51.053193}, {2873.404746, 50.538098}, + {2875.918784, 50.023406}, {2878.407097, 49.509114}, + {2880.869705, 48.995219}, {2883.306629, 48.481715}, + {2885.717886, 47.968599}, {2888.103498, 47.455867}, + {2890.463483, 46.943515}, {2892.797859, 46.431540}, + {2895.106646, 45.919936}, {2897.389862, 45.408701}, + {2899.647525, 44.897831}, {2901.879654, 44.387321}, + {2904.086266, 43.877168}, {2906.267380, 43.367368}, + {2908.423012, 42.857917}, {2910.553180, 42.348812}, + {2912.657901, 41.840049}, {2914.737193, 41.331624}, + {2916.791072, 40.823533}, {2918.819555, 40.315773}, + {2920.822658, 39.808340}, {2922.800397, 39.301231}, + {2924.752789, 38.794442}, {2926.679849, 38.287969}, + {2928.581593, 37.781809}, {2930.458038, 37.275958}, + {2932.309197, 36.770412}, {2934.135086, 36.265169}, + {2935.935721, 35.760225}, {2937.711116, 35.255576}, + {2939.461286, 34.751219}, {2941.186245, 34.247150}, + {2942.886008, 33.743367}, {2944.560589, 33.239865}, + {2946.210002, 32.736642}, {2947.834260, 32.233693}, + {2949.433378, 31.731017}, {2951.007369, 31.228610}, + {2952.556245, 30.726467}, {2954.080022, 30.224587}, + {2955.578711, 29.722966}, {2957.052325, 29.221601}, + {2958.500877, 28.720488}, {2959.924380, 28.219625}, + {2961.322846, 27.719009}, {2962.696287, 27.218636}, + {2964.044715, 26.718503}, {2965.368143, 26.218609}, + {2966.666582, 25.718948}, {2967.940044, 25.219520}, + {2969.188540, 24.720320}, {2970.412081, 24.221346}, + {2971.610680, 23.722595}, {2972.784346, 23.224065}, + {2973.933092, 22.725752}, {2975.056927, 22.227653}, + {2976.155862, 21.729767}, {2977.229909, 21.232091}, + {2978.279077, 20.734621}, {2979.303376, 20.237356}, + {2980.302817, 19.740292}, {2981.277410, 19.243428}, + {2982.227165, 18.746760}, {2983.152091, 18.250287}, + {2984.052199, 17.754006}, {2984.927497, 17.257915}, + {2985.777995, 16.762011}, {2986.603702, 16.266292}, + {2987.404629, 15.770756}, {2988.180782, 15.275402}, + {2988.932173, 14.780225}, {2989.658809, 14.285226}, + {2990.360700, 13.790402}, {2991.037854, 13.295750}, + {2991.690279, 12.801269}, {2992.317985, 12.306957}, + {2992.920979, 11.812813}, {2993.499270, 11.318834}, + {2994.052867, 10.825019}, {2994.581776, 10.331367}, + {2995.086007, 9.837875}, {2995.565568, 9.344543}, + {2996.020466, 8.851368}, {2996.450709, 8.358350}, + {2996.856305, 7.865487}, {2997.237261, 7.372779}, + {2997.593586, 6.880223}, {2997.925287, 6.387819}, + {2998.232372, 5.895565}, {2998.514848, 5.403462}, + {2998.772722, 4.911507}, {2999.006002, 4.419700}, + {2999.214696, 3.928041}, {2999.398810, 3.436528}, + {2999.558352, 2.945161}, {2999.693330, 2.453940}, + {2999.803750, 1.962863}, {2999.889620, 1.471931}, + {2999.950946, 0.981144}, {2999.987737, 0.490500}, + {2999.998745, 0.156943}, {2999.999950, 0.031348}, + {2999.999998, 0.006229}, {3000.000000, 0.001206}, + {3000.000000, 0.000201}, {3000.000000, 0.000000}, + }}, + {395, + { + {905.722649, 250.000000}, {905.722649, 250.000000}, + {905.722649, 250.000000}, {915.489801, 249.123798}, + {927.918178, 248.011271}, {940.291097, 246.905506}, + {952.608895, 245.806396}, {964.871901, 244.713839}, + {977.080440, 243.627733}, {989.234833, 242.547983}, + {1001.335395, 241.474492}, {1013.382436, 240.407170}, + {1025.376264, 239.345927}, {1037.317179, 238.290676}, + {1049.205479, 237.241332}, {1061.041458, 236.197812}, + {1072.825404, 235.160037}, {1084.557603, 234.127926}, + {1096.238336, 233.101404}, {1107.867881, 232.080396}, + {1119.446512, 231.064828}, {1130.974498, 230.054630}, + {1142.452107, 229.049730}, {1153.879602, 228.050061}, + {1165.257242, 227.055556}, {1176.585285, 226.066149}, + {1187.863983, 225.081776}, {1199.093587, 224.102374}, + {1210.274343, 223.127882}, {1221.406496, 222.158239}, + {1232.490287, 221.193387}, {1243.525953, 220.233266}, + {1254.513731, 219.277821}, {1265.453851, 218.326995}, + {1276.346544, 217.380733}, {1287.192037, 216.438981}, + {1297.990554, 215.501688}, {1308.742316, 214.568799}, + {1319.447543, 213.640265}, {1330.106450, 212.716036}, + {1340.719252, 211.796061}, {1351.286161, 210.880293}, + {1361.807386, 209.968683}, {1372.283132, 209.061186}, + {1382.713606, 208.157753}, {1393.099008, 207.258341}, + {1403.439539, 206.362905}, {1413.735397, 205.471400}, + {1423.986777, 204.583782}, {1434.193871, 203.700011}, + {1444.356873, 202.820043}, {1454.475970, 201.943837}, + {1464.551350, 201.071352}, {1474.583197, 200.202549}, + {1484.571695, 199.337388}, {1494.517026, 198.475829}, + {1504.419368, 197.617835}, {1514.278898, 196.763368}, + {1524.095792, 195.912390}, {1533.870223, 195.064864}, + {1543.602363, 194.220755}, {1553.292383, 193.380027}, + {1562.940450, 192.542645}, {1572.546730, 191.708573}, + {1582.111389, 190.877778}, {1591.634589, 190.050226}, + {1601.116492, 189.225883}, {1610.557257, 188.404717}, + {1619.957042, 187.586696}, {1629.316004, 186.771787}, + {1638.634298, 185.959960}, {1647.912076, 185.151182}, + {1657.149491, 184.345423}, {1666.346693, 183.542653}, + {1675.503831, 182.742843}, {1684.621051, 181.945962}, + {1693.698499, 181.151981}, {1702.736321, 180.360873}, + {1711.734658, 179.572607}, {1720.693652, 178.787158}, + {1729.613443, 178.004496}, {1738.494171, 177.224596}, + {1747.335971, 176.447429}, {1756.138981, 175.672969}, + {1764.903335, 174.901191}, {1773.629167, 174.132067}, + {1782.316608, 173.365574}, {1790.965789, 172.601684}, + {1799.576841, 171.840375}, {1808.149890, 171.081620}, + {1816.685066, 170.325395}, {1825.182493, 169.571678}, + {1833.642296, 168.820443}, {1842.064598, 168.071668}, + {1850.449523, 167.325329}, {1858.797192, 166.581404}, + {1867.107724, 165.839870}, {1875.381238, 165.100704}, + {1883.617853, 164.363886}, {1891.817685, 163.629392}, + {1899.980849, 162.897201}, {1908.107462, 162.167293}, + {1916.197635, 161.439647}, {1924.251482, 160.714241}, + {1932.269115, 159.991054}, {1940.250643, 159.270068}, + {1948.196176, 158.551262}, {1956.105823, 157.834615}, + {1963.979691, 157.120110}, {1971.817887, 156.407725}, + {1979.620516, 155.697443}, {1987.387683, 154.989244}, + {1995.119492, 154.283110}, {2002.816046, 153.579022}, + {2010.477445, 152.876961}, {2018.103792, 152.176911}, + {2025.695186, 151.478854}, {2033.251727, 150.782771}, + {2040.773512, 150.088645}, {2048.260640, 149.396459}, + {2055.713206, 148.706196}, {2063.131307, 148.017839}, + {2070.515037, 147.331372}, {2077.864491, 146.646778}, + {2085.179761, 145.964041}, {2092.460941, 145.283144}, + {2099.708121, 144.604072}, {2106.921393, 143.926809}, + {2114.100847, 143.251340}, {2121.246572, 142.577649}, + {2128.358656, 141.905721}, {2135.437188, 141.235540}, + {2142.482253, 140.567092}, {2149.493940, 139.900362}, + {2156.472332, 139.235336}, {2163.417516, 138.571999}, + {2170.329574, 137.910336}, {2177.208591, 137.250334}, + {2184.054649, 136.591979}, {2190.867829, 135.935256}, + {2197.648215, 135.280152}, {2204.395885, 134.626654}, + {2211.110920, 133.974748}, {2217.793399, 133.324420}, + {2224.443401, 132.675658}, {2231.061004, 132.028448}, + {2237.646284, 131.382778}, {2244.199320, 130.738635}, + {2250.720186, 130.096006}, {2257.208958, 129.454878}, + {2263.665711, 128.815240}, {2270.090519, 128.177078}, + {2276.483455, 127.540382}, {2282.844593, 126.905138}, + {2289.174005, 126.271335}, {2295.471762, 125.638961}, + {2301.737937, 125.008004}, {2307.972598, 124.378453}, + {2314.175817, 123.750296}, {2320.347662, 123.123522}, + {2326.488203, 122.498119}, {2332.597508, 121.874077}, + {2338.675645, 121.251384}, {2344.722680, 120.630029}, + {2350.738681, 120.010002}, {2356.723713, 119.391292}, + {2362.677843, 118.773888}, {2368.601134, 118.157779}, + {2374.493653, 117.542956}, {2380.355462, 116.929407}, + {2386.186625, 116.317122}, {2391.987205, 115.706092}, + {2397.757265, 115.096305}, {2403.496867, 114.487753}, + {2409.206071, 113.880425}, {2414.884939, 113.274310}, + {2420.533532, 112.669401}, {2426.151909, 112.065686}, + {2431.740130, 111.463156}, {2437.298254, 110.861802}, + {2442.826340, 110.261614}, {2448.324445, 109.662583}, + {2453.792627, 109.064699}, {2459.230943, 108.467954}, + {2464.639450, 107.872338}, {2470.018205, 107.277842}, + {2475.367262, 106.684457}, {2480.686678, 106.092174}, + {2485.976507, 105.500985}, {2491.236804, 104.910880}, + {2496.467622, 104.321851}, {2501.669016, 103.733890}, + {2506.841037, 103.146987}, {2511.983740, 102.561134}, + {2517.097177, 101.976323}, {2522.181399, 101.392545}, + {2527.236457, 100.809792}, {2532.262403, 100.228056}, + {2537.259288, 99.647328}, {2542.227161, 99.067601}, + {2547.166073, 98.488866}, {2552.076072, 97.911116}, + {2556.957209, 97.334342}, {2561.809531, 96.758536}, + {2566.633086, 96.183691}, {2571.427924, 95.609799}, + {2576.194090, 95.036853}, {2580.931632, 94.464843}, + {2585.640598, 93.893764}, {2590.321032, 93.323607}, + {2594.972981, 92.754365}, {2599.596491, 92.186030}, + {2604.191607, 91.618595}, {2608.758373, 91.052053}, + {2613.296834, 90.486396}, {2617.807034, 89.921617}, + {2622.289017, 89.357709}, {2626.742827, 88.794664}, + {2631.168505, 88.232476}, {2635.566096, 87.671138}, + {2639.935640, 87.110643}, {2644.277181, 86.550983}, + {2648.590759, 85.992151}, {2652.876416, 85.434142}, + {2657.134194, 84.876947}, {2661.364131, 84.320560}, + {2665.566270, 83.764975}, {2669.740649, 83.210185}, + {2673.887308, 82.656183}, {2678.006287, 82.102962}, + {2682.097623, 81.550516}, {2686.161357, 80.998839}, + {2690.197526, 80.447923}, {2694.206169, 79.897763}, + {2698.187321, 79.348352}, {2702.141022, 78.799684}, + {2706.067308, 78.251752}, {2709.966216, 77.704550}, + {2713.837781, 77.158072}, {2717.682041, 76.612312}, + {2721.499030, 76.067263}, {2725.288785, 75.522919}, + {2729.051340, 74.979274}, {2732.786730, 74.436323}, + {2736.494989, 73.894059}, {2740.176153, 73.352476}, + {2743.830254, 72.811568}, {2747.457326, 72.271329}, + {2751.057403, 71.731754}, {2754.630518, 71.192836}, + {2758.176703, 70.654570}, {2761.695991, 70.116950}, + {2765.188414, 69.579970}, {2768.654004, 69.043625}, + {2772.092792, 68.507908}, {2775.504810, 67.972815}, + {2778.890089, 67.438339}, {2782.248660, 66.904475}, + {2785.580552, 66.371217}, {2788.885796, 65.838560}, + {2792.164423, 65.306499}, {2795.416461, 64.775028}, + {2798.641940, 64.244141}, {2801.840889, 63.713833}, + {2805.013338, 63.184099}, {2808.159314, 62.654933}, + {2811.278845, 62.126331}, {2814.371961, 61.598286}, + {2817.438688, 61.070794}, {2820.479054, 60.543849}, + {2823.493086, 60.017447}, {2826.480812, 59.491581}, + {2829.442257, 58.966248}, {2832.377450, 58.441441}, + {2835.286415, 57.917156}, {2838.169178, 57.393388}, + {2841.025766, 56.870131}, {2843.856204, 56.347381}, + {2846.660517, 55.825133}, {2849.438730, 55.303382}, + {2852.190867, 54.782122}, {2854.916954, 54.261350}, + {2857.617014, 53.741059}, {2860.291072, 53.221247}, + {2862.939151, 52.701906}, {2865.561274, 52.183034}, + {2868.157466, 51.664624}, {2870.727748, 51.146673}, + {2873.272144, 50.629176}, {2875.790677, 50.112127}, + {2878.283368, 49.595523}, {2880.750240, 49.079359}, + {2883.191315, 48.563630}, {2885.606614, 48.048331}, + {2887.996159, 47.533459}, {2890.359970, 47.019008}, + {2892.698070, 46.504974}, {2895.010478, 45.991353}, + {2897.297215, 45.478140}, {2899.558302, 44.965331}, + {2901.793759, 44.452921}, {2904.003604, 43.940907}, + {2906.187859, 43.429283}, {2908.346542, 42.918046}, + {2910.479673, 42.407190}, {2912.587271, 41.896713}, + {2914.669354, 41.386610}, {2916.725941, 40.876876}, + {2918.757050, 40.367508}, {2920.762701, 39.858501}, + {2922.742909, 39.349851}, {2924.697695, 38.841554}, + {2926.627074, 38.333606}, {2928.531064, 37.826003}, + {2930.409682, 37.318740}, {2932.262946, 36.811815}, + {2934.090872, 36.305223}, {2935.893477, 35.798960}, + {2937.670776, 35.293022}, {2939.422787, 34.787406}, + {2941.149525, 34.282107}, {2942.851006, 33.777121}, + {2944.527245, 33.272446}, {2946.178258, 32.768077}, + {2947.804060, 32.264010}, {2949.404666, 31.760241}, + {2950.980091, 31.256768}, {2952.530350, 30.753586}, + {2954.055457, 30.250692}, {2955.555427, 29.748082}, + {2957.030272, 29.245753}, {2958.480009, 28.743701}, + {2959.904649, 28.241922}, {2961.304208, 27.740414}, + {2962.678697, 27.239173}, {2964.028132, 26.738195}, + {2965.352523, 26.237477}, {2966.651886, 25.737016}, + {2967.926231, 25.236808}, {2969.175573, 24.736851}, + {2970.399923, 24.237140}, {2971.599293, 23.737674}, + {2972.773696, 23.238448}, {2973.923144, 22.739460}, + {2975.047648, 22.240707}, {2976.147220, 21.742185}, + {2977.221872, 21.243892}, {2978.271615, 20.745825}, + {2979.296460, 20.247981}, {2980.296419, 19.750357}, + {2981.271501, 19.252950}, {2982.221719, 18.755757}, + {2983.147082, 18.258777}, {2984.047602, 17.762005}, + {2984.923288, 17.265440}, {2985.774151, 16.769080}, + {2986.600201, 16.272921}, {2987.401448, 15.776961}, + {2988.177902, 15.281197}, {2988.929573, 14.785629}, + {2989.656470, 14.290252}, {2990.358603, 13.795065}, + {2991.035981, 13.300067}, {2991.688614, 12.805254}, + {2992.316511, 12.310624}, {2992.919681, 11.816176}, + {2993.498133, 11.321908}, {2994.051876, 10.827818}, + {2994.580919, 10.333905}, {2995.085271, 9.840165}, + {2995.564940, 9.346599}, {2996.019935, 8.853203}, + {2996.450265, 8.359978}, {2996.855937, 7.866920}, + {2997.236961, 7.374030}, {2997.593344, 6.881305}, + {2997.925095, 6.388745}, {2998.232223, 5.896347}, + {2998.514734, 5.404112}, {2998.772638, 4.912038}, + {2999.005942, 4.420125}, {2999.214654, 3.928371}, + {2999.398783, 3.436775}, {2999.558336, 2.945337}, + {2999.693321, 2.454057}, {2999.803746, 1.962934}, + {2999.889618, 1.471967}, {2999.950946, 0.981155}, + {2999.987737, 0.490500}, {2999.998745, 0.156943}, + {2999.999950, 0.031348}, {2999.999998, 0.006229}, + {3000.000000, 0.001206}, {3000.000000, 0.000201}, + {3000.000000, 0.000000}, + }}, + {385, + { + {986.524002, 250.000000}, {986.524002, 250.000000}, + {991.725533, 249.488842}, {1004.169530, 248.271036}, + {1016.552865, 247.062377}, {1028.875992, 245.862696}, + {1041.139355, 244.671826}, {1053.343391, 243.489608}, + {1065.488528, 242.315888}, {1077.575188, 241.150514}, + {1089.603784, 239.993341}, {1101.574724, 238.844228}, + {1113.488405, 237.703035}, {1125.345222, 236.569631}, + {1137.145560, 235.443884}, {1148.889799, 234.325668}, + {1160.578312, 233.214860}, {1172.211467, 232.111339}, + {1183.789625, 231.014989}, {1195.313142, 229.925695}, + {1206.782368, 228.843347}, {1218.197648, 227.767836}, + {1229.559320, 226.699056}, {1240.867719, 225.636904}, + {1252.123174, 224.581280}, {1263.326008, 223.532083}, + {1274.476540, 222.489220}, {1285.575086, 221.452595}, + {1296.621953, 220.422116}, {1307.617449, 219.397694}, + {1318.561872, 218.379240}, {1329.455520, 217.366670}, + {1340.298684, 216.359898}, {1351.091652, 215.358842}, + {1361.834709, 214.363421}, {1372.528134, 213.373558}, + {1383.172202, 212.389173}, {1393.767186, 211.410192}, + {1404.313354, 210.436540}, {1414.810971, 209.468145}, + {1425.260298, 208.504934}, {1435.661593, 207.546839}, + {1446.015108, 206.593791}, {1456.321096, 205.645721}, + {1466.579803, 204.702566}, {1476.791474, 203.764259}, + {1486.956349, 202.830737}, {1497.074666, 201.901938}, + {1507.146659, 200.977801}, {1517.172561, 200.058266}, + {1527.152599, 199.143274}, {1537.087001, 198.232767}, + {1546.975987, 197.326688}, {1556.819779, 196.424982}, + {1566.618593, 195.527594}, {1576.372645, 194.634469}, + {1586.082145, 193.745555}, {1595.747304, 192.860801}, + {1605.368328, 191.980154}, {1614.945421, 191.103566}, + {1624.478785, 190.230985}, {1633.968619, 189.362366}, + {1643.415119, 188.497658}, {1652.818481, 187.636816}, + {1662.178896, 186.779794}, {1671.496555, 185.926546}, + {1680.771644, 185.077028}, {1690.004350, 184.231196}, + {1699.194855, 183.389007}, {1708.343340, 182.550419}, + {1717.449986, 181.715389}, {1726.514967, 180.883877}, + {1735.538460, 180.055843}, {1744.520638, 179.231247}, + {1753.461670, 178.410049}, {1762.361726, 177.592212}, + {1771.220974, 176.777697}, {1780.039578, 175.966468}, + {1788.817702, 175.158487}, {1797.555507, 174.353718}, + {1806.253153, 173.552127}, {1814.910799, 172.753677}, + {1823.528599, 171.958335}, {1832.106709, 171.166067}, + {1840.645282, 170.376839}, {1849.144468, 169.590618}, + {1857.604418, 168.807372}, {1866.025279, 168.027069}, + {1874.407197, 167.249677}, {1882.750319, 166.475166}, + {1891.054785, 165.703504}, {1899.320739, 164.934663}, + {1907.548321, 164.168612}, {1915.737670, 163.405322}, + {1923.888922, 162.644764}, {1932.002214, 161.886910}, + {1940.077680, 161.131732}, {1948.115453, 160.379203}, + {1956.115666, 159.629294}, {1964.078447, 158.881980}, + {1972.003928, 158.137234}, {1979.892234, 157.395030}, + {1987.743494, 156.655342}, {1995.557831, 155.918145}, + {2003.335370, 155.183414}, {2011.076233, 154.451124}, + {2018.780543, 153.721252}, {2026.448418, 152.993772}, + {2034.079979, 152.268662}, {2041.675343, 151.545898}, + {2049.234627, 150.825457}, {2056.757946, 150.107317}, + {2064.245416, 149.391454}, {2071.697148, 148.677848}, + {2079.113256, 147.966475}, {2086.493851, 147.257315}, + {2093.839043, 146.550347}, {2101.148940, 145.845549}, + {2108.423651, 145.142900}, {2115.663283, 144.442380}, + {2122.867942, 143.743970}, {2130.037732, 143.047648}, + {2137.172758, 142.353396}, {2144.273123, 141.661194}, + {2151.338929, 140.971023}, {2158.370276, 140.282863}, + {2165.367265, 139.596697}, {2172.329995, 138.912505}, + {2179.258564, 138.230269}, {2186.153070, 137.549972}, + {2193.013609, 136.871596}, {2199.840277, 136.195122}, + {2206.633169, 135.520533}, {2213.392377, 134.847813}, + {2220.117996, 134.176944}, {2226.810118, 133.507910}, + {2233.468833, 132.840693}, {2240.094232, 132.175278}, + {2246.686405, 131.511648}, {2253.245441, 130.849788}, + {2259.771428, 130.189681}, {2266.264453, 129.531311}, + {2272.724602, 128.874664}, {2279.151962, 128.219723}, + {2285.546617, 127.566474}, {2291.908651, 126.914902}, + {2298.238148, 126.264992}, {2304.535191, 125.616729}, + {2310.799862, 124.970099}, {2317.032242, 124.325087}, + {2323.232411, 123.681679}, {2329.400449, 123.039861}, + {2335.536436, 122.399620}, {2341.640450, 121.760941}, + {2347.712569, 121.123811}, {2353.752870, 120.488217}, + {2359.761429, 119.854144}, {2365.738322, 119.221581}, + {2371.683624, 118.590513}, {2377.597410, 117.960928}, + {2383.479754, 117.332813}, {2389.330728, 116.706156}, + {2395.150406, 116.080944}, {2400.938858, 115.457164}, + {2406.696158, 114.834805}, {2412.422374, 114.213853}, + {2418.117578, 113.594297}, {2423.781838, 112.976126}, + {2429.415225, 112.359326}, {2435.017805, 111.743888}, + {2440.589647, 111.129797}, {2446.130818, 110.517045}, + {2451.641385, 109.905618}, {2457.121413, 109.295506}, + {2462.570968, 108.686697}, {2467.990115, 108.079181}, + {2473.378918, 107.472946}, {2478.737441, 106.867982}, + {2484.065748, 106.264278}, {2489.363900, 105.661823}, + {2494.631961, 105.060606}, {2499.869992, 104.460617}, + {2505.078053, 103.861845}, {2510.256206, 103.264281}, + {2515.404511, 102.667914}, {2520.523027, 102.072734}, + {2525.611814, 101.478730}, {2530.670930, 100.885894}, + {2535.700432, 100.294214}, {2540.700380, 99.703681}, + {2545.670829, 99.114286}, {2550.611836, 98.526018}, + {2555.523459, 97.938869}, {2560.405751, 97.352828}, + {2565.258769, 96.767887}, {2570.082567, 96.184035}, + {2574.877199, 95.601264}, {2579.642720, 95.019565}, + {2584.379183, 94.438928}, {2589.086639, 93.859344}, + {2593.765143, 93.280804}, {2598.414746, 92.703300}, + {2603.035499, 92.126823}, {2607.627453, 91.551363}, + {2612.190660, 90.976912}, {2616.725170, 90.403462}, + {2621.231031, 89.831004}, {2625.708295, 89.259529}, + {2630.157008, 88.689028}, {2634.577222, 88.119495}, + {2638.968982, 87.550919}, {2643.332337, 86.983294}, + {2647.667335, 86.416610}, {2651.974022, 85.850860}, + {2656.252444, 85.286035}, {2660.502648, 84.722128}, + {2664.724679, 84.159130}, {2668.918584, 83.597034}, + {2673.084405, 83.035831}, {2677.222189, 82.475514}, + {2681.331979, 81.916076}, {2685.413818, 81.357508}, + {2689.467751, 80.799803}, {2693.493820, 80.242953}, + {2697.492067, 79.686950}, {2701.462536, 79.131788}, + {2705.405267, 78.577459}, {2709.320302, 78.023955}, + {2713.207683, 77.471269}, {2717.067450, 76.919394}, + {2720.899642, 76.368322}, {2724.704302, 75.818047}, + {2728.481467, 75.268560}, {2732.231177, 74.719856}, + {2735.953472, 74.171927}, {2739.648389, 73.624766}, + {2743.315967, 73.078365}, {2746.956244, 72.532719}, + {2750.569258, 71.987821}, {2754.155045, 71.443662}, + {2757.713643, 70.900237}, {2761.245087, 70.357540}, + {2764.749415, 69.815562}, {2768.226661, 69.274298}, + {2771.676862, 68.733741}, {2775.100053, 68.193884}, + {2778.496268, 67.654721}, {2781.865542, 67.116245}, + {2785.207909, 66.578450}, {2788.523404, 66.041330}, + {2791.812059, 65.504878}, {2795.073908, 64.969088}, + {2798.308984, 64.433953}, {2801.517320, 63.899467}, + {2804.698947, 63.365624}, {2807.853898, 62.832418}, + {2810.982204, 62.299843}, {2814.083898, 61.767893}, + {2817.159009, 61.236561}, {2820.207569, 60.705841}, + {2823.229609, 60.175728}, {2826.225157, 59.646216}, + {2829.194245, 59.117298}, {2832.136902, 58.588970}, + {2835.053157, 58.061224}, {2837.943038, 57.534055}, + {2840.806576, 57.007457}, {2843.643798, 56.481425}, + {2846.454733, 55.955953}, {2849.239407, 55.431035}, + {2851.997850, 54.906666}, {2854.730088, 54.382840}, + {2857.436147, 53.859551}, {2860.116056, 53.336794}, + {2862.769840, 52.814563}, {2865.397525, 52.292854}, + {2867.999138, 51.771659}, {2870.574704, 51.250975}, + {2873.124248, 50.730796}, {2875.647796, 50.211116}, + {2878.145372, 49.691930}, {2880.617001, 49.173233}, + {2883.062708, 48.655019}, {2885.482515, 48.137284}, + {2887.876448, 47.620021}, {2890.244529, 47.103227}, + {2892.586782, 46.586896}, {2894.903230, 46.071023}, + {2897.193896, 45.555602}, {2899.458802, 45.040629}, + {2901.697970, 44.526099}, {2903.911422, 44.012007}, + {2906.099181, 43.498348}, {2908.261268, 42.985116}, + {2910.397703, 42.472308}, {2912.508509, 41.959918}, + {2914.593706, 41.447942}, {2916.653314, 40.936375}, + {2918.687353, 40.425212}, {2920.695845, 39.914448}, + {2922.678808, 39.404078}, {2924.636262, 38.894099}, + {2926.568227, 38.384505}, {2928.474722, 37.875293}, + {2930.355766, 37.366456}, {2932.211377, 36.857991}, + {2934.041574, 36.349894}, {2935.846376, 35.842160}, + {2937.625799, 35.334784}, {2939.379863, 34.827763}, + {2941.108584, 34.321091}, {2942.811981, 33.814765}, + {2944.490069, 33.308780}, {2946.142867, 32.803132}, + {2947.770391, 32.297817}, {2949.372657, 31.792830}, + {2950.949682, 31.288168}, {2952.501482, 30.783826}, + {2954.028072, 30.279801}, {2955.529470, 29.776088}, + {2957.005689, 29.272684}, {2958.456746, 28.769584}, + {2959.882655, 28.266784}, {2961.283432, 27.764281}, + {2962.659090, 27.262071}, {2964.009646, 26.760150}, + {2965.335113, 26.258514}, {2966.635504, 25.757160}, + {2967.910835, 25.256083}, {2969.161120, 24.755281}, + {2970.386370, 24.254749}, {2971.586601, 23.754485}, + {2972.761825, 23.254484}, {2973.912056, 22.754743}, + {2975.037306, 22.255259}, {2976.137588, 21.756029}, + {2977.212915, 21.257048}, {2978.263299, 20.758315}, + {2979.288753, 20.259825}, {2980.289288, 19.761575}, + {2981.264916, 19.263563}, {2982.215650, 18.765785}, + {2983.141501, 18.268239}, {2984.042480, 17.770921}, + {2984.918598, 17.273828}, {2985.769868, 16.776958}, + {2986.596300, 16.280308}, {2987.397904, 15.783875}, + {2988.174692, 15.287657}, {2988.926675, 14.791650}, + {2989.653863, 14.295853}, {2990.356266, 13.800263}, + {2991.033894, 13.304877}, {2991.686758, 12.809694}, + {2992.314868, 12.314710}, {2992.918234, 11.819924}, + {2993.496866, 11.325334}, {2994.050773, 10.830937}, + {2994.579964, 10.336732}, {2995.084451, 9.842717}, + {2995.564241, 9.348889}, {2996.019344, 8.855248}, + {2996.449770, 8.361791}, {2996.855528, 7.868516}, + {2997.236626, 7.375423}, {2997.593075, 6.882510}, + {2997.924882, 6.389776}, {2998.232057, 5.897218}, + {2998.514608, 5.404837}, {2998.772545, 4.912630}, + {2999.005875, 4.420597}, {2999.214609, 3.928738}, + {2999.398753, 3.437050}, {2999.558318, 2.945534}, + {2999.693311, 2.454188}, {2999.803741, 1.963012}, + {2999.889616, 1.472006}, {2999.950946, 0.981168}, + {2999.987737, 0.490500}, {2999.998745, 0.156943}, + {2999.999950, 0.031348}, {2999.999998, 0.006229}, + {3000.000000, 0.001206}, {3000.000000, 0.000201}, + {3000.000000, 0.000000}, + }}, + {376, + { + {1065.277806, 250.000000}, {1065.277806, 250.000000}, + {1066.951150, 249.819943}, {1079.408842, 248.487728}, + {1091.800225, 247.167577}, {1104.125895, 245.859231}, + {1116.386437, 244.562438}, {1128.582421, 243.276955}, + {1140.714409, 242.002548}, {1152.782947, 240.738988}, + {1164.788574, 239.486057}, {1176.731813, 238.243540}, + {1188.613183, 237.011230}, {1200.433187, 235.788929}, + {1212.192321, 234.576440}, {1223.891071, 233.373576}, + {1235.529914, 232.180153}, {1247.109318, 230.995994}, + {1258.629741, 229.820925}, {1270.091634, 228.654779}, + {1281.495438, 227.497393}, {1292.841588, 226.348606}, + {1304.130510, 225.208266}, {1315.362622, 224.076221}, + {1326.538336, 222.952324}, {1337.658055, 221.836434}, + {1348.722176, 220.728411}, {1359.731089, 219.628120}, + {1370.685178, 218.535429}, {1381.584819, 217.450208}, + {1392.430382, 216.372333}, {1403.222232, 215.301680}, + {1413.960728, 214.238132}, {1424.646220, 213.181570}, + {1435.279057, 212.131881}, {1445.859577, 211.088954}, + {1456.388118, 210.052680}, {1466.865009, 209.022953}, + {1477.290575, 207.999671}, {1487.665135, 206.982731}, + {1497.989004, 205.972035}, {1508.262492, 204.967485}, + {1518.485904, 203.968988}, {1528.659540, 202.976452}, + {1538.783696, 201.989785}, {1548.858663, 201.008899}, + {1558.884728, 200.033708}, {1568.862174, 199.064127}, + {1578.791279, 198.100074}, {1588.672317, 197.141467}, + {1598.505560, 196.188226}, {1608.291272, 195.240275}, + {1618.029718, 194.297537}, {1627.721154, 193.359938}, + {1637.365838, 192.427405}, {1646.964020, 191.499865}, + {1656.515948, 190.577250}, {1666.021866, 189.659490}, + {1675.482016, 188.746519}, {1684.896636, 187.838270}, + {1694.265960, 186.934679}, {1703.590219, 186.035682}, + {1712.869641, 185.141218}, {1722.104452, 184.251225}, + {1731.294874, 183.365644}, {1740.441126, 182.484417}, + {1749.543423, 181.607485}, {1758.601980, 180.734792}, + {1767.617007, 179.866284}, {1776.588712, 179.001905}, + {1785.517300, 178.141604}, {1794.402973, 177.285326}, + {1803.245931, 176.433022}, {1812.046373, 175.584641}, + {1820.804492, 174.740133}, {1829.520482, 173.899449}, + {1838.194532, 173.062543}, {1846.826830, 172.229368}, + {1855.417561, 171.399877}, {1863.966908, 170.574025}, + {1872.475053, 169.751768}, {1880.942174, 168.933062}, + {1889.368447, 168.117865}, {1897.754047, 167.306135}, + {1906.099146, 166.497829}, {1914.403914, 165.692908}, + {1922.668520, 164.891332}, {1930.893130, 164.093061}, + {1939.077908, 163.298057}, {1947.223017, 162.506281}, + {1955.328616, 161.717697}, {1963.394865, 160.932268}, + {1971.421921, 160.149957}, {1979.409938, 159.370730}, + {1987.359070, 158.594550}, {1995.269468, 157.821385}, + {2003.141283, 157.051199}, {2010.974662, 156.283960}, + {2018.769752, 155.519636}, {2026.526698, 154.758193}, + {2034.245642, 153.999600}, {2041.926728, 153.243826}, + {2049.570095, 152.490840}, {2057.175881, 151.740613}, + {2064.744224, 150.993113}, {2072.275260, 150.248312}, + {2079.769122, 149.506181}, {2087.225944, 148.766692}, + {2094.645857, 148.029816}, {2102.028990, 147.295525}, + {2109.375473, 146.563794}, {2116.685433, 145.834594}, + {2123.958995, 145.107900}, {2131.196285, 144.383685}, + {2138.397425, 143.661924}, {2145.562538, 142.942591}, + {2152.691744, 142.225662}, {2159.785164, 141.511112}, + {2166.842914, 140.798917}, {2173.865114, 140.089053}, + {2180.851877, 139.381496}, {2187.803320, 138.676223}, + {2194.719556, 137.973212}, {2201.600698, 137.272440}, + {2208.446856, 136.573883}, {2215.258141, 135.877522}, + {2222.034662, 135.183333}, {2228.776528, 134.491295}, + {2235.483845, 133.801388}, {2242.156719, 133.113590}, + {2248.795256, 132.427882}, {2255.399559, 131.744241}, + {2261.969732, 131.062650}, {2268.505875, 130.383087}, + {2275.008090, 129.705533}, {2281.476478, 129.029969}, + {2287.911137, 128.356377}, {2294.312164, 127.684736}, + {2300.679659, 127.015029}, {2307.013715, 126.347237}, + {2313.314430, 125.681343}, {2319.581897, 125.017327}, + {2325.816209, 124.355174}, {2332.017460, 123.694864}, + {2338.185741, 123.036381}, {2344.321143, 122.379708}, + {2350.423757, 121.724827}, {2356.493670, 121.071723}, + {2362.530973, 120.420379}, {2368.535752, 119.770778}, + {2374.508094, 119.122904}, {2380.448085, 118.476742}, + {2386.355811, 117.832276}, {2392.231355, 117.189490}, + {2398.074801, 116.548369}, {2403.886233, 115.908897}, + {2409.665732, 115.271059}, {2415.413379, 114.634841}, + {2421.129256, 114.000228}, {2426.813442, 113.367206}, + {2432.466016, 112.735759}, {2438.087057, 112.105874}, + {2443.676642, 111.477536}, {2449.234849, 110.850731}, + {2454.761753, 110.225447}, {2460.257431, 109.601668}, + {2465.721957, 108.979382}, {2471.155406, 108.358574}, + {2476.557851, 107.739233}, {2481.929366, 107.121344}, + {2487.270022, 106.504894}, {2492.579891, 105.889871}, + {2497.859044, 105.276262}, {2503.107552, 104.664055}, + {2508.325484, 104.053235}, {2513.512910, 103.443793}, + {2518.669898, 102.835714}, {2523.796515, 102.228987}, + {2528.892830, 101.623600}, {2533.958908, 101.019541}, + {2538.994817, 100.416798}, {2544.000621, 99.815359}, + {2548.976385, 99.215213}, {2553.922174, 98.616348}, + {2558.838052, 98.018753}, {2563.724081, 97.422416}, + {2568.580325, 96.827326}, {2573.406844, 96.233473}, + {2578.203702, 95.640845}, {2582.970959, 95.049430}, + {2587.708676, 94.459220}, {2592.416911, 93.870201}, + {2597.095725, 93.282365}, {2601.745177, 92.695700}, + {2606.365324, 92.110197}, {2610.956225, 91.525843}, + {2615.517937, 90.942630}, {2620.050517, 90.360547}, + {2624.554020, 89.779584}, {2629.028503, 89.199731}, + {2633.474021, 88.620978}, {2637.890628, 88.043315}, + {2642.278379, 87.466733}, {2646.637328, 86.891220}, + {2650.967528, 86.316769}, {2655.269031, 85.743369}, + {2659.541891, 85.171011}, {2663.786158, 84.599685}, + {2668.001885, 84.029383}, {2672.189122, 83.460094}, + {2676.347919, 82.891810}, {2680.478327, 82.324521}, + {2684.580396, 81.758218}, {2688.654174, 81.192893}, + {2692.699709, 80.628537}, {2696.717051, 80.065140}, + {2700.706247, 79.502693}, {2704.667344, 78.941189}, + {2708.600389, 78.380618}, {2712.505429, 77.820972}, + {2716.382510, 77.262242}, {2720.231676, 76.704420}, + {2724.052974, 76.147497}, {2727.846448, 75.591465}, + {2731.612143, 75.036316}, {2735.350101, 74.482041}, + {2739.060368, 73.928632}, {2742.742986, 73.376081}, + {2746.397998, 72.824380}, {2750.025445, 72.273522}, + {2753.625371, 71.723497}, {2757.197816, 71.174298}, + {2760.742821, 70.625918}, {2764.260428, 70.078348}, + {2767.750676, 69.531581}, {2771.213606, 68.985609}, + {2774.649256, 68.440424}, {2778.057667, 67.896019}, + {2781.438878, 67.352387}, {2784.792925, 66.809519}, + {2788.119848, 66.267408}, {2791.419685, 65.726048}, + {2794.692472, 65.185430}, {2797.938246, 64.645547}, + {2801.157045, 64.106393}, {2804.348903, 63.567959}, + {2807.513858, 63.030239}, {2810.651945, 62.493226}, + {2813.763199, 61.956913}, {2816.847654, 61.421292}, + {2819.905345, 60.886357}, {2822.936306, 60.352101}, + {2825.940572, 59.818516}, {2828.918175, 59.285597}, + {2831.869148, 58.753336}, {2834.793524, 58.221726}, + {2837.691337, 57.690762}, {2840.562617, 57.160436}, + {2843.407396, 56.630741}, {2846.225706, 56.101671}, + {2849.017579, 55.573220}, {2851.783044, 55.045382}, + {2854.522132, 54.518148}, {2857.234873, 53.991515}, + {2859.921298, 53.465474}, {2862.581436, 52.940019}, + {2865.215315, 52.415146}, {2867.822964, 51.890846}, + {2870.404413, 51.367114}, {2872.959690, 50.843944}, + {2875.488822, 50.321330}, {2877.991837, 49.799265}, + {2880.468762, 49.277744}, {2882.919624, 48.756761}, + {2885.344451, 48.236310}, {2887.743269, 47.716384}, + {2890.116103, 47.196978}, {2892.462979, 46.678086}, + {2894.783924, 46.159703}, {2897.078962, 45.641822}, + {2899.348119, 45.124439}, {2901.591418, 44.607546}, + {2903.808885, 44.091139}, {2906.000544, 43.575212}, + {2908.166418, 43.059759}, {2910.306532, 42.544775}, + {2912.420908, 42.030255}, {2914.509569, 41.516193}, + {2916.572538, 41.002583}, {2918.609838, 40.489421}, + {2920.621491, 39.976700}, {2922.607519, 39.464416}, + {2924.567944, 38.952564}, {2926.502786, 38.441137}, + {2928.412068, 37.930132}, {2930.295810, 37.419542}, + {2932.154032, 36.909364}, {2933.986756, 36.399591}, + {2935.794001, 35.890218}, {2937.575788, 35.381242}, + {2939.332135, 34.872656}, {2941.063063, 34.364456}, + {2942.768591, 33.856637}, {2944.448736, 33.349195}, + {2946.103519, 32.842123}, {2947.732958, 32.335419}, + {2949.337070, 31.829077}, {2950.915874, 31.323092}, + {2952.469388, 30.817459}, {2953.997629, 30.312175}, + {2955.500614, 29.807235}, {2956.978361, 29.302634}, + {2958.430886, 28.798368}, {2959.858206, 28.294432}, + {2961.260337, 27.790822}, {2962.637296, 27.287534}, + {2963.989099, 26.784563}, {2965.315761, 26.281906}, + {2966.617297, 25.779558}, {2967.893724, 25.277514}, + {2969.145056, 24.775772}, {2970.371309, 24.274327}, + {2971.572496, 23.773175}, {2972.748633, 23.272311}, + {2973.899734, 22.771733}, {2975.025814, 22.271437}, + {2976.126885, 21.771418}, {2977.202962, 21.271673}, + {2978.254059, 20.772198}, {2979.280189, 20.272990}, + {2980.281365, 19.774045}, {2981.257600, 19.275360}, + {2982.208907, 18.776931}, {2983.135299, 18.278755}, + {2984.036789, 17.780829}, {2984.913388, 17.283150}, + {2985.765110, 16.785714}, {2986.591966, 16.288517}, + {2987.393967, 15.791559}, {2988.171127, 15.294834}, + {2988.923457, 14.798341}, {2989.650967, 14.302076}, + {2990.353670, 13.806037}, {2991.031576, 13.310222}, + {2991.684698, 12.814626}, {2992.313044, 12.319249}, + {2992.916628, 11.824088}, {2993.495459, 11.329139}, + {2994.049547, 10.834402}, {2994.578904, 10.339873}, + {2995.083540, 9.845551}, {2995.563464, 9.351433}, + {2996.018688, 8.857518}, {2996.449221, 8.363804}, + {2996.855073, 7.870289}, {2997.236255, 7.376971}, + {2997.592775, 6.883849}, {2997.924644, 6.390920}, + {2998.231872, 5.898185}, {2998.514468, 5.405641}, + {2998.772441, 4.913287}, {2999.005801, 4.421122}, + {2999.214558, 3.929145}, {2999.398720, 3.437355}, + {2999.558298, 2.945751}, {2999.693300, 2.454333}, + {2999.803736, 1.963099}, {2999.889615, 1.472049}, + {2999.950945, 0.981183}, {2999.987737, 0.490500}, + {2999.998745, 0.156943}, {2999.999950, 0.031348}, + {2999.999998, 0.006229}, {3000.000000, 0.001206}, + {3000.000000, 0.000201}, {3000.000000, 0.000000}, + }}, + {367, + { + {1142.065914, 250.000000}, {1142.065914, 250.000000}, + {1142.065914, 250.000000}, {1153.657448, 248.645856}, + {1166.053723, 247.205151}, {1178.378344, 245.779673}, + {1190.632062, 244.369052}, {1202.815612, 242.972931}, + {1214.929709, 241.590967}, {1226.975054, 240.222826}, + {1238.952329, 238.868189}, {1250.862203, 237.526747}, + {1262.705326, 236.198200}, {1274.482338, 234.882259}, + {1286.193860, 233.578645}, {1297.840504, 232.287087}, + {1309.422864, 231.007324}, {1320.941525, 229.739101}, + {1332.397056, 228.482174}, {1343.790018, 227.236304}, + {1355.120958, 226.001262}, {1366.390410, 224.776822}, + {1377.598899, 223.562768}, {1388.746941, 222.358890}, + {1399.835038, 221.164984}, {1410.863684, 219.980850}, + {1421.833362, 218.806296}, {1432.744548, 217.641134}, + {1443.597706, 216.485184}, {1454.393292, 215.338268}, + {1465.131754, 214.200213}, {1475.813531, 213.070854}, + {1486.439053, 211.950026}, {1497.008743, 210.837572}, + {1507.523016, 209.733338}, {1517.982278, 208.637173}, + {1528.386931, 207.548932}, {1538.737366, 206.468473}, + {1549.033969, 205.395657}, {1559.277120, 204.330348}, + {1569.467189, 203.272416}, {1579.604542, 202.221732}, + {1589.689540, 201.178171}, {1599.722534, 200.141611}, + {1609.703873, 199.111934}, {1619.633897, 198.089024}, + {1629.512942, 197.072767}, {1639.341337, 196.063053}, + {1649.119408, 195.059775}, {1658.847473, 194.062826}, + {1668.525846, 193.072106}, {1678.154837, 192.087512}, + {1687.734748, 191.108948}, {1697.265880, 190.136318}, + {1706.748526, 189.169529}, {1716.182977, 188.208489}, + {1725.569517, 187.253108}, {1734.908427, 186.303301}, + {1744.199984, 185.358981}, {1753.444460, 184.420065}, + {1762.642123, 183.486473}, {1771.793238, 182.558123}, + {1780.898065, 181.634939}, {1789.956859, 180.716844}, + {1798.969875, 179.803763}, {1807.937359, 178.895624}, + {1816.859559, 177.992355}, {1825.736715, 177.093886}, + {1834.569066, 176.200149}, {1843.356846, 175.311076}, + {1852.100288, 174.426603}, {1860.799620, 173.546664}, + {1869.455066, 172.671198}, {1878.066850, 171.800142}, + {1886.635189, 170.933435}, {1895.160301, 170.071020}, + {1903.642397, 169.212837}, {1912.081689, 168.358830}, + {1920.478383, 167.508943}, {1928.832685, 166.663121}, + {1937.144796, 165.821312}, {1945.414915, 164.983462}, + {1953.643240, 164.149520}, {1961.829963, 163.319435}, + {1969.975278, 162.493158}, {1978.079373, 161.670641}, + {1986.142435, 160.851835}, {1994.164648, 160.036693}, + {2002.146195, 159.225170}, {2010.087255, 158.417221}, + {2017.988005, 157.612802}, {2025.848622, 156.811868}, + {2033.669278, 156.014377}, {2041.450145, 155.220287}, + {2049.191391, 154.429558}, {2056.893183, 153.642148}, + {2064.555688, 152.858018}, {2072.179066, 152.077129}, + {2079.763481, 151.299442}, {2087.309090, 150.524920}, + {2094.816051, 149.753525}, {2102.284519, 148.985222}, + {2109.714649, 148.219974}, {2117.106592, 147.457747}, + {2124.460499, 146.698505}, {2131.776517, 145.942214}, + {2139.054793, 145.188842}, {2146.295473, 144.438354}, + {2153.498700, 143.690720}, {2160.664615, 142.945906}, + {2167.793360, 142.203881}, {2174.885072, 141.464615}, + {2181.939890, 140.728077}, {2188.957948, 139.994237}, + {2195.939380, 139.263066}, {2202.884320, 138.534534}, + {2209.792899, 137.808614}, {2216.665246, 137.085277}, + {2223.501490, 136.364495}, {2230.301759, 135.646241}, + {2237.066177, 134.930488}, {2243.794869, 134.217209}, + {2250.487959, 133.506380}, {2257.145568, 132.797973}, + {2263.767816, 132.091963}, {2270.354824, 131.388327}, + {2276.906708, 130.687038}, {2283.423585, 129.988072}, + {2289.905572, 129.291406}, {2296.352783, 128.597017}, + {2302.765330, 127.904880}, {2309.143327, 127.214973}, + {2315.486883, 126.527273}, {2321.796109, 125.841758}, + {2328.071113, 125.158406}, {2334.312003, 124.477194}, + {2340.518885, 123.798103}, {2346.691865, 123.121109}, + {2352.831048, 122.446194}, {2358.936536, 121.773335}, + {2365.008432, 121.102512}, {2371.046838, 120.433707}, + {2377.051853, 119.766897}, {2383.023577, 119.102065}, + {2388.962108, 118.439190}, {2394.867544, 117.778253}, + {2400.739982, 117.119236}, {2406.579516, 116.462120}, + {2412.386241, 115.806886}, {2418.160251, 115.153517}, + {2423.901639, 114.501993}, {2429.610496, 113.852298}, + {2435.286914, 113.204414}, {2440.930982, 112.558324}, + {2446.542790, 111.914010}, {2452.122427, 111.271455}, + {2457.669979, 110.630642}, {2463.185534, 109.991555}, + {2468.669178, 109.354178}, {2474.120995, 108.718495}, + {2479.541069, 108.084488}, {2484.929485, 107.452143}, + {2490.286324, 106.821443}, {2495.611670, 106.192373}, + {2500.905602, 105.564918}, {2506.168202, 104.939063}, + {2511.399548, 104.314792}, {2516.599720, 103.692090}, + {2521.768796, 103.070943}, {2526.906853, 102.451337}, + {2532.013968, 101.833256}, {2537.090216, 101.216687}, + {2542.135674, 100.601615}, {2547.150415, 99.988026}, + {2552.134513, 99.375907}, {2557.088042, 98.765243}, + {2562.011074, 98.156022}, {2566.903680, 97.548229}, + {2571.765932, 96.941851}, {2576.597900, 96.336876}, + {2581.399654, 95.733289}, {2586.171263, 95.131079}, + {2590.912796, 94.530232}, {2595.624320, 93.930735}, + {2600.305903, 93.332576}, {2604.957611, 92.735742}, + {2609.579510, 92.140221}, {2614.171666, 91.546001}, + {2618.734142, 90.953070}, {2623.267005, 90.361415}, + {2627.770316, 89.771025}, {2632.244138, 89.181887}, + {2636.688535, 88.593991}, {2641.103568, 88.007323}, + {2645.489298, 87.421874}, {2649.845786, 86.837631}, + {2654.173091, 86.254583}, {2658.471274, 85.672720}, + {2662.740392, 85.092028}, {2666.980506, 84.512499}, + {2671.191671, 83.934120}, {2675.373946, 83.356881}, + {2679.527387, 82.780771}, {2683.652051, 82.205780}, + {2687.747993, 81.631896}, {2691.815268, 81.059110}, + {2695.853931, 80.487410}, {2699.864036, 79.916787}, + {2703.845637, 79.347231}, {2707.798786, 78.778730}, + {2711.723536, 78.211275}, {2715.619939, 77.644857}, + {2719.488047, 77.079464}, {2723.327911, 76.515087}, + {2727.139581, 75.951717}, {2730.923107, 75.389344}, + {2734.678540, 74.827957}, {2738.405928, 74.267548}, + {2742.105319, 73.708107}, {2745.776762, 73.149625}, + {2749.420305, 72.592091}, {2753.035995, 72.035498}, + {2756.623878, 71.479835}, {2760.184002, 70.925094}, + {2763.716411, 70.371265}, {2767.221151, 69.818340}, + {2770.698267, 69.266310}, {2774.147804, 68.715165}, + {2777.569805, 68.164897}, {2780.964315, 67.615497}, + {2784.331376, 67.066956}, {2787.671032, 66.519266}, + {2790.983324, 65.972419}, {2794.268295, 65.426405}, + {2797.525985, 64.881217}, {2800.756437, 64.336846}, + {2803.959690, 63.793283}, {2807.135785, 63.250521}, + {2810.284762, 62.708551}, {2813.406660, 62.167365}, + {2816.501518, 61.626955}, {2819.569374, 61.087313}, + {2822.610268, 60.548431}, {2825.624236, 60.010301}, + {2828.611317, 59.472915}, {2831.571546, 58.936266}, + {2834.504962, 58.400345}, {2837.411599, 57.865146}, + {2840.291494, 57.330660}, {2843.144682, 56.796880}, + {2845.971199, 56.263797}, {2848.771079, 55.731406}, + {2851.544357, 55.199698}, {2854.291066, 54.668666}, + {2857.011240, 54.138303}, {2859.704913, 53.608601}, + {2862.372117, 53.079554}, {2865.012885, 52.551153}, + {2867.627248, 52.023393}, {2870.215240, 51.496265}, + {2872.776890, 50.969763}, {2875.312231, 50.443879}, + {2877.821294, 49.918608}, {2880.304107, 49.393942}, + {2882.760703, 48.869873}, {2885.191109, 48.346397}, + {2887.595357, 47.823505}, {2889.973474, 47.301191}, + {2892.325490, 46.779448}, {2894.651433, 46.258270}, + {2896.951331, 45.737651}, {2899.225212, 45.217583}, + {2901.473103, 44.698061}, {2903.695032, 44.179077}, + {2905.891024, 43.660626}, {2908.061107, 43.142701}, + {2910.205307, 42.625297}, {2912.323650, 42.108406}, + {2914.416161, 41.592022}, {2916.482865, 41.076140}, + {2918.523787, 40.560754}, {2920.538952, 40.045857}, + {2922.528385, 39.531443}, {2924.492109, 39.017507}, + {2926.430147, 38.504042}, {2928.342524, 37.991043}, + {2930.229263, 37.478504}, {2932.090386, 36.966419}, + {2933.925916, 36.454783}, {2935.735876, 35.943589}, + {2937.520286, 35.432833}, {2939.279170, 34.922508}, + {2941.012548, 34.412610}, {2942.720441, 33.903132}, + {2944.402871, 33.394069}, {2946.059858, 32.885416}, + {2947.691423, 32.377167}, {2949.297585, 31.869318}, + {2950.878365, 31.361863}, {2952.433781, 30.854796}, + {2953.963854, 30.348113}, {2955.468602, 29.841809}, + {2956.948044, 29.335879}, {2958.402199, 28.830317}, + {2959.831085, 28.325118}, {2961.234720, 27.820279}, + {2962.613122, 27.315793}, {2963.966308, 26.811657}, + {2965.294296, 26.307865}, {2966.597103, 25.804413}, + {2967.874745, 25.301296}, {2969.127241, 24.798510}, + {2970.354605, 24.296050}, {2971.556854, 23.793912}, + {2972.734004, 23.292091}, {2973.886071, 22.790583}, + {2975.013070, 22.289384}, {2976.115017, 21.788489}, + {2977.191926, 21.287895}, {2978.243814, 20.787598}, + {2979.270693, 20.287593}, {2980.272580, 19.787876}, + {2981.249488, 19.288444}, {2982.201431, 18.789293}, + {2983.128424, 18.290419}, {2984.030480, 17.791818}, + {2984.907613, 17.293487}, {2985.759835, 16.795422}, + {2986.587162, 16.297620}, {2987.389604, 15.800078}, + {2988.167176, 15.302792}, {2988.919890, 14.805759}, + {2989.647758, 14.308975}, {2990.350793, 13.812439}, + {2991.029008, 13.316146}, {2991.682414, 12.820094}, + {2992.311023, 12.324280}, {2992.914848, 11.828702}, + {2993.493899, 11.333357}, {2994.048189, 10.838241}, + {2994.577729, 10.343354}, {2995.082530, 9.848691}, + {2995.562604, 9.354252}, {2996.017961, 8.860034}, + {2996.448613, 8.366035}, {2996.854570, 7.872253}, + {2997.235843, 7.378685}, {2997.592444, 6.885331}, + {2997.924382, 6.392189}, {2998.231668, 5.899256}, + {2998.514313, 5.406532}, {2998.772326, 4.914014}, + {2999.005719, 4.421703}, {2999.214502, 3.929596}, + {2999.398684, 3.437693}, {2999.558276, 2.945992}, + {2999.693288, 2.454493}, {2999.803730, 1.963195}, + {2999.889613, 1.472097}, {2999.950945, 0.981199}, + {2999.987737, 0.490500}, {2999.998745, 0.156943}, + {2999.999950, 0.031348}, {2999.999998, 0.006229}, + {3000.000000, 0.001206}, {3000.000000, 0.000201}, + {3000.000000, 0.000000}, + }}, + {357, + { + {1216.978643, 250.000000}, {1216.978643, 250.000000}, + {1226.925199, 248.731029}, {1239.322481, 247.160238}, + {1251.641707, 245.608794}, {1263.883831, 244.076163}, + {1276.049781, 242.561836}, {1288.140460, 241.065322}, + {1300.156747, 239.586150}, {1312.099497, 238.123865}, + {1323.969544, 236.678030}, {1335.767701, 235.248226}, + {1347.494758, 233.834047}, {1359.151486, 232.435101}, + {1370.738639, 231.051013}, {1382.256950, 229.681419}, + {1393.707135, 228.325969}, {1405.089892, 226.984323}, + {1416.405904, 225.656156}, {1427.655837, 224.341150}, + {1438.840340, 223.039000}, {1449.960051, 221.749412}, + {1461.015588, 220.472099}, {1472.007560, 219.206785}, + {1482.936560, 217.953203}, {1493.803167, 216.711093}, + {1504.607950, 215.480206}, {1515.351463, 214.260298}, + {1526.034248, 213.051134}, {1536.656839, 211.852486}, + {1547.219754, 210.664131}, {1557.723504, 209.485857}, + {1568.168587, 208.317455}, {1578.555491, 207.158723}, + {1588.884696, 206.009464}, {1599.156670, 204.869489}, + {1609.371872, 203.738614}, {1619.530754, 202.616658}, + {1629.633757, 201.503447}, {1639.681313, 200.398812}, + {1649.673848, 199.302588}, {1659.611778, 198.214615}, + {1669.495512, 197.134738}, {1679.325451, 196.062806}, + {1689.101988, 194.998670}, {1698.825509, 193.942188}, + {1708.496394, 192.893220}, {1718.115016, 191.851631}, + {1727.681739, 190.817288}, {1737.196922, 189.790063}, + {1746.660920, 188.769831}, {1756.074077, 187.756469}, + {1765.436735, 186.749858}, {1774.749229, 185.749883}, + {1784.011887, 184.756430}, {1793.225032, 183.769390}, + {1802.388983, 182.788655}, {1811.504053, 181.814119}, + {1820.570548, 180.845682}, {1829.588771, 179.883243}, + {1838.559020, 178.926705}, {1847.481587, 177.975974}, + {1856.356760, 177.030955}, {1865.184823, 176.091560}, + {1873.966054, 175.157699}, {1882.700729, 174.229286}, + {1891.389117, 173.306238}, {1900.031485, 172.388471}, + {1908.628094, 171.475905}, {1917.179203, 170.568462}, + {1925.685066, 169.666065}, {1934.145934, 168.768638}, + {1942.562053, 167.876108}, {1950.933665, 166.988404}, + {1959.261012, 166.105454}, {1967.544328, 165.227191}, + {1975.783846, 164.353547}, {1983.979796, 163.484456}, + {1992.132404, 162.619854}, {2000.241893, 161.759678}, + {2008.308481, 160.903866}, {2016.332387, 160.052357}, + {2024.313823, 159.205093}, {2032.253001, 158.362015}, + {2040.150128, 157.523067}, {2048.005409, 156.688193}, + {2055.819047, 155.857338}, {2063.591242, 155.030450}, + {2071.322190, 154.207475}, {2079.012086, 153.388363}, + {2086.661122, 152.573063}, {2094.269487, 151.761525}, + {2101.837367, 150.953702}, {2109.364948, 150.149546}, + {2116.852412, 149.349010}, {2124.299939, 148.552048}, + {2131.707705, 147.758616}, {2139.075888, 146.968670}, + {2146.404658, 146.182166}, {2153.694189, 145.399062}, + {2160.944649, 144.619317}, {2168.156204, 143.842889}, + {2175.329019, 143.069738}, {2182.463259, 142.299825}, + {2189.559082, 141.533112}, {2196.616649, 140.769559}, + {2203.636116, 140.009129}, {2210.617639, 139.251787}, + {2217.561371, 138.497495}, {2224.467464, 137.746218}, + {2231.336067, 136.997921}, {2238.167329, 136.252569}, + {2244.961397, 135.510130}, {2251.718414, 134.770569}, + {2258.438525, 134.033854}, {2265.121870, 133.299952}, + {2271.768590, 132.568833}, {2278.378822, 131.840465}, + {2284.952704, 131.114816}, {2291.490371, 130.391858}, + {2297.991956, 129.671560}, {2304.457593, 128.953892}, + {2310.887411, 128.238827}, {2317.281540, 127.526336}, + {2323.640108, 126.816390}, {2329.963242, 126.108963}, + {2336.251066, 125.404026}, {2342.503706, 124.701554}, + {2348.721283, 124.001520}, {2354.903918, 123.303898}, + {2361.051732, 122.608662}, {2367.164844, 121.915787}, + {2373.243369, 121.225248}, {2379.287426, 120.537021}, + {2385.297129, 119.851082}, {2391.272591, 119.167406}, + {2397.213925, 118.485970}, {2403.121243, 117.806750}, + {2408.994655, 117.129725}, {2414.834270, 116.454870}, + {2420.640196, 115.782165}, {2426.412540, 115.111586}, + {2432.151407, 114.443113}, {2437.856903, 113.776723}, + {2443.529131, 113.112395}, {2449.168194, 112.450109}, + {2454.774193, 111.789844}, {2460.347228, 111.131579}, + {2465.887400, 110.475295}, {2471.394807, 109.820971}, + {2476.869546, 109.168587}, {2482.311713, 108.518125}, + {2487.721406, 107.869565}, {2493.098717, 107.222887}, + {2498.443741, 106.578074}, {2503.756570, 105.935107}, + {2509.037297, 105.293967}, {2514.286012, 104.654637}, + {2519.502806, 104.017098}, {2524.687767, 103.381333}, + {2529.840983, 102.747323}, {2534.962542, 102.115053}, + {2540.052531, 101.484505}, {2545.111035, 100.855661}, + {2550.138140, 100.228505}, {2555.133928, 99.603021}, + {2560.098483, 98.979192}, {2565.031888, 98.357002}, + {2569.934224, 97.736435}, {2574.805572, 97.117475}, + {2579.646011, 96.500106}, {2584.455622, 95.884313}, + {2589.234482, 95.270080}, {2593.982668, 94.657392}, + {2598.700259, 94.046234}, {2603.387330, 93.436591}, + {2608.043956, 92.828448}, {2612.670212, 92.221791}, + {2617.266171, 91.616605}, {2621.831908, 91.012876}, + {2626.367495, 90.410589}, {2630.873003, 89.809731}, + {2635.348503, 89.210287}, {2639.794067, 88.612244}, + {2644.209763, 88.015588}, {2648.595660, 87.420305}, + {2652.951827, 86.826383}, {2657.278332, 86.233807}, + {2661.575241, 85.642564}, {2665.842621, 85.052642}, + {2670.080538, 84.464028}, {2674.289056, 83.876708}, + {2678.468241, 83.290670}, {2682.618155, 82.705901}, + {2686.738862, 82.122390}, {2690.830425, 81.540122}, + {2694.892905, 80.959087}, {2698.926364, 80.379272}, + {2702.930863, 79.800665}, {2706.906461, 79.223254}, + {2710.853218, 78.647027}, {2714.771193, 78.071972}, + {2718.660444, 77.498079}, {2722.521029, 76.925334}, + {2726.353006, 76.353727}, {2730.156430, 75.783246}, + {2733.931358, 75.213881}, {2737.677846, 74.645619}, + {2741.395948, 74.078450}, {2745.085718, 73.512363}, + {2748.747211, 72.947346}, {2752.380479, 72.383390}, + {2755.985576, 71.820483}, {2759.562553, 71.258615}, + {2763.111463, 70.697775}, {2766.632356, 70.137953}, + {2770.125284, 69.579138}, {2773.590295, 69.021319}, + {2777.027440, 68.464488}, {2780.436768, 67.908633}, + {2783.818328, 67.353745}, {2787.172167, 66.799813}, + {2790.498333, 66.246827}, {2793.796873, 65.694779}, + {2797.067834, 65.143657}, {2800.311261, 64.593453}, + {2803.527202, 64.044156}, {2806.715699, 63.495758}, + {2809.876800, 62.948248}, {2813.010546, 62.401617}, + {2816.116983, 61.855857}, {2819.196153, 61.310957}, + {2822.248100, 60.766908}, {2825.272865, 60.223703}, + {2828.270491, 59.681330}, {2831.241019, 59.139782}, + {2834.184490, 58.599049}, {2837.100944, 58.059123}, + {2839.990422, 57.519995}, {2842.852963, 56.981656}, + {2845.688607, 56.444098}, {2848.497392, 55.907311}, + {2851.279357, 55.371288}, {2854.034540, 54.836020}, + {2856.762978, 54.301498}, {2859.464708, 53.767715}, + {2862.139768, 53.234662}, {2864.788192, 52.702330}, + {2867.410019, 52.170712}, {2870.005281, 51.639800}, + {2872.574016, 51.109585}, {2875.116257, 50.580059}, + {2877.632039, 50.051216}, {2880.121395, 49.523046}, + {2882.584360, 48.995542}, {2885.020966, 48.468697}, + {2887.431246, 47.942502}, {2889.815232, 47.416950}, + {2892.172957, 46.892033}, {2894.504451, 46.367745}, + {2896.809747, 45.844077}, {2899.088874, 45.321022}, + {2901.341864, 44.798573}, {2903.568747, 44.276723}, + {2905.769551, 43.755464}, {2907.944308, 43.234789}, + {2910.093045, 42.714691}, {2912.215791, 42.195163}, + {2914.312575, 41.676198}, {2916.383425, 41.157790}, + {2918.428368, 40.639930}, {2920.447431, 40.122613}, + {2922.440643, 39.605832}, {2924.408028, 39.089579}, + {2926.349613, 38.573848}, {2928.265426, 38.058634}, + {2930.155490, 37.543928}, {2932.019831, 37.029725}, + {2933.858474, 36.516018}, {2935.671445, 36.002800}, + {2937.458767, 35.490067}, {2939.220463, 34.977810}, + {2940.956559, 34.466024}, {2942.667077, 33.954703}, + {2944.352041, 33.443840}, {2946.011473, 32.933430}, + {2947.645395, 32.423467}, {2949.253831, 31.913944}, + {2950.836801, 31.404856}, {2952.394327, 30.896198}, + {2953.926431, 30.387962}, {2955.433134, 29.880143}, + {2956.914456, 29.372737}, {2958.370417, 28.865737}, + {2959.801039, 28.359137}, {2961.206341, 27.852933}, + {2962.586342, 27.347118}, {2963.941062, 26.841688}, + {2965.270521, 26.336637}, {2966.574735, 25.831960}, + {2967.853726, 25.327652}, {2969.107510, 24.823708}, + {2970.336105, 24.320122}, {2971.539531, 23.816890}, + {2972.717803, 23.314007}, {2973.870940, 22.811468}, + {2974.998958, 22.309268}, {2976.101875, 21.807403}, + {2977.179707, 21.305867}, {2978.232470, 20.804658}, + {2979.260181, 20.303769}, {2980.262855, 19.803196}, + {2981.240508, 19.302936}, {2982.193156, 18.802984}, + {2983.120814, 18.303335}, {2984.023497, 17.803987}, + {2984.901220, 17.304934}, {2985.753998, 16.806173}, + {2986.581845, 16.307700}, {2987.384775, 15.809511}, + {2988.162803, 15.311602}, {2988.915942, 14.813971}, + {2989.644207, 14.316613}, {2990.347610, 13.819525}, + {2991.026166, 13.322704}, {2991.679887, 12.826146}, + {2992.308787, 12.329849}, {2992.912879, 11.833809}, + {2993.492174, 11.338024}, {2994.046687, 10.842490}, + {2994.576430, 10.347205}, {2995.081414, 9.852166}, + {2995.561652, 9.357371}, {2996.017157, 8.862818}, + {2996.447940, 8.368503}, {2996.854013, 7.874425}, + {2997.235388, 7.380582}, {2997.592077, 6.886971}, + {2997.924091, 6.393591}, {2998.231442, 5.900440}, + {2998.514141, 5.407517}, {2998.772199, 4.914819}, + {2999.005628, 4.422346}, {2999.214439, 3.930095}, + {2999.398643, 3.438067}, {2999.558252, 2.946259}, + {2999.693275, 2.454671}, {2999.803724, 1.963301}, + {2999.889610, 1.472150}, {2999.950945, 0.981217}, + {2999.987737, 0.490500}, {2999.998745, 0.156943}, + {2999.999950, 0.031348}, {2999.999998, 0.006229}, + {3000.000000, 0.001206}, {3000.000000, 0.000201}, + {3000.000000, 0.000000}, + }}, + {348, + { + {1290.095815, 250.000000}, {1290.095815, 250.000000}, + {1299.209094, 248.731151}, {1311.602879, 247.020240}, + {1323.911725, 245.333604}, {1336.136827, 243.670496}, + {1348.279345, 242.030200}, {1360.340401, 240.412031}, + {1372.321085, 238.815334}, {1384.222455, 237.239479}, + {1396.045539, 235.683863}, {1407.791333, 234.147907}, + {1419.460807, 232.631056}, {1431.054903, 231.132777}, + {1442.574536, 229.652556}, {1454.020597, 228.189902}, + {1465.393954, 226.744341}, {1476.695447, 225.315416}, + {1487.925900, 223.902690}, {1499.086111, 222.505739}, + {1510.176858, 221.124157}, {1521.198901, 219.757553}, + {1532.152979, 218.405548}, {1543.039812, 217.067777}, + {1553.860103, 215.743891}, {1564.614539, 214.433548}, + {1575.303789, 213.136423}, {1585.928504, 211.852200}, + {1596.489324, 210.580572}, {1606.986869, 209.321246}, + {1617.421748, 208.073935}, {1627.794556, 206.838366}, + {1638.105872, 205.614270}, {1648.356263, 204.401391}, + {1658.546285, 203.199478}, {1668.676479, 202.008292}, + {1678.747377, 200.827597}, {1688.759496, 199.657167}, + {1698.713344, 198.496784}, {1708.609420, 197.346234}, + {1718.448209, 196.205312}, {1728.230187, 195.073818}, + {1737.955821, 193.951559}, {1747.625569, 192.838346}, + {1757.239878, 191.733998}, {1766.799186, 190.638337}, + {1776.303924, 189.551193}, {1785.754514, 188.472398}, + {1795.151369, 187.401790}, {1804.494894, 186.339213}, + {1813.785487, 185.284513}, {1823.023538, 184.237543}, + {1832.209431, 183.198157}, {1841.343540, 182.166216}, + {1850.426235, 181.141583}, {1859.457878, 180.124125}, + {1868.438824, 179.113714}, {1877.369422, 178.110223}, + {1886.250016, 177.113530}, {1895.080942, 176.123516}, + {1903.862532, 175.140066}, {1912.595110, 174.163066}, + {1921.278997, 173.192406}, {1929.914506, 172.227979}, + {1938.501948, 171.269681}, {1947.041625, 170.317409}, + {1955.533837, 169.371065}, {1963.978877, 168.430551}, + {1972.377035, 167.495774}, {1980.728596, 166.566641}, + {1989.033838, 165.643062}, {1997.293039, 164.724949}, + {2005.506468, 163.812217}, {2013.674393, 162.904782}, + {2021.797076, 162.002563}, {2029.874778, 161.105480}, + {2037.907751, 160.213454}, {2045.896247, 159.326410}, + {2053.840515, 158.444274}, {2061.740796, 157.566973}, + {2069.597331, 156.694435}, {2077.410357, 155.826591}, + {2085.180106, 154.963374}, {2092.906808, 154.104716}, + {2100.590690, 153.250554}, {2108.231974, 152.400822}, + {2115.830881, 151.555460}, {2123.387628, 150.714405}, + {2130.902428, 149.877599}, {2138.375492, 149.044982}, + {2145.807029, 148.216499}, {2153.197244, 147.392092}, + {2160.546339, 146.571707}, {2167.854514, 145.755290}, + {2175.121966, 144.942788}, {2182.348889, 144.134150}, + {2189.535476, 143.329324}, {2196.681916, 142.528263}, + {2203.788395, 141.730915}, {2210.855099, 140.937235}, + {2217.882209, 140.147175}, {2224.869906, 139.360689}, + {2231.818366, 138.577731}, {2238.727766, 137.798259}, + {2245.598278, 137.022227}, {2252.430074, 136.249594}, + {2259.223322, 135.480318}, {2265.978189, 134.714357}, + {2272.694839, 133.951672}, {2279.373437, 133.192221}, + {2286.014141, 132.435968}, {2292.617112, 131.682872}, + {2299.182507, 130.932896}, {2305.710479, 130.186004}, + {2312.201183, 129.442159}, {2318.654770, 128.701325}, + {2325.071390, 127.963467}, {2331.451191, 127.228551}, + {2337.794318, 126.496541}, {2344.100917, 125.767406}, + {2350.371130, 125.041111}, {2356.605098, 124.317625}, + {2362.802961, 123.596915}, {2368.964858, 122.878950}, + {2375.090924, 122.163698}, {2381.181295, 121.451131}, + {2387.236104, 120.741217}, {2393.255482, 120.033927}, + {2399.239561, 119.329232}, {2405.188470, 118.627103}, + {2411.102335, 117.927512}, {2416.981283, 117.230430}, + {2422.825440, 116.535832}, {2428.634928, 115.843689}, + {2434.409870, 115.153974}, {2440.150386, 114.466663}, + {2445.856595, 113.781728}, {2451.528617, 113.099143}, + {2457.166568, 112.418885}, {2462.770563, 111.740928}, + {2468.340717, 111.065246}, {2473.877144, 110.391817}, + {2479.379955, 109.720616}, {2484.849261, 109.051620}, + {2490.285171, 108.384805}, {2495.687795, 107.720149}, + {2501.057240, 107.057628}, {2506.393611, 106.397220}, + {2511.697014, 105.738903}, {2516.967553, 105.082656}, + {2522.205331, 104.428456}, {2527.410449, 103.776283}, + {2532.583009, 103.126115}, {2537.723110, 102.477932}, + {2542.830851, 101.831713}, {2547.906330, 101.187437}, + {2552.949643, 100.545085}, {2557.960886, 99.904636}, + {2562.940154, 99.266072}, {2567.887540, 98.629373}, + {2572.803137, 97.994519}, {2577.687038, 97.361492}, + {2582.539332, 96.730274}, {2587.360110, 96.100844}, + {2592.149461, 95.473186}, {2596.907472, 94.847280}, + {2601.634232, 94.223110}, {2606.329826, 93.600657}, + {2610.994340, 92.979904}, {2615.627859, 92.360834}, + {2620.230465, 91.743429}, {2624.802243, 91.127672}, + {2629.343273, 90.513547}, {2633.853638, 89.901037}, + {2638.333417, 89.290126}, {2642.782690, 88.680796}, + {2647.201536, 88.073033}, {2651.590032, 87.466820}, + {2655.948256, 86.862141}, {2660.276284, 86.258980}, + {2664.574192, 85.657323}, {2668.842054, 85.057154}, + {2673.079944, 84.458457}, {2677.287936, 83.861218}, + {2681.466102, 83.265421}, {2685.614514, 82.671053}, + {2689.733242, 82.078098}, {2693.822358, 81.486541}, + {2697.881931, 80.896369}, {2701.912030, 80.307568}, + {2705.912722, 79.720122}, {2709.884075, 79.134019}, + {2713.826157, 78.549244}, {2717.739033, 77.965784}, + {2721.622768, 77.383625}, {2725.477427, 76.802754}, + {2729.303075, 76.223157}, {2733.099775, 75.644822}, + {2736.867589, 75.067734}, {2740.606579, 74.491882}, + {2744.316807, 73.917252}, {2747.998334, 73.343832}, + {2751.651220, 72.771608}, {2755.275525, 72.200569}, + {2758.871307, 71.630701}, {2762.438624, 71.061994}, + {2765.977535, 70.494433}, {2769.488096, 69.928008}, + {2772.970363, 69.362707}, {2776.424394, 68.798516}, + {2779.850243, 68.235426}, {2783.247964, 67.673423}, + {2786.617612, 67.112497}, {2789.959240, 66.552636}, + {2793.272902, 65.993828}, {2796.558649, 65.436062}, + {2799.816534, 64.879327}, {2803.046607, 64.323612}, + {2806.248920, 63.768905}, {2809.423523, 63.215197}, + {2812.570464, 62.662475}, {2815.689794, 62.110729}, + {2818.781561, 61.559949}, {2821.845813, 61.010124}, + {2824.882597, 60.461243}, {2827.891961, 59.913297}, + {2830.873950, 59.366274}, {2833.828611, 58.820164}, + {2836.755989, 58.274957}, {2839.656129, 57.730644}, + {2842.529076, 57.187214}, {2845.374872, 56.644657}, + {2848.193563, 56.102963}, {2850.985190, 55.562123}, + {2853.749796, 55.022126}, {2856.487424, 54.482964}, + {2859.198113, 53.944627}, {2861.881907, 53.407104}, + {2864.538844, 52.870388}, {2867.168965, 52.334468}, + {2869.772310, 51.799335}, {2872.348918, 51.264981}, + {2874.898828, 50.731395}, {2877.422077, 50.198569}, + {2879.918703, 49.666495}, {2882.388745, 49.135162}, + {2884.832238, 48.604563}, {2887.249219, 48.074688}, + {2889.639725, 47.545530}, {2892.003790, 47.017078}, + {2894.341450, 46.489326}, {2896.652740, 45.962263}, + {2898.937693, 45.435883}, {2901.196345, 44.910176}, + {2903.428728, 44.385134}, {2905.634875, 43.860750}, + {2907.814819, 43.337014}, {2909.968592, 42.813920}, + {2912.096227, 42.291458}, {2914.197754, 41.769622}, + {2916.273204, 41.248402}, {2918.322609, 40.727792}, + {2920.345998, 40.207784}, {2922.343402, 39.688369}, + {2924.314850, 39.169541}, {2926.260371, 38.651291}, + {2928.179993, 38.133613}, {2930.073746, 37.616499}, + {2931.941657, 37.099942}, {2933.783754, 36.583934}, + {2935.600064, 36.068467}, {2937.390614, 35.553536}, + {2939.155431, 35.039133}, {2940.894541, 34.525251}, + {2942.607969, 34.011882}, {2944.295742, 33.499021}, + {2945.957884, 32.986660}, {2947.594420, 32.474792}, + {2949.205375, 31.963412}, {2950.790773, 31.452511}, + {2952.350638, 30.942084}, {2953.884993, 30.432124}, + {2955.393862, 29.922625}, {2956.877267, 29.413581}, + {2958.335231, 28.904984}, {2959.767777, 28.396830}, + {2961.174925, 27.889111}, {2962.556698, 27.381822}, + {2963.913118, 26.874957}, {2965.244204, 26.368509}, + {2966.549979, 25.862473}, {2967.830462, 25.356844}, + {2969.085673, 24.851615}, {2970.315633, 24.346781}, + {2971.520361, 23.842337}, {2972.699877, 23.338276}, + {2973.854198, 22.834593}, {2974.983345, 22.331284}, + {2976.087336, 21.828342}, {2977.166189, 21.325764}, + {2978.219921, 20.823543}, {2979.248552, 20.321674}, + {2980.252097, 19.820153}, {2981.230576, 19.318976}, + {2982.184003, 18.818136}, {2983.112397, 18.317630}, + {2984.015774, 17.817453}, {2984.894151, 17.317600}, + {2985.747543, 16.818068}, {2986.575965, 16.318851}, + {2987.379435, 15.819946}, {2988.157968, 15.321349}, + {2988.911578, 14.823055}, {2989.640281, 14.325061}, + {2990.344091, 13.827362}, {2991.023024, 13.329956}, + {2991.677094, 12.832839}, {2992.306315, 12.336007}, + {2992.910702, 11.839456}, {2993.490268, 11.343184}, + {2994.045027, 10.847187}, {2994.574993, 10.351463}, + {2995.080180, 9.856007}, {2995.560601, 9.360819}, + {2996.016269, 8.865894}, {2996.447197, 8.371230}, + {2996.853398, 7.876826}, {2997.234886, 7.382677}, + {2997.591672, 6.888783}, {2997.923770, 6.395141}, + {2998.231192, 5.901749}, {2998.513951, 5.408605}, + {2998.772059, 4.915708}, {2999.005528, 4.423055}, + {2999.214371, 3.930646}, {2999.398599, 3.438479}, + {2999.558225, 2.946553}, {2999.693260, 2.454866}, + {2999.803717, 1.963419}, {2999.889608, 1.472209}, + {2999.950944, 0.981236}, {2999.987737, 0.490500}, + {2999.998745, 0.156943}, {2999.999950, 0.031348}, + {2999.999998, 0.006229}, {3000.000000, 0.001206}, + {3000.000000, 0.000201}, {3000.000000, 0.000000}, + }}, + {340, + { + {1361.522768, 250.000000}, {1361.522768, 250.000000}, + {1361.522768, 250.000000}, {1370.491594, 248.638116}, + {1382.876958, 246.776445}, {1395.169992, 244.944924}, + {1407.372179, 243.142520}, {1419.484948, 241.368247}, + {1431.509683, 239.621165}, {1443.447722, 237.900376}, + {1455.300357, 236.205024}, {1467.068839, 234.534292}, + {1478.754382, 232.887397}, {1490.358156, 231.263594}, + {1501.881300, 229.662166}, {1513.324915, 228.082430}, + {1524.690069, 226.523731}, {1535.977799, 224.985442}, + {1547.189109, 223.466960}, {1558.324976, 221.967711}, + {1569.386347, 220.487139}, {1580.374143, 219.024716}, + {1591.289259, 217.579930}, {1602.132565, 216.152294}, + {1612.904906, 214.741336}, {1623.607104, 213.346605}, + {1634.239961, 211.967666}, {1644.804255, 210.604102}, + {1655.300746, 209.255509}, {1665.730171, 207.921501}, + {1676.093251, 206.601704}, {1686.390688, 205.295760}, + {1696.623165, 204.003322}, {1706.791349, 202.724057}, + {1716.895891, 201.457641}, {1726.937427, 200.203766}, + {1736.916574, 198.962131}, {1746.833939, 197.732447}, + {1756.690111, 196.514435}, {1766.485667, 195.307825}, + {1776.221172, 194.112355}, {1785.897175, 192.927775}, + {1795.514215, 191.753840}, {1805.072819, 190.590316}, + {1814.573501, 189.436973}, {1824.016765, 188.293591}, + {1833.403104, 187.159957}, {1842.733000, 186.035864}, + {1852.006924, 184.921112}, {1861.225340, 183.815507}, + {1870.388699, 182.718860}, {1879.497445, 181.630990}, + {1888.552013, 180.551719}, {1897.552828, 179.480877}, + {1906.500307, 178.418297}, {1915.394860, 177.363817}, + {1924.236887, 176.317281}, {1933.026783, 175.278538}, + {1941.764932, 174.247439}, {1950.451714, 173.223840}, + {1959.087500, 172.207603}, {1967.672655, 171.198592}, + {1976.207537, 170.196675}, {1984.692497, 169.201725}, + {1993.127880, 168.213616}, {2001.514026, 167.232228}, + {2009.851268, 166.257442}, {2018.139933, 165.289144}, + {2026.380342, 164.327223}, {2034.572812, 163.371569}, + {2042.717653, 162.422076}, {2050.815171, 161.478642}, + {2058.865666, 160.541165}, {2066.869434, 159.609548}, + {2074.826765, 158.683695}, {2082.737945, 157.763513}, + {2090.603256, 156.848911}, {2098.422973, 155.939800}, + {2106.197371, 155.036095}, {2113.926716, 154.137709}, + {2121.611273, 153.244562}, {2129.251301, 152.356573}, + {2136.847057, 151.473663}, {2144.398792, 150.595755}, + {2151.906756, 149.722775}, {2159.371191, 148.854648}, + {2166.792340, 147.991304}, {2174.170439, 147.132673}, + {2181.505723, 146.278686}, {2188.798422, 145.429276}, + {2196.048764, 144.584378}, {2203.256971, 143.743927}, + {2210.423266, 142.907861}, {2217.547866, 142.076119}, + {2224.630985, 141.248640}, {2231.672835, 140.425367}, + {2238.673625, 139.606240}, {2245.633561, 138.791204}, + {2252.552846, 137.980204}, {2259.431681, 137.173185}, + {2266.270263, 136.370094}, {2273.068787, 135.570879}, + {2279.827447, 134.775490}, {2286.546431, 133.983876}, + {2293.225927, 133.195988}, {2299.866121, 132.411779}, + {2306.467196, 131.631200}, {2313.029331, 130.854206}, + {2319.552705, 130.080750}, {2326.037493, 129.310789}, + {2332.483870, 128.544279}, {2338.892007, 127.781177}, + {2345.262072, 127.021439}, {2351.594234, 126.265026}, + {2357.888657, 125.511895}, {2364.145504, 124.762007}, + {2370.364937, 124.015323}, {2376.547116, 123.271804}, + {2382.692196, 122.531411}, {2388.800334, 121.794108}, + {2394.871683, 121.059857}, {2400.906395, 120.328622}, + {2406.904620, 119.600368}, {2412.866506, 118.875060}, + {2418.792199, 118.152662}, {2424.681844, 117.433142}, + {2430.535584, 116.716466}, {2436.353560, 116.002600}, + {2442.135913, 115.291513}, {2447.882780, 114.583172}, + {2453.594298, 113.877546}, {2459.270602, 113.174605}, + {2464.911825, 112.474318}, {2470.518100, 111.776654}, + {2476.089555, 111.081584}, {2481.626322, 110.389079}, + {2487.128527, 109.699110}, {2492.596296, 109.011649}, + {2498.029754, 108.326668}, {2503.429024, 107.644139}, + {2508.794228, 106.964036}, {2514.125487, 106.286330}, + {2519.422921, 105.610997}, {2524.686646, 104.938009}, + {2529.916779, 104.267341}, {2535.113437, 103.598968}, + {2540.276733, 102.932865}, {2545.406780, 102.269006}, + {2550.503689, 101.607367}, {2555.567571, 100.947925}, + {2560.598536, 100.290656}, {2565.596691, 99.635535}, + {2570.562143, 98.982540}, {2575.494997, 98.331648}, + {2580.395359, 97.682836}, {2585.263332, 97.036082}, + {2590.099018, 96.391363}, {2594.902519, 95.748659}, + {2599.673934, 95.107946}, {2604.413363, 94.469205}, + {2609.120903, 93.832413}, {2613.796652, 93.197550}, + {2618.440706, 92.564596}, {2623.053159, 91.933529}, + {2627.634106, 91.304331}, {2632.183638, 90.676981}, + {2636.701849, 90.051459}, {2641.188830, 89.427745}, + {2645.644669, 88.805822}, {2650.069456, 88.185669}, + {2654.463279, 87.567267}, {2658.826226, 86.950599}, + {2663.158382, 86.335646}, {2667.459833, 85.722388}, + {2671.730663, 85.110810}, {2675.970955, 84.500891}, + {2680.180793, 83.892616}, {2684.360258, 83.285966}, + {2688.509430, 82.680924}, {2692.628390, 82.077473}, + {2696.717217, 81.475596}, {2700.775988, 80.875276}, + {2704.804783, 80.276497}, {2708.803676, 79.679242}, + {2712.772745, 79.083494}, {2716.712063, 78.489239}, + {2720.621705, 77.896459}, {2724.501745, 77.305139}, + {2728.352255, 76.715263}, {2732.173307, 76.126816}, + {2735.964972, 75.539783}, {2739.727321, 74.954148}, + {2743.460422, 74.369895}, {2747.164344, 73.787011}, + {2750.839157, 73.205481}, {2754.484926, 72.625289}, + {2758.101719, 72.046421}, {2761.689601, 71.468863}, + {2765.248637, 70.892601}, {2768.778893, 70.317620}, + {2772.280431, 69.743907}, {2775.753315, 69.171447}, + {2779.197607, 68.600227}, {2782.613368, 68.030234}, + {2786.000660, 67.461453}, {2789.359544, 66.893872}, + {2792.690077, 66.327477}, {2795.992321, 65.762255}, + {2799.266332, 65.198193}, {2802.512168, 64.635278}, + {2805.729888, 64.073497}, {2808.919546, 63.512838}, + {2812.081199, 62.953289}, {2815.214902, 62.394836}, + {2818.320710, 61.837467}, {2821.398676, 61.281170}, + {2824.448854, 60.725934}, {2827.471296, 60.171745}, + {2830.466054, 59.618592}, {2833.433180, 59.066463}, + {2836.372726, 58.515347}, {2839.284740, 57.965232}, + {2842.169273, 57.416106}, {2845.026375, 56.867958}, + {2847.856093, 56.320776}, {2850.658477, 55.774550}, + {2853.433572, 55.229268}, {2856.181427, 54.684919}, + {2858.902087, 54.141492}, {2861.595599, 53.598977}, + {2864.262007, 53.057362}, {2866.901357, 52.516637}, + {2869.513693, 51.976791}, {2872.099058, 51.437815}, + {2874.657496, 50.899696}, {2877.189049, 50.362426}, + {2879.693759, 49.825994}, {2882.171669, 49.290389}, + {2884.622819, 48.755602}, {2887.047249, 48.221623}, + {2889.445001, 47.688442}, {2891.816113, 47.156048}, + {2894.160625, 46.624433}, {2896.478576, 46.093587}, + {2898.770003, 45.563500}, {2901.034944, 45.034162}, + {2903.273438, 44.505564}, {2905.485519, 43.977698}, + {2907.671225, 43.450553}, {2909.830592, 42.924120}, + {2911.963655, 42.398392}, {2914.070449, 41.873357}, + {2916.151008, 41.349008}, {2918.205367, 40.825336}, + {2920.233558, 40.302332}, {2922.235616, 39.779987}, + {2924.211573, 39.258292}, {2926.161461, 38.737240}, + {2928.085313, 38.216821}, {2929.983159, 37.697028}, + {2931.855031, 37.177852}, {2933.700960, 36.659285}, + {2935.520975, 36.141318}, {2937.315106, 35.623944}, + {2939.083384, 35.107154}, {2940.825836, 34.590941}, + {2942.542492, 34.075297}, {2944.233380, 33.560215}, + {2945.898527, 33.045685}, {2947.537962, 32.531702}, + {2949.151711, 32.018257}, {2950.739801, 31.505342}, + {2952.302258, 30.992952}, {2953.839109, 30.481077}, + {2955.350379, 29.969712}, {2956.836093, 29.458848}, + {2958.296276, 28.948479}, {2959.730953, 28.438598}, + {2961.140148, 27.929199}, {2962.523885, 27.420273}, + {2963.882187, 26.911815}, {2965.215078, 26.403817}, + {2966.522580, 25.896274}, {2967.804716, 25.389179}, + {2969.061509, 24.882525}, {2970.292980, 24.376306}, + {2971.499150, 23.870517}, {2972.680042, 23.365149}, + {2973.835676, 22.860199}, {2974.966072, 22.355659}, + {2976.071252, 21.851525}, {2977.151234, 21.347789}, + {2978.206040, 20.844447}, {2979.235689, 20.341493}, + {2980.240199, 19.838921}, {2981.219590, 19.336727}, + {2982.173881, 18.834904}, {2983.103090, 18.333447}, + {2984.007235, 17.832352}, {2984.886334, 17.331614}, + {2985.740405, 16.831227}, {2986.569466, 16.331187}, + {2987.373532, 15.831489}, {2988.152623, 15.332129}, + {2988.906754, 14.833102}, {2989.635941, 14.334403}, + {2990.340202, 13.836029}, {2991.019552, 13.337976}, + {2991.674008, 12.840239}, {2992.303584, 12.342814}, + {2992.908297, 11.845699}, {2993.488161, 11.348888}, + {2994.043193, 10.852379}, {2994.573407, 10.356168}, + {2995.078817, 9.860252}, {2995.559439, 9.364628}, + {2996.015287, 8.869293}, {2996.446376, 8.374244}, + {2996.852719, 7.879478}, {2997.234331, 7.384992}, + {2997.591225, 6.890784}, {2997.923416, 6.396852}, + {2998.230917, 5.903194}, {2998.513742, 5.409807}, + {2998.771904, 4.916689}, {2999.005418, 4.423839}, + {2999.214295, 3.931254}, {2999.398550, 3.438935}, + {2999.558195, 2.946878}, {2999.693244, 2.455083}, + {2999.803710, 1.963548}, {2999.889605, 1.472274}, + {2999.950944, 0.981258}, {2999.987737, 0.490500}, + {2999.998745, 0.156943}, {2999.999950, 0.031348}, + {2999.999998, 0.006229}, {3000.000000, 0.001206}, + {3000.000000, 0.000201}, {3000.000000, 0.000000}, + }}, + {330, + { + {1431.374621, 250.000000}, {1431.374621, 250.000000}, + {1440.738517, 248.450148}, {1453.110427, 246.426266}, + {1465.382072, 244.439519}, {1477.555272, 242.488495}, + {1489.631781, 240.571853}, {1501.613285, 238.688321}, + {1513.501410, 236.836690}, {1525.297723, 235.015811}, + {1537.003733, 233.224592}, {1548.620898, 231.461993}, + {1560.150623, 229.727025}, {1571.594267, 228.018745}, + {1582.953142, 226.336255}, {1594.228516, 224.678699}, + {1605.421615, 223.045258}, {1616.533625, 221.435153}, + {1627.565695, 219.847640}, {1638.518936, 218.282006}, + {1649.394426, 216.737571}, {1660.193207, 215.213685}, + {1670.916292, 213.709724}, {1681.564663, 212.225094}, + {1692.139271, 210.759222}, {1702.641040, 209.311563}, + {1713.070869, 207.881592}, {1723.429629, 206.468807}, + {1733.718168, 205.072724}, {1743.937308, 203.692882}, + {1754.087851, 202.328836}, {1764.170576, 200.980158}, + {1774.186240, 199.646439}, {1784.135584, 198.327284}, + {1794.019323, 197.022314}, {1803.838160, 195.731163}, + {1813.592777, 194.453481}, {1823.283837, 193.188929}, + {1832.911990, 191.937182}, {1842.477867, 190.697925}, + {1851.982087, 189.470855}, {1861.425250, 188.255682}, + {1870.807945, 187.052124}, {1880.130746, 185.859908}, + {1889.394213, 184.678773}, {1898.598894, 183.508467}, + {1907.745324, 182.348743}, {1916.834027, 181.199366}, + {1925.865514, 180.060108}, {1934.840285, 178.930747}, + {1943.758831, 177.811071}, {1952.621629, 176.700872}, + {1961.429150, 175.599951}, {1970.181852, 174.508114}, + {1978.880184, 173.425174}, {1987.524587, 172.350948}, + {1996.115492, 171.285262}, {2004.653322, 170.227943}, + {2013.138491, 169.178828}, {2021.571406, 168.137756}, + {2029.952464, 167.104570}, {2038.282056, 166.079121}, + {2046.560566, 165.061261}, {2054.788369, 164.050848}, + {2062.965834, 163.047744}, {2071.093323, 162.051815}, + {2079.171191, 161.062930}, {2087.199788, 160.080962}, + {2095.179457, 159.105788}, {2103.110534, 158.137288}, + {2110.993350, 157.175345}, {2118.828230, 156.219846}, + {2126.615493, 155.270681}, {2134.355453, 154.327741}, + {2142.048420, 153.390922}, {2149.694696, 152.460122}, + {2157.294580, 151.535241}, {2164.848366, 150.616183}, + {2172.356342, 149.702853}, {2179.818792, 148.795158}, + {2187.235996, 147.893010}, {2194.608229, 146.996320}, + {2201.935762, 146.105003}, {2209.218862, 145.218975}, + {2216.457790, 144.338155}, {2223.652806, 143.462464}, + {2230.804163, 142.591823}, {2237.912112, 141.726158}, + {2244.976901, 140.865392}, {2251.998772, 140.009455}, + {2258.977966, 139.158275}, {2265.914717, 138.311783}, + {2272.809259, 137.469911}, {2279.661822, 136.632593}, + {2286.472631, 135.799764}, {2293.241909, 134.971361}, + {2299.969876, 134.147320}, {2306.656749, 133.327583}, + {2313.302740, 132.512088}, {2319.908062, 131.700778}, + {2326.472921, 130.893595}, {2332.997523, 130.090484}, + {2339.482070, 129.291389}, {2345.926761, 128.496257}, + {2352.331794, 127.705035}, {2358.697361, 126.917671}, + {2365.023656, 126.134115}, {2371.310867, 125.354316}, + {2377.559180, 124.578225}, {2383.768781, 123.805796}, + {2389.939850, 123.036980}, {2396.072568, 122.271732}, + {2402.167111, 121.510006}, {2408.223655, 120.751757}, + {2414.242373, 119.996942}, {2420.223434, 119.245518}, + {2426.167009, 118.497443}, {2432.073261, 117.752674}, + {2437.942358, 117.011172}, {2443.774459, 116.272895}, + {2449.569727, 115.537805}, {2455.328318, 114.805863}, + {2461.050391, 114.077030}, {2466.736098, 113.351269}, + {2472.385594, 112.628543}, {2477.999028, 111.908815}, + {2483.576549, 111.192050}, {2489.118306, 110.478213}, + {2494.624443, 109.767269}, {2500.095104, 109.059183}, + {2505.530432, 108.353922}, {2510.930566, 107.651452}, + {2516.295646, 106.951742}, {2521.625808, 106.254759}, + {2526.921189, 105.560471}, {2532.181922, 104.868847}, + {2537.408140, 104.179857}, {2542.599973, 103.493469}, + {2547.757551, 102.809654}, {2552.881002, 102.128382}, + {2557.970452, 101.449625}, {2563.026027, 100.773353}, + {2568.047849, 100.099539}, {2573.036041, 99.428153}, + {2577.990724, 98.759170}, {2582.912017, 98.092561}, + {2587.800039, 97.428300}, {2592.654905, 96.766360}, + {2597.476732, 96.106715}, {2602.265634, 95.449339}, + {2607.021722, 94.794207}, {2611.745110, 94.141293}, + {2616.435907, 93.490574}, {2621.094221, 92.842023}, + {2625.720162, 92.195617}, {2630.313836, 91.551333}, + {2634.875348, 90.909145}, {2639.404803, 90.269032}, + {2643.902303, 89.630970}, {2648.367950, 88.994935}, + {2652.801846, 88.360906}, {2657.204090, 87.728861}, + {2661.574781, 87.098776}, {2665.914017, 86.470631}, + {2670.221892, 85.844404}, {2674.498504, 85.220073}, + {2678.743947, 84.597618}, {2682.958312, 83.977018}, + {2687.141694, 83.358251}, {2691.294183, 82.741299}, + {2695.415869, 82.126141}, {2699.506841, 81.512756}, + {2703.567188, 80.901125}, {2707.596997, 80.291229}, + {2711.596354, 79.683048}, {2715.565344, 79.076563}, + {2719.504052, 78.471756}, {2723.412562, 77.868608}, + {2727.290954, 77.267100}, {2731.139312, 76.667214}, + {2734.957716, 76.068932}, {2738.746245, 75.472236}, + {2742.504978, 74.877108}, {2746.233994, 74.283531}, + {2749.933370, 73.691487}, {2753.603181, 73.100959}, + {2757.243503, 72.511931}, {2760.854411, 71.924385}, + {2764.435978, 71.338304}, {2767.988278, 70.753673}, + {2771.511382, 70.170475}, {2775.005361, 69.588693}, + {2778.470286, 69.008311}, {2781.906226, 68.429314}, + {2785.313251, 67.851687}, {2788.691429, 67.275412}, + {2792.040826, 66.700476}, {2795.361510, 66.126862}, + {2798.653545, 65.554555}, {2801.916997, 64.983541}, + {2805.151931, 64.413805}, {2808.358409, 63.845332}, + {2811.536495, 63.278107}, {2814.686251, 62.712116}, + {2817.807737, 62.147345}, {2820.901016, 61.583779}, + {2823.966145, 61.021404}, {2827.003185, 60.460207}, + {2830.012195, 59.900174}, {2832.993232, 59.341291}, + {2835.946352, 58.783544}, {2838.871614, 58.226921}, + {2841.769072, 57.671407}, {2844.638782, 57.116990}, + {2847.480798, 56.563657}, {2850.295175, 56.011395}, + {2853.081964, 55.460190}, {2855.841220, 54.910030}, + {2858.572993, 54.360904}, {2861.277336, 53.812797}, + {2863.954298, 53.265698}, {2866.603930, 52.719595}, + {2869.226282, 52.174475}, {2871.821402, 51.630326}, + {2874.389339, 51.087137}, {2876.930140, 50.544896}, + {2879.443852, 50.003590}, {2881.930522, 49.463209}, + {2884.390195, 48.923741}, {2886.822918, 48.385174}, + {2889.228735, 47.847498}, {2891.607690, 47.310700}, + {2893.959827, 46.774770}, {2896.285188, 46.239697}, + {2898.583818, 45.705471}, {2900.855756, 45.172079}, + {2903.101046, 44.639512}, {2905.319728, 44.107759}, + {2907.511842, 43.576809}, {2909.677429, 43.046653}, + {2911.816527, 42.517279}, {2913.929176, 41.988677}, + {2916.015414, 41.460838}, {2918.075279, 40.933752}, + {2920.108808, 40.407407}, {2922.116038, 39.881796}, + {2924.097005, 39.356907}, {2926.051746, 38.832731}, + {2927.980296, 38.309259}, {2929.882689, 37.786481}, + {2931.758961, 37.264388}, {2933.609145, 36.742970}, + {2935.433275, 36.222219}, {2937.231383, 35.702124}, + {2939.003503, 35.182678}, {2940.749667, 34.663871}, + {2942.469906, 34.145695}, {2944.164252, 33.628140}, + {2945.832736, 33.111198}, {2947.475387, 32.594860}, + {2949.092236, 32.079119}, {2950.683314, 31.563965}, + {2952.248647, 31.049390}, {2953.788267, 30.535386}, + {2955.302200, 30.021946}, {2956.790475, 29.509060}, + {2958.253120, 28.996721}, {2959.690161, 28.484922}, + {2961.101625, 27.973654}, {2962.487539, 27.462909}, + {2963.847929, 26.952682}, {2965.182820, 26.442962}, + {2966.492238, 25.933745}, {2967.776207, 25.425021}, + {2969.034752, 24.916785}, {2970.267898, 24.409029}, + {2971.475667, 23.901745}, {2972.658084, 23.394928}, + {2973.815171, 22.888571}, {2974.946952, 22.382666}, + {2976.053449, 21.877207}, {2977.134684, 21.372188}, + {2978.190679, 20.867602}, {2979.221455, 20.363444}, + {2980.227033, 19.859706}, {2981.207436, 19.356384}, + {2982.162682, 18.853470}, {2983.092793, 18.350960}, + {2983.997788, 17.848848}, {2984.877687, 17.347127}, + {2985.732510, 16.845793}, {2986.562276, 16.344841}, + {2987.367004, 15.844264}, {2988.146712, 15.344058}, + {2988.901419, 14.844219}, {2989.631143, 14.344740}, + {2990.335902, 13.845618}, {2991.015713, 13.346847}, + {2991.670595, 12.848424}, {2992.300564, 12.350344}, + {2992.905638, 11.852603}, {2993.485833, 11.355196}, + {2994.041166, 10.858120}, {2994.571653, 10.361371}, + {2995.077311, 9.864946}, {2995.558156, 9.368840}, + {2996.014203, 8.873051}, {2996.445469, 8.377575}, + {2996.851968, 7.882409}, {2997.233717, 7.387550}, + {2997.590731, 6.892996}, {2997.923024, 6.398744}, + {2998.230613, 5.904790}, {2998.513511, 5.411134}, + {2998.771734, 4.917773}, {2999.005295, 4.424704}, + {2999.214211, 3.931926}, {2999.398495, 3.439438}, + {2999.558162, 2.947236}, {2999.693226, 2.455321}, + {2999.803701, 1.963691}, {2999.889602, 1.472345}, + {2999.950943, 0.981281}, {2999.987737, 0.490500}, + {2999.998745, 0.156943}, {2999.999950, 0.031348}, + {2999.999998, 0.006229}, {3000.000000, 0.001206}, + {3000.000000, 0.000201}, {3000.000000, 0.000000}, + }}, +}; + +} // namespace DeathStackBoard diff --git a/scripts/event_header_generator/Events.h.template b/src/boards/DeathStack/AeroBrakesController/trajectories/Trajectory.h similarity index 55% rename from scripts/event_header_generator/Events.h.template rename to src/boards/DeathStack/AeroBrakesController/trajectories/Trajectory.h index 3d79b58591da02b142395484b2d2865983d57a7f..2009a691df9e676ff3a60c47ffb0e1e6986f5745 100644 --- a/scripts/event_header_generator/Events.h.template +++ b/src/boards/DeathStack/AeroBrakesController/trajectories/Trajectory.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,46 +21,36 @@ * THE SOFTWARE. */ -/* - ****************************************************************************** - * THIS FILE IS AUTOGENERATED. DO NOT EDIT. * - ****************************************************************************** - */ - -// Generated from: {sheet_link} -// Autogen date: {date} - #pragma once -#include <cstdint> -#include <string> -#include <vector> +#include "Trajectories_data.h" +#include "TrajectoryPoint.h" -#include "events/Event.h" -#include "events/EventBroker.h" -#include "Topics.h" +namespace DeathStackBoard +{ -using std::string; +class Trajectory +{ +private: + uint32_t index; -namespace DeathStackBoard -{{ -/** - * Definition of all events in the Homeone Board software - * Refer to section 5.1.1 of the Software Design Document. - */ -enum Events : uint8_t -{{ -{enum_data} -}}; +public: + Trajectory(uint32_t index) : index(index) {} + Trajectory() : index(0) {} -const std::vector<uint8_t> EVENT_LIST {{{event_list}}}; + Trajectory& operator=(const Trajectory& other) + { + this->index = other.index; + return *this; + } -/** - * @brief Returns the name of the provided event - * - * @param event - * @return string - */ -string getEventString(uint8_t event); + uint32_t length() { return TRAJECTORIES_DATA[index].length; } + + TrajectoryPoint get(uint32_t idx) + { + point_t point = TRAJECTORIES_DATA[index].data[idx]; + return TrajectoryPoint(point.z, point.vz); + } +}; -}} +} // namespace DeathStackBoard \ No newline at end of file diff --git a/scripts/event_header_generator/Topics.h.template b/src/boards/DeathStack/AeroBrakesController/trajectories/TrajectoryPoint.h similarity index 58% rename from scripts/event_header_generator/Topics.h.template rename to src/boards/DeathStack/AeroBrakesController/trajectories/TrajectoryPoint.h index 87986edbad2dfd6f72a2377389d43da214e85816..0355c21c2513ca8f9baa9fc1248398808f40a36e 100644 --- a/scripts/event_header_generator/Topics.h.template +++ b/src/boards/DeathStack/AeroBrakesController/trajectories/TrajectoryPoint.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,42 +21,40 @@ * THE SOFTWARE. */ -/* - ****************************************************************************** - * THIS FILE IS AUTOGENERATED. DO NOT EDIT. * - ****************************************************************************** - */ - -// Generated from: {sheet_link} -// Autogen date: {date} - #pragma once -#include <stdint.h> -#include <string> -#include <vector> - -using std::string; +#include <math.h> namespace DeathStackBoard -{{ -/** - * Definition of various event topics to use in the EventBroker - */ -enum Topics : uint8_t -{{ -{enum_data} -}}; - -const std::vector<uint8_t> TOPIC_LIST {{{topic_list}}}; - -/** - * @brief Returns the name of the provided event - * - * @param event - * @return string - */ -string getTopicString(uint8_t topic); - -}} // namespace DeathStackBoard - +{ + +class TrajectoryPoint +{ +public: + TrajectoryPoint() : TrajectoryPoint(0, 0) {} + TrajectoryPoint(float z, float vz) : z(z), vz(vz) {} + + float getZ() { return z; } + float getVz() { return vz; } + + static float distance(TrajectoryPoint a, TrajectoryPoint b) + { + return powf(a.getZ() - b.getZ(), 2) + powf(a.getVz() - b.getVz(), 2); + } + + static float zDistance(TrajectoryPoint a, TrajectoryPoint b) + { + return abs(a.getZ() - b.getZ()); + } + + static float vzDistance(TrajectoryPoint a, TrajectoryPoint b) + { + return abs(a.getVz() - b.getVz()); + } + +private: + float z; + float vz; +}; + +} // namespace DeathStackBoard \ No newline at end of file diff --git a/src/boards/DeathStack/Algorithm.h b/src/boards/DeathStack/Algorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..0c40679515642c0c2db4aa90a08a52f8851dd30c --- /dev/null +++ b/src/boards/DeathStack/Algorithm.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2020 Skyward Experimental Rocketry + * Authors: Luca Conterio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +namespace DeathStackBoard +{ + +class Algorithm +{ +public: + /** + * @brief Initializes the Algorithm object, must be called as soon as the + * object is created. + * */ + virtual bool init() = 0; + + /** + * @brief Starts the execution of the algorithm and set the running flag to + * true. + * */ + void begin() { running = true; } + + /** + * @brief Terminates the algorithm's execution and sets the running flag to + * false. + * */ + void end() { running = false; } + + /** + * @brief Checks wether the algorithm is in a running state or not, and + * eventually calls the @see{step} routine. + * */ + void update() + { + if (running) + { + step(); + } + } + +protected: + /** + * @brief The actual algorithm step. + */ + virtual void step() = 0; + + bool running = false; +}; + +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/ServoInterface.h b/src/boards/DeathStack/ServoInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..77dc22bf1a52ec94f56c2a8c0a2a69bb626d90a0 --- /dev/null +++ b/src/boards/DeathStack/ServoInterface.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +namespace DeathStackBoard +{ + +/** + * @brief Class for interfacing with 180° servo motors. + * + * This class provides all the methods for enabling/disabling servo + * communication as well as methods for testing it (like reset, setMaxPosition + * and selftest). + * The function set(float) is used to send data to the servo and calls, in + * sequence, the preprocessPosition() and the setPosition() functions. This + * function must not be overridden and all the logic of preprocessing and + * sending position to the actual servo must be implemented via those two + * methods. + * */ +class ServoInterface +{ +public: + /** + * @brief Class constructor. + * + * @param minPosition The minimum position possible for the Servo + * @param maxPosition The maximum position possible for the Servo + * */ + ServoInterface(float minPosition, float maxPosition) + : MIN_POS(minPosition), MAX_POS(maxPosition), RESET_POS(minPosition) + { + } + + /** + * @brief Class constructor. + * + * @param minPosition The minimum position possible for the Servo + * @param maxPosition The maximum position possible for the Servo + * @param resetPosition The reset position for the Servo + * */ + ServoInterface(float minPosition, float maxPosition, float resetPosition) + : MIN_POS(minPosition), MAX_POS(maxPosition), RESET_POS(resetPosition) + { + } + + /** + * @brief Enables the communication with the servo and sets it to its reset + * position. + * */ + virtual void enable() = 0; + + /** + * @brief Disables the communication with the servo. + * */ + virtual void disable() = 0; + + /** + * @brief Sends the given input to the Servo. Before sending data the input + * is preprocessed in order to have a physical consistent position to send + * to the servo. Do not override this method, but use @see{setPosition} and + * @see{preprocessPosition}. + * + * @param angle The input to be sent to the Servo + * */ + void set(float angle) { setPosition(preprocessPosition(angle)); } + + /** + * @brief Sends the Servo the highest input possible + * */ + void setMaxPosition() { setPosition(MAX_POS); } + + /** + * @brief Sends the Servo the lowest input possible + * */ + void setMinPosition() { setPosition(MIN_POS); } + + /** + * @brief Sets servo to its reset position + * */ + void reset() { setPosition(RESET_POS); } + + /** + * @return current actuator position (in degrees) + */ + float getCurrentPosition() + { + return currentPosition; + } + + virtual void selfTest() = 0; + + const float MIN_POS = 0; + const float MAX_POS = 0; + const float RESET_POS = 0; + +protected: + /** + * @brief Sends the data to the servo + * + * @param angle Data to be sent to servo + * */ + virtual void setPosition(float angle) = 0; + + /** + * @brief Applies any transformation needed to the data before actually + * sending it to the servo + * + * @param angle Non normalized input position + * + * @returns Normalized input position + * */ + virtual float preprocessPosition(float angle) + { + if (angle > MAX_POS) + { + angle = MAX_POS; + } + else if (angle < MIN_POS) + { + angle = MIN_POS; + } + + return angle; + }; + + /** + * @brief Actuator's current position. + */ + float currentPosition = 0; +}; + +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/configs/AeroBrakesConfig.h b/src/boards/DeathStack/configs/AeroBrakesConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..63c7317d0e23390f60103399f42a8992b85aa451 --- /dev/null +++ b/src/boards/DeathStack/configs/AeroBrakesConfig.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "Constants.h" +#include "drivers/HardwareTimer.h" +#include "drivers/pwm/pwm.h" + +namespace DeathStackBoard +{ +namespace AeroBrakesConfigs +{ + +static const PWM::Timer SERVO_TIMER{ + TIM8, &(RCC->APB2ENR), RCC_APB2ENR_TIM8EN, + TimerUtils::getPrescalerInputFrequency(TimerUtils::InputClock::APB2)}; + +static constexpr PWMChannel SERVO_PWM_CH = PWMChannel::CH2; + +static constexpr uint32_t LOOKS = 50; +static constexpr uint32_t START_INDEX_OFFSET = -1; +static constexpr float M = 22; /**< rocket's mass */ +static constexpr float D = 0.15; /**< rocket's diameter */ +static constexpr float S0 = (PI * D * D) / 4; +static constexpr float RHO = 1.225; +static constexpr float Hn = 10400; +static constexpr float Kp = 77; +static constexpr float Ki = 5; +static constexpr float Co = 340.3; +static constexpr float ALPHA = -3.871e-3; +static constexpr float A = -1.04034; +static constexpr float B = 0.30548; +static constexpr float A_DELTAS = -9.43386 / 1000; +static constexpr float B_DELTAS = 19.86779 / 1000; +static constexpr float DELTA_S_AVAILABLE_MIN = 0; +static constexpr float DELTA_S_AVAILABLE_MAX = 0.01; +static constexpr float DELTA_S_AVAILABLE_STEP = 0.0005; + +static constexpr float SERVO_MAX_POS = 50.99; // deg, 0.89 in radians +static constexpr float SERVO_MIN_POS = 0; // deg +static constexpr float SERVO_MAX_RATE = 60 / 0.2; // deg/s +static constexpr float SERVO_MIN_RATE = -60 / 0.2; // deg/s +static constexpr float SERVO_WIGGLE_AMPLITUDE = 10; // deg, 0.17 in radians + +static constexpr float UPDATE_TIME = 0.05 * 1000; // ms -> 20 Hz + +static constexpr int SHADOW_MODE_DURATION = 7500; + +} // namespace AeroBrakesConfigs + +} // namespace DeathStackBoard \ No newline at end of file diff --git a/src/boards/DeathStack/events/EventStrings.cpp b/src/boards/DeathStack/events/EventStrings.cpp index 495e1ead073c1631b3cb3f74c7ab4cc955c57694..bc401bca0521ee1cc2ca092600a9a56e52f33872 100644 --- a/src/boards/DeathStack/events/EventStrings.cpp +++ b/src/boards/DeathStack/events/EventStrings.cpp @@ -1,5 +1,5 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* Copyright (c) 2018-2020 Skyward Experimental Rocketry + * Authors: Luca Erbetta, Alvise de' Faveri Tron * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,104 +26,94 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 -// Autogen date: 2019-11-06 23:09:09.820014 - - -#include "Events.h" -#include "Topics.h" +// Autogen date: 2021-03-13 22:05:05.465532 #include <map> using std::map; -namespace DeathStackBoard -{ +#include "Events.h" +#include "Topics.h" string getEventString(uint8_t event) { - static const map<uint8_t, string> event_string_map { - { EV_ADA_APOGEE_DETECTED, "EV_ADA_APOGEE_DETECTED" }, - { EV_ADA_DPL_ALT_DETECTED, "EV_ADA_DPL_ALT_DETECTED" }, - { EV_ADA_READY, "EV_ADA_READY" }, - { EV_APOGEE, "EV_APOGEE" }, - { EV_ARMED, "EV_ARMED" }, - { EV_BUTTON_DOWN, "EV_BUTTON_DOWN" }, - { EV_BUTTON_LONG_PRESS, "EV_BUTTON_LONG_PRESS" }, - { EV_BUTTON_SHORT_PRESS, "EV_BUTTON_SHORT_PRESS" }, - { EV_BUTTON_UP, "EV_BUTTON_UP" }, - { EV_BUTTON_VERY_LONG_PRESS, "EV_BUTTON_VERY_LONG_PRESS" }, - { EV_CALIBRATE_ADA, "EV_CALIBRATE_ADA" }, - { EV_CUT_BACKUP, "EV_CUT_BACKUP" }, - { EV_CUT_DROGUE, "EV_CUT_DROGUE" }, - { EV_CUT_PRIMARY, "EV_CUT_PRIMARY" }, - { EV_DISARMED, "EV_DISARMED" }, - { EV_DPL_ALTITUDE, "EV_DPL_ALTITUDE" }, - { EV_FLIGHTSTATS_TIMEOUT, "EV_FLIGHTSTATS_TIMEOUT" }, - { EV_INIT_ERROR, "EV_INIT_ERROR" }, - { EV_INIT_OK, "EV_INIT_OK" }, - { EV_LANDED, "EV_LANDED" }, - { EV_LIFTOFF, "EV_LIFTOFF" }, - { EV_NC_DETACHED, "EV_NC_DETACHED" }, - { EV_NC_OPEN, "EV_NC_OPEN" }, - { EV_RESET_SERVO, "EV_RESET_SERVO" }, - { EV_SEND_HR_TM, "EV_SEND_HR_TM" }, - { EV_SEND_LR_TM, "EV_SEND_LR_TM" }, - { EV_SEND_TEST_TM, "EV_SEND_TEST_TM" }, - { EV_TC_ARM, "EV_TC_ARM" }, - { EV_TC_BOARD_RESET, "EV_TC_BOARD_RESET" }, - { EV_TC_CALIBRATE_ADA, "EV_TC_CALIBRATE_ADA" }, - { EV_TC_CLOSE_LOG, "EV_TC_CLOSE_LOG" }, - { EV_TC_CUT_BACKUP, "EV_TC_CUT_BACKUP" }, - { EV_TC_CUT_DROGUE, "EV_TC_CUT_DROGUE" }, - { EV_TC_CUT_PRIMARY, "EV_TC_CUT_PRIMARY" }, - { EV_TC_DISARM, "EV_TC_DISARM" }, - { EV_TC_END_MISSION, "EV_TC_END_MISSION" }, - { EV_TC_FORCE_INIT, "EV_TC_FORCE_INIT" }, - { EV_TC_LAUNCH, "EV_TC_LAUNCH" }, - { EV_TC_NC_CLOSE, "EV_TC_NC_CLOSE" }, - { EV_TC_NC_OPEN, "EV_TC_NC_OPEN" }, - { EV_TC_RESET_SERVO, "EV_TC_RESET_SERVO" }, - { EV_TC_SET_DPL_ALTITUDE, "EV_TC_SET_DPL_ALTITUDE" }, - { EV_TC_SET_REFERENCE_ALTITUDE, "EV_TC_SET_REFERENCE_ALTITUDE" }, - { EV_TC_SET_REFERENCE_TEMP, "EV_TC_SET_REFERENCE_TEMP" }, - { EV_TC_START_ROGALLO_CONTROL, "EV_TC_START_ROGALLO_CONTROL" }, - { EV_TC_START_SENSOR_LOGGING, "EV_TC_START_SENSOR_LOGGING" }, - { EV_TC_STOP_SENSOR_LOGGING, "EV_TC_STOP_SENSOR_LOGGING" }, - { EV_TC_TEST_CUTTER_BACKUP, "EV_TC_TEST_CUTTER_BACKUP" }, - { EV_TC_TEST_CUTTER_PRIMARY, "EV_TC_TEST_CUTTER_PRIMARY" }, - { EV_TC_TEST_MODE, "EV_TC_TEST_MODE" }, - { EV_TC_WIGGLE_SERVO, "EV_TC_WIGGLE_SERVO" }, - { EV_TEST_CUTTER_BACKUP, "EV_TEST_CUTTER_BACKUP" }, - { EV_TEST_CUTTER_PRIMARY, "EV_TEST_CUTTER_PRIMARY" }, - { EV_TEST_MODE, "EV_TEST_MODE" }, - { EV_TIMEOUT_CUTTING, "EV_TIMEOUT_CUTTING" }, - { EV_TIMEOUT_END_MISSION, "EV_TIMEOUT_END_MISSION" }, - { EV_TIMEOUT_NC_OPEN, "EV_TIMEOUT_NC_OPEN" }, - { EV_TIMEOUT_PRESS_STABILIZATION, "EV_TIMEOUT_PRESS_STABILIZATION" }, - { EV_TIMEOUT_SERVO_RESET, "EV_TIMEOUT_SERVO_RESET" }, - { EV_TIMEOUT_SHADOW_MODE, "EV_TIMEOUT_SHADOW_MODE" }, - { EV_UMBILICAL_DETACHED, "EV_UMBILICAL_DETACHED" }, - { EV_WIGGLE_SERVO, "EV_WIGGLE_SERVO" } + static const map<uint8_t, string> event_string_map{ + {EV_LIFTOFF, "EV_LIFTOFF"}, + {EV_WIGGLE_SERVO, "EV_WIGGLE_SERVO"}, + {EV_RESET_SERVO, "EV_RESET_SERVO"}, + {EV_TEST_ABK, "EV_TEST_ABK"}, + {EV_SHADOW_MODE_TIMEOUT, "EV_SHADOW_MODE_TIMEOUT"}, + {EV_DISABLE_ABK, "EV_DISABLE_ABK"}, + {EV_APOGEE, "EV_APOGEE"}, + {EV_TEST_TIMEOUT, "EV_TEST_TIMEOUT"}, + {EV_ADA_APOGEE_DETECTED, "EV_ADA_APOGEE_DETECTED"}, + {EV_ADA_DPL_ALT_DETECTED, "EV_ADA_DPL_ALT_DETECTED"}, + {EV_ADA_READY, "EV_ADA_READY"}, + {EV_ARMED, "EV_ARMED"}, + {EV_BUTTON_DOWN, "EV_BUTTON_DOWN"}, + {EV_BUTTON_LONG_PRESS, "EV_BUTTON_LONG_PRESS"}, + {EV_BUTTON_SHORT_PRESS, "EV_BUTTON_SHORT_PRESS"}, + {EV_BUTTON_UP, "EV_BUTTON_UP"}, + {EV_BUTTON_VERY_LONG_PRESS, "EV_BUTTON_VERY_LONG_PRESS"}, + {EV_CALIBRATE_ADA, "EV_CALIBRATE_ADA"}, + {EV_CUT_BACKUP, "EV_CUT_BACKUP"}, + {EV_CUT_DROGUE, "EV_CUT_DROGUE"}, + {EV_CUT_PRIMARY, "EV_CUT_PRIMARY"}, + {EV_DISARMED, "EV_DISARMED"}, + {EV_DPL_ALTITUDE, "EV_DPL_ALTITUDE"}, + {EV_FLIGHTSTATS_TIMEOUT, "EV_FLIGHTSTATS_TIMEOUT"}, + {EV_INIT_ERROR, "EV_INIT_ERROR"}, + {EV_INIT_OK, "EV_INIT_OK"}, + {EV_LANDED, "EV_LANDED"}, + {EV_NC_DETACHED, "EV_NC_DETACHED"}, + {EV_NC_OPEN, "EV_NC_OPEN"}, + {EV_SEND_HR_TM, "EV_SEND_HR_TM"}, + {EV_SEND_LR_TM, "EV_SEND_LR_TM"}, + {EV_SEND_TEST_TM, "EV_SEND_TEST_TM"}, + {EV_TC_ARM, "EV_TC_ARM"}, + {EV_TC_BOARD_RESET, "EV_TC_BOARD_RESET"}, + {EV_TC_CALIBRATE_ADA, "EV_TC_CALIBRATE_ADA"}, + {EV_TC_CLOSE_LOG, "EV_TC_CLOSE_LOG"}, + {EV_TC_CUT_BACKUP, "EV_TC_CUT_BACKUP"}, + {EV_TC_CUT_DROGUE, "EV_TC_CUT_DROGUE"}, + {EV_TC_CUT_PRIMARY, "EV_TC_CUT_PRIMARY"}, + {EV_TC_DISARM, "EV_TC_DISARM"}, + {EV_TC_END_MISSION, "EV_TC_END_MISSION"}, + {EV_TC_FORCE_INIT, "EV_TC_FORCE_INIT"}, + {EV_TC_LAUNCH, "EV_TC_LAUNCH"}, + {EV_TC_NC_CLOSE, "EV_TC_NC_CLOSE"}, + {EV_TC_NC_OPEN, "EV_TC_NC_OPEN"}, + {EV_TC_RESET_SERVO, "EV_TC_RESET_SERVO"}, + {EV_TC_SET_DPL_ALTITUDE, "EV_TC_SET_DPL_ALTITUDE"}, + {EV_TC_SET_REFERENCE_ALTITUDE, "EV_TC_SET_REFERENCE_ALTITUDE"}, + {EV_TC_SET_REFERENCE_TEMP, "EV_TC_SET_REFERENCE_TEMP"}, + {EV_TC_START_ROGALLO_CONTROL, "EV_TC_START_ROGALLO_CONTROL"}, + {EV_TC_START_SENSOR_LOGGING, "EV_TC_START_SENSOR_LOGGING"}, + {EV_TC_STOP_SENSOR_LOGGING, "EV_TC_STOP_SENSOR_LOGGING"}, + {EV_TC_TEST_CUTTER_BACKUP, "EV_TC_TEST_CUTTER_BACKUP"}, + {EV_TC_TEST_CUTTER_PRIMARY, "EV_TC_TEST_CUTTER_PRIMARY"}, + {EV_TC_TEST_MODE, "EV_TC_TEST_MODE"}, + {EV_TC_WIGGLE_SERVO, "EV_TC_WIGGLE_SERVO"}, + {EV_TEST_CUTTER_BACKUP, "EV_TEST_CUTTER_BACKUP"}, + {EV_TEST_CUTTER_PRIMARY, "EV_TEST_CUTTER_PRIMARY"}, + {EV_TEST_MODE, "EV_TEST_MODE"}, + {EV_TIMEOUT_CUTTING, "EV_TIMEOUT_CUTTING"}, + {EV_TIMEOUT_END_MISSION, "EV_TIMEOUT_END_MISSION"}, + {EV_TIMEOUT_NC_OPEN, "EV_TIMEOUT_NC_OPEN"}, + {EV_TIMEOUT_PRESS_STABILIZATION, "EV_TIMEOUT_PRESS_STABILIZATION"}, + {EV_TIMEOUT_SERVO_RESET, "EV_TIMEOUT_SERVO_RESET"}, + {EV_TIMEOUT_SHADOW_MODE, "EV_TIMEOUT_SHADOW_MODE"}, + {EV_UMBILICAL_DETACHED, "EV_UMBILICAL_DETACHED"}, }; - auto it = event_string_map.find(event); + auto it = event_string_map.find(event); return it == event_string_map.end() ? "EV_UNKNOWN" : it->second; } string getTopicString(uint8_t topic) { - static const map<uint8_t, string> topic_string_map{ - { TOPIC_ADA, "TOPIC_ADA" }, - { TOPIC_CAN, "TOPIC_CAN" }, - { TOPIC_DEPLOYMENT, "TOPIC_DEPLOYMENT" }, - { TOPIC_FLIGHT_EVENTS, "TOPIC_FLIGHT_EVENTS" }, - { TOPIC_FMM, "TOPIC_FMM" }, - { TOPIC_IGNITION, "TOPIC_IGNITION" }, - { TOPIC_STATS, "TOPIC_STATS" }, - { TOPIC_TC, "TOPIC_TC" }, - { TOPIC_TMTC, "TOPIC_TMTC" } - }; - auto it = topic_string_map.find(topic); - return it == topic_string_map.end() ? "TOPIC_UNKNOWN" : it->second; -} - + static const map<uint8_t, string> topic_string_map{ + {TOPIC_FLIGHT_EVENTS, "TOPIC_FLIGHT_EVENTS"}, + {TOPIC_ABK, "TOPIC_ABK"}, + }; + auto it = topic_string_map.find(topic); + return it == topic_string_map.end() ? "TOPIC_UNKNOWN" : it->second; } \ No newline at end of file diff --git a/src/boards/DeathStack/events/Events.h b/src/boards/DeathStack/events/Events.h index 08a2460eada2cf725b2c0e13a8ab9ee4c1250e98..a4debd2165879c2100758d77421008f61d05f735 100644 --- a/src/boards/DeathStack/events/Events.h +++ b/src/boards/DeathStack/events/Events.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* Copyright (c) 2018-2021 Skyward Experimental Rocketry + * Authors: Luca Erbetta, Alvise de' Faveri Tron * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,7 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 -// Autogen date: 2019-11-06 23:09:09.820014 +// Autogen date: 2021-03-13 22:05:05.465532 #pragma once @@ -35,24 +34,29 @@ #include <string> #include <vector> +#include "Topics.h" #include "events/Event.h" #include "events/EventBroker.h" -#include "Topics.h" using std::string; -namespace DeathStackBoard -{ /** * Definition of all events in the Homeone Board software * Refer to section 5.1.1 of the Software Design Document. */ enum Events : uint8_t { - EV_ADA_APOGEE_DETECTED = EV_FIRST_SIGNAL, + EV_LIFTOFF = EV_FIRST_SIGNAL, + EV_WIGGLE_SERVO, + EV_RESET_SERVO, + EV_TEST_ABK, + EV_SHADOW_MODE_TIMEOUT, + EV_DISABLE_ABK, + EV_APOGEE, + EV_TEST_TIMEOUT, + EV_ADA_APOGEE_DETECTED, EV_ADA_DPL_ALT_DETECTED, EV_ADA_READY, - EV_APOGEE, EV_ARMED, EV_BUTTON_DOWN, EV_BUTTON_LONG_PRESS, @@ -70,10 +74,8 @@ enum Events : uint8_t EV_INIT_ERROR, EV_INIT_OK, EV_LANDED, - EV_LIFTOFF, EV_NC_DETACHED, EV_NC_OPEN, - EV_RESET_SERVO, EV_SEND_HR_TM, EV_SEND_LR_TM, EV_SEND_TEST_TM, @@ -111,17 +113,81 @@ enum Events : uint8_t EV_TIMEOUT_SERVO_RESET, EV_TIMEOUT_SHADOW_MODE, EV_UMBILICAL_DETACHED, - EV_WIGGLE_SERVO }; -const std::vector<uint8_t> EVENT_LIST {EV_ADA_APOGEE_DETECTED, EV_ADA_DPL_ALT_DETECTED, EV_ADA_READY, EV_APOGEE, EV_ARMED, EV_BUTTON_DOWN, EV_BUTTON_LONG_PRESS, EV_BUTTON_SHORT_PRESS, EV_BUTTON_UP, EV_BUTTON_VERY_LONG_PRESS, EV_CALIBRATE_ADA, EV_CUT_BACKUP, EV_CUT_DROGUE, EV_CUT_PRIMARY, EV_DISARMED, EV_DPL_ALTITUDE, EV_FLIGHTSTATS_TIMEOUT, EV_INIT_ERROR, EV_INIT_OK, EV_LANDED, EV_LIFTOFF, EV_NC_DETACHED, EV_NC_OPEN, EV_RESET_SERVO, EV_SEND_HR_TM, EV_SEND_LR_TM, EV_SEND_TEST_TM, EV_TC_ARM, EV_TC_BOARD_RESET, EV_TC_CALIBRATE_ADA, EV_TC_CLOSE_LOG, EV_TC_CUT_BACKUP, EV_TC_CUT_DROGUE, EV_TC_CUT_PRIMARY, EV_TC_DISARM, EV_TC_END_MISSION, EV_TC_FORCE_INIT, EV_TC_LAUNCH, EV_TC_NC_CLOSE, EV_TC_NC_OPEN, EV_TC_RESET_SERVO, EV_TC_SET_DPL_ALTITUDE, EV_TC_SET_REFERENCE_ALTITUDE, EV_TC_SET_REFERENCE_TEMP, EV_TC_START_ROGALLO_CONTROL, EV_TC_START_SENSOR_LOGGING, EV_TC_STOP_SENSOR_LOGGING, EV_TC_TEST_CUTTER_BACKUP, EV_TC_TEST_CUTTER_PRIMARY, EV_TC_TEST_MODE, EV_TC_WIGGLE_SERVO, EV_TEST_CUTTER_BACKUP, EV_TEST_CUTTER_PRIMARY, EV_TEST_MODE, EV_TIMEOUT_CUTTING, EV_TIMEOUT_END_MISSION, EV_TIMEOUT_NC_OPEN, EV_TIMEOUT_PRESS_STABILIZATION, EV_TIMEOUT_SERVO_RESET, EV_TIMEOUT_SHADOW_MODE, EV_UMBILICAL_DETACHED, EV_WIGGLE_SERVO}; +const std::vector<uint8_t> EVENT_LIST{ + EV_LIFTOFF, + EV_WIGGLE_SERVO, + EV_RESET_SERVO, + EV_TEST_ABK, + EV_SHADOW_MODE_TIMEOUT, + EV_DISABLE_ABK, + EV_APOGEE, + EV_TEST_TIMEOUT, + EV_ADA_APOGEE_DETECTED, + EV_ADA_DPL_ALT_DETECTED, + EV_ADA_READY, + EV_ARMED, + EV_BUTTON_DOWN, + EV_BUTTON_LONG_PRESS, + EV_BUTTON_SHORT_PRESS, + EV_BUTTON_UP, + EV_BUTTON_VERY_LONG_PRESS, + EV_CALIBRATE_ADA, + EV_CUT_BACKUP, + EV_CUT_DROGUE, + EV_CUT_PRIMARY, + EV_DISARMED, + EV_DPL_ALTITUDE, + EV_FLIGHTSTATS_TIMEOUT, + EV_INIT_ERROR, + EV_INIT_OK, + EV_LANDED, + EV_NC_DETACHED, + EV_NC_OPEN, + EV_SEND_HR_TM, + EV_SEND_LR_TM, + EV_SEND_TEST_TM, + EV_TC_ARM, + EV_TC_BOARD_RESET, + EV_TC_CALIBRATE_ADA, + EV_TC_CLOSE_LOG, + EV_TC_CUT_BACKUP, + EV_TC_CUT_DROGUE, + EV_TC_CUT_PRIMARY, + EV_TC_DISARM, + EV_TC_END_MISSION, + EV_TC_FORCE_INIT, + EV_TC_LAUNCH, + EV_TC_NC_CLOSE, + EV_TC_NC_OPEN, + EV_TC_RESET_SERVO, + EV_TC_SET_DPL_ALTITUDE, + EV_TC_SET_REFERENCE_ALTITUDE, + EV_TC_SET_REFERENCE_TEMP, + EV_TC_START_ROGALLO_CONTROL, + EV_TC_START_SENSOR_LOGGING, + EV_TC_STOP_SENSOR_LOGGING, + EV_TC_TEST_CUTTER_BACKUP, + EV_TC_TEST_CUTTER_PRIMARY, + EV_TC_TEST_MODE, + EV_TC_WIGGLE_SERVO, + EV_TEST_CUTTER_BACKUP, + EV_TEST_CUTTER_PRIMARY, + EV_TEST_MODE, + EV_TIMEOUT_CUTTING, + EV_TIMEOUT_END_MISSION, + EV_TIMEOUT_NC_OPEN, + EV_TIMEOUT_PRESS_STABILIZATION, + EV_TIMEOUT_SERVO_RESET, + EV_TIMEOUT_SHADOW_MODE, + EV_UMBILICAL_DETACHED, +}; /** * @brief Returns the name of the provided event - * - * @param event - * @return string + * + * @param event + * @return string */ -string getEventString(uint8_t event); - -} +string getEventString(uint8_t event); \ No newline at end of file diff --git a/src/boards/DeathStack/events/Topics.h b/src/boards/DeathStack/events/Topics.h index 48f9f322c3db48c9752d4a8013e6183eef7d3770..be4a0c8701376ef5a17b1106d1edf4ddbf74abe8 100644 --- a/src/boards/DeathStack/events/Topics.h +++ b/src/boards/DeathStack/events/Topics.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Authors: Luca Erbetta +/* Copyright (c) 2018-2021 Skyward Experimental Rocketry + * Authors: Luca Erbetta, Alvise de' Faveri Tron * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,36 +26,45 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 -// Autogen date: 2019-11-06 23:09:09.820014 +// Autogen date: 2021-03-13 22:05:05.465532 #pragma once -#include <stdint.h> +#include <cstdint> #include <string> #include <vector> using std::string; -namespace DeathStackBoard -{ /** * Definition of various event topics to use in the EventBroker */ enum Topics : uint8_t { - TOPIC_ADA, + TOPIC_FLIGHT_EVENTS, + TOPIC_ABK, TOPIC_CAN, TOPIC_DEPLOYMENT, - TOPIC_FLIGHT_EVENTS, TOPIC_FMM, TOPIC_IGNITION, TOPIC_STATS, TOPIC_TC, - TOPIC_TMTC + TOPIC_TMTC, + TOPIC_ADA }; -const std::vector<uint8_t> TOPIC_LIST {TOPIC_ADA, TOPIC_CAN, TOPIC_DEPLOYMENT, TOPIC_FLIGHT_EVENTS, TOPIC_FMM, TOPIC_IGNITION, TOPIC_STATS, TOPIC_TC, TOPIC_TMTC}; +const std::vector<uint8_t> TOPIC_LIST{ + TOPIC_FLIGHT_EVENTS, + TOPIC_ABK, + TOPIC_CAN, + TOPIC_DEPLOYMENT, + TOPIC_FMM, + TOPIC_IGNITION, + TOPIC_STATS, + TOPIC_TC, + TOPIC_TMTC, + TOPIC_ADA +}; /** * @brief Returns the name of the provided event @@ -63,7 +72,4 @@ const std::vector<uint8_t> TOPIC_LIST {TOPIC_ADA, TOPIC_CAN, TOPIC_DEPLOYMENT, T * @param event * @return string */ -string getTopicString(uint8_t topic); - -} // namespace DeathStackBoard - +string getTopicString(uint8_t topic); \ No newline at end of file diff --git a/src/tests/aerobrakes/test-aerobrakes-algorithm.cpp b/src/tests/aerobrakes/test-aerobrakes-algorithm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..446c4454ed081285c46631768401342b4eb65861 --- /dev/null +++ b/src/tests/aerobrakes/test-aerobrakes-algorithm.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <miosix.h> + +#include <cmath> +#include <cstdio> +#include <iostream> +#include <sstream> +#include <string> + +#define private public + +#include "AeroBrakesController/AeroBrakesControlAlgorithm.h" +#include "AeroBrakesController/AeroBrakesServo.h" +#include "drivers/HardwareTimer.h" +#include "sensors/Sensor.h" +#include "test_data.h" + +using namespace DeathStackBoard; +using namespace std; +class MockActuator : public AeroBrakesServo +{ +public: + MockActuator() {} + // void setPosition(float alpha) { lastAlpha = round(alpha * 180 / PI); } + float error(float alphaTest) { return abs(alphaTest - currentPosition); } + + // private: + // int lastAlpha; +}; + +template <typename T> +class MockSensor : public Sensor<T> +{ +private: + int ts = 0; + +protected: + T sampleImpl() override + { + input_t input = DATA[ts].input; + T sampled; + + sampled.z = input.z; + sampled.vz = input.vz; + sampled.vMod = input.vMod; + sampled.timestamp = ts; + + ts++; + + return sampled; + } + + bool init() override { return true; } + + bool selfTest() override { return true; } +}; + +class InputClass +{ +public: + float z; + float vz; + float vMod; + uint64_t timestamp; +}; + +MockActuator mockActuator; +MockSensor<InputClass> mockSensor; +AeroBrakesControlAlgorithm<InputClass> algorithm(mockSensor, &mockActuator); + +int main() +{ + { + miosix::FastInterruptDisableLock dLock; + + // Enable TIM5 peripheral clocks + RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; + } + + input_t input; + + input = DATA[0].input; + + HardwareTimer<uint32_t> hrclock( + TIM5, + TimerUtils::getPrescalerInputFrequency(TimerUtils::InputClock::APB1)); + hrclock.setPrescaler(127); + hrclock.start(); + + mockSensor.sample(); + + uint32_t t1 = hrclock.tick(); + algorithm.begin(); + uint32_t t2 = hrclock.tick(); + + float startTime = hrclock.toMilliSeconds(t2 - t1); + float stepTime = 0; + int maxAlphaError = 0; + + for (int i = 1; i < LEN_TEST; i++) + { + mockSensor.sample(); + t1 = hrclock.tick(); + algorithm.update(); + t2 = hrclock.tick(); + + int error = mockActuator.error(DATA[i].output.alpha); + + if (error > maxAlphaError) + { + maxAlphaError = error; + } + + stepTime += hrclock.toMilliSeconds(t2 - t1); + + cout << "z: " << mockSensor.getLastSample().z + << "\tvz: " << mockSensor.getLastSample().vz + << "\tvMod: " << mockSensor.getLastSample().vMod + << "\tservo: " << mockActuator.getCurrentPosition() << "\n"; + } + + miosix::Thread::sleep(AeroBrakesConfigs::UPDATE_TIME); + + printf("Max alpha error: %d\n", maxAlphaError); + + printf( + "Init time: %f ms\nAvg iter time: %f ms\nTotal computation time: %f " + "ms\n", + startTime, stepTime / (LEN_TEST - 1), stepTime + startTime); + + // avoid reboot + while (1) + { + } +} \ No newline at end of file diff --git a/src/tests/aerobrakes/test-aerobrakes-interactive.cpp b/src/tests/aerobrakes/test-aerobrakes-interactive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50be6426fe5155fce0b03c73ad8ef91404c6d748 --- /dev/null +++ b/src/tests/aerobrakes/test-aerobrakes-interactive.cpp @@ -0,0 +1,372 @@ +/** + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <miosix.h> + +#include <cstdio> +#include <iostream> +#include <sstream> +#include <string> + +#include "AeroBrakesController/AeroBrakesController.h" +#include "AeroBrakesController/AeroBrakesServo.h" +#include "events/Events.h" +#include "test_data.h" +#include "utils/testutils/TestHelper.h" + +using namespace DeathStackBoard; + +using namespace std; + +void testAlgorithm(); +void testAeroBrakes(); +void wiggleServo(); +void setServoFullyOpen(); +void setServoFullyClosed(); +void resetServo(); +void manualServoControl(); +void setServoParameters(); +void resetServoParameters(); +void waitUserInput(); + +class InputClass +{ +public: + float z; + float vz; + float vMod; + uint64_t timestamp; +}; + +template <typename T> +class MockSensor : public Sensor<T> +{ +private: + int ts = 0; + +protected: + T sampleImpl() override + { + input_t input = DATA[ts].input; + T sampled; + + sampled.z = input.z; + sampled.vz = input.vz; + sampled.vMod = input.vMod; + sampled.timestamp = ts; + + ts++; + + return sampled; + } + + bool init() override { return true; } + + bool selfTest() override { return true; } +}; + +float minPosition = AeroBrakesConfigs::SERVO_MIN_POS; +float maxPosition = AeroBrakesConfigs::SERVO_MAX_POS; +float resetPosition = AeroBrakesConfigs::SERVO_MIN_POS; + +int main() +{ + sEventBroker->start(); + + miosix::GpioPin pwmPin = miosix::GpioPin(GPIOC_BASE, 7); + pwmPin.mode(miosix::Mode::ALTERNATE); + pwmPin.alternateFunction(3); + + string temp; + for (;;) + { + int choice; + cout << "\n\nWhat do you want to do?:\n"; + cout << "1. Aerobrakes algorithm simulation (with test data)\n"; + cout << "2. Aerobrakes full extension\n"; + cout << "3. Servo wiggle\n"; + cout << "4. Servo fully open\n"; + cout << "5. Servo fully closed\n"; + cout << "6. Servo reset\n"; + cout << "7. Servo manual control\n"; + cout << "8. Set servo parameters\n"; + cout << "9. Reset servo parameters (default)\n"; + + getline(cin, temp); + stringstream(temp) >> choice; + + switch (choice) + { + case 1: + testAlgorithm(); + break; + case 2: + testAeroBrakes(); + break; + case 3: + wiggleServo(); + break; + case 4: + setServoFullyOpen(); + break; + case 5: + setServoFullyClosed(); + break; + case 6: + resetServo(); + break; + case 7: + manualServoControl(); + break; + case 8: + setServoParameters(); + break; + case 9: + resetServoParameters(); + break; + default: + cout << "Invalid option \n"; + break; + } + } +} + +void testAlgorithm() +{ + cout << "\n\n** AEROBRAKES ALGORITHM SIMULATION **\n\n"; + + waitUserInput(); + + // AeroBrakesController initialization + MockSensor<InputClass> sensor; + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + AeroBrakesController<InputClass> aerobrakesController(sensor, &servo); + + // Start the state machine + aerobrakesController.start(); + sensor.sample(); + EventCounter counter{*sEventBroker}; + counter.subscribe(TOPIC_FLIGHT_EVENTS); + + // Start test + cout << "Starting aerobrakes test\n"; + sEventBroker->post({EV_LIFTOFF}, TOPIC_FLIGHT_EVENTS); + while (counter.getCount(EV_SHADOW_MODE_TIMEOUT) < 1) + { + Thread::sleep(10); + } + + for (int i = 1; i < LEN_TEST; i++) + { + sensor.sample(); + aerobrakesController.update(); + cout << "z: " << sensor.getLastSample().z + << "\tvz: " << sensor.getLastSample().vz + << "\tvMod: " << sensor.getLastSample().vMod + << "\tservo: " << servo.getCurrentPosition() << "\n"; + Thread::sleep(AeroBrakesConfigs::UPDATE_TIME); + } + + aerobrakesController.stop(); + counter.stop(); + + cout << "\n\tTest finished!\n"; +} + +void testAeroBrakes() +{ + cout << "\n\n** AEROBRAKES FULL EXTENSION **\n\n"; + + waitUserInput(); + + // AeroBrakesController initialization + MockSensor<InputClass> sensor{}; + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + AeroBrakesController<InputClass> aerobrakesController{sensor, &servo}; + + // Start the state machine + aerobrakesController.start(); + EventCounter counter{*sEventBroker}; + counter.subscribe(TOPIC_ABK); + + // Start test + cout << "Starting aerobrakes test\n"; + sEventBroker->post({EV_TEST_ABK}, TOPIC_ABK); + + while (counter.getCount(EV_TEST_TIMEOUT) < 1) + { + Thread::sleep(100); + } + + aerobrakesController.stop(); + counter.stop(); + + cout << "\n\tTest finished!\n"; +} + +void wiggleServo() +{ + string temp; + cout << "\n\n** WIGGLE SERVO **\n\n"; + + waitUserInput(); + + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + servo.enable(); + + cout << "Wiggling ... \n"; + servo.selfTest(); + Thread::sleep(10000); + servo.disable(); + + cout << "\n\tDone!\n"; +} + +void setServoFullyOpen() +{ + string temp; + cout << "\n\n** SERVO FULLY OPEN **\n\n"; + + waitUserInput(); + + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + servo.enable(); + servo.setMaxPosition(); + Thread::sleep(10000); + servo.disable(); + + cout << "\n\tDone!\n"; +} + +void setServoFullyClosed() +{ + string temp; + cout << "\n\n** SERVO FULLY CLOSED **\n\n"; + + waitUserInput(); + + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + servo.enable(); + servo.setMinPosition(); + Thread::sleep(10000); + servo.disable(); + + cout << "\n\tDone!\n"; +} + +void resetServo() +{ + string temp; + cout << "\n\n** RESET SERVO **\n\n"; + + waitUserInput(); + + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + servo.enable(); + servo.reset(); + Thread::sleep(1000); + servo.disable(); + + cout << "\n\tDone!\n"; +} + +void manualServoControl() +{ + cout << "\n\n** MANUAL SERVO CONTROL **\n\n"; + + string temp; + float angle; + do + { + cout << "Write the servo postion (degrees):\n"; + getline(cin, temp); + stringstream(temp) >> angle; + } while (angle < minPosition || angle > maxPosition); + + AeroBrakesServo servo{minPosition, maxPosition, resetPosition}; + + servo.enable(); + while (servo.getCurrentPosition() != angle) + { + servo.set(angle); + Thread::sleep(AeroBrakesConfigs::UPDATE_TIME); + } + Thread::sleep(100); + servo.disable(); + + cout << "\n\tDone!\n"; +} + +void setServoParameters() +{ + cout << "\n\n** SET SERVO PARAMETERS **\n\n"; + + string temp; + do + { + cout << "Write the servo minimum postion (degrees):\n"; + getline(cin, temp); + stringstream(temp) >> minPosition; + } while (minPosition < 0 || minPosition > 180.0f); + + do + { + cout << "Write the servo maximum postion (degrees):\n"; + getline(cin, temp); + stringstream(temp) >> maxPosition; + } while (maxPosition < 0 || maxPosition > 180.0f); + + do + { + cout << "Write the servo reset postion (degrees):\n"; + getline(cin, temp); + stringstream(temp) >> resetPosition; + } while (resetPosition < 0 || resetPosition > 180.0f); + + cout << "Configured parameteres:\n"; + cout << "\tminimum position: " << minPosition << "\n"; + cout << "\tmaximum position: " << maxPosition << "\n"; + cout << "\treset position: " << resetPosition << "\n"; +} + +void resetServoParameters() +{ + minPosition = AeroBrakesConfigs::SERVO_MIN_POS; + maxPosition = AeroBrakesConfigs::SERVO_MAX_POS; + resetPosition = AeroBrakesConfigs::SERVO_MIN_POS; + + cout << "Configured parameteres (default):\n"; + cout << "\tminimum position: " << minPosition << "\n"; + cout << "\tmaximum position: " << maxPosition << "\n"; + cout << "\treset position: " << resetPosition << "\n"; +} + +void waitUserInput() +{ + string temp; + do + { + cout << "Write 'start' to begin the test:\n"; + getline(cin, temp); + } while (temp != "start"); +} \ No newline at end of file diff --git a/src/tests/aerobrakes/test_data.h b/src/tests/aerobrakes/test_data.h new file mode 100644 index 0000000000000000000000000000000000000000..a937b6966b2a1d64f6bd56005868f40428773987 --- /dev/null +++ b/src/tests/aerobrakes/test_data.h @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Vincenzo Santomarco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +static const int LEN_TEST = 169; + +struct input_t +{ + float z; + float vz; + float vMod; + float sampleTime; +}; + +struct output_t +{ + float z_setpoint; + float vz_setpoint; + float u; + float deltas; + int alpha; +}; + +struct test_t +{ + input_t input; + output_t output; +}; + +const test_t DATA[LEN_TEST] = { + {{1407.523534, 223.918458, 232.831273, 0.1}, + {1410.698478, 224.370516, 0.000000, 0.000000, 0}}, + {{1429.826222, 222.137686, 231.046739, 0.1}, + {1433.007837, 221.822602, 22.001227, 0.000000, 0}}, + {{1451.951540, 220.370997, 229.276914, 0.1}, + {1455.064742, 219.321178, 83.824886, 0.000000, 0}}, + {{1473.900883, 218.618135, 227.521532, 0.1}, + {1476.873741, 216.864257, 146.806876, 0.000000, 0}}, + {{1495.675620, 216.878841, 225.780334, 0.1}, + {1498.439192, 214.449971, 210.925533, 0.002500, 8}}, + {{1517.277018, 215.150907, 224.051216, 0.1}, + {1519.765268, 212.076566, 275.998544, 0.004500, 15}}, + {{1538.692467, 213.164813, 222.050419, 0.1}, + {1540.855976, 209.742391, 319.912919, 0.006000, 21}}, + {{1559.896941, 210.929504, 219.786565, 0.1}, + {1561.715159, 207.445889, 342.042809, 0.007000, 26}}, + {{1580.868317, 208.503942, 217.321830, 0.1}, + {1582.346512, 205.185595, 345.908908, 0.007000, 26}}, + {{1601.589631, 205.929325, 214.699801, 0.1}, + {1602.753584, 202.960124, 333.870736, 0.007000, 26}}, + {{1622.055564, 203.396178, 212.121054, 0.1}, + {1622.939793, 200.768167, 320.739091, 0.007000, 26}}, + {{1642.270215, 200.903468, 209.584307, 0.1}, + {1642.908428, 198.608488, 306.570638, 0.007000, 26}}, + {{1662.237560, 198.449839, 207.088281, 0.1}, + {1662.662657, 196.479916, 291.390833, 0.007000, 26}}, + {{1681.961982, 196.058211, 204.657393, 0.1}, + {1682.205536, 194.381342, 277.209978, 0.006500, 23}}, + {{1701.451202, 193.731747, 202.294942, 0.1}, + {1701.540011, 192.311716, 264.533577, 0.006500, 23}}, + {{1720.712684, 191.503026, 200.035297, 0.1}, + {1720.668927, 190.270041, 256.296072, 0.006500, 23}}, + {{1739.752816, 189.304576, 197.807258, 0.1}, + {1739.595032, 188.255368, 247.391254, 0.006500, 23}}, + {{1758.574577, 187.135466, 195.609965, 0.1}, + {1758.320980, 186.266798, 237.832929, 0.006000, 21}}, + {{1777.180861, 184.994918, 193.442602, 0.1}, + {1776.849338, 184.303477, 227.643718, 0.006000, 21}}, + {{1795.578146, 182.954926, 191.381404, 0.1}, + {1795.182591, 182.364588, 222.810466, 0.006000, 21}}, + {{1813.772666, 180.939526, 189.345943, 0.1}, + {1813.323143, 180.449357, 217.548324, 0.006000, 21}}, + {{1831.767240, 178.960146, 187.348411, 0.1}, + {1831.273322, 178.557045, 212.859568, 0.006000, 21}}, + {{1849.565570, 177.010170, 185.381850, 0.1}, + {1849.035385, 176.686946, 208.325170, 0.006000, 21}}, + {{1867.170012, 175.082317, 183.438539, 0.1}, + {1866.611519, 174.838389, 203.439009, 0.006000, 21}}, + {{1884.582753, 173.176068, 181.517929, 0.1}, + {1884.003846, 173.010730, 198.214336, 0.006000, 21}}, + {{1901.805928, 171.290886, 179.619473, 0.1}, + {1901.214426, 171.203355, 192.660780, 0.006000, 21}}, + {{1918.841611, 169.426147, 177.742548, 0.1}, + {1918.245256, 169.415678, 186.779343, 0.006000, 21}}, + {{1935.691826, 167.581464, 175.886774, 0.1}, + {1935.098279, 167.647137, 180.588101, 0.006000, 21}}, + {{1952.358556, 165.756368, 174.051669, 0.1}, + {1951.775381, 165.897193, 174.097177, 0.006000, 21}}, + {{1968.843737, 163.950404, 172.236762, 0.1}, + {1968.278396, 164.165332, 167.316651, 0.006000, 21}}, + {{1985.149439, 162.169295, 170.448186, 0.1}, + {1984.609107, 162.451059, 160.761439, 0.005500, 19}}, + {{2001.278287, 160.410614, 168.683383, 0.1}, + {2000.769249, 160.753900, 154.307788, 0.005500, 19}}, + {{2017.233572, 158.697809, 166.967443, 0.1}, + {2016.760511, 159.073401, 149.942314, 0.005500, 19}}, + {{2033.018389, 157.001195, 165.268700, 0.1}, + {2032.584538, 157.409124, 145.412723, 0.005500, 19}}, + {{2048.634338, 155.320412, 163.586791, 0.1}, + {2048.242929, 155.760649, 140.723784, 0.005500, 19}}, + {{2064.082987, 153.655113, 161.921368, 0.1}, + {2063.737245, 154.127573, 135.880349, 0.005000, 17}}, + {{2079.365866, 152.004960, 160.272087, 0.1}, + {2079.069006, 152.509506, 130.886994, 0.005000, 17}}, + {{2094.486432, 150.408612, 158.680445, 0.1}, + {2094.239695, 150.906075, 128.945069, 0.005000, 17}}, + {{2109.448027, 148.825441, 157.102924, 0.1}, + {2109.250756, 149.316919, 126.948556, 0.005000, 17}}, + {{2124.251954, 147.255236, 155.539324, 0.1}, + {2124.103601, 147.741691, 124.903075, 0.005000, 17}}, + {{2138.899517, 145.698979, 153.990723, 0.1}, + {2138.799604, 146.180055, 122.911826, 0.005500, 19}}, + {{2153.392272, 144.158165, 152.458755, 0.1}, + {2153.340110, 144.631690, 121.125681, 0.005500, 19}}, + {{2167.729859, 142.595759, 150.903540, 0.1}, + {2167.726428, 143.096281, 116.544249, 0.005000, 17}}, + {{2181.911853, 141.046238, 149.362216, 0.1}, + {2181.959840, 141.573528, 111.846697, 0.005000, 17}}, + {{2195.941149, 139.541589, 147.869341, 0.1}, + {2196.041597, 140.063140, 109.680869, 0.005000, 17}}, + {{2209.820551, 138.048329, 146.388841, 0.1}, + {2209.972921, 138.564834, 107.486848, 0.005000, 17}}, + {{2223.551186, 136.566227, 144.920493, 0.1}, + {2223.755007, 137.078337, 105.264693, 0.005000, 17}}, + {{2237.134161, 135.095065, 143.464081, 0.1}, + {2237.389022, 135.603386, 103.014797, 0.005000, 17}}, + {{2250.570557, 133.634627, 142.019394, 0.1}, + {2250.876108, 134.139726, 100.737494, 0.005000, 17}}, + {{2263.861436, 132.184701, 140.586228, 0.1}, + {2264.217381, 132.687107, 98.432779, 0.005000, 17}}, + {{2277.007840, 130.745074, 139.164381, 0.1}, + {2277.413934, 131.245290, 96.100334, 0.005000, 17}}, + {{2290.010788, 129.315539, 137.753660, 0.1}, + {2290.466835, 129.814042, 93.739752, 0.005000, 17}}, + {{2302.871343, 127.897638, 136.355777, 0.1}, + {2303.377130, 128.393136, 91.493595, 0.005000, 17}}, + {{2315.590644, 126.489974, 134.969234, 0.1}, + {2316.145842, 126.982353, 89.271851, 0.005000, 17}}, + {{2328.169653, 125.091761, 133.593199, 0.1}, + {2328.773972, 125.581479, 87.028189, 0.005000, 17}}, + {{2340.609305, 123.702814, 132.227500, 0.1}, + {2341.262502, 124.190307, 84.762076, 0.005000, 17}}, + {{2352.910518, 122.322948, 130.871970, 0.1}, + {2353.612390, 122.808635, 82.472658, 0.005000, 17}}, + {{2365.074191, 120.951981, 129.526447, 0.1}, + {2365.824578, 121.436267, 80.159115, 0.005000, 17}}, + {{2377.101205, 119.589741, 128.190773, 0.1}, + {2377.899985, 120.073012, 77.820896, 0.005000, 17}}, + {{2388.992425, 118.236061, 126.864795, 0.1}, + {2389.839515, 118.718683, 75.457721, 0.004500, 15}}, + {{2400.748697, 116.890780, 125.548366, 0.1}, + {2401.644050, 117.373101, 73.069412, 0.004500, 15}}, + {{2412.371612, 115.568806, 124.257936, 0.1}, + {2413.314456, 116.036087, 71.891017, 0.004500, 15}}, + {{2423.862714, 114.254488, 122.976329, 0.1}, + {2424.851582, 114.707470, 70.727132, 0.005000, 17}}, + {{2435.222760, 112.947681, 121.703422, 0.1}, + {2436.256259, 113.387082, 69.575894, 0.005000, 17}}, + {{2446.451788, 111.634162, 120.423512, 0.1}, + {2447.529301, 112.074759, 67.280809, 0.004500, 15}}, + {{2457.549877, 110.328894, 119.153172, 0.1}, + {2458.671507, 110.770342, 65.008026, 0.004500, 15}}, + {{2468.518481, 109.044366, 117.906294, 0.1}, + {2469.683660, 109.473673, 63.796332, 0.004500, 15}}, + {{2479.358982, 107.766798, 116.667643, 0.1}, + {2480.566527, 108.184601, 62.593195, 0.004500, 15}}, + {{2490.072068, 106.496060, 115.437113, 0.1}, + {2491.320859, 106.902976, 61.396891, 0.005000, 17}}, + {{2500.658417, 105.231983, 114.214575, 0.1}, + {2501.947396, 105.628652, 60.202504, 0.005000, 17}}, + {{2511.118055, 103.961930, 112.985948, 0.1}, + {2512.446858, 104.361488, 57.982258, 0.004500, 15}}, + {{2521.451029, 102.698677, 111.765518, 0.1}, + {2522.819957, 103.101343, 55.729628, 0.004500, 15}}, + {{2531.658591, 101.453613, 110.566106, 0.1}, + {2533.067385, 101.848081, 54.388563, 0.004500, 15}}, + {{2541.741959, 100.214775, 109.374353, 0.1}, + {2543.189826, 100.601569, 53.045474, 0.004500, 15}}, + {{2551.701750, 98.982052, 108.190179, 0.1}, + {2553.187947, 99.361675, 51.699514, 0.004500, 15}}, + {{2561.538570, 97.755336, 107.013501, 0.1}, + {2563.062404, 98.128272, 50.349771, 0.004500, 15}}, + {{2571.253014, 96.534517, 105.844243, 0.1}, + {2572.813840, 96.901233, 48.995142, 0.004500, 15}}, + {{2580.845666, 95.319487, 104.682332, 0.1}, + {2582.442885, 95.680437, 47.634353, 0.004500, 15}}, + {{2590.317100, 94.110134, 103.527695, 0.1}, + {2591.950157, 94.465761, 46.266054, 0.004500, 15}}, + {{2599.667867, 92.906047, 102.379915, 0.1}, + {2601.336262, 93.257089, 44.863988, 0.004500, 15}}, + {{2608.898492, 91.707370, 101.239199, 0.1}, + {2610.601795, 92.054303, 43.445653, 0.004000, 13}}, + {{2618.009521, 90.514092, 100.105582, 0.1}, + {2619.747339, 90.857290, 42.017225, 0.004000, 13}}, + {{2627.002040, 89.337126, 98.991641, 0.1}, + {2628.773466, 89.665938, 41.480883, 0.004000, 13}}, + {{2635.877108, 88.165040, 97.884362, 0.1}, + {2637.680735, 88.480138, 40.961420, 0.004500, 15}}, + {{2644.635208, 86.997737, 96.783700, 0.1}, + {2646.469697, 87.299782, 40.456275, 0.004500, 15}}, + {{2653.276298, 85.824893, 95.677786, 0.1}, + {2655.140892, 86.124763, 39.124360, 0.004500, 15}}, + {{2661.800350, 84.656946, 94.578723, 0.1}, + {2663.694846, 84.954979, 37.775662, 0.004500, 15}}, + {{2670.207848, 83.493807, 93.486471, 0.1}, + {2672.132080, 83.790326, 36.409646, 0.004000, 13}}, + {{2678.499269, 82.335394, 92.400999, 0.1}, + {2680.453100, 82.630705, 35.026106, 0.004000, 13}}, + {{2686.675545, 81.190866, 91.333090, 0.1}, + {2688.658406, 81.476016, 34.382681, 0.004000, 13}}, + {{2694.737585, 80.050628, 90.271622, 0.1}, + {2696.748485, 80.326164, 33.745383, 0.004000, 13}}, + {{2702.685811, 78.914571, 89.216537, 0.1}, + {2700.750465, 79.753021, 0.000000, 0.000000, 0}}, + {{2710.520635, 77.782587, 88.167786, 0.1}, + {2708.668599, 78.610244, 0.000000, 0.000000, 0}}, + {{2718.244674, 76.698652, 87.177631, 0.1}, + {2716.472686, 77.472068, 0.000000, 0.000000, 0}}, + {{2725.860456, 75.617439, 86.192585, 0.1}, + {2724.163181, 76.338400, 0.000000, 0.000000, 0}}, + {{2733.368175, 74.537122, 85.210554, 0.1}, + {2731.740532, 75.209151, 0.000000, 0.000000, 0}}, + {{2740.767967, 73.459160, 84.233359, 0.1}, + {2739.205174, 74.084232, 2.638818, 0.000000, 0}}, + {{2748.060095, 72.383840, 83.261426, 0.1}, + {2746.557537, 72.963557, 3.232653, 0.000000, 0}}, + {{2755.244822, 71.311123, 82.294793, 0.1}, + {2753.798041, 71.847038, 3.925782, 0.000000, 0}}, + {{2762.322406, 70.240971, 81.333504, 0.1}, + {2760.927097, 70.734592, 4.714279, 0.000000, 0}}, + {{2769.293100, 69.173345, 80.377603, 0.1}, + {2767.945109, 69.626135, 5.594345, 0.000000, 0}}, + {{2776.157158, 68.108208, 79.427143, 0.1}, + {2774.852471, 68.521586, 6.562208, 0.000000, 0}}, + {{2782.914824, 67.045519, 78.482177, 0.1}, + {2781.649570, 67.420863, 7.614075, 0.000000, 0}}, + {{2789.566341, 65.985236, 77.542764, 0.1}, + {2788.336784, 66.323887, 8.746139, 0.000000, 0}}, + {{2796.111950, 64.927316, 76.608969, 0.1}, + {2794.914485, 65.230580, 9.954627, 0.000000, 0}}, + {{2802.551882, 63.871717, 75.680859, 0.1}, + {2801.383035, 64.140865, 11.235865, 0.000000, 0}}, + {{2808.886369, 62.818398, 74.758508, 0.1}, + {2807.742790, 63.054665, 12.586344, 0.000000, 0}}, + {{2815.115636, 61.767318, 73.841996, 0.1}, + {2813.994097, 61.971905, 14.002770, 0.000000, 0}}, + {{2821.239906, 60.718440, 72.931408, 0.1}, + {2820.137297, 60.892512, 15.482087, 0.001000, 3}}, + {{2827.259396, 59.671727, 72.026834, 0.1}, + {2826.172723, 59.816412, 17.021470, 0.002500, 8}}, + {{2833.174044, 58.621604, 71.121232, 0.1}, + {2832.100700, 58.743534, 18.163957, 0.003500, 11}}, + {{2838.983308, 57.564111, 70.209511, 0.1}, + {2837.921548, 57.673807, 18.557488, 0.004000, 13}}, + {{2844.686607, 56.502319, 69.295655, 0.1}, + {2843.635577, 56.607161, 18.407003, 0.004500, 15}}, + {{2850.283663, 55.439136, 68.383536, 0.1}, + {2849.243093, 55.543527, 17.919713, 0.004500, 15}}, + {{2855.774270, 54.373463, 67.471945, 0.1}, + {2854.744393, 54.482838, 16.989111, 0.004000, 13}}, + {{2861.158442, 53.310395, 66.567992, 0.1}, + {2860.139768, 53.425025, 16.011311, 0.004000, 13}}, + {{2866.436640, 52.253928, 65.677398, 0.1}, + {2865.429503, 52.370024, 15.317990, 0.004000, 13}}, + {{2871.609301, 51.199672, 64.794534, 0.1}, + {2870.613876, 51.317768, 14.573491, 0.003500, 11}}, + {{2876.676648, 50.147640, 63.919552, 0.1}, + {2875.693158, 50.268194, 13.781458, 0.003500, 11}}, + {{2881.639061, 49.100977, 63.056873, 0.1}, + {2880.667613, 49.221238, 13.202782, 0.003000, 9}}, + {{2886.496920, 48.056611, 62.202318, 0.1}, + {2885.537501, 48.176836, 12.604339, 0.003000, 9}}, + {{2891.250636, 47.018088, 61.360933, 0.1}, + {2890.303074, 47.134928, 12.280825, 0.003000, 9}}, + {{2895.900617, 45.981928, 60.527937, 0.1}, + {2894.964578, 46.095452, 11.968529, 0.003500, 11}}, + {{2900.447101, 44.948158, 59.703518, 0.1}, + {2899.522253, 45.058347, 11.674383, 0.003500, 11}}, + {{2904.890167, 43.913570, 58.883223, 0.1}, + {2903.976334, 44.023555, 11.140163, 0.003500, 11}}, + {{2909.229897, 42.881424, 58.072049, 0.1}, + {2908.327049, 42.991016, 10.622481, 0.003000, 9}}, + {{2913.466530, 41.851616, 57.270212, 0.1}, + {2912.574619, 41.960672, 10.118410, 0.003000, 9}}, + {{2917.600434, 40.826803, 56.482155, 0.1}, + {2916.719263, 40.932466, 9.851340, 0.003000, 9}}, + {{2921.631953, 39.803918, 55.703792, 0.1}, + {2920.761191, 39.906341, 9.588696, 0.003500, 11}}, + {{2925.561287, 38.783108, 54.935412, 0.1}, + {2924.700607, 38.882242, 9.346359, 0.003500, 11}}, + {{2929.388524, 37.762009, 54.173486, 0.1}, + {2928.537713, 37.860112, 8.935239, 0.003500, 11}}, + {{2933.113764, 36.743153, 53.422213, 0.1}, + {2932.272702, 36.839897, 8.556173, 0.003500, 11}}, + {{2936.737228, 35.726506, 52.681892, 0.1}, + {2935.905762, 35.821543, 8.212388, 0.003500, 11}}, + {{2940.259136, 34.711992, 51.952833, 0.1}, + {2939.437078, 34.804997, 7.903881, 0.003500, 11}}, + {{2943.679695, 33.699509, 51.235358, 0.1}, + {2942.866827, 33.790206, 7.628086, 0.003500, 11}}, + {{2946.999101, 32.688846, 50.529650, 0.1}, + {2946.195183, 32.777117, 7.373489, 0.003500, 11}}, + {{2950.217493, 31.679292, 49.835035, 0.1}, + {2950.997969, 31.260565, 12.867386, 0.010000, 41}}, + {{2953.335016, 30.671441, 49.153096, 0.1}, + {2954.073563, 30.251509, 12.283864, 0.010000, 48}}, + {{2956.350647, 29.641635, 48.441400, 0.1}, + {2957.048328, 29.243979, 11.696148, 0.010000, 48}}, + {{2959.263303, 28.611932, 47.739490, 0.1}, + {2959.922414, 28.237924, 11.123138, 0.010000, 48}}, + {{2962.073123, 27.584913, 47.052590, 0.1}, + {2962.695966, 27.233296, 10.566719, 0.010000, 48}}, + {{2964.780373, 26.560521, 46.381113, 0.1}, + {2965.369125, 26.230046, 10.026509, 0.010000, 48}}, + {{2967.385314, 25.538714, 45.725492, 0.1}, + {2967.942025, 25.228128, 9.502122, 0.010000, 48}}, + {{2969.888201, 24.519460, 45.086174, 0.1}, + {2970.414798, 24.227493, 8.993173, 0.010000, 48}}, + {{2972.289290, 23.502736, 44.463621, 0.1}, + {2972.787570, 23.228095, 8.499271, 0.010000, 48}}, + {{2974.588832, 22.488518, 43.858309, 0.1}, + {2975.060462, 22.229890, 8.020013, 0.010000, 48}}, + {{2976.787076, 21.476777, 43.270725, 0.1}, + {2977.233591, 21.232831, 7.554990, 0.010000, 48}}, + {{2978.884269, 20.467481, 42.701369, 0.1}, + {2979.307070, 20.236874, 7.103775, 0.010000, 48}}, + {{2980.880652, 19.460587, 42.150748, 0.1}, + {2981.281006, 19.241976, 6.665932, 0.010000, 48}}, + {{2982.776464, 18.456044, 41.619378, 0.1}, + {2983.155503, 18.248095, 6.241007, 0.010000, 48}}, + {{2984.571937, 17.453792, 41.107781, 0.1}, + {2984.930661, 17.255187, 5.828534, 0.010000, 48}}, + {{2986.267297, 16.453765, 40.616482, 0.1}, + {2986.606575, 16.263212, 5.428031, 0.010000, 48}}, + {{2987.862762, 15.455888, 40.146011, 0.1}, + {2988.183337, 15.272130, 5.039001, 0.010000, 48}}, + {{2989.358540, 14.460001, 39.696907, 0.1}, + {2989.661033, 14.281903, 4.660909, 0.010000, 48}}, + {{2990.754830, 13.466130, 39.269688, 0.1}, + {2991.039748, 13.292492, 4.293264, 0.010000, 48}}, + {{2992.051832, 12.474233, 38.864869, 0.1}, + {2992.319561, 12.303862, 3.935539, 0.010000, 48}}, + {{2993.249740, 11.484250, 38.482958, 0.1}, + {2993.500549, 11.315977, 3.587188, 0.010000, 48}}, + {{2994.348743, 10.496116, 38.124445, 0.1}, + {2994.582783, 10.328804, 3.247651, 0.010000, 48}}, + {{2995.349023, 9.509767, 37.789806, 0.1}, + {2995.566335, 9.342312, 2.916352, 0.010000, 48}}, + {{2996.250754, 8.525139, 37.479491, 0.1}, + {2996.451270, 8.356472, 2.592704, 0.010000, 48}}, + {{2997.054106, 7.542171, 37.193927, 0.1}, + {2997.237653, 7.371257, 2.276107, 0.010000, 48}}, + {{2997.759242, 6.560805, 36.933508, 0.1}, + {2997.593906, 6.878876, 0.000000, 0.000000, 18}}, + {{2998.366319, 5.580987, 36.698594, 0.1}, + {2998.232574, 5.894551, 0.000000, 0.000000, 0}}, + {{2998.875647, 4.605733, 36.513507, 0.1}, + {2998.772838, 4.910794, 0.000000, 0.000000, 0}}, + {{2999.287586, 3.633139, 36.370710, 0.1}, + {2999.214753, 3.927587, 0.000000, 0.000000, 0}}, + {{2999.602292, 2.661052, 36.253879, 0.1}, + {2999.558375, 2.944913, 0.000000, 0.000000, 0}}, + {{2999.819812, 1.689438, 36.163201, 0.1}, + {2999.803756, 1.962763, 0.000000, 0.000000, 0}}, + {{2999.940194, 0.718271, 36.098808, 0.1}, + {2999.950947, 0.981127, 0.000000, 0.000000, 0}}, + {{2999.963481, -0.252449, 36.060779, 0.1}, + {2999.950947, 0.981127, 0.000000, 0.000000, 0}}, +}; diff --git a/src/tests/catch/ada/ada_kalman_p/test-ada-data.cpp b/src/tests/catch/ada/ada_kalman_p/test-ada-data.cpp index 940039cbb98f0f341d0e0fa80c36a39c46e05505..a9494b8152dc786ead418819a4762645313df10c 100644 --- a/src/tests/catch/ada/ada_kalman_p/test-ada-data.cpp +++ b/src/tests/catch/ada/ada_kalman_p/test-ada-data.cpp @@ -22,7 +22,7 @@ */ #include "test-ada-data.h" -const float SIMULATED_PRESSURE[DATA_SIZE] = { +const float ADA_SIMULATED_PRESSURE[DATA_SIZE] = { 85431.242948f, 85431.195530f, 85430.531818f, 85428.511661f, 85424.541375f, 85418.586756f, 85410.484742f, 85400.380605f, 85387.951291f, 85373.412847f, 85356.530561f, 85337.302634f, 85315.693843f, 85291.654118f, 85265.156486f, 85236.179384f, 85204.699993f, 85170.715288f, 85134.214699f, 85095.204539f, 85053.713878f, 85009.692280f, 84963.342580f, 84914.537170f, 84863.342981f, 84809.942661f, 84754.307845f, 84696.606779f, 84636.840947f, 84575.108256f, 84511.411803f, 84445.886248f, 84378.531812f, 84309.408539f, 84238.575457f, 84166.083903f, 84091.993574f, 84016.326350f, 83939.283495f, 83860.838930f, 83781.113349f, 83700.192751f, 83618.160747f, 83535.097047f, 83451.069870f, 83366.139284f, 83280.348743f, 83193.731035f, 83106.324146f, 83018.168763f, 82929.332706f, 82839.907721f, 82749.980821f, 82659.659037f, 82569.047818f, 82478.250367f, 82387.372687f, 82296.514121f, 82205.765806f, 82115.204232f, 82024.866544f, 81934.773692f, 81844.948233f, 81755.416882f, 81666.211710f, 81577.355814f, 81488.856279f, 81400.744909f, 81313.024685f, 81225.725720f, 81138.858951f, 81052.432671f, 80966.442916f, 80880.879969f, 80795.733506f, 80710.993461f, 80626.652792f, 80542.709300f, 80459.154952f, 80376.001162f, 80293.249194f, 80210.902104f, 80128.967362f, 80047.445669f, 79966.333243f, 79885.651990f, 79805.357504f, 79725.473811f, 79645.974136f, 79566.865375f, 79488.136895f, 79409.786770f, 79331.813688f, 79254.217678f, 79177.018164f, 79100.171172f, 79023.724092f, 78947.664215f, 78871.990160f, 78796.711133f, 78721.810653f, 78647.294473f, 78573.155658f, 78499.389033f, 78425.989137f, 78352.953270f, 78280.274531f, 78207.954674f, 78135.994226f, 78064.391522f, 77993.148588f, 77922.267607f, 77851.747240f, 77781.592871f, 77711.801941f, 77642.368219f, 77573.321504f, 77504.601044f, 77436.249004f, 77368.249493f, 77300.601718f, 77233.292329f, 77166.332527f, 77099.709056f, 77033.429981f, 76967.488574f, 76901.887521f, 76836.627276f, 76771.707698f, 76707.131456f, 76642.893513f, 76578.999459f, 76515.448480f, 76452.236220f, 76389.362923f, 76326.825701f, 76264.622110f, 76202.749523f, 76141.205158f, 76079.986697f, 76019.092066f, 75958.519777f, 75898.268885f, 75838.338743f, 75778.729023f, 75719.439688f, 75660.470760f, 75601.822193f, 75543.497084f, 75485.490333f, @@ -122,7 +122,7 @@ const float SIMULATED_PRESSURE[DATA_SIZE] = { 84580.016493f, 84580.873337f, 84581.729482f, 84582.585353f, 84583.441370f, 84584.297956f, 84585.155471f, 84586.013678f, 84586.872320f, 84587.731198f, 84588.590112f, 84589.448860f, 84590.307243f, 84591.165128f, 84592.022639f, 84592.879929f, 84593.737152f, 84594.594460f, 84595.452004f, 84596.309938f, 84597.168345f, 84598.027100f, 84598.886042f, 84599.745009f, 84600.603838f, 84601.462368f, 84602.320435f, 84603.178003f, 84604.035255f, 84604.892387f, 84605.749595f, 84606.607077f, 84607.465029f, 84608.324161f, 84609.184816f, 84610.046054f, 84610.906919f, 84611.766456f, 84612.623711f, 84613.477537 }; -const float SIMULATED_PRESSURE_SPEED[] = { +const float ADA_SIMULATED_PRESSURE_SPEED[] = { -0.948363f, -0.948363f, -13.274254f, -40.403141f, -79.405710f, -119.092389f, -162.040265f, -202.082736f, -248.586283f, -290.768883f, -337.645715f, -384.558541f, -432.175827f, -480.794502f, -529.952635f, -579.542043f, -629.587822f, -679.694102f, -730.011778f, -780.203192f, -829.813236f, -880.431945f, -926.994001f, -976.108202f, -1023.883786f, -1068.006391f, -1112.696323f, -1154.021320f, -1195.316651f, -1234.653809f, -1273.929067f, -1310.511099f, -1347.088722f, -1382.465466f, -1416.661632f, -1449.831084f, -1481.806571f, -1513.344488f, -1540.857087f, -1568.891304f, -1594.511632f, -1618.411951f, -1640.640080f, -1661.274003f, -1680.543531f, -1698.611728f, -1715.810816f, -1732.354168f, -1748.137780f, -1763.107652f, -1776.721145f, -1788.499697f, -1798.538005f, -1806.435685f, -1812.224381f, -1815.949022f, -1817.553582f, -1817.171319f, -1814.966301f, -1811.231493f, -1806.753756f, -1801.857044f, -1796.509169f, -1790.627019f, -1784.103445f, -1777.117924f, -1769.990709f, -1762.227380f, -1754.404480f, -1745.979311f, -1737.335373f, -1728.525613f, -1719.795091f, -1711.258934f, -1702.929259f, -1694.800914f, -1686.813373f, -1678.869836f, -1671.086967f, -1663.075796f, -1655.039355f, -1646.941808f, -1638.694844f, -1630.433859f, -1622.248517f, -1613.625054f, -1605.889735f, -1597.673857f, -1589.993489f, -1582.175234f, -1574.569597f, -1567.002497f, -1559.461641f, -1551.920197f, -1543.990283f, -1536.939837f, -1528.941596f, -1521.197540f, -1513.481103f, -1505.580544f, -1498.009587f, -1490.323611f, -1482.776293f, -1475.332504f, -1467.997921f, -1460.717334f, -1453.574783f, -1446.397141f, -1439.208953f, -1432.054093f, -1424.858679f, -1417.619623f, -1410.407338f, -1403.087371f, -1395.818595f, -1388.674458f, -1380.934283f, -1374.409215f, -1367.040802f, -1359.990206f, -1352.955497f, -1346.187796f, -1339.196030f, -1332.469424f, -1325.581498f, -1318.828149f, -1312.021043f, -1305.204915f, -1298.391547f, -1291.524853f, -1284.758862f, -1277.881065f, -1271.019585f, -1264.245204f, -1257.465943f, -1250.744429f, -1244.071819f, -1237.451756f, -1230.887296f, -1224.369212f, -1217.892631f, -1211.445773f, -1205.017845f, -1198.602846f, -1192.194381f, -1185.786708f, -1179.378571f, -1172.971336f, -1166.502184f, -1160.135006f, @@ -223,7 +223,7 @@ const float SIMULATED_PRESSURE_SPEED[] = { }; /* -const float SIMULATED_NOISY_PRESSURE[DATA_SIZE] = {85440.0f, 85440.0f, 85410.0f, 85440.0f, 85440.0f, 85410.0f, 85410.0f, 85410.0f, 85380.0f, 85380.0f, 85350.0f, 85350.0f, 85320.0f, 85290.0f, 85260.0f, 85230.0f, 85200.0f, 85170.0f, 85140.0f, 85110.0f, 85050.0f, 85020.0f, 84960.0f, 84930.0f, 84870.0f, 84810.0f, 84750.0f, 84690.0f, 84630.0f, 84570.0f, 84510.0f, 84450.0f, 84390.0f, 84300.0f, 84240.0f, 84150.0f, 84090.0f, 84030.0f, 83940.0f, 83850.0f, 83790.0f, 83700.0f, 83610.0f, 83520.0f, 83460.0f, 83370.0f, 83280.0f, 83190.0f, 83100.0f, 83010.0f, +const float ADA_SIMULATED_NOISY_PRESSURE[DATA_SIZE] = {85440.0f, 85440.0f, 85410.0f, 85440.0f, 85440.0f, 85410.0f, 85410.0f, 85410.0f, 85380.0f, 85380.0f, 85350.0f, 85350.0f, 85320.0f, 85290.0f, 85260.0f, 85230.0f, 85200.0f, 85170.0f, 85140.0f, 85110.0f, 85050.0f, 85020.0f, 84960.0f, 84930.0f, 84870.0f, 84810.0f, 84750.0f, 84690.0f, 84630.0f, 84570.0f, 84510.0f, 84450.0f, 84390.0f, 84300.0f, 84240.0f, 84150.0f, 84090.0f, 84030.0f, 83940.0f, 83850.0f, 83790.0f, 83700.0f, 83610.0f, 83520.0f, 83460.0f, 83370.0f, 83280.0f, 83190.0f, 83100.0f, 83010.0f, 82920.0f, 82860.0f, 82740.0f, 82650.0f, 82560.0f, 82470.0f, 82380.0f, 82290.0f, 82200.0f, 82110.0f, 82020.0f, 81930.0f, 81840.0f, 81750.0f, 81660.0f, 81570.0f, 81510.0f, 81390.0f, 81300.0f, 81240.0f, 81120.0f, 81060.0f, 80970.0f, 80880.0f, 80790.0f, 80700.0f, 80640.0f, 80550.0f, 80460.0f, 80370.0f, 80280.0f, 80220.0f, 80130.0f, 80040.0f, 79980.0f, 79890.0f, 79800.0f, 79710.0f, 79650.0f, 79560.0f, 79500.0f, 79410.0f, 79320.0f, 79260.0f, 79170.0f, 79110.0f, 79020.0f, 78930.0f, 78870.0f, 78810.0f, 78720.0f, 78630.0f, 78570.0f, 78510.0f, 78420.0f, 78360.0f, 78300.0f, 78210.0f, 78120.0f, 78060.0f, 78000.0f, 77940.0f, 77850.0f, 77790.0f, 77700.0f, 77640.0f, 77580.0f, 77490.0f, 77430.0f, 77370.0f, 77310.0f, 77250.0f, 77160.0f, 77100.0f, 77040.0f, 76950.0f, 76920.0f, 76830.0f, 76770.0f, 76710.0f, 76650.0f, 76590.0f, 76530.0f, 76440.0f, 76380.0f, 76320.0f, 76260.0f, 76200.0f, 76140.0f, 76080.0f, 76020.0f, 75960.0f, 75900.0f, 75840.0f, 75780.0f, 75720.0f, 75660.0f, 75600.0f, 75540.0f, 75480.0f, 75420.0f, 75360.0f, 75330.0f, 75270.0f, 75210.0f, 75150.0f, 75090.0f, 75030.0f, 74970.0f, 74910.0f, 74880.0f, 74820.0f, 74760.0f, 74700.0f, 74670.0f, 74610.0f, 74550.0f, 74490.0f, 74460.0f, 74400.0f, 74340.0f, 74280.0f, 74220.0f, 74190.0f, 74130.0f, 74070.0f, 74040.0f, 73980.0f, 73920.0f, 73890.0f, 73830.0f, 73800.0f, 73740.0f, 73710.0f, 73650.0f, 73590.0f, 73560.0f, 73500.0f, 73470.0f, 73410.0f, 73350.0f, 73320.0f, 73260.0f, 73230.0f, 73200.0f, 73140.0f, 73110.0f, 73050.0f, 73020.0f, 72990.0f, diff --git a/src/tests/catch/ada/ada_kalman_p/test-ada-data.h b/src/tests/catch/ada/ada_kalman_p/test-ada-data.h index 69d8d8a238651aa0f375ecd68e1fa676af675af1..1737bd7528e42cd2517e3df11f41fe390b3125db 100644 --- a/src/tests/catch/ada/ada_kalman_p/test-ada-data.h +++ b/src/tests/catch/ada/ada_kalman_p/test-ada-data.h @@ -24,6 +24,6 @@ #pragma once static const unsigned DATA_SIZE = 4840; -extern const float SIMULATED_PRESSURE[DATA_SIZE]; -extern const float SIMULATED_PRESSURE_SPEED[DATA_SIZE]; -// extern const float SIMULATED_NOISY_PRESSURE[DATA_SIZE]; \ No newline at end of file +extern const float ADA_SIMULATED_PRESSURE[DATA_SIZE]; +extern const float ADA_SIMULATED_PRESSURE_SPEED[DATA_SIZE]; +// extern const float ADA_SIMULATED_NOISY_PRESSURE[DATA_SIZE]; \ No newline at end of file diff --git a/src/tests/catch/ada/ada_kalman_p/test-ada-simulation.cpp b/src/tests/catch/ada/ada_kalman_p/test-ada-simulation.cpp index 34cf5be609905f7b93182a9c0ccad3b2182574ee..559f1b7598d22eca383300ad898d3ece454bbfc4 100644 --- a/src/tests/catch/ada/ada_kalman_p/test-ada-simulation.cpp +++ b/src/tests/catch/ada/ada_kalman_p/test-ada-simulation.cpp @@ -72,17 +72,17 @@ public: if (before_liftoff) { - press = addNoise(SIMULATED_PRESSURE[0]); + press = addNoise(ADA_SIMULATED_PRESSURE[0]); } else { if (i < DATA_SIZE) { - press = addNoise(SIMULATED_PRESSURE[i++]); + press = addNoise(ADA_SIMULATED_PRESSURE[i++]); } else { - press = addNoise(SIMULATED_PRESSURE[DATA_SIZE - 1]); + press = addNoise(ADA_SIMULATED_PRESSURE[DATA_SIZE - 1]); } } @@ -123,20 +123,20 @@ void checkState(unsigned int i, ADAKalmanState state) { if (i > 200) { - if (state.x0 == Approx(SIMULATED_PRESSURE[i]).margin(70)) + if (state.x0 == Approx(ADA_SIMULATED_PRESSURE[i]).margin(70)) SUCCEED(); else FAIL("i = " << i << "\t\t" << state.x0 - << " != " << SIMULATED_PRESSURE[i]); + << " != " << ADA_SIMULATED_PRESSURE[i]); // Flying under the chutes the speed estimation is not very precise if (i < 3000) { - if (state.x1 == Approx(SIMULATED_PRESSURE_SPEED[i]).margin(80)) + if (state.x1 == Approx(ADA_SIMULATED_PRESSURE_SPEED[i]).margin(80)) SUCCEED(); else FAIL("i = " << i << "\t\t" << state.x1 - << " != " << SIMULATED_PRESSURE_SPEED[i]); + << " != " << ADA_SIMULATED_PRESSURE_SPEED[i]); } } } @@ -173,7 +173,7 @@ TEST_CASE("Testing ada_controller from calibration to first descent phase") } float mean = ada_controller->calibrator.getReferenceValues().ref_pressure; - if (mean == Approx(SIMULATED_PRESSURE[0])) + if (mean == Approx(ADA_SIMULATED_PRESSURE[0])) FAIL("Calibration value"); else SUCCEED(); @@ -227,7 +227,7 @@ TEST_CASE("Testing ada_controller from calibration to first descent phase") // false apogee) for (unsigned i = 0; i < SHADOW_MODE_END_INDEX; i++) { - // float noisy_p = addNoise(SIMULATED_PRESSURE[i]); + // float noisy_p = addNoise(ADA_SIMULATED_PRESSURE[i]); mock_baro.sample(); Thread::sleep(5); ada_controller->update(); @@ -249,7 +249,7 @@ TEST_CASE("Testing ada_controller from calibration to first descent phase") bool apogee_checked = false; for (unsigned i = SHADOW_MODE_END_INDEX; i < DATA_SIZE; i++) { - // float noisy_p = addNoise(SIMULATED_PRESSURE[i]); + // float noisy_p = addNoise(ADA_SIMULATED_PRESSURE[i]); mock_baro.sample(); Thread::sleep(5); ada_controller->update(); diff --git a/src/tests/catch/fsm/test-aerobrakes.cpp b/src/tests/catch/fsm/test-aerobrakes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b43d21f08c51bc0db648b0a4c90d3a6e911816cf --- /dev/null +++ b/src/tests/catch/fsm/test-aerobrakes.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2021 Skyward Experimental Rocketry + * Authors: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef STANDALONE_CATCH1_TEST +#include "catch/catch-tests-entry.cpp" +#endif + +// We need access to the handleEvent(...) function in state machines in order to +// test them synchronously +#define protected public + +#include <miosix.h> + +#include <utils/testutils/catch.hpp> + +#include "AeroBrakesController/AeroBrakesController.h" +#include "AeroBrakesController/AeroBrakesServo.h" +#include "configs/AeroBrakesConfig.h" +#include "events/Events.h" +#include "utils/testutils/TestHelper.h" + +using miosix::Thread; +using namespace DeathStackBoard; + +class InputClass +{ +public: + float z; + float vz; + float vMod; + uint64_t timestamp; +}; + +template <typename T> +class MockSensor : public Sensor<T> +{ +private: + int ts = 0; + +protected: + T sampleImpl() override + { + T data; + return data; + } + + bool init() override { return true; } + + bool selfTest() override { return true; } +}; + +class AeroBrakesControllerFixture +{ +public: + // This is called at the beginning of each test / section + AeroBrakesControllerFixture() + { + controller = new AeroBrakesController<InputClass>(sensor); + sEventBroker->start(); + controller->start(); + } + + // This is called at the end of each test / section + ~AeroBrakesControllerFixture() + { + controller->stop(); + sEventBroker->unsubscribe(controller); + sEventBroker->clearDelayedEvents(); + delete controller; + } + +protected: + AeroBrakesController<InputClass>* controller; + + MockSensor<InputClass> sensor; +}; + +TEST_CASE_METHOD(AeroBrakesControllerFixture, + "Testing transitions from initialization") +{ + controller->transition( + &AeroBrakesController<InputClass>::state_initialization); + + REQUIRE( + controller->testState(&AeroBrakesController<InputClass>::state_idle)); +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, "Testing transitions from idle") +{ + controller->transition(&AeroBrakesController<InputClass>::state_idle); + + SECTION("EV_LIFTOFF -> SHADOW_MODE") + { + REQUIRE(testFSMTransition( + *controller, {EV_LIFTOFF}, + &AeroBrakesController<InputClass>::state_shadowMode)); + } + + SECTION("EV_WIGGLE_SERVO -> IDLE") + { + REQUIRE( + testFSMTransition(*controller, {EV_WIGGLE_SERVO}, + &AeroBrakesController<InputClass>::state_idle)); + } + + SECTION("EV_RESET_SERVO -> IDLE") + { + REQUIRE( + testFSMTransition(*controller, {EV_RESET_SERVO}, + &AeroBrakesController<InputClass>::state_idle)); + } + + SECTION("EV_TEST_ABK -> TEST_AEROBRAKES") + { + REQUIRE(testFSMTransition( + *controller, {EV_TEST_ABK}, + &AeroBrakesController<InputClass>::state_testAerobrakes)); + } +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, + "Testing transitions from shadow_mode") +{ + controller->transition( + &AeroBrakesController<InputClass>::state_shadowMode); + + SECTION("EV_SHADOW_MODE_TIMEOUT -> ENABLED") + { + REQUIRE(testFSMTransition( + *controller, {EV_SHADOW_MODE_TIMEOUT}, + &AeroBrakesController<InputClass>::state_enabled)); + } + + SECTION("EV_DISABLE_ABK -> DISABLED") + { + REQUIRE(testFSMTransition( + *controller, {EV_DISABLE_ABK}, + &AeroBrakesController<InputClass>::state_disabled)); + } +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, + "Testing transitions from enabled") +{ + controller->transition(&AeroBrakesController<InputClass>::state_enabled); + + SECTION("EV_APOGEE -> END") + { + REQUIRE( + testFSMTransition(*controller, {EV_APOGEE}, + &AeroBrakesController<InputClass>::state_end)); + } + + SECTION("EV_DISABLE_ABK -> DISABLED") + { + REQUIRE(testFSMTransition( + *controller, {EV_DISABLE_ABK}, + &AeroBrakesController<InputClass>::state_disabled)); + } +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, "Testing transitions from end") +{ + controller->transition(&AeroBrakesController<InputClass>::state_end); +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, + "Testing transitions from disabled") +{ + controller->transition(&AeroBrakesController<InputClass>::state_disabled); +} + +TEST_CASE_METHOD(AeroBrakesControllerFixture, + "Testing transitions from test_aerobrakes") +{ + controller->transition( + &AeroBrakesController<InputClass>::state_testAerobrakes); + + SECTION("EV_TEST_TIMEOUT -> IDLE") + { + REQUIRE( + testFSMTransition(*controller, {EV_TEST_TIMEOUT}, + &AeroBrakesController<InputClass>::state_idle)); + } +} \ No newline at end of file diff --git a/src/tests/mock_sensors/test-mock-data.cpp b/src/tests/mock_sensors/test-mock-data.cpp index 90e768b0296728b96537545224b214fad9374841..f5f08f35f8fe18f09e1de90be7ca89ba702ff8b5 100644 --- a/src/tests/mock_sensors/test-mock-data.cpp +++ b/src/tests/mock_sensors/test-mock-data.cpp @@ -22,7 +22,7 @@ * IN THE SOFTWARE. */ #include "test-mock-data.h" -/* + const float SIMULATED_PRESSURE[PRESSURE_DATA_SIZE] = { 85431.2429484683, 85430.6695060933, 85428.1328530587, 85423.2079044552, 85415.8936319942, 85406.0939791952, 85393.7323461432, 85378.8122328271, @@ -1098,7 +1098,7 @@ const float SIMULATED_PRESSURE[PRESSURE_DATA_SIZE] = { 85410.5612028571, 85412.5781016313, 85414.5950004054, 85416.6119137141, 85418.6291353124, 85420.6463569106, 85422.6635785088, 85424.680800107, 85426.6980217052, 85428.7152433034, 85430.7324649016}; -*/ + const float SIMULATED_LAT[GPS_DATA_SIZE] = { 41.809017, 41.8090170467145, 41.8090172305643, 41.8090175635122, 41.8090180361511, 41.8090184858135, 41.8090189345961, 41.8090196645904, diff --git a/src/tests/mock_sensors/test-mock-data.h b/src/tests/mock_sensors/test-mock-data.h index 27d06fed011156fea0faa839143bf9c086fda841..9d5d4797958cd1b2e857248ef4816d9ccedf6df1 100644 --- a/src/tests/mock_sensors/test-mock-data.h +++ b/src/tests/mock_sensors/test-mock-data.h @@ -26,6 +26,6 @@ static const unsigned PRESSURE_DATA_SIZE = 4295; static const unsigned GPS_DATA_SIZE = 2148; -//extern const float SIMULATED_PRESSURE[PRESSURE_DATA_SIZE]; +extern const float SIMULATED_PRESSURE[PRESSURE_DATA_SIZE]; extern const float SIMULATED_LAT[GPS_DATA_SIZE]; extern const float SIMULATED_LON[GPS_DATA_SIZE]; \ No newline at end of file