Compare commits

..

20 commits
main ... satsim

Author SHA1 Message Date
Avery Klingbeil dd5295c3fb oops didn't remove the call to astropy 2023-01-03 21:59:59 -06:00
Avery Klingbeil f856c7b619 removed astropy: it was making bad calls 2023-01-03 21:56:33 -06:00
Laika 44ce4b07d3 Added basic file read/write module 2021-07-08 21:37:03 -04:00
Laika 9598a855c4 more org 2021-07-08 20:17:25 -04:00
Laika b823c0d6d8 organized a bit 2021-07-08 20:15:56 -04:00
Laika 7935441d91 Sat interface now pulls from the right file 2021-07-03 15:03:41 -04:00
Laika c575625013 added some auxilary files 2021-07-03 14:55:51 -04:00
Laika 4a1640d1c3 minor tweaks 2021-07-03 14:54:30 -04:00
Laika 2458fb3616 added basic telnet interface 2021-07-03 14:53:50 -04:00
Laika 2ff27a652d moved heartbeat and location functions to modules 2021-07-03 11:38:27 -04:00
Laika 9b58ca7528 ingests GET/SET/EXE commands 2021-07-03 11:37:47 -04:00
Laika 41356f5922 prototype module 2021-07-03 11:37:12 -04:00
Laika 9728b5cc98 renamed gamma sensor 2021-07-03 11:36:52 -04:00
Laika 652e122d30 Added sensor a sensor module to work out GET/SET/EXE/NOT api 2021-06-27 19:51:46 -04:00
Laika a9a7e1eead tiny amount of progress. 2021-05-01 09:36:26 -04:00
Laika 813783c9f9 Merge branch 'satsim' of github.com:Sakimori/BoSLOO into satsim 2021-04-22 19:45:48 -04:00
Laika 9cb4e1f74c Added periodic check of command queue 2021-04-22 19:45:15 -04:00
Laika 5fd6c6a753 wrote basic test command stream 2021-04-22 17:57:46 -04:00
Áva Klingbeil ac51bd67f6 wrote basic test command stream 2021-04-22 17:52:16 -04:00
Áva Klingbeil c24a62e503 barely started scaffold for simsat 2021-04-22 17:51:49 -04:00
93 changed files with 440 additions and 16431 deletions

63
.gitattributes vendored
View file

@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

466
.gitignore vendored
View file

@ -1,371 +1,129 @@
## Ignore Visual Studio temporary files, build results, and # Byte-compiled / optimized / DLL files
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/ __pycache__/
*.pyc *.py[cod]
*$py.class
# Cake - Uncomment if you are using it # C extensions
# tools/** *.so
# !tools/packages.config
# Tabs Studio # Distribution / packaging
*.tss .Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Telerik's JustMock configuration file # PyInstaller
*.jmconfig # Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# BizTalk build output # Installer logs
*.btp.cs pip-log.txt
*.btm.cs pip-delete-this-directory.txt
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results # Unit test / coverage reports
OpenCover/ htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Azure Stream Analytics local run output # Translations
ASALocalRun/ *.mo
*.pot
# MSBuild Binary and Structured Log # Django stuff:
*.binlog *.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# NVidia Nsight GPU debugger configuration file # Flask stuff:
*.nvuser instance/
.webassets-cache
# MFractors (Xamarin productivity tool) working folder # Scrapy stuff:
.mfractor/ .scrapy
# Local History for Visual Studio # Sphinx documentation
.localhistory/ docs/_build/
# BeatPulse healthcheck temp database # PyBuilder
healthchecksdb target/
# Backup folder for Package Reference Convert tool in Visual Studio 2017 # Jupyter Notebook
MigrationBackup/ .ipynb_checkpoints
# Ionide (cross platform F# VS Code tools) working folder # IPython
.ionide/ profile_default/
ipython_config.py
# Fody - auto-generated XML schema # pyenv
FodyWeavers.xsd .python-version
# user files # pipenv
ConfigFiles/ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/ env/
GroundControlFiles/ venv/
SatFiles/ ENV/
/test.png env.bak/
/bosloo_env venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,143 +0,0 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>2bab9fec-2055-4075-95d0-f60299d91bd3</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>OrbitSim.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>BoSLOO</Name>
<RootNamespace>BoSLOO</RootNamespace>
<InterpreterId>MSBuild|BoSLOOenv|$(MSBuildProjectFullPath)</InterpreterId>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="OrbitSim.py" />
<Compile Include="renderer.py">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Interpreter Include="bosloo_env\">
<Id>bosloo_env</Id>
<Version>3.10</Version>
<Description>bosloo_env (Python 3.10 (64-bit))</Description>
<InterpreterPath>Scripts\python.exe</InterpreterPath>
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
<Architecture>X64</Architecture>
</Interpreter>
<Interpreter Include="env\BoSLOOenv\">
<Id>BoSLOOenv</Id>
<Version>3.8</Version>
<Description>BoSLOOenv (Python 3.8 (32-bit))</Description>
<InterpreterPath>Scripts\python.exe</InterpreterPath>
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
<Architecture>X86</Architecture>
</Interpreter>
</ItemGroup>
<ItemGroup>
<Folder Include="Assets\" />
<Folder Include="Assets\Sphere\" />
<Folder Include="GroundControl\" />
<Folder Include="GroundControl\Assets\" />
<Folder Include="GroundControl\frontend\" />
<Folder Include="GroundControl\frontend\public\" />
<Folder Include="GroundControl\frontend\public\Assets\" />
<Folder Include="GroundControl\frontend\public\Assets\image\" />
<Folder Include="GroundControl\frontend\public\Assets\sound\" />
<Folder Include="GroundControl\frontend\src\" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\Sphere\0001.png" />
<Content Include="Assets\Sphere\0002.png" />
<Content Include="Assets\Sphere\0003.png" />
<Content Include="Assets\Sphere\0004.png" />
<Content Include="Assets\Sphere\0005.png" />
<Content Include="Assets\Sphere\0006.png" />
<Content Include="Assets\Sphere\0007.png" />
<Content Include="Assets\Sphere\0008.png" />
<Content Include="Assets\Sphere\0009.png" />
<Content Include="Assets\Sphere\0010.png" />
<Content Include="Assets\Sphere\0011.png" />
<Content Include="Assets\Sphere\0012.png" />
<Content Include="Assets\Sphere\0013.png" />
<Content Include="Assets\Sphere\0014.png" />
<Content Include="Assets\Sphere\0015.png" />
<Content Include="Assets\Sphere\0016.png" />
<Content Include="Assets\Sphere\0017.png" />
<Content Include="Assets\Sphere\0018.png" />
<Content Include="Assets\Sphere\0019.png" />
<Content Include="Assets\Sphere\0020.png" />
<Content Include="Assets\Sphere\0021.png" />
<Content Include="Assets\Sphere\0022.png" />
<Content Include="Assets\Sphere\0023.png" />
<Content Include="Assets\Sphere\0024.png" />
<Content Include="Assets\Sphere\0025.png" />
<Content Include="Assets\Sphere\0026.png" />
<Content Include="Assets\Sphere\0027.png" />
<Content Include="Assets\Sphere\0028.png" />
<Content Include="Assets\Sphere\0029.png" />
<Content Include="Assets\Sphere\0030.png" />
<Content Include="Assets\Sphere\0031.png" />
<Content Include="Assets\Sphere\0032.png" />
<Content Include="Assets\Sphere\0033.png" />
<Content Include="Assets\Sphere\0034.png" />
<Content Include="Assets\Sphere\0035.png" />
<Content Include="Assets\Sphere\0036.png" />
<Content Include="Assets\Sphere\0037.png" />
<Content Include="Assets\Sphere\0038.png" />
<Content Include="Assets\Sphere\0039.png" />
<Content Include="Assets\Sphere\0040.png" />
<Content Include="Assets\Sphere\0041.png" />
<Content Include="Assets\Sphere\0042.png" />
<Content Include="Assets\Sphere\0043.png" />
<Content Include="Assets\Sphere\0044.png" />
<Content Include="Assets\Sphere\0045.png" />
<Content Include="Assets\Sphere\0046.png" />
<Content Include="Assets\Sphere\0047.png" />
<Content Include="Assets\Sphere\0048.png" />
<Content Include="Assets\Sphere\0049.png" />
<Content Include="Assets\Sphere\0050.png" />
<Content Include="GroundControl\frontend\public\Assets\image\BoSLOO logo.txt" />
<Content Include="GroundControl\frontend\public\Assets\image\testMap.png" />
<Content Include="GroundControl\frontend\public\Assets\sound\apricot-rustle-boot.wav" />
<Content Include="GroundControl\frontend\public\Assets\sound\disc-seek-test.mp3" />
<Content Include="GroundControl\frontend\src\BoSLOO logo.json" />
<Content Include="GroundControl\frontend\.gitignore" />
<Content Include="GroundControl\frontend\package-lock.json" />
<Content Include="GroundControl\frontend\package.json" />
<Content Include="GroundControl\frontend\public\favicon.ico" />
<Content Include="GroundControl\frontend\public\index.html" />
<Content Include="GroundControl\frontend\public\logo192.png" />
<Content Include="GroundControl\frontend\public\logo512.png" />
<Content Include="GroundControl\frontend\public\manifest.json" />
<Content Include="GroundControl\frontend\public\robots.txt" />
<Content Include="GroundControl\frontend\README.md" />
<Content Include="GroundControl\frontend\src\commands.js" />
<Content Include="GroundControl\frontend\src\index.css" />
<Content Include="GroundControl\frontend\src\index.js" />
<Content Include="GroundControl\frontend\src\statusbar.js" />
<Content Include="GroundControl\frontend\src\terminal.js" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
the BeforeBuild and AfterBuild targets below. -->
<!--<Target Name="CoreCompile" />-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
</Project>

View file

@ -1,23 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31105.61
MinimumVisualStudioVersion = 10.0.40219.1
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "BoSLOO", "BoSLOO.pyproj", "{2BAB9FEC-2055-4075-95D0-F60299D91BD3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2BAB9FEC-2055-4075-95D0-F60299D91BD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BAB9FEC-2055-4075-95D0-F60299D91BD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BBAD12CA-6246-44EF-80F1-E21768C3AECA}
EndGlobalSection
EndGlobal

View file

@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View file

@ -1,70 +0,0 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

File diff suppressed because it is too large Load diff

View file

@ -1,43 +0,0 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"babel-runtime": "^6.26.0",
"react": "^18.2.0",
"react-animated-text": "^0.1.4",
"react-clickable-div": "^1.0.0",
"react-dom": "^18.2.0",
"react-keyboard-event-handler": "^1.5.4",
"react-scripts": "5.0.1",
"react-typing-animation": "^1.6.2",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View file

@ -1,14 +0,0 @@
┌──────────┐ ┌─────────┐ ┌─┐ ┌─┬───────┬┐ ┌─┬───────┬┐
│┼┼───────┼│ │┼┼───────┘ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼┼───────┴┘ ┌────────┐ └─┴──────┬┐ │┼│ │┼│ ││ │┼│ ││
│┼│ \\ │┼┼─────┼│ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ \\ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ ┌┐ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼┼───────┼│ │┼┼─────┼│ ┌────────┼│ │┼┼───────┐ │┼│ ││ │┼│ ││
└──────────┘ └────────┘ └─────────┘ └─────────┘ └─┴───────┴┘ └─┴───────┴┘

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -1,44 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<audio id="boot-sound" src="./Assets/sound/disc-seek-test.mp3">Your browser does not support audio.</audio>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View file

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View file

@ -1,3 +0,0 @@
{
"logo": " ______ _______ _____ _______ _______ \n| __ \\.-----.| __|| |_ | || |\n| __ <| _ ||__ || || - || - |\n|______/|_____||_______||_______||_______||_______|"
}

View file

@ -1,68 +0,0 @@
import Typing from 'react-typing-animation';
import React from 'react';
class Command {
constructor(keyword, fullName) {
this.keyword = keyword;
this.fullName = fullName;
this.helpString = "No help text for this command. Vivian, please be sure to fix this before deploying."
}
call(body) {
return 'This command exists, but does nothing. Vivian, please be sure to fix this before deploying.';
}
}
class helpCommand extends Command{
constructor() {
super('help','help');
this.helpString = "This contains basic help and usage instructions for all commands."
}
call(body) {
if (body === "") {
var commands = "";
for (let command of commandList) {
commands += command.keyword + " ";
}
return (commands);
} else {
for (let command of commandList) {
if (body === command.keyword || body === command.fullName) {
return (command.helpString);
}
}
return ("Unrecognized command. Use without arguments to see full list.")
}
}
}
class loremCommand extends Command {
constructor() {
super('lorem', 'loremipsum');
this.helpString = 'Prints a lorem string.'
}
call(body) {
return ('Space, the final frontier. These are the voyages of the Starship Enterprise. Its five-year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before. Many say exploration is part of our destiny, but it is actually our duty to future generations and their quest to ensure the survival of the human species.');
}
}
const commandList = [new helpCommand(), new loremCommand()];
function sentCommand(sentCommand) {
var commandId = sentCommand.split(" ")[0]
var commandBody = sentCommand.split(" ").slice(1).join(' ')
for (let command of commandList) {
if (commandId === command.keyword || commandId === command.fullName) {
return (<Typing className='typed-line' speed={5}>{command.call(commandBody.trim())}</Typing>);
}
}
return (<Typing className='typed-line' speed={5}>Unrecognized command.</Typing>);
}
export default sentCommand

View file

@ -1,126 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=VT323');
body {
font: 18px "VT323", "Courier New", monospace;
background-color: black;
background-image: radial-gradient(at bottom right, rgb(30 30 30), black);
height: 100vh;
overflow: hidden;
color: #02d300;
text-shadow: 0 0 6px #73ff71;
}
body::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 99vh;
background: repeating-linear-gradient( 0deg, rgb(0 0 0 / 0.20), rgb(0 0 0 / 0.15) 3px, transparent 2px, transparent 6px);
pointer-events: none;
}
::selection{
background: #793d71;
text-shadow: none;
}
.power-on-container {
height: 90vh;
align-items:center;
justify-items:center;
text-align: center;
}
.power-on-box {
position: relative;
justify-self: center;
margin-top: 20vh;
}
#start-text {
font-size: 30px;
border: ridge;
padding: 2em 6em;
box-shadow: 0 0 3px 1px rgb(49 255 0 / 0.70);
}
.console {
padding-top: 15vh;
height: 70vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.logo {
white-space: pre-wrap;
}
.fail-text {
color: #d82222;
text-shadow: 0 0 6px #ff1111;
}
.power-on-self-test{
padding-left: 4em;
}
.terminal-window {
}
.power-on-self-test, .terminal-window {
border:groove;
margin-left: 5vw;
margin-top: -5vh;
padding-bottom: 1em;
padding-right: 2em;
width: 60vw;
overflow-y: auto;
overflow-x: hidden;
flex-grow: 1;
display: flex;
flex-direction: column-reverse;
box-sizing: border-box;
box-shadow: 0 0 3px 1px rgb(49 255 0 / 0.70);
}
.terminal{
}
.active-line{
outline: none;
width: 2em;
resize:horizontal;
}
.blink-text {
animation: blinker 1s step-start infinite;
}
.typed-line{
display: inline;
}
.terminal-line th{
text-align: right;
vertical-align: top;
padding-right: 0.2em;
width: 4em;
}
.terminal-line td{
text-align: left;
}
@keyframes blinker {
50% {
opacity: 0;
}
}

View file

@ -1,98 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import Typing from 'react-typing-animation';
import ClickableDiv from 'react-clickable-div';
import KeyboardEventHandler from 'react-keyboard-event-handler'
import './index.css';
import logos from './BoSLOO logo.json';
import Terminal from './terminal.js';
import StatusBar from './statusbar.js';
const nominal = <Terminal />;
class Console extends React.Component {
constructor(props) {
super(props);
this.swapper = this.swapper.bind(this);
this.state = {
bodyObj: <PowerOn onClick={this.swapper} />,
init: 0,
}
}
swapper(key, e) {
if (this.state.init === 0) {
this.replaceBody(<SelfTest />);
this.playSound();
} else if (this.state.init === 1) {
this.replaceBody(nominal);
}
this.setState({ init: this.state.init + 1 });
}
appendToBody(newContent) {
let bodyObj = JSON.parse(JSON.stringify(this.state.bodyObj)) + newContent;
this.setState({
bodyObj: bodyObj
});
}
replaceBody(newContent) {
this.setState({
bodyObj: newContent
});
}
playSound() {
var sound = document.getElementById("boot-sound")
sound.volume = 0.1;
sound.play();
}
render() {
return (
<div className='console'>
<KeyboardEventHandler handleKeys={['all']} onKeyEvent={this.swapper} />
{this.state.bodyObj}
{this.state.init >= 2 ? <StatusBar/> : null}
</div>
);
}
}
class SelfTest extends React.Component {
constructor(props) {
super(props);
this.state = {
logodisplay: false
}
}
render() {
const final = <span className='logo'>{logos.logo} < br /><br /><br /><Typing speed={5}>Press any key to continue...<br /><span>{'>'} <span className='blink-text'>_</span></span></Typing></span>;
return (
<div className='power-on-self-test'>
{this.state.logodisplay ? final : null}
<Typing speed={30} onFinishedTyping={() => this.setState({ logodisplay: true })}>
BoSLOO ACPI BIOS v0.1<br />
Sakimori Ind. 2022<br />
<Typing.Speed ms={ 5}/>Initializing cache.................................<Typing.Speed ms={200} />...<Typing.Speed ms={5} /> OK!<br />
Initializing network.........<Typing.Speed ms={500} />....<Typing.Speed ms={5} />.................<Typing.Speed ms={300} />....<Typing.Speed ms={5} /> OK!<br />
Initializing GPU...................................<Typing.Speed ms={1000} />...<Typing.Speed ms={5} /> <span className='fail-text'>FAIL!</span><br />
<br />
</Typing>
</div>
)
}
}
function PowerOn(props) {
return (
<div className="power-on-container"><div className='power-on-box'><span id='start-text' onClick={props.onClick}><span className='blink-text'>START</span></span></div></div>
);
}
// =========================================
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Console />);

View file

@ -1,9 +0,0 @@
import React from 'react';
class StatusBar extends React.Component {
render() {
return null;
}
}
export default StatusBar

View file

@ -1,100 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import * as KeyboardEventHandler from 'react-keyboard-event-handler';
import sentCommand from './commands.js'
class Terminal extends React.Component {
constructor(props) {
super(props);
this.state = {
lines: [<tr className='terminal-line' key={-20}><th>-20</th><td>Welcome to BoSLOO Ground Control Console.</td></tr>, <tr className='terminal-line' key={-10}><th>-10</th><td> Time of connection: {new Date().toLocaleString('en-US')}</td></tr>],
lastLine : '',
waitForUser: false,
lineNumber: 0,
controlHeld: false,
};
this.charIn = this.charIn.bind(this);
this.handleKey = this.handleKey.bind(this);
const window = document.getRootNode();
window.addEventListener('paste', (e) => {
e.preventDefault();
let paste = (e.clipboardData || window.clipboardData).getData('text');
this.appendText(paste);
});
}
addLines(newLinesArray) {
let currLines = this.state.lines
this.setState({
lines: currLines.concat(newLinesArray),
});
}
addCharacter(newChar) {
this.setState({
lastLine: JSON.parse(JSON.stringify(this.state.lastLine)) + newChar,
});
}
appendText(newText) {
this.setState({
lastLine: JSON.parse(JSON.stringify(this.state.lastLine)) + newText,
});
}
deleteCharacter() {
this.setState({
lastLine: this.state.lastLine.slice(0,-1),
});
}
finishLine() {
let commandBody = sentCommand(this.state.lastLine);
this.addLines([<tr className='terminal-line' key={this.state.lineNumber}><th>{this.state.lineNumber}</th><td>{'>'}{this.state.lastLine}</td></tr>,
<tr className='terminal-line' key={this.state.lineNumber + 10}><th>{this.state.lineNumber + 10}</th><td>{commandBody}</td></tr>]);
this.setState({ lastLine: '', lineNumber: this.state.lineNumber+20 });
}
charIn(newCharObj) {
this.setState({
lastLine: newCharObj.target.value,
});
}
handleKey(key, e) {
if (e.key === 'Enter') {
this.finishLine();
} else if (e.keyCode === 8) { /*backspace*/
this.deleteCharacter();
} else if (e.ctrlKey) {
return;
} else if (e.keyCode === 32) {
this.addCharacter(' ');
} else if (e.keyCode >= 40) {
this.addCharacter(e.key);
}
}
displayLines() {
return this.state.lines;
}
render() {
return (
<div className='terminal-window'>
<table className='terminal'>
<tbody>
<KeyboardEventHandler handleKeys={['all']} onKeyEvent={this.handleKey} />
{this.displayLines()}
<tr className='terminal-line'><th>{this.state.lineNumber}</th><td>{'>'}{this.state.lastLine}<span className='blink-text'>_</span></td></tr>
</tbody>
</table>
</div>
)
}
}
export default Terminal

View file

@ -1,224 +0,0 @@
import os, json, numpy, pygame, time, threading, jsonpickle
from renderer import *
from copy import deepcopy
groundControlPath = "GroundControl"
stateFilePath = os.path.join("SatState.json")
configPath = os.path.join("ConfigFiles", "OrbitSim")
configFilename = os.path.join(configPath, "Universe.cfg")
satSavePath = os.path.join(configPath, "Orbit.cfg")
mapFilename = os.path.join(configPath, "Map.png")
STATE_EVENT = pygame.event.custom_type()
def config():
"""Returns the config dictionary. Generates with default values if no config dictionary exists."""
if not os.path.exists(configPath):
os.makedirs(configPath)
if not os.path.exists(configFilename):
#generate default
config_dic = {
"G": 6.674e-11,
"earthMass": 5.972e24, #in kg
"earthRadius": 6378000, #meters
"timeScale": 1, #higher number go faster wheeeeee
"updateTick": 300 #seconds to wait between save to file
}
with open(configFilename, "w") as file:
json.dump(config_dic, file, indent = 4)
return config_dic
else:
with open(configFilename) as file:
return json.load(file)
class OrbitingBody:
"""a zero-mass point object parented to a planet"""
def __init__(self, location:Point, velocity:Point, name, displaySize, parentPlanet):
self.location = location
self.resetLocation = location.copy()
self.velocity = velocity
self.resetVelocity = velocity.copy()
self.name = name
self.displaySize = displaySize #the size of the object on camera in pixels, for visibility reasons
self.parentPlanet = parentPlanet
self.lastDelta = 0
self.lastSecondDelta = 0
self.keepFreeze = 3
def stationKeep(self):
currDelta = Point.subtract(self.resetLocation, self.location).magnitude()
currSecondDelta = currDelta - self.lastDelta
if (currSecondDelta > 0) and (self.lastSecondDelta <= 0) and self.keepFreeze <= 0:
self.location = self.resetLocation.copy()
self.velocity = self.resetVelocity.copy()
self.keepFreeze = 3
elif self.keepFreeze > 0:
self.keepFreeze -= 1
self.lastDelta = currDelta
self.lastSecondDelta = currSecondDelta
def latLongAlt(self):
rho, theta, phi = self.location.polar()
rawLat, rawLong = self.parentPlanet.sphericalToLatLong(theta, phi) #negative lat is north, positive lat is south, positive long is east, negative long is west
return (rho - self.parentPlanet.radius), rawLat, rawLong
def writeStateReadable(self):
alt, lat, long = self.latLongAlt()
stateDic = {
"notes": "lat: pos S, neg N; long: pos E, neg W",
"latitude": lat,
"longitude": long,
"altitude": alt,
"velocity": self.velocity.magnitude()
}
with open(stateFilePath, "w") as file:
json.dump(stateDic, file, indent=4)
def saveState(self):
stateDic = {
"location": jsonpickle.encode(self.location),
"velocity": jsonpickle.encode(self.velocity),
}
def loadState(self):
if os.path.exists(satSavePath):
with open(satSavePath) as file:
state = json.load(file)
self.location = jsonpickle.decode(state["location"])
self.velocity = jsonpickle.decode(state["velocity"])
return True
else:
return False
class Planet:
"""A massive body at 0,0,0 and a given radius."""
def __init__(self, name, mass, radius, rotationPeriod, location:Point = deepcopy(Point.zero)):
"""Rotation period given in seconds."""
self.location = location
self.name = name
self.mass = mass
self.radius = radius
self.rotationPercentage = 0.00
self.rotationPeriod = rotationPeriod
def rotate(self, timeDelta):
self.rotationPercentage += timeDelta*100/self.rotationPeriod
if self.rotationPercentage >= 100.0:
self.rotationPercentage -= 100.0
def sphericalToLatLong(self, theta, phi):
"""Converts theta and phi spherical coordinates to latitude and longitude. -> lat, long"""
rotRadian = self.rotationPercentage/100 * 2 * math.pi
lat = math.degrees(phi - (math.pi/2)) #negative lat is north, positive is south
long = rotRadian - theta #positive long is east, negative is west
if long < -math.pi:
long += math.pi*2
elif long > math.pi:
long -= math.pi*2
return (lat, math.degrees(long))
class DisplayPoint:
"""A single point of any color"""
def __init__(self, location, color):
self.location = location
self.color = color
class DecayPoint(DisplayPoint):
"""A display point that slowly fades to black"""
decayTick = 1
currentDecayTick = 0
color = (255,255,255,255)
def update(self):
self.currentDecayTick += 1
if self.currentDecayTick >= self.decayTick:
self.currentDecayTick = 0
self.color = (self.color[0], self.color[1], self.color[2], (max((self.color[3]-5, 0))))
def copy(self):
"""returns a distinct copy of the point"""
return DecayPoint(self.location, self.color)
Planet.Earth = Planet("Earth", config()["earthMass"], config()["earthRadius"], 86400)
def physicsUpdate(objects, orbitlines, deltaTime):
"""updates the positions of all orbiting objects in [objects] with timestep deltaTime"""
for obj in objects:
if type(obj).__name__ == "OrbitingBody":
orbitlines.append(DecayPoint(deepcopy(obj.location), (255,255,255,255)))
if len(orbitlines) > 100:
orbitlines.pop(0)
accel = Point.scalarMult(Point.subtract(obj.location, obj.parentPlanet.location).normalize(),-(config()["G"] * obj.parentPlanet.mass)/(Point.subtract(obj.location, obj.parentPlanet.location).magnitude() ** 2))
obj.velocity = Point.add(obj.velocity, Point.scalarMult(accel, deltaTime))
obj.location = Point.add(obj.location, Point.scalarMult(obj.velocity, deltaTime))
obj.stationKeep()
elif type(obj).__name__ == "Planet":
obj.rotate(deltaTime)
for line in orbitlines:
line.update()
if __name__=="__main__":
pygame.init()
pygame.display.set_caption("Spinny")
window = pygame.display.set_mode((900, 900))
resolutionDownscaling = 2
pygame.display.flip()
FPS = 144 #max framerate
frameTime = 1/144
running = True
display = False
thisEarth = deepcopy(Planet.Earth)
sat = OrbitingBody(Point(0, config()["earthRadius"]*5, config()["earthRadius"]*2), Point(-2500,0,0), "BoSLOO", 5, thisEarth)
orbitlines = []
renderObjects = [thisEarth, sat, orbitlines]
configFile = config()
clock = pygame.time.Clock()
stateTimer = pygame.time.set_timer(STATE_EVENT, configFile["updateTick"]*1000)
mapThread = threading.Thread()
save = False
clock.tick(FPS)
while running:
clock.tick(FPS)
if display:
#deltaTime = frameTime * config()["timeScale"]
deltaTime = (clock.get_time()/1000) * configFile["timeScale"]
physicsUpdate(renderObjects, orbitlines, deltaTime)
camera.renderFrame(save=save)
save=False
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if not display:
display = True
camera = Camera(window, Point(10 * configFile["earthRadius"], 0, 0), thisEarth, renderObjects)
camera.renderFrame()
pygame.display.flip()
else:
save = True
if not mapThread.is_alive():
mapThread = threading.Thread(target=camera.saveGroundTrack())
mapThread.start()
elif event.type == STATE_EVENT:
sat.writeStateReadable()
configFile = config()
#time.sleep(frameTime)
pygame.quit()
print("Bye!")

View file

@ -2,7 +2,7 @@
Browser-based MMO Satellite Toy/Idle Game Browser-based MMO Satellite Toy/Idle Game
## Glossary: **This is incomplete and will be added to as we go** ### Glossary: **This is incomplete and will be added to as we go**
@ -19,13 +19,3 @@ Ground station -> Any given researcher's UI in browser, and any upgrades they ma
Missions -> Research tasks that will result in government funding + grants Missions -> Research tasks that will result in government funding + grants
Funding -> The amount of cash available to use to upgrade a user's ground station/schedule sensor time. Funding -> The amount of cash available to use to upgrade a user's ground station/schedule sensor time.
## Constants:
G: 6.674 * 10^-11
M🜨: 5.972 * 10^24 kg
R🜨: 6378000 m
Period of Rotation(🜨): 86400

View file

@ -1,7 +0,0 @@
{
"notes": "lat: pos S, neg N; long: pos E, neg W",
"latitude": -12.808893957460064,
"longitude": 140.55873504072275,
"altitude": 19134253.574575923,
"velocity": 3777.2583558704296
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

62
interface/sat_infc.py Normal file
View file

@ -0,0 +1,62 @@
import asyncio, telnetlib3
@asyncio.coroutine
def shell(reader, writer):
writer.write('\r\nWelcome to the BoSLOO Primitive Interface!\r\nBPI for debugging and has no checking or feedback, use with caution!\r\n-=>')
go = True
com = ""
while go:
inp = yield from reader.read(1)
for c in inp:
com += c
if c == '\x7f':
writer.write("\r" + " "*(len(com)+1))
com = com[:-2]
writer.write("\r-=>" + com + " ")
writer.write("\r-=>" + com)
yield from writer.drain()
else:
writer.echo(inp)
if c == '\r':
print(com)
writer.write('\r\n')
com = com.strip()
if com == "bye":
writer.close()
go = False
elif com[:4] == "help":
writer.write('ops: GET/SET/EXE\r\n')
writer.write('Op:MTE(s):Subsystem:Field:Parameter\r\n')
writer.write('Parameter only for SET\r\n')
writer.write('MTE to get current time\r\n')
yield from writer.drain()
elif com[:4].upper() == "GET:" or com[:4].upper() == "SET:" or com[:4].upper() == "EXE:":
parts = com.split(":")
if (parts[0].upper() == "GET" or parts[0].upper() == "EXE") and len(parts) == 4:
print("wrote command = ", parts[1]+":"+parts[0].upper()+":"+parts[2]+":"+parts[3])
with open('../satsim/command_q', "a") as q:
q.write(parts[1]+":"+parts[0].upper()+":"+parts[2]+":"+parts[3]+"\n")
elif parts[0].upper() == "SET" and len(parts) == 5:
print("wrote command = ", parts[1]+":"+parts[0].upper()+":"+parts[2]+":"+parts[3]+":"+parts[4])
with open('../satsim/command_q', "a") as q:
q.write(parts[1]+":"+parts[0].upper()+":"+parts[2]+":"+parts[3]+":"+parts[4]+"\n")
else:
writer.write("BAD OP COMMAND\r\n")
yield from writer.drain()
elif com[:3].upper() == "MTE" and len(com) == 3:
with open("../satsim/status", "r") as statfile:
mte = statfile.read()
writer.write(mte + "\r\n")
yield from writer.drain()
else:
writer.write("BAD COMMAND\r\n")
yield from writer.drain()
if go:
writer.write('-=>')
yield from writer.drain()
com = ""
loop = asyncio.get_event_loop()
coro = telnetlib3.create_server(port=7000, shell=shell)
server = loop.run_until_complete(coro)
loop.run_until_complete(server.wait_closed())

View file

@ -1,271 +0,0 @@
import numpy, pygame, math, os
import pygame.freetype
ASSET_DIR = "Assets"
SPHERE_FOLDER_NAME = "Sphere"
MAPS_FOLDER_NAME = "Maps"
class Point:
"""Numpy 3-vec"""
def __init__(self, x, y, z):
self.vector = numpy.array([x, y, z])
def copy(self):
return Point(self.vector[0], self.vector[1], self.vector[2])
def polar(self):
"""Converts the vector rectangular coordinates to polar coordinates."""
if self.vector[0] == 0:
self.vector[0] = 0.1
if self.vector[2] == 0:
self.vector[2] = 0.1
rho = math.sqrt(int(self.vector[0]) ** 2 + int(self.vector[1]) ** 2 + int(self.vector[2]) ** 2)
theta = math.atan(self.vector[1]/self.vector[0]) #this has a range of -pi/2 to pi/2 but we need 0 to 2pi so more work needed
phi = math.acos(self.vector[2]/rho)
if self.vector[0] < 0:
if self.vector[1] >= 0: #if x is positive, atan is fine. need to check if x is negative, first.
theta += math.pi
else:
theta -= math.pi
return [rho, theta, phi]
def magnitude(self):
return float(numpy.linalg.norm(self.vector))
def normalize(self):
self.vector = self.vector/self.magnitude()
return self
def distanceFromPoint(self, otherPoint:"Point"):
return numpy.linalg.norm(self.vector - otherPoint.vector)
def distanceFromLine(self, line:"Line"):
return numpy.linalg.norm(numpy.cross(line.p2.vector - line.p1.vector, self.vector - line.p1.vector)/numpy.linalg.norm(line.p2.vector - line.p1.vector))
def add(p1, p2):
sum = numpy.add(p1.vector, p2.vector)
return Point(sum[0], sum[1], sum[2])
def subtract(p1, p2):
diff = numpy.subtract(p1.vector, p2.vector)
return Point(diff[0], diff[1], diff[2])
def dot(p1, p2):
return numpy.dot(p1.vector, p2.vector)
def scalarMult(p1, scalar):
mult = p1.vector * scalar
return Point(mult[0], mult[1], mult[2])
Point.zero = Point(0, 0, 0)
class Ray:
def __init__(self, origin:Point, direction:Point):
self.origin = origin
self.direction = direction
class Line:
def __init__(self, p1:Point, p2:Point):
self.p1 = p1
self.p2 = p2
def intersectWithPlane(self, plane):
lineVec = Point.subtract(self.p2, self.p1)
dot = Point.dot(plane.normal, lineVec)
if abs(dot) > 1e-6:
w = Point.subtract(self.p1, plane.point)
fac = -Point.dot(plane.normal, w) / dot
u = Point.scalarMult(lineVec, fac)
return Point.add(self.p1, u)
else:
return None
class Plane:
def __init__(self, point:Point, normal:Point):
self.point = point
self.normal = normal
class PlanetSprite(pygame.sprite.Sprite):
def __init__(self, camera, parentPlanet:"Planet"):
pygame.sprite.Sprite.__init__(self)
#the rotation animation loops every 64th of a rotation, so determine and store the frame number.
self.frames = {}
for imgName in os.listdir(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME)):
if imgName.endswith(".png"):
self.frames[imgName.strip(".png")] = pygame.image.load(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME, imgName)).convert_alpha()
self.parentPlanet = parentPlanet
self.frameNumber = str(round(math.modf(self.parentPlanet.rotationPercentage/100 * 64)[0] * 49) + 1).zfill(4)
self.image = self.frames[self.frameNumber]
self.setSize(camera)
def setSize(self, camera):
winWidth, winHeight = camera.surface.get_size()
#distance = Point.subtract(camera.location, self.parentPlanet.location).magnitude()
#radius = self.parentPlanet.radius
#self.sideLength = int((1/math.tan(numpy.radians(camera.hFOV)/2))*radius/math.sqrt(distance**2 - radius**2)*winWidth/2)
lineToCam = Line(Point.add(self.parentPlanet.location, Point(0, self.parentPlanet.radius,0)), camera.location)
intersectPoint = lineToCam.intersectWithPlane(camera.screenPlane)
radius = intersectPoint.vector[1]
self.sideLength = int(radius*2*600/530)
self.image = pygame.transform.scale(self.image, (self.sideLength, self.sideLength))
self.rect = self.image.get_rect()
self.rect.center = (winWidth/2, winHeight/2)
def update(self):
self.frameNumber = str(round(math.modf(self.parentPlanet.rotationPercentage/100 * 64)[0] * 49) + 1).zfill(4)
self.image = pygame.image.load(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME, f"{self.frameNumber}.png")).convert_alpha()
if self.sideLength is not None:
self.image = pygame.transform.scale(self.image, (self.sideLength, self.sideLength))
class Camera:
"""Object in charge of rendering both the realtime 3D scene and a ground track map."""
def __init__(self, surface:pygame.Surface, location:Point, target:"Planet", objects, hFOV = 60):
self.surface = surface
self.objects = objects
self.location = location
self.target = target
self.hFOV = hFOV
self.spriteGroup = pygame.sprite.Group()
self.pastTrackPoints = []
self.trackSampleRate = 8
self.trackSampleCount = 0
self.mapSurface = pygame.image.load(os.path.join(ASSET_DIR, MAPS_FOLDER_NAME, "rect_color.png"))
self.mapWidth, self.mapHeight = self.mapSurface.get_size()
winWidth, winHeight = self.surface.get_size()
winDistance = winWidth / (2 * math.tan(numpy.radians(self.hFOV/2))) #distance for a virtual screen to exist in-space to give the correct FOV
vecToCenter = Point.subtract(self.target.location, self.location)
vecToCenter.normalize()
self.screenPlane = Plane(Point.add(self.location, Point.scalarMult(vecToCenter, winDistance)), vecToCenter)
self.spriteGroup.add(PlanetSprite(self, self.target))
def isInside(self, planet:"Planet"):
"""returns True if camera is inside the planet."""
return numpy.linalg.norm(self.location.magnitude) < planet.radius
def renderFrame(self, save=False):
"""generates a frame and draws it to the surface. Does not update screen; use pygame.display.flip()"""
font = pygame.freetype.SysFont("Comic Sans MS", 14)
winWidth, winHeight = self.surface.get_size()
frontSurface = pygame.Surface((winWidth, winHeight), pygame.SRCALPHA)
backSurface = pygame.Surface((winWidth, winHeight), pygame.SRCALPHA)
backgroundSurface = pygame.Surface((winWidth, winHeight))
backgroundSurface.fill((15,15,15))
backSurface.fill((0,0,0,0))
frontSurface.fill((0,0,0,0))
#pygame uses 0,0 as the top left corner
for obj in self.objects:
if type(obj).__name__ == "OrbitingBody":
sat = obj
lineToCamera = Line(obj.location, self.location)
intersectPoint = lineToCamera.intersectWithPlane(self.screenPlane)
intersectPoint.vector[2] = -intersectPoint.vector[2]
if intersectPoint is not None:
intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2))) #x is meaningless here
if sat.location.vector[0] < 0:
drawSurface = backSurface
else:
drawSurface = frontSurface
pygame.draw.circle(drawSurface, (255,255,150,255), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), obj.displaySize)
elif isinstance(obj, list):
for orbitline in obj:
if orbitline.color != (0,0,0):
lineToCamera = Line(orbitline.location, self.location)
intersectPoint = lineToCamera.intersectWithPlane(self.screenPlane)
intersectPoint.vector[2] = -intersectPoint.vector[2]
if intersectPoint is not None:
intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
if orbitline.color[3] != 0:
if orbitline.location.vector[0] < 0:
drawSurface = backSurface
else:
drawSurface = frontSurface
pygame.draw.circle(drawSurface, orbitline.color, (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 1)
#DEBUG DOTS
#lineToCam = Line(Point.add(self.target.location, Point(0,self.target.radius,0)), self.location)
#intersectPoint = lineToCam.intersectWithPlane(self.screenPlane)
#intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
#pygame.draw.circle(frontSurface, (255,150,150,255), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 5)
#newLineToCam = Line(Point.add(self.screenPlane.point, Point(0,750,0)), self.location)
#intersectPoint = newLineToCam.intersectWithPlane(self.screenPlane)
#intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
#pygame.draw.circle(screenSurface, (150,255,150), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 5)
#generate text
alt, rawLat, rawLong = sat.latLongAlt()
self.updateTrackList(rawLat, rawLong)
latString = f"Latitude: {round(rawLat,4)}⁰ S" if rawLat >= 0 else f"Latitude: {-round(rawLat,4)}⁰ N"
longString = f"Longitude: {round(rawLong,4)}⁰ E" if rawLong >= 0 else f"Longitude: {-round(rawLong,4)}⁰ W"
font.render_to(backSurface, (0,0), f"Speed: {round(sat.velocity.magnitude()/1000,3)} km/s", (255,255,255))
font.render_to(backSurface, (0,20), f"Altitude: {round((alt)/1000)} km", (255,255,255))
font.render_to(backSurface, (0,50), latString, (255,255,255))
font.render_to(backSurface, (0,70), longString, (255,255,255))
self.spriteGroup.update()
self.spriteGroup.draw(backSurface)
self.surface.blit(backgroundSurface, (0,0))
self.surface.blit(backSurface, (0,0))
self.surface.blit(frontSurface, (0,0))
if save:
pygame.image.save(self.surface, "test.png")
def updateTrackList(self, lat, long):
"""Updates the ground track map list of points."""
if self.trackSampleCount != self.trackSampleRate:
self.trackSampleCount += 1
return
if len(self.pastTrackPoints) > 20000:
self.pastTrackPoints.pop(0)
#latitude is from -90 to 90; longitude is from -180 to 180.
latPercent = (lat + 90)/180
longPercent = (long + 180)/360
lat = self.mapHeight * latPercent
long = self.mapWidth * longPercent
self.pastTrackPoints.append((long, lat))
self.trackSampleCount = 0
def saveGroundTrack(self):
mapSurface = pygame.Surface.copy(self.mapSurface)
sets = []
currStart = 0
for i in range(1,len(self.pastTrackPoints)):
if abs(self.pastTrackPoints[i][0] - self.pastTrackPoints[i-1][0]) > 400:
sets.append(self.pastTrackPoints[currStart:i])
currStart = i
sets.append(self.pastTrackPoints[currStart:])
colors = [(122,255,243), (211,122,255), (222,0,177)]
for i in range(0,len(sets)):
try:
pygame.draw.lines(mapSurface, colors[i%3], False, sets[i], width=5)
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long, lat+1) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long+1, lat) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long, lat-1) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long-1, lat) for long, lat in sets[i]])
except:
pass
pygame.image.save(mapSurface, "testMap.png")

10
satsim/command_q Normal file
View file

@ -0,0 +1,10 @@
2:GET:heartbeat:MTE
4:GET:location:coords
5:SET:memory:filename:shark.bmp
6:SET:memory:buffer:Qk1+BgAAAAAAAD4AAAAoAAAAZAAAAGQAAAABAAEAAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wD////////////////wAAAA////////////////8AAAAP////////////////AAAAD//////////8/////wAAAA//////////+P////8AAAAP//////////j/////AAAAD//////////4f////wAAAA///////////H////8AAAAP//////////x/////AAAAD//n//////x8f////wAAAA//x//////4fD////8AAAAP/8P/+fgH/H4/////AAAAD//j//HwB/w+H////wAAAA//4//x+Af8Px////8AAAAP/+P/8f/H/j8P////AAAAD//h//D/x/4AD////wAAAA//8f/4/8f+AAf///8AAAAP//H/+P/H/wAH////AAAAD//w//j/x/+Hw////wAAAA//+P/4f4f/x+P///8AAAAP//j4PH+P/8Pj////AAAAD//4ABx/j//h4////wAAAA//+AAcf4//4eP///8AAAAP//gDPD+H8/H3////AAAAD//4//4/g8P7/////wAAAA//+P/+P8AD//////8AAAAP//h//j/gB///////AAAAD//8f/9/8B///////wAAAA///Hx///////////8AAAAP//wAf///////////AAAAD//8AP///////////wAAAA///gH/+P////////8AAAAP//////D/////////AAAAD//////w/////////wAAAA//////4P////////8AAAAP/////+D/////////AAAAD/////+Af////f///wAAAA//////AH////H///8AAAAP/////gx////A////AAAAD////8AAA///AP///wAAAA////+AAAAH/gD///8AAAAP///+AAAAAPgY////AAAAD////Bx/+AAgeP///wAAAA////g+///wAPj///8AAAAP///wf////AP4////AAAAD///4B////AD+P///wAAAA///8AP///gYfD///8AAAAP///Dz///wfBw////AAAAD///h////gP4MP///wAAAA///4////wP/BH///8AAAAP//+P4//wH/4B////AAAAD///j8P/wP//Af///wAAAA///w/D/gH//8H///8AAAAP//8f5/wH///h////AAAAD///H//gB///8f///wAAAA///w//AMf///H///8AAAAP//8P/AGH////////AAAAD///gAAPj////////wAAAA///4AAB4////////8AAAAP///AAAGP////////AAAAD//////Aj////////wAAAA//////8A////////8AAAAP//////gP////////AAAAD//////8D////////wAAAA///////g////////8AAAAP//////+f////////AAAAD////////////////wAAAA////////////////8AAAAP////////////////AAAAD////////////////wAAAA////////////////8AAAAP////////////////AAAAD////////////////wAAAA////////////////8AAAAP////////////////AAAAD////////////////wAAAA////////////////8AAAAP////////////////AAAAD/////gf/n///////wAAAA/n///wH/x///////8AAAAPx/8B8A/8P///////AAAAD8f+APuP/j///////wAAAA/H/gD/j/4///////8AAAAPx/45/4/+H///////AAAAD8f+P/+P/x///////wAAAA/H/j//D/8f//////8AAAAPx/4//x//H///////AAAAD8f+P/4f/w///////wAAAA+H/AH8P/+MH/////8AAAAPj/gB+H/ngB//////AAAAD4/8A/j/wAA//////wAAAA8P/h/4H8AB//////8AAAAPH/4/+APgD///////AAAADx/+AAwD/////////wAAAAAf/gAPx/////////8AAAAAAA8AH///////////AAAAAAAP/////////////wAAAA4AH/////////////8AAAAP////////////////AAAAD////////////////wAAAA
7:EXE:memory
8:GET:memory:freeSpace
8:SET:memory:mode:download
8:SET:memory:filename:badtest
9:EXE:memory
10:SET:heartbeat:kill:1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

43
satsim/modules/gamma.py Normal file
View file

@ -0,0 +1,43 @@
from .module import module
from random import randint
class gamma_sensor(module):
def __init__(self):
super().__init__("gammaSensor")
self.fields["detections"] = 0
self.fields["detections_str"] = []
self.fields["threshold"] = 90
self.fields["flush"] = 0
self.writable = ["threshold","flush"]
def mod_get(self, field="none"):
if field not in self.fields:
return (-1, "GET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
return (self.fields[field], "GET OK")
def mod_set(self, field="none", value="none"):
if field not in self.fields:
return (-1, "SET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
if field not in self.writable:
return (-1, "SET FATAL: field '" + field + "' is not writable in module: " + self.fields["name"])
try:
self.fields[field] = int(value)
return (0, "SET OK")
except:
return (-1, "SET FATAL: field '" + field + "' in module: " + self.fields["name"] + " takes int")
def mod_exe(self):
pass
def mod_not(self):
pass
def mod_update(self):
if self.fields["flush"] != 0:
self.fields["detections"] = 0
self.fields["detections_str"] = []
self.fields["flush"] = 0
for i in range(0,randint(4,100)):
strength = randint(0,100)
if strength > self.fields["threshold"]:
self.fields["detections"] += 1
self.fields["detections_str"].append(strength)

View file

@ -0,0 +1,33 @@
from .module import module
class heartbeat_module(module):
def __init__(self):
super().__init__("heartbeat")
self.fields["MTE"] = 0
self.fields["kill"] = 0
self.writable = ["kill"]
def mod_get(self, field="none"):
if field not in self.fields:
return (-1, "GET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
return (self.fields[field], "GET OK")
def mod_set(self, field="none", value="none"):
if field not in self.fields:
return (-1, "SET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
if field not in self.writable:
return (-1, "SET FATAL: field '" + field + "' is not writable in module: " + self.fields["name"])
try:
self.fields[field] = int(value)
return (0, "SET OK")
except:
return (-1, "SET FATAL: field '" + field + "' in module: " + self.fields["name"] + " takes int")
def mod_exe(self):
pass
def mod_not(self):
pass
def mod_update(self):
self.fields["MTE"] += 1

View file

@ -0,0 +1,28 @@
from .module import module
class location_module(module):
id_c = 0
def __init__(self):
super().__init__("location")
self.fields["coords"] = "space"
def mod_get(self, field="none"):
if field not in self.fields:
return (-1, "GET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
return (self.fields[field], "GET OK")
def mod_set(self, field="none", value="none"):
if field not in self.fields:
return (-1, "SET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
if field not in self.writable:
return (-1, "SET FATAL: field '" + field + "' is not writable in module: " + self.fields["name"])
try:
self.fields[field] = int(value)
return (0, "SET OK")
except:
return (-1, "SET FATAL: field '" + field + "' in module: " + self.fields["name"] + " takes int")
def mod_not(self):
print("[!] NOT CALLED ON PRIMITIVE MODULE")
def mod_update(self):
pass

51
satsim/modules/memory.py Normal file
View file

@ -0,0 +1,51 @@
from .module import module
class memory_module(module):
def __init__(self):
super().__init__("memoryBank")
self.fields["files"] = []
self.fields["freeSpace"] = 4000
self.fields["mode"] = "upload"
self.fields["buffer"] = 0
self.fields["filename"] = ""
self.writable = ["buffer","filename", "mode"]
def mod_get(self, field="none"):
if field not in self.fields:
return (-1, "GET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
return (self.fields[field], "GET OK")
def mod_set(self, field="none", value="none"):
if field not in self.fields:
return (-1, "SET FATAL: field '" + field + "'' does not exist in module: " + self.fields["name"])
if field not in self.writable:
return (-1, "SET FATAL: field '" + field + "' is not writable in module: " + self.fields["name"])
if field == "mode" and (value == "upload" or value == "download"):
self.fields[field] = value
return (0, "SET OK")
self.fields[field] = value
return (0, "SET OK")
def mod_exe(self):
if self.fields["mode"] == "upload":
if self.fields["freeSpace"] - len(self.fields["buffer"]) >= 0:
self.fields["freeSpace"] -= len(self.fields["buffer"])
with open("./datastore/"+self.fields["filename"],"wb+") as f:
f.write(bytes(self.fields["buffer"],encoding="UTF-8"))
return (0, "WRITE OK")
else:
return (-1, "WRITE FATAL: OUT OF MEMORY")
if self.fields["mode"] == "download":
try:
with open("./datastore/"+self.fields["filename"],"rb") as f:
return (f.read(), "READ OK")
except:
return (-1, "READ FATAL: FILE NOT FOUND")
def mod_not(self):
pass
def mod_update(self):
pass

22
satsim/modules/module.py Normal file
View file

@ -0,0 +1,22 @@
class module:
id_c = 0
def __init__(self, name):
self.fields = {}
self.fields["name"] = name
self.id = module.id_c
module.id_c += 1
def mod_get(self):
print("[!] GET CALLED ON PRIMITIVE MODULE")
def mod_set(self):
print("[!] SET CALLED ON PRIMITIVE MODULE")
def mod_exe(self):
print("[!] EXE CALLED ON PRIMITIVE MODULE")
def mod_not(self):
print("[!] NOT CALLED ON PRIMITIVE MODULE")
def mod_update(self):
pass

77
satsim/satsim.py Normal file
View file

@ -0,0 +1,77 @@
import numpy as np
from modules.gamma import gamma_sensor
from modules.heartbeat import heartbeat_module
from modules.location import location_module
from modules.memory import memory_module
from time import sleep
from os import system
#debugg to rebuild the file every test
system('cp command_q test_q')
ONSAT_FILESTORE = "DATA"
DOWNLINK_FILESTORE = "../store/data"
class sat:
def __init__(self):
self.attitude = "Fellin pretty good" #astropy is broke rn
self.battery = 100.00
self.maneuver_TTC = 0 #time to completion
self.gyro_saturation = 0
self.modules = {
"heartbeat" : heartbeat_module(),
"location" : location_module(),
#"power" : power_manager(),
#"attitude" : attitude_module(),
"memory" : memory_module(),
"gamma_sensor" : gamma_sensor()
}
def check_command_q(self):
cur_batch = []
with open("command_q","r") as q:
com_q = q.read().splitlines()
for com in com_q:
if int(com.split(":")[0]) == self.modules["heartbeat"].mod_get("MTE")[0]:
cur_batch.append(com)
return cur_batch
def spin(self):
while True:
MTE = self.modules["heartbeat"].mod_get("MTE")[0]
print(MTE)
batch = self.check_command_q()
for c in batch:
print(c)
com = c.split(":")
if com[1] == "GET" and len(com) == 4:
res = self.modules[com[2]].mod_get(com[3])
elif com[1] == "SET" and len(com) == 5:
res = self.modules[com[2]].mod_set(com[3],com[4])
elif com[1] == "EXE" and len(com) == 3:
res = self.modules[com[2]].mod_exe()
else:
res = (-1, "BAD COMMAND: " + c)
print(res)
for m in self.modules:
self.modules[m].mod_update()
if self.modules["heartbeat"].mod_get("kill")[0] == 1:
print("heading to bed")
return
with open("MTE", "r+") as statfile:
statfile.seek(0)
statfile.truncate()
statfile.write(str(MTE))
sleep(1)
if __name__ == "__main__":
BoSLOO = sat()
BoSLOO.spin()

1
satsim/status Normal file
View file

@ -0,0 +1 @@
43

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB