From fc915d78d67867f070292677fb0493e493bbd177 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 15 Aug 2023 12:09:14 +0000 Subject: [PATCH 001/153] [nasa/nos3#127] Added executible bit to scripts; --- gsw/scripts/checkout.sh | 0 gsw/scripts/create_cosmos_gem.sh | 0 gsw/scripts/fsw_respawn.sh | 0 gsw/scripts/reboot.sh | 0 gsw/scripts/sc_launch.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gsw/scripts/checkout.sh mode change 100644 => 100755 gsw/scripts/create_cosmos_gem.sh mode change 100644 => 100755 gsw/scripts/fsw_respawn.sh mode change 100644 => 100755 gsw/scripts/reboot.sh mode change 100644 => 100755 gsw/scripts/sc_launch.sh diff --git a/gsw/scripts/checkout.sh b/gsw/scripts/checkout.sh old mode 100644 new mode 100755 diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh old mode 100644 new mode 100755 diff --git a/gsw/scripts/fsw_respawn.sh b/gsw/scripts/fsw_respawn.sh old mode 100644 new mode 100755 diff --git a/gsw/scripts/reboot.sh b/gsw/scripts/reboot.sh old mode 100644 new mode 100755 diff --git a/gsw/scripts/sc_launch.sh b/gsw/scripts/sc_launch.sh old mode 100644 new mode 100755 From c787a7e1ec4a0efffa1e1c25046d0bb47894bbaf Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 16 Aug 2023 05:11:58 -0400 Subject: [PATCH 002/153] [nasa/nos3#127] Updated create_cosmos_gem.sh with error messages and to self escalate to allow plugin generation on host; --- gsw/scripts/create_cosmos_gem.sh | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 27033de2..7716e87f 100755 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -3,6 +3,12 @@ # Convenience script for NOS3 development # +# Self escalate screipt +if [ "$EUID" -ne 0 ] +then + exec sudo -s "$0" "$@" +fi + SCRIPT_DIR=$(cd `dirname $0` && pwd) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 @@ -13,11 +19,25 @@ cd $SCRIPT_DIR/../cosmos # Delete any previous run info rm -rf build +if [ -d "build" ] +then + echo "" + echo "ERROR: Failed to delete build directory!" + echo "" + exit 1 +fi # Start generating the plugin mkdir build cd build /opt/nos3/cosmos/openc3.sh cliroot generate plugin nos3 +if [ ! -d "openc3-cosmos-nos3" ] +then + echo "" + echo "ERROR: cliroot generate plugin nos3 failed!" + echo "" + exit 1 +fi # Copy targets mkdir openc3-cosmos-nos3/targets @@ -48,6 +68,14 @@ cp -r ../../lib . # Create plugin.txt echo "Create plugin..." rm plugin.txt +if [ -f "plugin.txt" ] +then + echo "" + echo "ERROR: Failed to remove plugin.txt file!" + echo "" + exit 1 +fi + for i in $targets do if [ "$i" != "SYSTEM" ] @@ -76,6 +104,13 @@ echo "" # Build plugin echo "Build plugin..." /opt/nos3/cosmos/openc3.sh cliroot rake build VERSION=1.0.$DATE +if [ ! -f "openc3-cosmos-nos3-1.0.$DATE.gem" ] +then + echo "" + echo "ERROR: cliroot rake build failed!" + echo "" + exit 1 +fi echo "" # Install plugin @@ -89,6 +124,9 @@ echo "Load plugin..." /opt/nos3/cosmos/openc3.sh cliroot load openc3-cosmos-nos3-1.0.$DATE.gem echo "" +# Set permissions on build files +chmod -R 777 $BASE_DIR/gsw/cosmos/build + echo "Create COSMOS gem script complete." echo "Note that while this script is complete, COSMOS is likely still be processing behind the scenes!" echo "" From 485ff7f9b4ae70011952243b3d990f42001e2f15 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 16 Aug 2023 06:38:01 -0400 Subject: [PATCH 003/153] [nasa/nos3#138] Radio functioning after forwarding additional ports to OpenC3 in compoase.yaml - will require base box update; --- gsw/scripts/create_cosmos_gem.sh | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 7716e87f..e9ffb1d7 100755 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -78,21 +78,41 @@ fi for i in $targets do - if [ "$i" != "SYSTEM" ] + if [ "$i" != "SIM_42_TRUTH" -a "$i" != "SYSTEM" -a "$i" != "TO_DEBUG" ] then + debug=$i"_DEBUG" + radio=$i"_RADIO" + echo TARGET $i $debug >> plugin.txt + echo TARGET $i $radio >> plugin.txt + else echo TARGET $i $i >> plugin.txt fi done echo "" >> plugin.txt + echo "INTERFACE DEBUG udp_interface.rb host.docker.internal 5012 5013 nil nil 128 10.0 nil" >> plugin.txt for i in $targets do - if [ "$i" != "SIM_42_TRUTH" -a "$i" != "SYSTEM" ] + if [ "$i" != "SIM_42_TRUTH" -a "$i" != "SYSTEM" -a "$i" != "TO_DEBUG" ] then - echo " MAP_TARGET $i" >> plugin.txt + debug=$i"_DEBUG" + echo " MAP_TARGET $debug" >> plugin.txt fi done +echo " MAP_TARGET TO_DEBUG" >> plugin.txt echo "" >> plugin.txt + +echo "INTERFACE RADIO udp_interface.rb host.docker.internal 5010 5011 nil nil 128 10.0 nil" >> plugin.txt +for i in $targets +do + if [ "$i" != "SIM_42_TRUTH" -a "$i" != "SYSTEM" -a "$i" != "TO_DEBUG" ] + then + radio=$i"_RADIO" + echo " MAP_TARGET $radio" >> plugin.txt + fi +done +echo "" >> plugin.txt + echo "INTERFACE SIM_42_TRUTH_INT udp_interface.rb host.docker.internal 5110 5111 nil nil 128 10.0 nil" >> plugin.txt echo " MAP_TARGET SIM_42_TRUTH" >> plugin.txt From 22d495620be22ea5612980aea7e5a4dfe71b1170 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 23 Aug 2023 09:30:46 -0400 Subject: [PATCH 004/153] [nasa/nos3#163] Addition of docker commands (dall, dfsw, dgsw) - cFS error in container currently; --- Makefile | 15 ++- gsw/scripts/create_cosmos_gem.sh | 10 +- gsw/scripts/docker_build.sh | 5 +- gsw/scripts/docker_build_fsw.sh | 11 ++ gsw/scripts/docker_build_sim.sh | 11 ++ gsw/scripts/docker_launch.sh | 167 ++++++++++++++++++++----- gsw/scripts/docker_stop.sh | 54 +++++--- gsw/scripts/env.sh | 34 +++++ sims/cfg/nos3-simulator.xml | 67 +++++----- sims/cfg/nos_engine_server_config.json | 4 +- 10 files changed, 289 insertions(+), 89 deletions(-) create mode 100644 gsw/scripts/docker_build_fsw.sh create mode 100644 gsw/scripts/docker_build_sim.sh create mode 100644 gsw/scripts/env.sh diff --git a/Makefile b/Makefile index 4933f69f..af7bf968 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all fsw fsw-prep pack sim sim-prep clean clean-fsw clean-sim checkout gsw gsm-prep launch log real-clean stop sc-launch +LOCALTGTS := all fsw fsw-prep sim sim-prep clean clean-fsw clean-gsw clean-sim dall dfsw dsim dlaunch gsw gsw-launch launch log real-clean sc-launch stop OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -97,6 +97,18 @@ clean-gsw: checkout: ./gsw/scripts/checkout.sh +dall: + ./gsw/scripts/docker_build.sh + +dfsw: + ./gsw/scripts/docker_build_fsw.sh + +dsim: + ./gsw/scripts/docker_build_sim.sh + +dlaunch: + ./gsw/scripts/docker_launch.sh + gsw-launch: ./gsw/scripts/gsw.sh @@ -117,4 +129,5 @@ sc-launch: ./gsw/scripts/sc_launch.sh stop: + ./gsw/scripts/docker_stop.sh ./gsw/scripts/stop.sh diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 27033de2..607ec6e1 100644 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -8,6 +8,8 @@ BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 DATE=$(date "+%Y%m%d%H%M") +OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" + # Start by changing to a known location cd $SCRIPT_DIR/../cosmos @@ -17,7 +19,7 @@ rm -rf build # Start generating the plugin mkdir build cd build -/opt/nos3/cosmos/openc3.sh cliroot generate plugin nos3 +$OPENC3_PATH cliroot generate plugin nos3 # Copy targets mkdir openc3-cosmos-nos3/targets @@ -75,18 +77,18 @@ echo "" # Build plugin echo "Build plugin..." -/opt/nos3/cosmos/openc3.sh cliroot rake build VERSION=1.0.$DATE +$OPENC3_PATH cliroot rake build VERSION=1.0.$DATE echo "" # Install plugin echo "Install plugin..." cd $GSW_BIN -/opt/nos3/cosmos/openc3.sh cliroot geminstall ./openc3-cosmos-nos3-1.0.$DATE.gem +$OPENC3_PATH cliroot geminstall ./openc3-cosmos-nos3-1.0.$DATE.gem echo "" # Load plugin echo "Load plugin..." -/opt/nos3/cosmos/openc3.sh cliroot load openc3-cosmos-nos3-1.0.$DATE.gem +$OPENC3_PATH cliroot load openc3-cosmos-nos3-1.0.$DATE.gem echo "" echo "Create COSMOS gem script complete." diff --git a/gsw/scripts/docker_build.sh b/gsw/scripts/docker_build.sh index 7e7b9c3b..6377945e 100755 --- a/gsw/scripts/docker_build.sh +++ b/gsw/scripts/docker_build.sh @@ -8,4 +8,7 @@ SCRIPT_DIR=$(cd `dirname $0` && pwd) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it nos3 make clean all +docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw sim + +# Note that GSW cannot from inside docker +make gsw diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh new file mode 100644 index 00000000..9eda35c8 --- /dev/null +++ b/gsw/scripts/docker_build_fsw.sh @@ -0,0 +1,11 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://docs.docker.com/engine/install/ubuntu/ +# + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) + +docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh new file mode 100644 index 00000000..b07cf6e5 --- /dev/null +++ b/gsw/scripts/docker_build_sim.sh @@ -0,0 +1,11 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://docs.docker.com/engine/install/ubuntu/ +# + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) + +docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make sim diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 37c357f1..90f03f04 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -1,59 +1,162 @@ #!/bin/bash -i # # Convenience script for NOS3 development -# Use with the Dockerfile in the deployment repository # https://docs.docker.com/engine/install/ubuntu/ # SCRIPT_DIR=$(cd `dirname $0` && pwd) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 +FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 +GSW_DIR=$BASE_DIR/gsw/cosmos SIM_DIR=$BASE_DIR/sims/build SIM_BIN=$SIM_DIR/bin SIMS=$(cd $SIM_BIN; ls nos3*simulator) +if [ -f "/etc/redhat-release" ]; then + DFLAGS="sudo docker run --rm --group-add keep-groups -it" + DCREATE="sudo docker create --rm -it" + DNETWORK="sudo docker network" +else + DFLAGS="docker run --rm -it" + DCREATE="docker create --rm -it" + DNETWORK="docker network" +fi + # Debugging #echo "Script directory = " $SCRIPT_DIR #echo "Base directory = " $BASE_DIR -#echo "FSW directory = " $FSW_BIN +#echo "DFLAGS = " $DFLAGS +#echo "FSW directory = " $FSW_DIR +#echo "GSW directory = " $GSW_DIR #echo "Sim directory = " $SIM_BIN #echo "Sim list = " $SIMS +#echo "Docker flags = " $DFLAGS +#echo "Docker create = " $DCREATE +#echo "Docker network = " $DNETWORK #exit -#echo "Make /tmp folders..." -#mkdir /tmp/data 2> /dev/null -#mkdir /tmp/data/hk 2> /dev/null -#mkdir /tmp/uplink 2> /dev/null -echo "42..." +echo "Make data folders..." +# FSW Side +mkdir $FSW_DIR/data 2> /dev/null +mkdir $FSW_DIR/data/cam 2> /dev/null +mkdir $FSW_DIR/data/evs 2> /dev/null +mkdir $FSW_DIR/data/hk 2> /dev/null +mkdir $FSW_DIR/data/inst 2> /dev/null +# GSW Side +mkdir /tmp/data 2> /dev/null +mkdir /tmp/data/cam 2> /dev/null +mkdir /tmp/data/evs 2> /dev/null +mkdir /tmp/data/hk 2> /dev/null +mkdir /tmp/data/inst 2> /dev/null +mkdir /tmp/uplink 2> /dev/null +cp $BASE_DIR/fsw/build/exe/cpu1/cf/cfe_es_startup.scr /tmp/uplink/tmp0.so 2> /dev/null +cp $BASE_DIR/fsw/build/exe/cpu1/cf/sample.so /tmp/uplink/tmp1.so 2> /dev/null +# 42 cd /opt/nos3/42/ rm -rf NOS3InOut cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut -xhost +local:* -docker run -d -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --network=host -w /opt/nos3/42 -t nos3 /opt/nos3/42/42 NOS3InOut - -echo "Simulators..." -#cd $SIM_BIN -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN -t nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos-time-driver -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-simulator-terminal -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-cam-simulator -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-generic-reactionwheel-simulator -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-gps-simulator -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-sample-simulator -docker run --rm -d -v $SIM_DIR:$SIM_DIR --network=host -w $SIM_BIN nos3 $SIM_BIN/nos3-single-simulator truth42sim -echo "COSMOS Ground Station..." -cd $BASE_DIR/gsw/cosmos -export MISSION_NAME=$(echo "NOS3") -export PROCESSOR_ENDIANNESS=$(echo "LITTLE_ENDIAN") -docker run --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:ro -e QT_X11_NO_MITSHM=1 \ - -v /home/nos3/Desktop/github-nos3/gsw/cosmos:/cosmos/cosmos \ - -v /home/nos3/Desktop/github-nos3/components/:/COMPONENTS -w /cosmos/cosmos -d --network=host \ - ballaerospace/cosmos /bin/bash -c 'ruby Launcher -c nos3_launcher.txt --system nos3_system.txt && true' # true is necessary to avoid setpgrp error +echo "Create ground networks..." +$DNETWORK create \ + --driver=bridge \ + --subnet=192.168.41.0/24 \ + --gateway=192.168.41.1 \ + NOS3_GC +echo "" + + +echo "Create NOS interfaces..." +export GND_CFG_FILE="-f nos3-simulator.xml" +gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE stdio-terminal +gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_udp_terminal" --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE udp-terminal +echo "" + + +export SATNUM=1 + +# +# Spacecraft Loop +# +for (( i=1; i<=$SATNUM; i++ )) +do + export SC_NUM="sc_"$i + export SC_NETNAME="sc_"$i"_satnet" + export SC_CFG_FILE="-f nos3-simulator.xml" #"-f sc_"$i"_nos3_simulator.xml" + + # Debugging + #echo "Spacecraft number = " $SC_NUM + #echo "Spacecraft network = " $SC_NETNAME + #echo "Spacecraft configuration = " $SC_CFG_FILE + + echo $SC_NUM " - Create spacecraft network..." + $DNETWORK create $SC_NETNAME + echo "" + + echo $SC_NUM " - 42..." + cd /opt/nos3/42/ + xhost +local:* + gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut + echo "" + + echo $SC_NUM " - Flight Software..." + cd $FSW_DIR + gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $FSW_DIR:$FSW_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=1500 ivvitc/nos3 ./core-cpu1 -R PO & + echo "" + + # Debugging + # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually + + echo $SC_NUM " - Simulators..." + cd $SIM_BIN + gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos3_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json + gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE truth42sim + gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE camsim + gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_css_sim + gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim + gnome-terminal --tab --title=$SC_NUM" - FSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_fss_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-fss-sim + gnome-terminal --tab --title=$SC_NUM" - IMU Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_imu_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_imu_sim + gnome-terminal --tab --title=$SC_NUM" - GPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_gps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE gps + gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 + gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 + gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 + gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim + gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample-sim + gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + docker network connect $SC_NETNAME nos_terminal + docker network connect $SC_NETNAME nos_udp_terminal + echo "" + + + +done + + +echo "NOS Time Driver..." sleep 5 +gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE time +sleep 1 +for (( i=1; i<=$SATNUM; i++ )) +do + export SC_NUM="sc_"$i + export SC_NETNAME=$SC_NUM"_satnet" + export TIMENAME=$SC_NUM"_nos_time_driver" + $DNETWORK connect --alias nos_time_driver $SC_NETNAME nos_time_driver +done +echo "" + + +echo "COSMOS Ground Station..." +#cd $BASE_DIR/gsw/cosmos +#export MISSION_NAME=$(echo "NOS3") +#export PROCESSOR_ENDIANNESS=$(echo "LITTLE_ENDIAN") +#ruby Launcher -c nos3_launcher.txt --system nos3_system.txt & +pidof firefox > /dev/null +if [ $? -eq 1 ] +then + firefox localhost:2900 & +fi +echo "" -echo "Flight Software..." -cd $FSW_BIN -gnome-terminal --title="NOS3 Flight Software" -- docker run --rm -it -v $FSW_BIN:$FSW_BIN --network=host -w $FSW_BIN --sysctl fs.mqueue.msg_max=500 nos3 $FSW_BIN/core-cpu1 -R PO & +echo "Docker launch script completed!" diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index d7ab16dc..6631ecc4 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -4,14 +4,20 @@ # https://docs.docker.com/engine/install/ubuntu/ # -export SCRIPT_DIR=$(cd `dirname $0` && pwd) -export BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -export FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -export SIM_DIR=$BASE_DIR/sims/build -export SIM_BIN=$SIM_DIR/bin -export SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -# NOS3 +SCRIPT_DIR=$(cd `dirname $0` && pwd) +BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 +GSW_DIR=$BASE_DIR/gsw/cosmos +if [ -f "/etc/redhat-release" ]; then + # https://github.com/containers/podman/issues/14284#issuecomment-1130113553 + # sudo sed -i 's/runtime = "runc"/runtime = "crun" # "runc"/g' /usr/share/containers/containers.conf + DFLAG="sudo docker" +else + DFLAG="docker" +fi +SIM_DIR=$BASE_DIR/sims/build +SIM_BIN=$SIM_DIR/bin +SIMS=$(cd $SIM_BIN; ls nos3*simulator) # NOS3 GPIO rm -rf /tmp/gpio_fake @@ -20,21 +26,31 @@ rm -rf /tmp/gpio_fake rm -rf $BASE_DIR/fsw/build/exe/cpu1/scratch/* # Docker -cd $SCRIPT_DIR; docker compose down -for i in $(docker container ls -q); do - docker container kill $i -done -docker container prune -f +cd $SCRIPT_DIR; $DFLAG compose down > /dev/null 2>&1 +#for i in $($DFLAG container ls -q); do +# if [ "$i" == "openc3"* ] +# then +# $DFLAG container kill $i > /dev/null 2>&1 +# fi +#done +docker ps --filter=name="sc_*" -aq | xargs docker stop > /dev/null 2>&1 +docker ps --filter=name="nos_*" -aq | xargs docker stop > /dev/null 2>&1 + +$DFLAG container prune -f > /dev/null 2>&1 +$DFLAG network rm NOS3_GC > /dev/null 2>&1 +$DFLAG network rm sc_1_satnet > /dev/null 2>&1 +$DFLAG network rm sc_2_satnet > /dev/null 2>&1 +$DFLAG network rm sc_3_satnet > /dev/null 2>&1 +$DFLAG network rm sc_21_splitnet > /dev/null 2>&1 +$DFLAG network rm sc_32_splitnet > /dev/null 2>&1 # 42 rm -rf /opt/nos3/42/NOS3InOut rm -rf /tmp/gpio* -# cFS - # COSMOS -yes | rm $BASE_DIR/gsw/cosmos/Gemfile 2> /dev/null -yes | rm $BASE_DIR/gsw/cosmos/Gemfile.lock 2> /dev/null -yes | rm -r $BASE_DIR/gsw/cosmos/COMPONENTS 2> /dev/null +yes | rm $GSW_DIR/Gemfile > /dev/null 2>&1 +yes | rm $GSW_DIR/Gemfile.lock > /dev/null 2>&1 +yes | rm -r $GSW_DIR/COMPONENTS > /dev/null 2>&1 -exit 0 \ No newline at end of file +exit 0 diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh new file mode 100644 index 00000000..456065fc --- /dev/null +++ b/gsw/scripts/env.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Convenience script for NOS3 development +# + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 +GSW_DIR=$BASE_DIR/gsw/cosmos +SIM_DIR=$BASE_DIR/sims/build +SIM_BIN=$SIM_DIR/bin +SIMS=$(cd $SIM_BIN; ls nos3*simulator) + +if [ -f "/etc/redhat-release" ]; then + DFLAGS="sudo docker run --rm --group-add keep-groups -it" + DCREATE="sudo docker create --rm -it" + DNETWORK="sudo docker network" +else + DFLAGS="docker run --rm -it" + DCREATE="docker create --rm -it" + DNETWORK="docker network" +fi + +# Debugging +echo "Script directory = " $SCRIPT_DIR +echo "Base directory = " $BASE_DIR +echo "DFLAGS = " $DFLAGS +echo "FSW directory = " $FSW_DIR +echo "GSW directory = " $GSW_DIR +echo "Sim directory = " $SIM_BIN +echo "Sim list = " $SIMS +echo "Docker flags = " $DFLAGS +echo "Docker create = " $DCREATE +echo "Docker network = " $DNETWORK diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index a8c3b952..9ede2e4c 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -10,7 +10,7 @@ 814048200.0 10000 10000 - tcp://0.0.0.0:12001 + tcp://nos_engine_server:12001 @@ -21,29 +21,16 @@ TimeDriver - time - command - time-driver - - + + stdio-terminal true @@ -80,6 +67,7 @@ + udp-terminal true @@ -116,6 +104,11 @@ + + + + + sample_sim true @@ -137,6 +130,7 @@ + gps true @@ -152,7 +146,7 @@ GPS42SOCKET - localhost + fortytwo 4245 5 5 @@ -166,6 +160,7 @@ --> + camsim true @@ -186,6 +181,7 @@ + generic_eps_sim true @@ -266,6 +262,7 @@ + generic-reactionwheel-sim0 true @@ -281,7 +278,7 @@ GENERICRWSIMDATA42SOCKETPROVIDER - localhost + fortytwo 4277 4278 5 @@ -291,6 +288,7 @@ + generic-reactionwheel-sim1 true @@ -306,7 +304,7 @@ GENERICRWSIMDATA42SOCKETPROVIDER - localhost + fortytwo 4377 4378 5 @@ -316,6 +314,7 @@ + generic-reactionwheel-sim2 true @@ -331,7 +330,7 @@ GENERICRWSIMDATA42SOCKETPROVIDER - localhost + fortytwo 4477 4478 5 @@ -341,6 +340,7 @@ + generic_css_sim true @@ -356,7 +356,7 @@ GENERIC_CSS_42_PROVIDER - localhost + fortytwo 4227 5 5 @@ -369,6 +369,7 @@ + generic_torquer_sim true @@ -397,6 +398,7 @@ + truth42sim true @@ -412,7 +414,7 @@ TRUTH42PROVIDER - localhost + fortytwo 9999 10 0 @@ -420,6 +422,7 @@ + generic-fss-sim true @@ -435,7 +438,7 @@ GENERIC_FSS_42_PROVIDER - localhost + fortytwo 4281 5 5 @@ -443,6 +446,7 @@ + generic_radio_sim true @@ -457,19 +461,19 @@ fsw - 0.0.0.0 + nos_fsw 5010 5011 5015 radio - 0.0.0.0 + radio_sim 5014 gsw - 0.0.0.0 + cosmos 6010 6011 @@ -481,7 +485,7 @@ prox - 0.0.0.0 + radio_sim 7012 7010 7011 @@ -493,6 +497,7 @@ + generic_imu_sim true @@ -511,7 +516,7 @@ GENERIC_IMU_42_PROVIDER - localhost + fortytwo 4280 5 5 @@ -519,6 +524,7 @@ + generic_mag_sim true @@ -537,7 +543,7 @@ GENERIC_MAG_42_PROVIDER - localhost + fortytwo 4234 5 5 @@ -545,5 +551,6 @@ + diff --git a/sims/cfg/nos_engine_server_config.json b/sims/cfg/nos_engine_server_config.json index 0a20c275..624fc68c 100644 --- a/sims/cfg/nos_engine_server_config.json +++ b/sims/cfg/nos_engine_server_config.json @@ -6,11 +6,11 @@ "server_uris": [ { "name": "fsw", - "server_uri": "tcp://0.0.0.0:12000" + "server_uri": "tcp://nos_engine_server:12000" }, { "name": "nos3", - "server_uri": "tcp://0.0.0.0:12001" + "server_uri": "tcp://nos_engine_server:12001" } ] } From 70fcf3cf8764c7491a1cf26bbb0df49934fb924f Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 23 Aug 2023 17:18:05 -0400 Subject: [PATCH 005/153] [nasa/nos3#163] Updated SCRIPT_DIR variable in all scripts and got FSW launching without error - still problems connecting various pieces; --- components/novatel_oem615 | 2 +- fsw/psp | 2 +- gsw/scripts/checkout.sh | 2 +- gsw/scripts/create_cosmos_gem.sh | 2 +- gsw/scripts/docker_build.sh | 2 +- gsw/scripts/docker_build_fsw.sh | 2 +- gsw/scripts/docker_build_sim.sh | 2 +- gsw/scripts/docker_compose_launch.sh | 2 +- gsw/scripts/docker_launch.sh | 17 ++++++++--------- gsw/scripts/docker_stop.sh | 2 +- gsw/scripts/env.sh | 2 +- gsw/scripts/gsw.sh | 2 +- gsw/scripts/l0.sh | 2 +- gsw/scripts/launch.sh | 2 +- gsw/scripts/log.sh | 2 +- gsw/scripts/real_clean.sh | 2 +- gsw/scripts/reboot.sh | 2 +- gsw/scripts/sc_launch.sh | 2 +- gsw/scripts/stop.sh | 2 +- 19 files changed, 26 insertions(+), 27 deletions(-) diff --git a/components/novatel_oem615 b/components/novatel_oem615 index d1d31d48..75c93346 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit d1d31d48022589fa3486c715e5168300a27a3c22 +Subproject commit 75c93346d7349d3d24067bfb79485140deb149fc diff --git a/fsw/psp b/fsw/psp index 07c3ce7b..537b7523 160000 --- a/fsw/psp +++ b/fsw/psp @@ -1 +1 @@ -Subproject commit 07c3ce7b58f3f9d4b20ef692f837c15d1bed1179 +Subproject commit 537b7523b944e1dbe2cf7994fad9370fe00ed56c diff --git a/gsw/scripts/checkout.sh b/gsw/scripts/checkout.sh index 6aca954d..3b2f7a6c 100644 --- a/gsw/scripts/checkout.sh +++ b/gsw/scripts/checkout.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 SIM_BIN=$BASE_DIR/sims/build/bin diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 607ec6e1..29258341 100644 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 DATE=$(date "+%Y%m%d%H%M") diff --git a/gsw/scripts/docker_build.sh b/gsw/scripts/docker_build.sh index 6377945e..2c24f818 100755 --- a/gsw/scripts/docker_build.sh +++ b/gsw/scripts/docker_build.sh @@ -5,7 +5,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw sim diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index 9eda35c8..3cf7817c 100644 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -5,7 +5,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index b07cf6e5..9a8dd421 100644 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -5,7 +5,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make sim diff --git a/gsw/scripts/docker_compose_launch.sh b/gsw/scripts/docker_compose_launch.sh index 86661249..7af0b373 100755 --- a/gsw/scripts/docker_compose_launch.sh +++ b/gsw/scripts/docker_compose_launch.sh @@ -5,7 +5,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -export SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) export BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) export FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 export SIM_DIR=$BASE_DIR/sims/build diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 90f03f04..7882d86a 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -4,7 +4,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 GSW_DIR=$BASE_DIR/gsw/cosmos @@ -82,7 +82,7 @@ export SATNUM=1 for (( i=1; i<=$SATNUM; i++ )) do export SC_NUM="sc_"$i - export SC_NETNAME="sc_"$i"_satnet" + export SC_NETNAME="nos3_"$SC_NUM export SC_CFG_FILE="-f nos3-simulator.xml" #"-f sc_"$i"_nos3_simulator.xml" # Debugging @@ -102,7 +102,8 @@ do echo $SC_NUM " - Flight Software..." cd $FSW_DIR - gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $FSW_DIR:$FSW_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=1500 ivvitc/nos3 ./core-cpu1 -R PO & + gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $FSW_DIR:$FSW_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --cap-add sys_nice ivvitc/nos3 ./core-cpu1 -R PO & + docker network connect openc3-cosmos-network nos_fsw echo "" # Debugging @@ -122,14 +123,12 @@ do gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim + $DNETWORK connect openc3-cosmos-network radio_sim gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample-sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim - docker network connect $SC_NETNAME nos_terminal - docker network connect $SC_NETNAME nos_udp_terminal + $DNETWORK connect $SC_NETNAME nos_terminal + $DNETWORK connect $SC_NETNAME nos_udp_terminal echo "" - - - done @@ -140,7 +139,7 @@ sleep 1 for (( i=1; i<=$SATNUM; i++ )) do export SC_NUM="sc_"$i - export SC_NETNAME=$SC_NUM"_satnet" + export SC_NETNAME="nos3_"$SC_NUM export TIMENAME=$SC_NUM"_nos_time_driver" $DNETWORK connect --alias nos_time_driver $SC_NETNAME nos_time_driver done diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index 6631ecc4..1f0f0aaf 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -4,7 +4,7 @@ # https://docs.docker.com/engine/install/ubuntu/ # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 GSW_DIR=$BASE_DIR/gsw/cosmos diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 456065fc..6b9ffc23 100644 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 GSW_DIR=$BASE_DIR/gsw/cosmos diff --git a/gsw/scripts/gsw.sh b/gsw/scripts/gsw.sh index b17cf3b3..c48e8229 100755 --- a/gsw/scripts/gsw.sh +++ b/gsw/scripts/gsw.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 diff --git a/gsw/scripts/l0.sh b/gsw/scripts/l0.sh index a19c092f..6425169d 100755 --- a/gsw/scripts/l0.sh +++ b/gsw/scripts/l0.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) DATE=$(date "+%Y%m%d_%H%M") COSMOS_DIR=$(cd $BASE_DIR/gsw/cosmos && pwd) diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index ab9d7ab1..93524075 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 SIM_BIN=$BASE_DIR/sims/build/bin diff --git a/gsw/scripts/log.sh b/gsw/scripts/log.sh index a0b2fa34..319800ae 100755 --- a/gsw/scripts/log.sh +++ b/gsw/scripts/log.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) DATE=$(date "+%Y%m%d_%H%M") CAP_NAME=$DATE'_console.txt' diff --git a/gsw/scripts/real_clean.sh b/gsw/scripts/real_clean.sh index fd2dd355..12250636 100755 --- a/gsw/scripts/real_clean.sh +++ b/gsw/scripts/real_clean.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) echo "Cleaning up all COSMOS files..." diff --git a/gsw/scripts/reboot.sh b/gsw/scripts/reboot.sh index 1d548118..b5fc26cd 100644 --- a/gsw/scripts/reboot.sh +++ b/gsw/scripts/reboot.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 SIM_BIN=$BASE_DIR/sims/build/bin diff --git a/gsw/scripts/sc_launch.sh b/gsw/scripts/sc_launch.sh index 60e92d7b..8d21c458 100644 --- a/gsw/scripts/sc_launch.sh +++ b/gsw/scripts/sc_launch.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 SIM_BIN=$BASE_DIR/sims/build/bin diff --git a/gsw/scripts/stop.sh b/gsw/scripts/stop.sh index 98bb87ac..a99dcacf 100755 --- a/gsw/scripts/stop.sh +++ b/gsw/scripts/stop.sh @@ -3,7 +3,7 @@ # Convenience script for NOS3 development # -SCRIPT_DIR=$(cd `dirname $0` && pwd) +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) # cFS From ccea009eaad125ea640744b9a00da6a67f3a3a47 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 28 Aug 2023 08:24:28 -0400 Subject: [PATCH 006/153] [nasa/nos3#163] Scripts leverage single env.sh setup, updated nos3-simulator.xml file to increase 42 connection attempts, updated 42 Inp_ files to use hostname; --- Vagrantfile | 8 ++++ components/generic_radio | 2 +- fsw/apps/hwlib | 2 +- fsw/nos3_defs/cpu1_device_cfg.h | 14 ++++++ gsw/scripts/checkout.sh | 6 +-- gsw/scripts/create_cosmos_gem.sh | 6 +-- gsw/scripts/docker_build.sh | 2 +- gsw/scripts/docker_build_fsw.sh | 3 +- gsw/scripts/docker_build_sim.sh | 2 +- gsw/scripts/docker_compose_launch.sh | 14 +----- gsw/scripts/docker_launch.sh | 65 +++++++++------------------- gsw/scripts/docker_stop.sh | 41 +++++------------- gsw/scripts/env.sh | 29 ++++++++----- gsw/scripts/gsw.sh | 3 +- gsw/scripts/launch.sh | 15 +------ gsw/scripts/real_clean.sh | 2 +- gsw/scripts/reboot.sh | 13 +----- gsw/scripts/sc_launch.sh | 13 +----- gsw/scripts/stop.sh | 2 +- sims/cfg/InOut/Inp_IPC.txt | 30 ++++++------- sims/cfg/InOut/Inp_NOS3.txt | 2 +- sims/cfg/nos3-simulator.xml | 48 +++++++++++--------- 22 files changed, 131 insertions(+), 191 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 64844122..136b43db 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,4 +1,12 @@ Vagrant.configure("2") do |config| + ### + ### Notes: + ### Using the provided base boxes is not required to use the software + ### Base boxes are provisioned from the following location + ### * https://github.com/nasa-itc/deployment + ### Links to which commit was used is captured in the box release notes + ### + ### Uncomment one of the following to select configuration #config.vm.box = "nos3/rocky" config.vm.box = "nos3/ubuntu" diff --git a/components/generic_radio b/components/generic_radio index 9dbd0d0a..ac6554c8 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 9dbd0d0a2c2d8f1c9cc0d6658236bef0236bace7 +Subproject commit ac6554c89d4f547c8b070cd5ecc399d005848ccf diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index ce3a7662..d9e0f6f9 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit ce3a76629f2cef2d3a1443692865360319989d18 +Subproject commit d9e0f6f901499a0e3e8dd5d3445968785054a31a diff --git a/fsw/nos3_defs/cpu1_device_cfg.h b/fsw/nos3_defs/cpu1_device_cfg.h index 64d47b26..d7fddb07 100644 --- a/fsw/nos3_defs/cpu1_device_cfg.h +++ b/fsw/nos3_defs/cpu1_device_cfg.h @@ -43,5 +43,19 @@ #define SAMPLE_CFG_MS_TIMEOUT 50 /* Max 255 */ //#define SAMPLE_CFG_DEBUG +/* +** GENERIC_RADIO Configuration +*/ +#define GENERIC_RADIO_CFG +#define GENERIC_RADIO_CFG_PROX_DATA_SIZE 64 +#define GENERIC_RADIO_CFG_FSW_IP "nos_fsw" +#define GENERIC_RADIO_CFG_DEVICE_IP "radio_sim" +#define GENERIC_RADIO_CFG_DEVICE_DELAY_MS 10 +#define GENERIC_RADIO_CFG_UDP_PROX_TO_FSW 7010 +#define GENERIC_RADIO_CFG_UDP_FSW_TO_PROX 7011 +#define GENERIC_RADIO_CFG_UDP_FSW_TO_RADIO 5014 +#define GENERIC_RADIO_CFG_UDP_RADIO_TO_FSW 5015 +//#define GENERIC_RADIO_CFG_DEBUG + #endif /* _cpu1_device_cfg_ */ diff --git a/gsw/scripts/checkout.sh b/gsw/scripts/checkout.sh index 3b2f7a6c..48fae875 100644 --- a/gsw/scripts/checkout.sh +++ b/gsw/scripts/checkout.sh @@ -4,11 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -SIM_BIN=$BASE_DIR/sims/build/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) - +source $SCRIPT_DIR/env.sh echo "Simulators..." cd $SIM_BIN diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 29258341..ca52e67c 100644 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -4,11 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 -DATE=$(date "+%Y%m%d%H%M") - -OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" +source $SCRIPT_DIR/env.sh # Start by changing to a known location cd $SCRIPT_DIR/../cosmos diff --git a/gsw/scripts/docker_build.sh b/gsw/scripts/docker_build.sh index 2c24f818..12aaa5f1 100755 --- a/gsw/scripts/docker_build.sh +++ b/gsw/scripts/docker_build.sh @@ -6,7 +6,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +source $SCRIPT_DIR/env.sh docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw sim diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index 3cf7817c..762375db 100644 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -6,6 +6,5 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) - +source $SCRIPT_DIR/env.sh docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index 9a8dd421..7b49aec7 100644 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -6,6 +6,6 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +source $SCRIPT_DIR/env.sh docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make sim diff --git a/gsw/scripts/docker_compose_launch.sh b/gsw/scripts/docker_compose_launch.sh index 7af0b373..0a3c55e9 100755 --- a/gsw/scripts/docker_compose_launch.sh +++ b/gsw/scripts/docker_compose_launch.sh @@ -6,19 +6,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -export BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -export FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -export SIM_DIR=$BASE_DIR/sims/build -export SIM_BIN=$SIM_DIR/bin -export SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#echo "FSW directory = " $FSW_BIN -#echo "Sim directory = " $SIM_BIN -#echo "Sim list = " $SIMS -#exit +source $SCRIPT_DIR/env.sh #echo "Make /tmp folders..." #mkdir /tmp/data 2> /dev/null diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 7882d86a..8db277e4 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -5,35 +5,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 -GSW_DIR=$BASE_DIR/gsw/cosmos -SIM_DIR=$BASE_DIR/sims/build -SIM_BIN=$SIM_DIR/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -if [ -f "/etc/redhat-release" ]; then - DFLAGS="sudo docker run --rm --group-add keep-groups -it" - DCREATE="sudo docker create --rm -it" - DNETWORK="sudo docker network" -else - DFLAGS="docker run --rm -it" - DCREATE="docker create --rm -it" - DNETWORK="docker network" -fi - -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#echo "DFLAGS = " $DFLAGS -#echo "FSW directory = " $FSW_DIR -#echo "GSW directory = " $GSW_DIR -#echo "Sim directory = " $SIM_BIN -#echo "Sim list = " $SIMS -#echo "Docker flags = " $DFLAGS -#echo "Docker create = " $DCREATE -#echo "Docker network = " $DNETWORK -#exit +source $SCRIPT_DIR/env.sh echo "Make data folders..." @@ -63,14 +35,14 @@ $DNETWORK create \ --driver=bridge \ --subnet=192.168.41.0/24 \ --gateway=192.168.41.1 \ - NOS3_GC + nos3_core echo "" echo "Create NOS interfaces..." export GND_CFG_FILE="-f nos3-simulator.xml" -gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE stdio-terminal -gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_udp_terminal" --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE udp-terminal +gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE stdio-terminal +gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_udp_terminal" --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE udp-terminal echo "" @@ -113,28 +85,31 @@ do cd $SIM_BIN gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos3_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE truth42sim - gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE camsim - gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_css_sim - gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim - gnome-terminal --tab --title=$SC_NUM" - FSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_fss_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-fss-sim - gnome-terminal --tab --title=$SC_NUM" - IMU Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_imu_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_imu_sim - gnome-terminal --tab --title=$SC_NUM" - GPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_gps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE gps - gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 - gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 - gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim - $DNETWORK connect openc3-cosmos-network radio_sim - gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample-sim - gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + $DNETWORK connect $SC_NETNAME nos_terminal $DNETWORK connect $SC_NETNAME nos_udp_terminal + $DNETWORK connect openc3-cosmos-network radio_sim + + gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE camsim + gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_css_sim + gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim + gnome-terminal --tab --title=$SC_NUM" - FSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_fss_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_fss_sim + gnome-terminal --tab --title=$SC_NUM" - GPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_gps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE gps + gnome-terminal --tab --title=$SC_NUM" - IMU Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_imu_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_imu_sim + gnome-terminal --tab --title=$SC_NUM" - MAG Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_mag_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_mag_sim + gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 + gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 + gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 + gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim + gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim echo "" done echo "NOS Time Driver..." sleep 5 -gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=NOS3_GC -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE time +gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE time sleep 1 for (( i=1; i<=$SATNUM; i++ )) do diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index 1f0f0aaf..9a04e132 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -5,19 +5,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -GSW_DIR=$BASE_DIR/gsw/cosmos -if [ -f "/etc/redhat-release" ]; then - # https://github.com/containers/podman/issues/14284#issuecomment-1130113553 - # sudo sed -i 's/runtime = "runc"/runtime = "crun" # "runc"/g' /usr/share/containers/containers.conf - DFLAG="sudo docker" -else - DFLAG="docker" -fi -SIM_DIR=$BASE_DIR/sims/build -SIM_BIN=$SIM_DIR/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) +source $SCRIPT_DIR/env.sh # NOS3 GPIO rm -rf /tmp/gpio_fake @@ -25,24 +13,17 @@ rm -rf /tmp/gpio_fake # NOS3 Stored HK rm -rf $BASE_DIR/fsw/build/exe/cpu1/scratch/* -# Docker +# Docker stop cd $SCRIPT_DIR; $DFLAG compose down > /dev/null 2>&1 -#for i in $($DFLAG container ls -q); do -# if [ "$i" == "openc3"* ] -# then -# $DFLAG container kill $i > /dev/null 2>&1 -# fi -#done -docker ps --filter=name="sc_*" -aq | xargs docker stop > /dev/null 2>&1 -docker ps --filter=name="nos_*" -aq | xargs docker stop > /dev/null 2>&1 - -$DFLAG container prune -f > /dev/null 2>&1 -$DFLAG network rm NOS3_GC > /dev/null 2>&1 -$DFLAG network rm sc_1_satnet > /dev/null 2>&1 -$DFLAG network rm sc_2_satnet > /dev/null 2>&1 -$DFLAG network rm sc_3_satnet > /dev/null 2>&1 -$DFLAG network rm sc_21_splitnet > /dev/null 2>&1 -$DFLAG network rm sc_32_splitnet > /dev/null 2>&1 +$DCALL ps --filter=name="sc_*" -aq | xargs $DCALL stop > /dev/null 2>&1 & +$DCALL ps --filter=name="nos_*" -aq | xargs $DCALL stop > /dev/null 2>&1 & + +# Intentionally wait to complete +wait + +# Docker cleanup +$DCALL container prune -f > /dev/null 2>&1 +$DNETWORK ls --filter=name="nos" | xargs $DNETWORK rm > /dev/null 2>&1 & # 42 rm -rf /opt/nos3/42/NOS3InOut diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 6b9ffc23..8bdb9614 100644 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -6,29 +6,38 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 +GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 GSW_DIR=$BASE_DIR/gsw/cosmos SIM_DIR=$BASE_DIR/sims/build SIM_BIN=$SIM_DIR/bin SIMS=$(cd $SIM_BIN; ls nos3*simulator) if [ -f "/etc/redhat-release" ]; then + DCALL="sudo docker" DFLAGS="sudo docker run --rm --group-add keep-groups -it" DCREATE="sudo docker create --rm -it" DNETWORK="sudo docker network" else + DCALL="docker" DFLAGS="docker run --rm -it" DCREATE="docker create --rm -it" DNETWORK="docker network" fi +DATE=$(date "+%Y%m%d%H%M") +OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" + # Debugging -echo "Script directory = " $SCRIPT_DIR -echo "Base directory = " $BASE_DIR -echo "DFLAGS = " $DFLAGS -echo "FSW directory = " $FSW_DIR -echo "GSW directory = " $GSW_DIR -echo "Sim directory = " $SIM_BIN -echo "Sim list = " $SIMS -echo "Docker flags = " $DFLAGS -echo "Docker create = " $DCREATE -echo "Docker network = " $DNETWORK +#echo "Script directory = " $SCRIPT_DIR +#echo "Base directory = " $BASE_DIR +#echo "DFLAGS = " $DFLAGS +#echo "FSW directory = " $FSW_DIR +#echo "GSW bin = " $GSW_BIN +#echo "GSW directory = " $GSW_DIR +#echo "Sim directory = " $SIM_BIN +#echo "Sim list = " $SIMS +#echo "Docker flags = " $DFLAGS +#echo "Docker create = " $DCREATE +#echo "Docker network = " $DNETWORK +#echo "Date = " $DATE +#echo "OpenC3 path = " $OPENC3_PATH diff --git a/gsw/scripts/gsw.sh b/gsw/scripts/gsw.sh index c48e8229..2646dbdb 100755 --- a/gsw/scripts/gsw.sh +++ b/gsw/scripts/gsw.sh @@ -4,8 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 +source $SCRIPT_DIR/env.sh # Debugging #echo "Script directory = " $SCRIPT_DIR diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index 93524075..c4a3ac56 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -4,18 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -SIM_BIN=$BASE_DIR/sims/build/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#echo "FSW directory = " $FSW_BIN -#echo "Sim directory = " $SIM_BIN -#echo "Sim list = " $SIMS -#exit +source $SCRIPT_DIR/env.sh #echo "Make /tmp folders..." #mkdir /tmp/data 2> /dev/null @@ -55,7 +44,7 @@ gnome-terminal --tab --title="42 Truth Sim" -- $SIM_BIN/nos3-single-simula gnome-terminal --tab --title='CAM Sim' -- $SIM_BIN/nos3-single-simulator camsim gnome-terminal --tab --title='CSS Sim' -- $SIM_BIN/nos3-single-simulator generic_css_sim gnome-terminal --tab --title='EPS Sim' -- $SIM_BIN/nos3-single-simulator generic_eps_sim -gnome-terminal --tab --title="FSS Sim" -- $SIM_BIN/nos3-single-simulator generic-fss-sim +gnome-terminal --tab --title="FSS Sim" -- $SIM_BIN/nos3-single-simulator generic_fss_sim gnome-terminal --tab --title='IMU Sim' -- $SIM_BIN/nos3-single-simulator generic_imu_sim gnome-terminal --tab --title='MAG Sim' -- $SIM_BIN/nos3-single-simulator generic_mag_sim gnome-terminal --tab --title='Radio Sim' -- $SIM_BIN/nos3-single-simulator generic_radio_sim diff --git a/gsw/scripts/real_clean.sh b/gsw/scripts/real_clean.sh index 12250636..21a90dc9 100755 --- a/gsw/scripts/real_clean.sh +++ b/gsw/scripts/real_clean.sh @@ -4,7 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +source $SCRIPT_DIR/env.sh echo "Cleaning up all COSMOS files..." yes | rm $BASE_DIR/gsw/cosmos/Gemfile 2> /dev/null diff --git a/gsw/scripts/reboot.sh b/gsw/scripts/reboot.sh index b5fc26cd..730d41cd 100644 --- a/gsw/scripts/reboot.sh +++ b/gsw/scripts/reboot.sh @@ -4,18 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -SIM_BIN=$BASE_DIR/sims/build/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#echo "FSW directory = " $FSW_BIN -#echo "Sim directory = " $SIM_BIN -#echo "Sim list = " $SIMS -#exit +source $SCRIPT_DIR/env.sh killall -q -r -INT core-cpu* diff --git a/gsw/scripts/sc_launch.sh b/gsw/scripts/sc_launch.sh index 8d21c458..de17cf51 100644 --- a/gsw/scripts/sc_launch.sh +++ b/gsw/scripts/sc_launch.sh @@ -4,18 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) -FSW_BIN=$BASE_DIR/fsw/build/exe/cpu1 -SIM_BIN=$BASE_DIR/sims/build/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) - -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#echo "FSW directory = " $FSW_BIN -#echo "Sim directory = " $SIM_BIN -#echo "Sim list = " $SIMS -#exit +source $SCRIPT_DIR/env.sh #echo "Make /tmp folders..." #mkdir /tmp/data 2> /dev/null diff --git a/gsw/scripts/stop.sh b/gsw/scripts/stop.sh index a99dcacf..0f0609b9 100755 --- a/gsw/scripts/stop.sh +++ b/gsw/scripts/stop.sh @@ -4,7 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +source $SCRIPT_DIR/env.sh # cFS killall -q -r -9 fsw_respawn.sh diff --git a/sims/cfg/InOut/Inp_IPC.txt b/sims/cfg/InOut/Inp_IPC.txt index dc2c55e7..0d0a9efe 100644 --- a/sims/cfg/InOut/Inp_IPC.txt +++ b/sims/cfg/InOut/Inp_IPC.txt @@ -5,7 +5,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State00.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4242 ! Server Host Name, Port +fortytwo 4242 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -15,7 +15,7 @@ RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State01.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4278 ! Server Host Name, Port +fortytwo 4278 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -25,7 +25,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 1 ! AC.ID for ACS mode "State02.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4277 ! Server Host Name, Port +fortytwo 4277 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -35,7 +35,7 @@ RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State01.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4378 ! Server Host Name, Port +fortytwo 4378 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -45,7 +45,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 1 ! AC.ID for ACS mode "State02.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4377 ! Server Host Name, Port +fortytwo 4377 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -55,7 +55,7 @@ RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State01.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4478 ! Server Host Name, Port +fortytwo 4478 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -65,7 +65,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 1 ! AC.ID for ACS mode "State02.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4477 ! Server Host Name, Port +fortytwo 4477 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -75,7 +75,7 @@ RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 1 ! AC.ID for ACS mode "Torquer.Rx" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4279 ! Server Host Name, Port +fortytwo 4279 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -85,7 +85,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State03.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4245 ! Server Host Name, Port +fortytwo 4245 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -95,7 +95,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State04.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4227 ! Server Host Name, Port +fortytwo 4227 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -105,7 +105,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State05.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4234 ! Server Host Name, Port +fortytwo 4234 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -115,7 +115,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 9999 ! Server Host Name, Port +fortytwo 9999 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 7 ! Number of TX prefixes @@ -131,7 +131,7 @@ WRITEFILE ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "State.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 6008 ! Server Host Name, Port +fortytwo 6008 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 7 ! Number of TX prefixes @@ -147,7 +147,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "FSS.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4281 ! Server Host Name, Port +fortytwo 4281 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes @@ -157,7 +157,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE 0 ! AC.ID for ACS mode "IMU.42" ! File name for WRITE or READ SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -localhost 4280 ! Server Host Name, Port +fortytwo 4280 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes diff --git a/sims/cfg/InOut/Inp_NOS3.txt b/sims/cfg/InOut/Inp_NOS3.txt index 0ee2025c..eb8b0eb0 100644 --- a/sims/cfg/InOut/Inp_NOS3.txt +++ b/sims/cfg/InOut/Inp_NOS3.txt @@ -1,3 +1,3 @@ <<<<<<<<<<<<<<<< 42 NOS3 Time Configuration File >>>>>>>>>>>>>>>>>>> command ! NOS3 Time Bus -tcp://127.0.0.1:12001 ! NOS3 Time Connection String +tcp://nos_engine_server:12001 ! NOS3 Time Connection String diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index 9ede2e4c..8a2cae5e 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -127,6 +127,11 @@ SAMPLE_42_PROVIDER + fortytwo + 4242 + 20 + 1 + 0 @@ -148,8 +153,8 @@ GPS42SOCKET fortytwo 4245 - 5 - 5 + 20 + 1 0 0 37 @@ -281,8 +286,8 @@ fortytwo 4277 4278 - 5 - 5 + 20 + 1 0 0 @@ -307,8 +312,8 @@ fortytwo 4377 4378 - 5 - 5 + 20 + 1 0 1 @@ -333,8 +338,8 @@ fortytwo 4477 4478 - 5 - 5 + 20 + 1 0 2 @@ -358,8 +363,8 @@ GENERIC_CSS_42_PROVIDER fortytwo 4227 - 5 - 5 + 20 + 1 0 <42-css-scale-factor>1.0 @@ -384,9 +389,11 @@ + GENERIC_TORQUER_42_PROVIDER + fortytwo 4279 - 10 - 5 + 20 + 1 3 @@ -416,7 +423,8 @@ TRUTH42PROVIDER fortytwo 9999 - 10 + 20 + 1 0 0 @@ -424,7 +432,7 @@ - generic-fss-sim + generic_fss_sim true libgeneric_fss_sim.so @@ -440,8 +448,8 @@ GENERIC_FSS_42_PROVIDER fortytwo 4281 - 5 - 5 + 20 + 1 0 @@ -518,8 +526,8 @@ GENERIC_IMU_42_PROVIDER fortytwo 4280 - 5 - 5 + 20 + 1 0 @@ -545,8 +553,8 @@ GENERIC_MAG_42_PROVIDER fortytwo 4234 - 5 - 5 + 20 + 1 0 From 22b9dbb98b18d72c1676d34860ead2aa3c19a215 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 29 Aug 2023 08:26:19 -0400 Subject: [PATCH 007/153] [nasa/nos3#163] Telemetry flowing to COSMOS from debug and 42 truth sim - commanding broken; --- fsw/apps/to_lab | 2 +- fsw/nos3_defs/tables/sc_rts001.c | 2 +- gsw/cosmos | 2 +- gsw/scripts/docker_launch.sh | 9 ++++++--- gsw/scripts/docker_stop.sh | 2 +- sims/cfg/nos3-simulator.xml | 1 + sims/truth_42_sim | 2 +- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fsw/apps/to_lab b/fsw/apps/to_lab index 96677978..9b461b02 160000 --- a/fsw/apps/to_lab +++ b/fsw/apps/to_lab @@ -1 +1 @@ -Subproject commit 966779788b78fdac728b7fb34d8912123f40063c +Subproject commit 9b461b023b675d87735f73b7c171b0db5e17856f diff --git a/fsw/nos3_defs/tables/sc_rts001.c b/fsw/nos3_defs/tables/sc_rts001.c index 2a3ff346..2c4ddec3 100644 --- a/fsw/nos3_defs/tables/sc_rts001.c +++ b/fsw/nos3_defs/tables/sc_rts001.c @@ -59,7 +59,7 @@ SC_RtsTable001_t SC_Rts001 = { /* 2 - Enable Debug */ .hdr2.TimeTag = 1, .cmd2.CmdHeader = CFE_MSG_CMD_HDR_INIT(TO_LAB_CMD_MID, SC_MEMBER_SIZE(cmd2), TO_LAB_OUTPUT_ENABLE_CC, 0x00), - .cmd2.Payload.dest_IP = "127.0.0.1", + .cmd2.Payload.dest_IP = "cosmos", /* 3 - Enable RTS 3-64 */ .hdr3.TimeTag = 1, diff --git a/gsw/cosmos b/gsw/cosmos index ca9d6aae..22f37c8a 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit ca9d6aae5434c45fb76ae5a11e1e0f892bbd4e11 +Subproject commit 22f37c8ae1ea8e0923c7cf4d181d1cb8e78aa5a7 diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 8db277e4..72f7e4a6 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -66,6 +66,10 @@ do $DNETWORK create $SC_NETNAME echo "" + echo $SC_NUM " - Connect COSMOS to spacecraft network..." + $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos + echo "" + echo $SC_NUM " - 42..." cd /opt/nos3/42/ xhost +local:* @@ -75,7 +79,6 @@ do echo $SC_NUM " - Flight Software..." cd $FSW_DIR gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $FSW_DIR:$FSW_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --cap-add sys_nice ivvitc/nos3 ./core-cpu1 -R PO & - docker network connect openc3-cosmos-network nos_fsw echo "" # Debugging @@ -85,12 +88,11 @@ do cd $SIM_BIN gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos3_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE truth42sim - gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim $DNETWORK connect $SC_NETNAME nos_terminal $DNETWORK connect $SC_NETNAME nos_udp_terminal - $DNETWORK connect openc3-cosmos-network radio_sim + # Component simulators gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE camsim gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_css_sim gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim @@ -101,6 +103,7 @@ do gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 + gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME --network-alias=radio_sim -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim echo "" diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index 9a04e132..382c0ce6 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -23,7 +23,7 @@ wait # Docker cleanup $DCALL container prune -f > /dev/null 2>&1 -$DNETWORK ls --filter=name="nos" | xargs $DNETWORK rm > /dev/null 2>&1 & +$DNETWORK ls --filter=name="nos" | xargs $DNETWORK rm > /dev/null 2>&1 # 42 rm -rf /opt/nos3/42/NOS3InOut diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index 8a2cae5e..1d0dbe3a 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -412,6 +412,7 @@ libtruth_42_sim.so TRUTH42 + cosmos 5111 1.0 100 diff --git a/sims/truth_42_sim b/sims/truth_42_sim index d121234b..3abce84a 160000 --- a/sims/truth_42_sim +++ b/sims/truth_42_sim @@ -1 +1 @@ -Subproject commit d121234bc1be2e6a8b4fbed70061e8098df26390 +Subproject commit 3abce84acce56c0999d24db212624e0917096e2c From a9ec10f18785bfd3dedac7ae4dc63575c3823dc7 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 29 Aug 2023 11:29:49 -0400 Subject: [PATCH 008/153] [nasa/nos3#163] Update HWLIB to use hostname for engine connections; --- fsw/apps/hwlib | 2 +- gsw/scripts/docker_launch.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index d9e0f6f9..dab85ebc 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit d9e0f6f901499a0e3e8dd5d3445968785054a31a +Subproject commit dab85ebc2264f7e3179aa42841b735d373bf08d6 diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 72f7e4a6..2af87b7f 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -63,11 +63,11 @@ do #echo "Spacecraft configuration = " $SC_CFG_FILE echo $SC_NUM " - Create spacecraft network..." - $DNETWORK create $SC_NETNAME + $DNETWORK create $SC_NETNAME 2> /dev/null echo "" echo $SC_NUM " - Connect COSMOS to spacecraft network..." - $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos + $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos 2> /dev/null echo "" echo $SC_NUM " - 42..." From 098b74f73103af1c180918a6e1933c1074b7aea9 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 30 Aug 2023 07:36:13 -0400 Subject: [PATCH 009/153] [nasa/nos3#163] Update create cosmos gem script to use nos_fsw hostname; --- fsw/osal | 2 +- gsw/scripts/create_cosmos_gem.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fsw/osal b/fsw/osal index e7cc0ff0..8b046477 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit e7cc0ff0b9a97eff033fc2aab0ea4d79b7f916a3 +Subproject commit 8b046477f047ae371be27f4ee7942fa4f863e7ac diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index ca52e67c..1d1905a5 100644 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -7,7 +7,7 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh # Start by changing to a known location -cd $SCRIPT_DIR/../cosmos +cd $GSW_DIR # Delete any previous run info rm -rf build @@ -54,7 +54,7 @@ do fi done echo "" >> plugin.txt -echo "INTERFACE DEBUG udp_interface.rb host.docker.internal 5012 5013 nil nil 128 10.0 nil" >> plugin.txt +echo "INTERFACE DEBUG udp_interface.rb nos_fsw 5012 5013 nil nil 128 10.0 nil" >> plugin.txt for i in $targets do if [ "$i" != "SIM_42_TRUTH" -a "$i" != "SYSTEM" ] From 51d353fc072d40016e37f8a568ab721d97d79e91 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 30 Aug 2023 10:50:30 -0400 Subject: [PATCH 010/153] [nasa/nos3#163] Standard launch and dlaunch now look the same, have to edit create_cosmos_gem.sh to enable standard; --- gsw/scripts/docker_launch.sh | 4 +++- gsw/scripts/fsw_respawn.sh | 7 +++++-- gsw/scripts/launch.sh | 11 +++-------- sims/cfg/nos3-simulator.xml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 2af87b7f..261b4ad9 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -46,8 +46,10 @@ gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR echo "" +# Note only currently working with a single spacecraft export SATNUM=1 + # # Spacecraft Loop # @@ -86,7 +88,7 @@ do echo $SC_NUM " - Simulators..." cd $SIM_BIN - gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos3_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json + gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE truth42sim $DNETWORK connect $SC_NETNAME nos_terminal diff --git a/gsw/scripts/fsw_respawn.sh b/gsw/scripts/fsw_respawn.sh index f3c1dee8..d13417da 100644 --- a/gsw/scripts/fsw_respawn.sh +++ b/gsw/scripts/fsw_respawn.sh @@ -3,10 +3,13 @@ # Script to start FSW and restart it if it dies/is killed # -FSW_BIN=$1 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh #echo "fsw_respawn.sh script" +cd $FSW_DIR + while [ 1 ] do pidof core-cpu1 > /dev/null @@ -16,7 +19,7 @@ do pidof core-cpu1 > /dev/null if [ $? -eq 1 ] then - gnome-terminal --title="NOS3 Flight Software" -- $FSW_BIN/core-cpu1 -R PO + gnome-terminal --title="NOS3 Flight Software" -- $FSW_DIR/core-cpu1 -R PO fi fi sleep 1 diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index c4a3ac56..ecb36a61 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -6,11 +6,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -#echo "Make /tmp folders..." -#mkdir /tmp/data 2> /dev/null -#mkdir /tmp/data/hk 2> /dev/null -#mkdir /tmp/uplink 2> /dev/null - echo "Make data folders..." # FSW Side mkdir $FSW_BIN/data 2> /dev/null @@ -37,7 +32,6 @@ gnome-terminal --tab --title="42 Dynamic Simulator" -- /opt/nos3/42/42 NOS3InOut echo "Simulators..." cd $SIM_BIN gnome-terminal --tab --title="NOS Engine Server" -- /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json -gnome-terminal --tab --title="NOS Time Driver" -- $SIM_BIN/nos3-single-simulator time gnome-terminal --tab --title="NOS STDIO Terminal" -- $SIM_BIN/nos3-single-simulator stdio-terminal gnome-terminal --tab --title="NOS UDP Terminal" -- $SIM_BIN/nos3-single-simulator udp-terminal gnome-terminal --tab --title="42 Truth Sim" -- $SIM_BIN/nos3-single-simulator truth42sim @@ -45,15 +39,16 @@ gnome-terminal --tab --title='CAM Sim' -- $SIM_BIN/nos3-single-simula gnome-terminal --tab --title='CSS Sim' -- $SIM_BIN/nos3-single-simulator generic_css_sim gnome-terminal --tab --title='EPS Sim' -- $SIM_BIN/nos3-single-simulator generic_eps_sim gnome-terminal --tab --title="FSS Sim" -- $SIM_BIN/nos3-single-simulator generic_fss_sim +gnome-terminal --tab --title='GPS Sim' -- $SIM_BIN/nos3-single-simulator gps gnome-terminal --tab --title='IMU Sim' -- $SIM_BIN/nos3-single-simulator generic_imu_sim gnome-terminal --tab --title='MAG Sim' -- $SIM_BIN/nos3-single-simulator generic_mag_sim gnome-terminal --tab --title='Radio Sim' -- $SIM_BIN/nos3-single-simulator generic_radio_sim gnome-terminal --tab --title='RW 0 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim0 gnome-terminal --tab --title='RW 1 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim1 gnome-terminal --tab --title='RW 2 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim2 -gnome-terminal --tab --title='Torquer Sim' -- $SIM_BIN/nos3-single-simulator generic_torquer_sim -gnome-terminal --tab --title='GPS Sim' -- $SIM_BIN/nos3-single-simulator gps gnome-terminal --tab --title='Sample Sim' -- $SIM_BIN/nos3-single-simulator sample_sim +gnome-terminal --tab --title='Torquer Sim' -- $SIM_BIN/nos3-single-simulator generic_torquer_sim +gnome-terminal --tab --title="NOS Time Driver" -- $SIM_BIN/nos3-single-simulator time #echo "CryptoLib..." #mkdir $BASE_DIR/components/cryptolib/build/ diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index 1d0dbe3a..87d01c29 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -23,7 +23,7 @@ time - tcp://sc_1_nos3_engine_server:12001 + tcp://sc_1_nos_engine_server:12001 command sc1-time-driver From 0c46c432316fb8007cfa417b5fa9df65d8ce439d Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 7 Sep 2023 08:05:59 -0400 Subject: [PATCH 011/153] [nasa/nos3#163] Major transition - docker only implementation; --- Makefile | 68 +++++++------------------------ gsw/scripts/checkout.sh | 43 ++++++++++++++++---- gsw/scripts/docker_build.sh | 14 ------- gsw/scripts/docker_build_fsw.sh | 4 +- gsw/scripts/docker_build_sim.sh | 3 +- gsw/scripts/docker_launch.sh | 4 +- gsw/scripts/env.sh | 7 +++- gsw/scripts/fsw_respawn.sh | 2 +- gsw/scripts/reboot.sh | 17 -------- gsw/scripts/sc_launch.sh | 71 --------------------------------- 10 files changed, 65 insertions(+), 168 deletions(-) delete mode 100755 gsw/scripts/docker_build.sh delete mode 100644 gsw/scripts/reboot.sh delete mode 100644 gsw/scripts/sc_launch.sh diff --git a/Makefile b/Makefile index af7bf968..d9591a8f 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all fsw fsw-prep sim sim-prep clean clean-fsw clean-gsw clean-sim dall dfsw dsim dlaunch gsw gsw-launch launch log real-clean sc-launch stop +LOCALTGTS := all build-fsw build-sim checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log real-clean sim stop OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -35,48 +35,26 @@ OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) .PHONY: $(LOCALTGTS) $(OTHERTGTS) # -# Generic Commands +# Commands # all: $(MAKE) fsw $(MAKE) sim $(MAKE) gsw -# -# FSW -# -fsw: - $(MAKE) fsw-prep - $(MAKE) --no-print-directory -C $(FSWBUILDDIR) mission-install - -fsw-prep: +build-fsw: mkdir -p $(FSWBUILDDIR) cd $(FSWBUILDDIR) && cmake $(PREP_OPTS) ../cfe + $(MAKE) --no-print-directory -C $(FSWBUILDDIR) mission-install -# -# Sims -# -sim: - $(MAKE) sim-prep - $(MAKE) --no-print-directory -C $(SIMBUILDDIR) install - -sim-prep: +build-sim: mkdir -p $(SIMBUILDDIR) cd $(SIMBUILDDIR) && cmake -DCMAKE_INSTALL_PREFIX=$(SIMBUILDDIR) .. + $(MAKE) --no-print-directory -C $(SIMBUILDDIR) install -# -# GSW -# -gsw: - $(MAKE) gsw-prep - ./gsw/scripts/create_cosmos_gem.sh - -gsw-prep: - mkdir -p ./gsw/cosmos/build +checkout: + ./gsw/scripts/checkout.sh -# -# Clean -# clean: $(MAKE) clean-fsw $(MAKE) clean-sim @@ -91,32 +69,14 @@ clean-sim: clean-gsw: rm -rf gsw/cosmos/build -# -# Script Calls -# -checkout: - ./gsw/scripts/checkout.sh - -dall: - ./gsw/scripts/docker_build.sh - -dfsw: +fsw: ./gsw/scripts/docker_build_fsw.sh -dsim: - ./gsw/scripts/docker_build_sim.sh - -dlaunch: - ./gsw/scripts/docker_launch.sh - -gsw-launch: - ./gsw/scripts/gsw.sh +gsw: + ./gsw/scripts/create_cosmos_gem.sh launch: - ./gsw/scripts/launch.sh - -reboot: - ./gsw/scripts/reboot.sh + ./gsw/scripts/docker_launch.sh log: ./gsw/scripts/log.sh @@ -125,8 +85,8 @@ real-clean: $(MAKE) clean ./gsw/scripts/real_clean.sh -sc-launch: - ./gsw/scripts/sc_launch.sh +sim: + ./gsw/scripts/docker_build_sim.sh stop: ./gsw/scripts/docker_stop.sh diff --git a/gsw/scripts/checkout.sh b/gsw/scripts/checkout.sh index 48fae875..47990111 100644 --- a/gsw/scripts/checkout.sh +++ b/gsw/scripts/checkout.sh @@ -6,13 +6,42 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -echo "Simulators..." -cd $SIM_BIN -gnome-terminal --tab --title="NOS Engine Server" -- /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json -gnome-terminal --tab --title="NOS Time Driver" -- $SIM_BIN/nos3-single-simulator time -gnome-terminal --tab --title="NOS STDIO Terminal" -- $SIM_BIN/nos3-single-simulator stdio-terminal +export SC_NUM="sc_1" +export SC_NETNAME="nos3_"$SC_NUM +export SC_CFG_FILE="-f nos3-simulator.xml" #"-f sc_"$i"_nos3_simulator.xml" +echo "Create spacecraft network..." +$DNETWORK create $SC_NETNAME 2> /dev/null +echo "" + +# Debugging +# Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually + +#echo "42..." +#cd /opt/nos3/42/ +#rm -rf NOS3InOut +#cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut +#xhost +local:* +#gnome-terminal --window-with-profile=KeepOpen --title="42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut +#echo "" + +echo "NOS Core..." +gnome-terminal --tab --title="NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json +gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE time +gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE stdio-terminal + +echo "Checkout..." # Rename for your simulator under test to allow checkout -gnome-terminal --tab --title='Sample Sim' -- $SIM_BIN/nos3-single-simulator sample_sim +gnome-terminal --tab --title="Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim + +# Example manual build for sample checkout: +# cd ./components/sample/support +# mkdir build +# cd build +# cmake .. -DTGTNAME=cpu1 +# make + +# Rename for your checkout under test to allow checkout +gnome-terminal --title="Sample Sim" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR ivvitc/nos3 ./components/sample/support/build/sample_checkout -# It is assumed you'll build and launch the checkout manually +echo "" diff --git a/gsw/scripts/docker_build.sh b/gsw/scripts/docker_build.sh deleted file mode 100755 index 12aaa5f1..00000000 --- a/gsw/scripts/docker_build.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -i -# -# Convenience script for NOS3 development -# Use with the Dockerfile in the deployment repository -# https://docs.docker.com/engine/install/ubuntu/ -# - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -source $SCRIPT_DIR/env.sh - -docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw sim - -# Note that GSW cannot from inside docker -make gsw diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index 762375db..585366e9 100644 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -7,4 +7,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make fsw + +mkdir -p $BASE_DIR/fsw/build +$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j build-fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index 7b49aec7..1f2abe9e 100644 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -8,4 +8,5 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -docker run --rm -v $BASE_DIR:$BASE_DIR -w $BASE_DIR -it ivvitc/nos3 make sim +mkdir -p $BASE_DIR/sim/build +$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j build-sim diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 261b4ad9..9eb0c503 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -74,13 +74,15 @@ do echo $SC_NUM " - 42..." cd /opt/nos3/42/ + rm -rf NOS3InOut + cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut xhost +local:* gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut echo "" echo $SC_NUM " - Flight Software..." cd $FSW_DIR - gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $FSW_DIR:$FSW_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --cap-add sys_nice ivvitc/nos3 ./core-cpu1 -R PO & + gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --cap-add sys_nice ivvitc/nos3 $SCRIPT_DIR/fsw_respawn.sh & echo "" # Debugging diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 8bdb9614..cf6db30e 100644 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -10,7 +10,10 @@ GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 GSW_DIR=$BASE_DIR/gsw/cosmos SIM_DIR=$BASE_DIR/sims/build SIM_BIN=$SIM_DIR/bin -SIMS=$(cd $SIM_BIN; ls nos3*simulator) + +if [ -d $SIM_DIR/bin ]; then + SIMS=$(ls $SIM_BIN/nos3*simulator) +fi if [ -f "/etc/redhat-release" ]; then DCALL="sudo docker" @@ -27,6 +30,8 @@ fi DATE=$(date "+%Y%m%d%H%M") OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" +NUM_CPUS="$( nproc )" + # Debugging #echo "Script directory = " $SCRIPT_DIR #echo "Base directory = " $BASE_DIR diff --git a/gsw/scripts/fsw_respawn.sh b/gsw/scripts/fsw_respawn.sh index d13417da..d57f00cd 100644 --- a/gsw/scripts/fsw_respawn.sh +++ b/gsw/scripts/fsw_respawn.sh @@ -19,7 +19,7 @@ do pidof core-cpu1 > /dev/null if [ $? -eq 1 ] then - gnome-terminal --title="NOS3 Flight Software" -- $FSW_DIR/core-cpu1 -R PO + $FSW_DIR/core-cpu1 -R PO & fi fi sleep 1 diff --git a/gsw/scripts/reboot.sh b/gsw/scripts/reboot.sh deleted file mode 100644 index 730d41cd..00000000 --- a/gsw/scripts/reboot.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -i -# -# Convenience script for NOS3 development -# - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -source $SCRIPT_DIR/env.sh - -killall -q -r -INT core-cpu* - -sleep 5 - -echo "Flight Software..." -cd $FSW_BIN -gnome-terminal --title="NOS3 Flight Software" -- $FSW_BIN/core-cpu1 -R PO & -# Note: Can keep open if desired after a new gnome-profile is manually created -#gnome-terminal --window-with-profile=KeepOpen --title="NOS3 Flight Software" -- $FSW_BIN/core-cpu1 -R PO & diff --git a/gsw/scripts/sc_launch.sh b/gsw/scripts/sc_launch.sh deleted file mode 100644 index de17cf51..00000000 --- a/gsw/scripts/sc_launch.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -i -# -# Convenience script for NOS3 development -# - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -source $SCRIPT_DIR/env.sh - -#echo "Make /tmp folders..." -#mkdir /tmp/data 2> /dev/null -#mkdir /tmp/data/hk 2> /dev/null -#mkdir /tmp/uplink 2> /dev/null - -echo "Make data folders..." -# FSW Side -mkdir $FSW_BIN/data 2> /dev/null -mkdir $FSW_BIN/data/cam 2> /dev/null -mkdir $FSW_BIN/data/evs 2> /dev/null -mkdir $FSW_BIN/data/hk 2> /dev/null -mkdir $FSW_BIN/data/inst 2> /dev/null -# GSW Side -mkdir /tmp/data 2> /dev/null -mkdir /tmp/data/cam 2> /dev/null -mkdir /tmp/data/evs 2> /dev/null -mkdir /tmp/data/hk 2> /dev/null -mkdir /tmp/data/inst 2> /dev/null -mkdir /tmp/uplink 2> /dev/null -cp $BASE_DIR/fsw/build/exe/cpu1/cf/cfe_es_startup.scr /tmp/uplink/tmp0.so 2> /dev/null -cp $BASE_DIR/fsw/build/exe/cpu1/cf/sample.so /tmp/uplink/tmp1.so 2> /dev/null - -echo "42..." -cd /opt/nos3/42/ -rm -rf NOS3InOut -cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut -gnome-terminal --tab --title="42 Dynamic Simulator" -- /opt/nos3/42/42 NOS3InOut - -echo "Simulators..." -cd $SIM_BIN -gnome-terminal --tab --title="NOS Engine Server" -- /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json -#gnome-terminal --tab --title="NOS Time Driver" -- $SIM_BIN/nos3-single-simulator time -#gnome-terminal --tab --title="NOS STDIO Terminal" -- $SIM_BIN/nos3-single-simulator stdio-terminal -#gnome-terminal --tab --title="NOS UDP Terminal" -- $SIM_BIN/nos3-single-simulator udp-terminal -gnome-terminal --tab --title="42 Truth Sim" -- $SIM_BIN/nos3-single-simulator truth42sim -gnome-terminal --tab --title='CAM Sim' -- $SIM_BIN/nos3-single-simulator camsim -gnome-terminal --tab --title='CSS Sim' -- $SIM_BIN/nos3-single-simulator generic_css_sim -gnome-terminal --tab --title='EPS Sim' -- $SIM_BIN/nos3-single-simulator generic_eps_sim -gnome-terminal --tab --title="FSS Sim" -- $SIM_BIN/nos3-single-simulator generic-fss-sim -gnome-terminal --tab --title='IMU Sim' -- $SIM_BIN/nos3-single-simulator generic_imu_sim -gnome-terminal --tab --title='MAG Sim' -- $SIM_BIN/nos3-single-simulator generic_mag_sim -gnome-terminal --tab --title='Radio Sim' -- $SIM_BIN/nos3-single-simulator generic_radio_sim -gnome-terminal --tab --title='RW 0 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim0 -gnome-terminal --tab --title='RW 1 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim1 -gnome-terminal --tab --title='RW 2 Sim' -- $SIM_BIN/nos3-single-simulator generic-reactionwheel-sim2 -gnome-terminal --tab --title='Torquer Sim' -- $SIM_BIN/nos3-single-simulator generic_torquer_sim -gnome-terminal --tab --title='GPS Sim' -- $SIM_BIN/nos3-single-simulator gps -gnome-terminal --tab --title='Sample Sim' -- $SIM_BIN/nos3-single-simulator sample_sim - -echo "COSMOS Ground Station..." -cd $BASE_DIR/gsw/cosmos -export MISSION_NAME=$(echo "NOS3") -export PROCESSOR_ENDIANNESS=$(echo "LITTLE_ENDIAN") -ruby Launcher -c nos3_launcher.txt --system nos3_system.txt & - -sleep 5 - -echo "Flight Software..." -cd $FSW_BIN -gnome-terminal --title="NOS3 Flight Software" -- $FSW_BIN/core-cpu1 -R PO & - -# Note: Can keep open if desired after a new gnome-profile is manually created -#gnome-terminal --window-with-profile=KeepOpen --title="NOS3 Flight Software" -- $FSW_BIN/core-cpu1 -R PO & From f50f77e713c81404b9198fec791f79140ebf5702 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 7 Sep 2023 18:05:17 -0400 Subject: [PATCH 012/153] [nasa/nos3#163] Update to udp example and cosmos defaults to use hostnames; --- fsw/apps/to | 2 +- gsw/cosmos | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fsw/apps/to b/fsw/apps/to index 515bc92c..26e14899 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 515bc92c13f3f54b46f823e2a78e5eb7b388097a +Subproject commit 26e148998dabe2a7748aab50b88e0fa42a95eee3 diff --git a/gsw/cosmos b/gsw/cosmos index 22f37c8a..89aaffb4 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 22f37c8ae1ea8e0923c7cf4d181d1cb8e78aa5a7 +Subproject commit 89aaffb49509ca107b7c67d65c18cc3bfa0dea1a From bbe7a1b1802a5fe2b420d642942da7ea5ecb560b Mon Sep 17 00:00:00 2001 From: Harris Date: Fri, 8 Sep 2023 13:45:59 -0400 Subject: [PATCH 013/153] Altered version using more of the original arducam and less of the new one --- components/arducam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/arducam b/components/arducam index 761e6a66..f1b51b94 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit 761e6a661f9c4037f2b48f60af51c78d62c2019d +Subproject commit f1b51b9402620dc63b4ba3a34ee0ae67d341e3e9 From 4ff281330525302df81297632bf69f30416d95d0 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 11 Sep 2023 14:14:28 -0400 Subject: [PATCH 014/153] [nasa/nos3#163] Updated docker build scripts to use NUM_CPUS to stop GCC crashes due to lack of memory; --- Vagrantfile | 2 +- gsw/scripts/docker_build_fsw.sh | 2 +- gsw/scripts/docker_build_sim.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 136b43db..8b2a75f2 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -25,6 +25,6 @@ Vagrant.configure("2") do |config| vbox.gui = true ### Enable additional configuration as needed vbox.cpus = 6 - vbox.memory = "6144" + vbox.memory = "6144" # Should always be > (cpus * 1024) end end diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index 585366e9..936dfb2a 100644 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/fsw/build -$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j build-fsw +$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index 1f2abe9e..4769473c 100644 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/sim/build -$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j build-sim +$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim From 9a6405f37a7fcd9e128ff55d843c3190c9feec31 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 11 Sep 2023 16:51:58 -0400 Subject: [PATCH 015/153] [nasa/nos3#163] Added Dockerfile from https://github.com/nasa-itc/deployment/commit/98ec5dfc840f5b6cd5b09c2ffe756a4e14ae98ec --- gsw/scripts/Dockerfile | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 gsw/scripts/Dockerfile diff --git a/gsw/scripts/Dockerfile b/gsw/scripts/Dockerfile new file mode 100644 index 00000000..46b13478 --- /dev/null +++ b/gsw/scripts/Dockerfile @@ -0,0 +1,70 @@ +# NOS3 Ubuntu Dockerfile +# +# docker build -t nos3 . +# docker run -it -v /home/nos3/Desktop/github-nos3:/git nos3 /bin/bash + +FROM ubuntu:20.04 AS nos1 + +# Enable i386 architecture +RUN dpkg --add-architecture i386 + +# Install required packages +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update -y \ + && apt-get install -y \ + cmake \ + g++-multilib \ + gcc-multilib \ + git \ + gdb \ + python-apt \ + python3-dev \ + python3-pip \ + dwarves \ + freeglut3-dev:i386 \ + lib32z1 \ + libboost-dev:i386 \ + libboost-system-dev:i386 \ + libboost-program-options-dev:i386 \ + libboost-filesystem-dev:i386 \ + libboost-thread-dev:i386 \ + libboost-regex-dev:i386 \ + libgtest-dev \ + libicu-dev:i386 \ + libncurses5-dev \ + libreadline-dev:i386 \ + libsocketcan-dev \ + libxerces-c-dev \ + wget \ + netcat \ + && rm -rf /var/lib/apt/lists/* + +# Install Xerces-C required for NOS Engine +FROM nos1 AS nos2 +RUN cd /tmp \ + && wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/xerces-c/3.2.0+debian-2/xerces-c_3.2.0+debian.orig.tar.gz \ + && tar -xf /tmp/xerces-c_3.2.0+debian.orig.tar.gz \ + && cd /tmp/xerces-c-3.2.0 \ + && /tmp/xerces-c-3.2.0/configure --prefix=/usr CFLAGS=-m32 CXXFLAGS=-m32 \ + && cd /tmp/xerces-c-3.2.0 \ + && make install + +# Configure environment +FROM nos2 AS nos3 +ADD ./nos3_filestore /nos3_filestore/ +RUN sed 's/fs.mqueue.msg_max/fs.mqueue.msg_max=500/' /etc/sysctl.conf \ + && apt-get install -y \ + /nos3_filestore/packages/ubuntu/itc-common-Release_1.10.1_i386.deb \ + /nos3_filestore/packages/ubuntu/nos-engine-Release_1.6.1_i386.deb + +RUN mkdir -p /opt/nos3 \ + && cd /opt/nos3 \ + && git clone https://github.com/ericstoneking/42.git \ + && cd /opt/nos3/42 \ + && git checkout f20d8d517b352b868d2f45ee3bffdb7deeedb218 + +RUN cd /opt/nos3/42 \ + && sed 's/ARCHFLAG =/ARCHFLAG=-m32 /; s/LFLAGS = -L/LFLAGS = -m32 -L/; s/#GLUT_OR_GLFW = _USE_GLUT_/GLUT_OR_GLFW = _USE_GLUT_/' -i /opt/nos3/42/Makefile \ + && make \ + && ln -s /usr/lib/libnos_engine_client.so /usr/lib/libnos_engine_client_cxx11.so + From 936d2c8ef3b7beae560832154cc8008b6c8e760c Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 12 Sep 2023 08:54:52 -0400 Subject: [PATCH 016/153] [nasa/nos3#163] Removed Dockerfile since it requires the packages in the deployment repository and fixed minor bug in docker_build_sim.sh creating an invalid build directory; --- gsw/scripts/Dockerfile | 70 --------------------------------- gsw/scripts/docker_build_sim.sh | 2 +- 2 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 gsw/scripts/Dockerfile diff --git a/gsw/scripts/Dockerfile b/gsw/scripts/Dockerfile deleted file mode 100644 index 46b13478..00000000 --- a/gsw/scripts/Dockerfile +++ /dev/null @@ -1,70 +0,0 @@ -# NOS3 Ubuntu Dockerfile -# -# docker build -t nos3 . -# docker run -it -v /home/nos3/Desktop/github-nos3:/git nos3 /bin/bash - -FROM ubuntu:20.04 AS nos1 - -# Enable i386 architecture -RUN dpkg --add-architecture i386 - -# Install required packages -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update -y \ - && apt-get install -y \ - cmake \ - g++-multilib \ - gcc-multilib \ - git \ - gdb \ - python-apt \ - python3-dev \ - python3-pip \ - dwarves \ - freeglut3-dev:i386 \ - lib32z1 \ - libboost-dev:i386 \ - libboost-system-dev:i386 \ - libboost-program-options-dev:i386 \ - libboost-filesystem-dev:i386 \ - libboost-thread-dev:i386 \ - libboost-regex-dev:i386 \ - libgtest-dev \ - libicu-dev:i386 \ - libncurses5-dev \ - libreadline-dev:i386 \ - libsocketcan-dev \ - libxerces-c-dev \ - wget \ - netcat \ - && rm -rf /var/lib/apt/lists/* - -# Install Xerces-C required for NOS Engine -FROM nos1 AS nos2 -RUN cd /tmp \ - && wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/xerces-c/3.2.0+debian-2/xerces-c_3.2.0+debian.orig.tar.gz \ - && tar -xf /tmp/xerces-c_3.2.0+debian.orig.tar.gz \ - && cd /tmp/xerces-c-3.2.0 \ - && /tmp/xerces-c-3.2.0/configure --prefix=/usr CFLAGS=-m32 CXXFLAGS=-m32 \ - && cd /tmp/xerces-c-3.2.0 \ - && make install - -# Configure environment -FROM nos2 AS nos3 -ADD ./nos3_filestore /nos3_filestore/ -RUN sed 's/fs.mqueue.msg_max/fs.mqueue.msg_max=500/' /etc/sysctl.conf \ - && apt-get install -y \ - /nos3_filestore/packages/ubuntu/itc-common-Release_1.10.1_i386.deb \ - /nos3_filestore/packages/ubuntu/nos-engine-Release_1.6.1_i386.deb - -RUN mkdir -p /opt/nos3 \ - && cd /opt/nos3 \ - && git clone https://github.com/ericstoneking/42.git \ - && cd /opt/nos3/42 \ - && git checkout f20d8d517b352b868d2f45ee3bffdb7deeedb218 - -RUN cd /opt/nos3/42 \ - && sed 's/ARCHFLAG =/ARCHFLAG=-m32 /; s/LFLAGS = -L/LFLAGS = -m32 -L/; s/#GLUT_OR_GLFW = _USE_GLUT_/GLUT_OR_GLFW = _USE_GLUT_/' -i /opt/nos3/42/Makefile \ - && make \ - && ln -s /usr/lib/libnos_engine_client.so /usr/lib/libnos_engine_client_cxx11.so - diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index 4769473c..34ef2761 100644 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -8,5 +8,5 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -mkdir -p $BASE_DIR/sim/build +mkdir -p $BASE_DIR/sims/build $DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim From ad1fc4e303e1db1d72a4bf9238a37e64df36c469 Mon Sep 17 00:00:00 2001 From: Harris Date: Tue, 12 Sep 2023 11:31:30 -0400 Subject: [PATCH 017/153] Corrections to the TLM message --- components/arducam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/arducam b/components/arducam index f1b51b94..c6f92202 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit f1b51b9402620dc63b4ba3a34ee0ae67d341e3e9 +Subproject commit c6f92202ce5e33d64f06ab3ab3ce4314fc8a524e From 814cb8d0f8fef3267c13ac56181eb8f0fe5d67b8 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 13 Sep 2023 12:57:42 -0400 Subject: [PATCH 018/153] [nasa/nos3#164] Update arducam submodule after PR; --- components/arducam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/arducam b/components/arducam index c6f92202..bafb309d 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit c6f92202ce5e33d64f06ab3ab3ce4314fc8a524e +Subproject commit bafb309d18cf649cf451929381fb7e7b4e0e0dbb From 4d4f788480fb5210db15a3dcce57c45e81798dd5 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 15 Sep 2023 13:08:23 +0000 Subject: [PATCH 019/153] [nasa/nos3#163] Updated env.sh DFLAGS to use current user:group and pointed scripts to the deployment repository for the Dockerfile; --- gsw/scripts/checkout.sh | 2 ++ gsw/scripts/create_cosmos_gem.sh | 0 gsw/scripts/docker_build_fsw.sh | 2 +- gsw/scripts/docker_build_sim.sh | 2 +- gsw/scripts/docker_compose_launch.sh | 2 +- gsw/scripts/docker_debug.sh | 12 ++++++++++++ gsw/scripts/docker_launch.sh | 3 ++- gsw/scripts/docker_stop.sh | 5 +++-- gsw/scripts/env.sh | 2 +- gsw/scripts/launch.sh | 2 ++ 10 files changed, 25 insertions(+), 7 deletions(-) mode change 100644 => 100755 gsw/scripts/create_cosmos_gem.sh mode change 100644 => 100755 gsw/scripts/docker_build_fsw.sh mode change 100644 => 100755 gsw/scripts/docker_build_sim.sh create mode 100755 gsw/scripts/docker_debug.sh mode change 100644 => 100755 gsw/scripts/env.sh diff --git a/gsw/scripts/checkout.sh b/gsw/scripts/checkout.sh index 47990111..ccc00227 100755 --- a/gsw/scripts/checkout.sh +++ b/gsw/scripts/checkout.sh @@ -1,6 +1,8 @@ #!/bin/bash -i # # Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh old mode 100644 new mode 100755 diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh old mode 100644 new mode 100755 index 936dfb2a..cab38e45 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -2,7 +2,7 @@ # # Convenience script for NOS3 development # Use with the Dockerfile in the deployment repository -# https://docs.docker.com/engine/install/ubuntu/ +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh old mode 100644 new mode 100755 index 34ef2761..05f29d0f --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -2,7 +2,7 @@ # # Convenience script for NOS3 development # Use with the Dockerfile in the deployment repository -# https://docs.docker.com/engine/install/ubuntu/ +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/docker_compose_launch.sh b/gsw/scripts/docker_compose_launch.sh index 0a3c55e9..b072f2b0 100755 --- a/gsw/scripts/docker_compose_launch.sh +++ b/gsw/scripts/docker_compose_launch.sh @@ -2,7 +2,7 @@ # # Convenience script for NOS3 development # Use with the Dockerfile in the deployment repository -# https://docs.docker.com/engine/install/ubuntu/ +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/docker_debug.sh b/gsw/scripts/docker_debug.sh new file mode 100755 index 00000000..f4021a13 --- /dev/null +++ b/gsw/scripts/docker_debug.sh @@ -0,0 +1,12 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +mkdir -p $BASE_DIR/fsw/build +$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR ivvitc/nos3 bash diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index c36b97cd..0e0e3d51 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -1,7 +1,8 @@ #!/bin/bash -i # # Convenience script for NOS3 development -# https://docs.docker.com/engine/install/ubuntu/ +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index 382c0ce6..937fc6ee 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -1,7 +1,8 @@ -#!/bin/bash +#!/bin/bash -i # # Convenience script for NOS3 development -# https://docs.docker.com/engine/install/ubuntu/ +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh old mode 100644 new mode 100755 index cf6db30e..a90d5c93 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -22,7 +22,7 @@ if [ -f "/etc/redhat-release" ]; then DNETWORK="sudo docker network" else DCALL="docker" - DFLAGS="docker run --rm -it" + DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u):$(id -g)" DCREATE="docker create --rm -it" DNETWORK="docker network" fi diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index ecb36a61..2a53fcc4 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -1,6 +1,8 @@ #!/bin/bash -i # # Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) From 20d27179990e8d5a49f3a2640651cd5c462850ca Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Sep 2023 13:14:35 -0400 Subject: [PATCH 020/153] [nasa/nos3#163] Updated real-clean script and added DFLAGS_CPU environmental variable; --- gsw/scripts/docker_build_fsw.sh | 2 +- gsw/scripts/docker_build_sim.sh | 2 +- gsw/scripts/docker_debug.sh | 2 +- gsw/scripts/env.sh | 22 ++++++++++++---------- gsw/scripts/real_clean.sh | 2 ++ 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index cab38e45..852c7f27 100755 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/fsw/build -$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index 05f29d0f..f7a85dc1 100755 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/sims/build -$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim diff --git a/gsw/scripts/docker_debug.sh b/gsw/scripts/docker_debug.sh index f4021a13..95df27c3 100755 --- a/gsw/scripts/docker_debug.sh +++ b/gsw/scripts/docker_debug.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/fsw/build -$DFLAGS --cpus=$NUM_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR ivvitc/nos3 bash +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR --name "nos3_debug" ivvitc/nos3 bash diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index a90d5c93..4770e155 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -15,23 +15,25 @@ if [ -d $SIM_DIR/bin ]; then SIMS=$(ls $SIM_BIN/nos3*simulator) fi +DATE=$(date "+%Y%m%d%H%M") +OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" + +NUM_CPUS="$( nproc )" + if [ -f "/etc/redhat-release" ]; then - DCALL="sudo docker" - DFLAGS="sudo docker run --rm --group-add keep-groups -it" - DCREATE="sudo docker create --rm -it" - DNETWORK="sudo docker network" + DCALL="podman" + DFLAGS="podman run --rm --group-add keep-groups -it" + DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" + DCREATE="podman create --rm -it" + DNETWORK="podman network" else DCALL="docker" - DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u):$(id -g)" + DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(stat -c '%U:%U' $SCRIPT_DIR/env.sh)" + DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" DCREATE="docker create --rm -it" DNETWORK="docker network" fi -DATE=$(date "+%Y%m%d%H%M") -OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" - -NUM_CPUS="$( nproc )" - # Debugging #echo "Script directory = " $SCRIPT_DIR #echo "Base directory = " $BASE_DIR diff --git a/gsw/scripts/real_clean.sh b/gsw/scripts/real_clean.sh index 21a90dc9..cecae881 100755 --- a/gsw/scripts/real_clean.sh +++ b/gsw/scripts/real_clean.sh @@ -18,4 +18,6 @@ yes | rm $BASE_DIR/minicom.cap 2> /dev/null echo "Cleaning up CryptoLib build..." yes | rm $BASE_DIR/minicom.cap 2> /dev/null +$DCALL system prune -f + exit 0 From 02689d85b6d6369a4f1117b0b53e3eb867abed85 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Sep 2023 13:59:36 -0400 Subject: [PATCH 021/153] [nasa/nos3#163] Iteration to support both local and vbox shared folder builds; --- Vagrantfile | 2 +- gsw/cosmos | 2 +- gsw/scripts/env.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 8b2a75f2..23c0c3e9 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -8,7 +8,7 @@ Vagrant.configure("2") do |config| ### ### Uncomment one of the following to select configuration - #config.vm.box = "nos3/rocky" + #config.vm.box = "nos3/rocky" # Not yet updated to support config.vm.box = "nos3/ubuntu" ### Specify version diff --git a/gsw/cosmos b/gsw/cosmos index 89aaffb4..15bc5d12 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 89aaffb49509ca107b7c67d65c18cc3bfa0dea1a +Subproject commit 15bc5d12c43d9f65f4e2da773b7e92a6229fc2da diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 4770e155..185077f0 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -28,7 +28,7 @@ if [ -f "/etc/redhat-release" ]; then DNETWORK="podman network" else DCALL="docker" - DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(stat -c '%U:%U' $SCRIPT_DIR/env.sh)" + DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(id -g $(stat -c '%G' $SCRIPT_DIR/env.sh))" DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" DCREATE="docker create --rm -it" DNETWORK="docker network" From 1a4311dda2602f851b531fa63d0a2831b2911062 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Sep 2023 14:27:47 -0400 Subject: [PATCH 022/153] [nasa/nos3#163] Update submodules after merge of PRs; --- components/generic_radio | 2 +- fsw/apps/hwlib | 2 +- fsw/apps/to | 2 +- fsw/apps/to_lab | 2 +- fsw/psp | 2 +- gsw/cosmos | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/generic_radio b/components/generic_radio index ac6554c8..80c950c1 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit ac6554c89d4f547c8b070cd5ecc399d005848ccf +Subproject commit 80c950c1029b767d5ebde960daf1cebec6c48acc diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index dab85ebc..405f028a 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit dab85ebc2264f7e3179aa42841b735d373bf08d6 +Subproject commit 405f028a35c31585c2e07bb8d8ac85bca476ca21 diff --git a/fsw/apps/to b/fsw/apps/to index 26e14899..471e41ca 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 26e148998dabe2a7748aab50b88e0fa42a95eee3 +Subproject commit 471e41ca5dd395c037dfe31f562cba5e06943d96 diff --git a/fsw/apps/to_lab b/fsw/apps/to_lab index 9b461b02..bdee03fe 160000 --- a/fsw/apps/to_lab +++ b/fsw/apps/to_lab @@ -1 +1 @@ -Subproject commit 9b461b023b675d87735f73b7c171b0db5e17856f +Subproject commit bdee03feae576efc8a91a97b0574cb8d6392627c diff --git a/fsw/psp b/fsw/psp index 537b7523..bc6daca0 160000 --- a/fsw/psp +++ b/fsw/psp @@ -1 +1 @@ -Subproject commit 537b7523b944e1dbe2cf7994fad9370fe00ed56c +Subproject commit bc6daca063ac83c191bd5571ed0b474052461461 diff --git a/gsw/cosmos b/gsw/cosmos index 15bc5d12..06084250 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 15bc5d12c43d9f65f4e2da773b7e92a6229fc2da +Subproject commit 0608425026e4018e762f31cf0a92ed94f4f39bef From 411ad4a5c6fbc59d754c887eaa1dd3cc556b1ad3 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 29 Sep 2023 10:53:13 -0400 Subject: [PATCH 023/153] [nasa/nos3#215] Initial commit attempting to resolve local nos3 ubuntu runs; --- fsw/psp | 2 +- gsw/scripts/env.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fsw/psp b/fsw/psp index bc6daca0..6699a3df 160000 --- a/fsw/psp +++ b/fsw/psp @@ -1 +1 @@ -Subproject commit bc6daca063ac83c191bd5571ed0b474052461461 +Subproject commit 6699a3df30985d825d0743f531eb710600f47bc8 diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 185077f0..d57f64ae 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -28,7 +28,7 @@ if [ -f "/etc/redhat-release" ]; then DNETWORK="podman network" else DCALL="docker" - DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(id -g $(stat -c '%G' $SCRIPT_DIR/env.sh))" + DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(getent group $(stat -c '%G' $SCRIPT_DIR/env.sh) | cut -d: -f3)" DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" DCREATE="docker create --rm -it" DNETWORK="docker network" From c0bcb4d374c49ad90fe22649d4e652b2cc5f31a9 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Thu, 5 Oct 2023 14:10:31 -0400 Subject: [PATCH 024/153] https://github.com/nasa/nos3/issues/166 - Initial star tracker code generated by template generator/sample code. --- components/generic_star_tracker/.gitignore | 1 + .../generic_star_tracker/CMakeLists.txt | 16 + components/generic_star_tracker/LICENSE | 263 ++++++++ components/generic_star_tracker/README.md | 138 +++++ .../generic_star_tracker_perfids.h | 21 + .../generic_star_tracker_msgids.h | 28 + .../generic_star_tracker_platform_cfg.h | 29 + .../fsw/src/generic_star_tracker_app.c | 576 ++++++++++++++++++ .../fsw/src/generic_star_tracker_app.h | 100 +++ .../fsw/src/generic_star_tracker_device.c | 274 +++++++++ .../fsw/src/generic_star_tracker_device.h | 77 +++ .../fsw/src/generic_star_tracker_events.h | 47 ++ .../fsw/src/generic_star_tracker_msg.h | 89 +++ .../fsw/src/generic_star_tracker_version.h | 19 + .../cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt | 49 ++ .../cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt | 44 ++ .../gsw/GENERIC_STAR_TRACKER/target.txt | 10 + .../generic_star_tracker/sim/CMakeLists.txt | 31 + .../generic_star_tracker_42_data_provider.hpp | 30 + .../inc/generic_star_tracker_data_point.hpp | 46 ++ .../generic_star_tracker_data_provider.hpp | 29 + .../generic_star_tracker_hardware_model.hpp | 61 ++ .../generic_star_tracker_42_data_provider.cpp | 32 + .../src/generic_star_tracker_data_point.cpp | 81 +++ .../generic_star_tracker_data_provider.cpp | 28 + .../generic_star_tracker_hardware_model.cpp | 326 ++++++++++ .../support/CMakeLists.txt | 69 +++ .../generic_star_tracker/support/device_cfg.h | 15 + .../support/generic_star_tracker_checkout.c | 278 +++++++++ .../support/generic_star_tracker_checkout.h | 68 +++ fsw/nos3_defs/cpu1_cfe_es_startup.scr | 1 + fsw/nos3_defs/targets.cmake | 1 + 32 files changed, 2877 insertions(+) create mode 100644 components/generic_star_tracker/.gitignore create mode 100644 components/generic_star_tracker/CMakeLists.txt create mode 100644 components/generic_star_tracker/LICENSE create mode 100644 components/generic_star_tracker/README.md create mode 100644 components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h create mode 100644 components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h create mode 100644 components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_app.c create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_app.h create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_device.c create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_device.h create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_events.h create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h create mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_version.h create mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt create mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt create mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt create mode 100644 components/generic_star_tracker/sim/CMakeLists.txt create mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp create mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp create mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp create mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp create mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp create mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp create mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp create mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp create mode 100644 components/generic_star_tracker/support/CMakeLists.txt create mode 100644 components/generic_star_tracker/support/device_cfg.h create mode 100644 components/generic_star_tracker/support/generic_star_tracker_checkout.c create mode 100644 components/generic_star_tracker/support/generic_star_tracker_checkout.h diff --git a/components/generic_star_tracker/.gitignore b/components/generic_star_tracker/.gitignore new file mode 100644 index 00000000..cfea098e --- /dev/null +++ b/components/generic_star_tracker/.gitignore @@ -0,0 +1 @@ +support/build \ No newline at end of file diff --git a/components/generic_star_tracker/CMakeLists.txt b/components/generic_star_tracker/CMakeLists.txt new file mode 100644 index 00000000..148cec8a --- /dev/null +++ b/components/generic_star_tracker/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.6.4) +project(CFS_GENERIC_STAR_TRACKER_APP C) + +include(../ComponentSettings.cmake) + +include_directories(fsw/public_inc) +include_directories(fsw/mission_inc) +include_directories(fsw/platform_inc) +include_directories(fsw/src) + +include_directories(${hwlib_MISSION_DIR}/fsw/public_inc) + +aux_source_directory(fsw/src APP_SRC_FILES) + +# Create the app module +add_cfe_app(generic_st ${APP_SRC_FILES}) diff --git a/components/generic_star_tracker/LICENSE b/components/generic_star_tracker/LICENSE new file mode 100644 index 00000000..50a36292 --- /dev/null +++ b/components/generic_star_tracker/LICENSE @@ -0,0 +1,263 @@ +NASA OPEN SOURCE AGREEMENT VERSION 1.3 + +THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, +REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN +COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT +AS REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT +AGENCY"). THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT +AGENCY, IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT +DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO +USES, REPRODUCES, DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT +SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, +ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN +THIS AGREEMENT. + +Government Agency: NASA +Government Agency Original Software Designation: GSC-17737-1 +Government Agency Original Software Title: + NASA Operational Simulator for Small Satellites +User Registration Requested. Please Visit + https://github.com/nasa/nos3 +Government Agency Point of Contact for Original Software: + John.P.Lucas@nasa.gov + +1. DEFINITIONS + +A. "Contributor" means Government Agency, as the developer of the +Original Software, and any entity that makes a Modification. +B. "Covered Patents" mean patent claims licensable by a Contributor +that are necessarily infringed by the use or sale of its Modification +alone or when combined with the Subject Software. +C. "Display" means the showing of a copy of the Subject Software, +either directly or by means of an image, or any other device. +D. "Distribution" means conveyance or transfer of the Subject +Software, regardless of means, to another. +E. "Larger Work" means computer software that combines Subject +Software, or portions thereof, with software separate from the Subject +Software that is not governed by the terms of this Agreement. +F. "Modification" means any alteration of, including addition to or +deletion from, the substance or structure of either the Original +Software or Subject Software, and includes derivative works, as that +term is defined in the Copyright Statute, 17 USC 101. However, the +act of including Subject Software as part of a Larger Work does not in +and of itself constitute a Modification. +G. "Original Software" means the computer software first released +under this Agreement by Government Agency with Government Agency +designation GSC-17776-1 and entitled Core Flight System Cryptography +Library, including source code, object code and accompanying +documentation, if any. +H. "Recipient" means anyone who acquires the Subject Software under +this Agreement, including all Contributors. +I. "Redistribution" means Distribution of the Subject Software after a +Modification has been made. +J. "Reproduction" means the making of a counterpart, image or copy of +the Subject Software. +K. "Sale" means the exchange of the Subject Software for money or +equivalent value. +L. "Subject Software" means the Original Software, Modifications, or +any respective parts thereof. +M. "Use" means the application or employment of the Subject Software +for any purpose. + +2. GRANT OF RIGHTS + +A. Under Non-Patent Rights: Subject to the terms and conditions of +this Agreement, each Contributor, with respect to its own contribution +to the Subject Software, hereby grants to each Recipient a +non-exclusive, world-wide, royalty-free license to engage in the +following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Modification +5. Redistribution +6. Display + +B. Under Patent Rights: Subject to the terms and conditions of this +Agreement, each Contributor, with respect to its own contribution to +the Subject Software, hereby grants to each Recipient under Covered +Patents a non-exclusive, world-wide, royalty-free license to engage in +the following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Sale +5. Offer for Sale + +C. The rights granted under Paragraph B. also apply to the combination +of a Contributor's Modification and the Subject Software if, at the +time the Modification is added by the Contributor, the addition of +such Modification causes the combination to be covered by the Covered +Patents. It does not apply to any other combinations that include a +Modification. + +D. The rights granted in Paragraphs A. and B. allow the Recipient to +sublicense those same rights. Such sublicense must be under the same +terms and conditions of this Agreement. + +3. OBLIGATIONS OF RECIPIENT + +A. Distribution or Redistribution of the Subject Software must be made +under this Agreement except for additions covered under paragraph 3H. + +1. Whenever a Recipient distributes or redistributes the Subject + Software, a copy of this Agreement must be included with each copy + of the Subject Software; and +2. If Recipient distributes or redistributes the Subject Software in + any form other than source code, Recipient must also make the + source code freely available, and must provide with each copy of + the Subject Software information on how to obtain the source code + in a reasonable manner on or through a medium customarily used for + software exchange. + +B. Each Recipient must ensure that the following copyright notice +appears prominently in the Subject Software: + +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ + +C. Each Contributor must characterize its alteration of the Subject +Software as a Modification and must identify itself as the originator +of its Modification in a manner that reasonably allows subsequent +Recipients to identify the originator of the Modification. In +fulfillment of these requirements, Contributor must include a file +(e.g., a change log file) that describes the alterations made and the +date of the alterations, identifies Contributor as originator of the +alterations, and consents to characterization of the alterations as a +Modification, for example, by including a statement that the +Modification is derived, directly or indirectly, from Original +Software provided by Government Agency. Once consent is granted, it +may not thereafter be revoked. + +D. A Contributor may add its own copyright notice to the Subject +Software. Once a copyright notice has been added to the Subject +Software, a Recipient may not remove it without the express permission +of the Contributor who added the notice. + +E. A Recipient may not make any representation in the Subject Software +or in any promotional, advertising or other material that may be +construed as an endorsement by Government Agency or by any prior +Recipient of any product or service provided by Recipient, or that may +seek to obtain commercial advantage by the fact of Government Agency's +or a prior Recipient's participation in this Agreement. + +F. In an effort to track usage and maintain accurate records of the +Subject Software, each Recipient, upon receipt of the Subject +Software, is requested to register with Government Agency by visiting +the following website: https://github.com/nasa/CryptoLib. Recipient's +name and personal information shall be used for statistical purposes +only. Once a Recipient makes a Modification available, it is requested +that the Recipient inform Government Agency at the web site provided +above how to access the Modification. + +G. Each Contributor represents that that its Modification is believed +to be Contributor's original creation and does not violate any +existing agreements, regulations, statutes or rules, and further that +Contributor has sufficient rights to grant the rights conveyed by this +Agreement. + +H. A Recipient may choose to offer, and to charge a fee for, warranty, +support, indemnity and/or liability obligations to one or more other +Recipients of the Subject Software. A Recipient may do so, however, +only on its own behalf and not on behalf of Government Agency or any +other Recipient. Such a Recipient must make it absolutely clear that +any such warranty, support, indemnity and/or liability obligation is +offered by that Recipient alone. Further, such Recipient agrees to +indemnify Government Agency and every other Recipient for any +liability incurred by them as a result of warranty, support, indemnity +and/or liability offered by such Recipient. + +I. A Recipient may create a Larger Work by combining Subject Software +with separate software not governed by the terms of this agreement and +distribute the Larger Work as a single product. In such case, the +Recipient must make sure Subject Software, or portions thereof, +included in the Larger Work is subject to this Agreement. + +J. Notwithstanding any provisions contained herein, Recipient is +hereby put on notice that export of any goods or technical data from +the United States may require some form of export license from the +U.S. Government. Failure to obtain necessary export licenses may +result in criminal liability under U.S. laws. Government Agency +neither represents that a license shall not be required nor that, if +required, it shall be issued. Nothing granted herein provides any +such export license. + +4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION + +A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY +WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, +INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE +WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM +INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR +FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO +THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, +CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT +OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY +OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. +FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES +REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, +AND DISTRIBUTES IT "AS IS." + +B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS +AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND +SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF +THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, +EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM +PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT +SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED +STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY +PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE +REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL +TERMINATION OF THIS AGREEMENT. + + +5. GENERAL TERMS + +A. Termination: This Agreement and the rights granted hereunder will +terminate automatically if a Recipient fails to comply with these +terms and conditions, and fails to cure such noncompliance within +thirty (30) days of becoming aware of such noncompliance. Upon +termination, a Recipient agrees to immediately cease use and +distribution of the Subject Software. All sublicenses to the Subject +Software properly granted by the breaching Recipient shall survive any +such termination of this Agreement. + +B. Severability: If any provision of this Agreement is invalid or +unenforceable under applicable law, it shall not affect the validity +or enforceability of the remainder of the terms of this Agreement. + +C. Applicable Law: This Agreement shall be subject to United States +federal law only for all purposes, including, but not limited to, +determining the validity of this Agreement, the meaning of its +provisions and the rights, obligations and remedies of the parties. + +D. Entire Understanding: This Agreement constitutes the entire +understanding and agreement of the parties relating to release of the +Subject Software and may not be superseded, modified or amended except +by further written agreement duly executed by the parties. + +E. Binding Authority: By accepting and using the Subject Software +under this Agreement, a Recipient affirms its authority to bind the +Recipient to all terms and conditions of this Agreement and that that +Recipient hereby agrees to all terms and conditions herein. + +F. Point of Contact: Any Recipient contact with Government Agency is +to be directed to the designated representative as follows: + John.P.Lucas@nasa.gov \ No newline at end of file diff --git a/components/generic_star_tracker/README.md b/components/generic_star_tracker/README.md new file mode 100644 index 00000000..b9a654d4 --- /dev/null +++ b/components/generic_star_tracker/README.md @@ -0,0 +1,138 @@ +# Generic_star_tracker - NOS3 Component +This repository contains the NOS3 Generic_star_tracker Component. +This includes flight software (FSW), ground software (GSW), simulation, and support directories. + +## Component Template +This component template utilizes canned files from the existing [generic_star_tracker component](https://github.com/nasa-itc/generic_star_tracker) to generate a new component to do development in. + +Expected utilization: +* Determine the desired component name +* Create a new submodule for the component via GitHub +* Add the submodule to this project + * `git submodule init` + * `git submodule add -f -b main ./components/` +* Generate the new files + * `./generate_template.sh ` + * Note that must be <= 10 characters by default or you'll need to shorten the software bus pipe name after the fact +* The new files should be placed in the submodule + * `..//` +* Commit the new files to the submodule + * `git add * && git add .gitignore` + * `git commit -m "Initial component template based on version 0.0.0"` +* Add new component to flight software (fsw) in the following files: + * `./fsw/nos3_defs/cpu1_cfe_es_startup.scr` + * `./fsw/nos3_defs/targets.cmake` + * `./fsw/nos3_defs/tables/*` +* Add new component to ground software (gsw) in the following files: + * `./gsw/cosmos/config/system/nos3_system.txt` + * `./gsw/cosmos/config/tools/cmd_tlm_server/nos3_cmd_tlm_server.txt` + * `./gsw/scripts/launch.sh` + +## Overview +In addition to being used by the template generator, the generic_star_tracker component provides an executable example for the user. This generic_star_tracker component is a UART device that accepts multiple commands, including requests for telemetry and data. +The available FSW is for use in the core Flight System (cFS) while the GSW supports COSMOS. +A NOS3 simulation is available which includes both generic_star_tracker and 42 data providers. + + +# Device Communications +The protocol, commands, and responses of the component are captured below. + +## Protocol +The protocol in use is UART 115200 8N1. +The device is speak when spoken too. +All communications with the device require / contain a header of 0xDEAD and a trailer of 0xBEEF. + +## Commands +All commands received by the device are echoed back to the sender to confirm receipt. +Should commmands involve a reply, the device immediately sends the reply after the command echo. +Device commands are all formatted in the same manner and are fixed in size: +* uint16, 0xDEAD +* uint8, command identifier + - (0) Get Housekeeping + - (1) Get Generic_star_tracker + - (2) Set Configuration +* uint32, command payload + - Unused for all but set configuration command +* uint16, 0xBEEF + +## Response +Response formats are as follows: +* Housekeeping + - uint16, 0xDEAD + - uint32, Command Counter + * Increments for each command received + - uint32, Configuration + * Internal configuration number in use by the device + - uint32, Status + * Self reported status of the component where zero is completely healthy and each bit represents different errors + * No means to clear / set status except for a power cycle to the device + - uint16, 0xBEEF +* Generic_star_tracker + - uint16, 0xDEAD + - uint32, Command Counter + * Increments for each command received + - uint16, Data X + * X component of generic_star_tracker data + - uint16, Data Y + * X component of generic_star_tracker data + - uint16, Data Z + * X component of generic_star_tracker data + - uint16, 0xBEEF + + +# Configuration +The various configuration parameters available for each portion of the component are captured below. + +## FSW +Refer to the file [fsw/platform_inc/generic_star_tracker_platform_cfg.h](fsw/platform_inc/generic_star_tracker_platform_cfg.h) for the default +configuration settings, as well as a summary on overriding parameters in mission-specific repositories. + +## Simulation +The default configuration returns data that is X * 0.001, Y * 0.002, and Z * 0.003 the request count after conversions: +``` + + generic_star_tracker_sim + true + libgeneric_star_tracker_sim.so + + GENERIC_STAR_TRACKER + + command + command + generic_star_tracker-sim-command-node + + usart + usart_29 + 29 + + + + GENERIC_STAR_TRACKER_PROVIDER + + + +``` + +## 42 +Optionally the 42 data provider can be configured in the `nos3-simulator.xml`: +``` + + GENERIC_STAR_TRACKER_42_PROVIDER + localhost + 4242 + 5 + 5 + 0 + +``` + + +# Documentation +If this generic_star_tracker application had an ICD and/or test procedure, they would be linked here. + +## Releases +We use [SemVer](http://semver.org/) for versioning. For the versions available, see the tags on this repository. +* v1.0.0 - X/Y/Z + - Updated to be a component repository including FSW, GSW, Sim, and Standalone checkout +* v0.1.0 - 10/9/2021 + - Initial release with version tagging diff --git a/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h b/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h new file mode 100644 index 00000000..b0ba2c9a --- /dev/null +++ b/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h @@ -0,0 +1,21 @@ +/******************************************************************************* +** File: +** $Id: generic_star_tracker_perfids.h $ +** +** Purpose: +** Define GENERIC_STAR_TRACKER Performance IDs +** +** Notes: +** +*************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_PERFIDS_H_ +#define _GENERIC_STAR_TRACKER_PERFIDS_H_ + +/* +** define any performance id integer for the app - try to not have this +** id conflict with other apps. Performance IDs are used for cFE performance +** metrics. +*/ +#define GENERIC_STAR_TRACKER_PERF_ID 500 + +#endif /* _GENERIC_STAR_TRACKER_PERFIDS_H_ */ diff --git a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h new file mode 100644 index 00000000..88bc2fa4 --- /dev/null +++ b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h @@ -0,0 +1,28 @@ +/************************************************************************ +** File: +** $Id: generic_star_tracker_msgids.h $ +** +** Purpose: +** Define GENERIC_STAR_TRACKER Message IDs +** +*************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_MSGIDS_H_ +#define _GENERIC_STAR_TRACKER_MSGIDS_H_ + +/* +** CCSDS V1 Command Message IDs (MID) must be 0x18xx +*/ +#define GENERIC_STAR_TRACKER_CMD_MID 0x1935 + +/* +** This MID is for commands telling the app to publish its telemetry message +*/ +#define GENERIC_STAR_TRACKER_REQ_HK_MID 0x1936 + +/* +** CCSDS V1 Telemetry Message IDs must be 0x08xx +*/ +#define GENERIC_STAR_TRACKER_HK_TLM_MID 0x0935 +#define GENERIC_STAR_TRACKER_DEVICE_TLM_MID 0x0936 + +#endif /* _GENERIC_STAR_TRACKER_MSGIDS_H_ */ diff --git a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h new file mode 100644 index 00000000..fe026fa8 --- /dev/null +++ b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h @@ -0,0 +1,29 @@ +/************************************************************************ +** File: +** $Id: generic_star_tracker_platform_cfg.h $ +** +** Purpose: +** Define generic_star_tracker Platform Configuration Parameters +** +** Notes: +** +*************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ +#define _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ + +/* +** Default GENERIC_STAR_TRACKER Configuration +*/ +#ifndef GENERIC_STAR_TRACKER_CFG + /* Notes: + ** NOS3 uart requires matching handle and bus number + */ + #define GENERIC_STAR_TRACKER_CFG_STRING "usart_29" + #define GENERIC_STAR_TRACKER_CFG_HANDLE 29 + #define GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ 115200 + #define GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT 50 /* Max 255 */ + /* Note: Debug flag disabled (commented out) by default */ + //#define GENERIC_STAR_TRACKER_CFG_DEBUG +#endif + +#endif /* _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c new file mode 100644 index 00000000..69051fc4 --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c @@ -0,0 +1,576 @@ +/******************************************************************************* +** File: generic_star_tracker_app.c +** +** Purpose: +** This file contains the source code for the GENERIC_STAR_TRACKER application. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include +#include "generic_star_tracker_app.h" + + +/* +** Global Data +*/ +GENERIC_STAR_TRACKER_AppData_t GENERIC_STAR_TRACKER_AppData; + +/* +** Application entry point and main process loop +*/ +void ST_AppMain(void) +{ + int32 status = OS_SUCCESS; + + /* + ** Create the first Performance Log entry + */ + CFE_ES_PerfLogEntry(GENERIC_STAR_TRACKER_PERF_ID); + + /* + ** Perform application initialization + */ + status = GENERIC_STAR_TRACKER_AppInit(); + if (status != CFE_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; + } + + /* + ** Main loop + */ + while (CFE_ES_RunLoop(&GENERIC_STAR_TRACKER_AppData.RunStatus) == true) + { + /* + ** Performance log exit stamp + */ + CFE_ES_PerfLogExit(GENERIC_STAR_TRACKER_PERF_ID); + + /* + ** Pend on the arrival of the next Software Bus message + ** Note that this is the standard, but timeouts are available + */ + status = CFE_SB_ReceiveBuffer((CFE_SB_Buffer_t **)&GENERIC_STAR_TRACKER_AppData.MsgPtr, GENERIC_STAR_TRACKER_AppData.CmdPipe, CFE_SB_PEND_FOREVER); + + /* + ** Begin performance metrics on anything after this line. This will help to determine + ** where we are spending most of the time during this app execution. + */ + CFE_ES_PerfLogEntry(GENERIC_STAR_TRACKER_PERF_ID); + + /* + ** If the CFE_SB_ReceiveBuffer was successful, then continue to process the command packet + ** If not, then exit the application in error. + ** Note that a SB read error should not always result in an app quitting. + */ + if (status == CFE_SUCCESS) + { + GENERIC_STAR_TRACKER_ProcessCommandPacket(); + } + else + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: SB Pipe Read Error = %d", (int) status); + GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; + } + } + + /* + ** Disable component, which cleans up the interface, upon exit + */ + GENERIC_STAR_TRACKER_Disable(); + + /* + ** Performance log exit stamp + */ + CFE_ES_PerfLogExit(GENERIC_STAR_TRACKER_PERF_ID); + + /* + ** Exit the application + */ + CFE_ES_ExitApp(GENERIC_STAR_TRACKER_AppData.RunStatus); +} + + +/* +** Initialize application +*/ +int32 GENERIC_STAR_TRACKER_AppInit(void) +{ + int32 status = OS_SUCCESS; + + GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_RUN; + + /* + ** Register the events + */ + status = CFE_EVS_Register(NULL, 0, CFE_EVS_EventFilter_BINARY); /* as default, no filters are used */ + if (status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("GENERIC_STAR_TRACKER: Error registering for event services: 0x%08X\n", (unsigned int) status); + return status; + } + + /* + ** Create the Software Bus command pipe + */ + status = CFE_SB_CreatePipe(&GENERIC_STAR_TRACKER_AppData.CmdPipe, GENERIC_STAR_TRACKER_PIPE_DEPTH, "GENERIC_ST_CMD_PIPE"); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Creating SB Pipe,RC=0x%08X",(unsigned int) status); + return status; + } + + /* + ** Subscribe to ground commands + */ + status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_CMD_MID), GENERIC_STAR_TRACKER_AppData.CmdPipe); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_SUB_CMD_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Subscribing to HK Gnd Cmds, MID=0x%04X, RC=0x%08X", + GENERIC_STAR_TRACKER_CMD_MID, (unsigned int) status); + return status; + } + + /* + ** Subscribe to housekeeping (hk) message requests + */ + status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_REQ_HK_MID), GENERIC_STAR_TRACKER_AppData.CmdPipe); + if (status != CFE_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_SUB_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, + "Error Subscribing to HK Request, MID=0x%04X, RC=0x%08X", + GENERIC_STAR_TRACKER_REQ_HK_MID, (unsigned int) status); + return status; + } + + /* + ** TODO: Subscribe to any other messages here + */ + + + /* + ** Initialize the published HK message - this HK message will contain the + ** telemetry that has been defined in the GENERIC_STAR_TRACKER_HkTelemetryPkt for this app. + */ + CFE_MSG_Init(CFE_MSG_PTR(GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.TlmHeader), + CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_HK_TLM_MID), + GENERIC_STAR_TRACKER_HK_TLM_LNGTH); + + /* + ** Initialize the device packet message + ** This packet is specific to your application + */ + CFE_MSG_Init(CFE_MSG_PTR(GENERIC_STAR_TRACKER_AppData.DevicePkt.TlmHeader), + CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_DEVICE_TLM_MID), + GENERIC_STAR_TRACKER_DEVICE_TLM_LNGTH); + + /* + ** TODO: Initialize any other messages that this app will publish + */ + + + /* + ** Always reset all counters during application initialization + */ + GENERIC_STAR_TRACKER_ResetCounters(); + + /* + ** Initialize application data + ** Note that counters are excluded as they were reset in the previous code block + */ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_DISABLED; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceCounter = 0; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceConfig = 0; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceStatus = 0; + + /* + ** Send an information event that the app has initialized. + ** This is useful for debugging the loading of individual applications. + */ + status = CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_STARTUP_INF_EID, CFE_EVS_EventType_INFORMATION, + "GENERIC_STAR_TRACKER App Initialized. Version %d.%d.%d.%d", + GENERIC_STAR_TRACKER_MAJOR_VERSION, + GENERIC_STAR_TRACKER_MINOR_VERSION, + GENERIC_STAR_TRACKER_REVISION, + GENERIC_STAR_TRACKER_MISSION_REV); + if (status != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("GENERIC_STAR_TRACKER: Error sending initialization event: 0x%08X\n", (unsigned int) status); + } + return status; +} + + +/* +** Process packets received on the GENERIC_STAR_TRACKER command pipe +*/ +void GENERIC_STAR_TRACKER_ProcessCommandPacket(void) +{ + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); + switch (CFE_SB_MsgIdToValue(MsgId)) + { + /* + ** Ground Commands with command codes fall under the GENERIC_STAR_TRACKER_CMD_MID (Message ID) + */ + case GENERIC_STAR_TRACKER_CMD_MID: + GENERIC_STAR_TRACKER_ProcessGroundCommand(); + break; + + /* + ** All other messages, other than ground commands, add to this case statement. + */ + case GENERIC_STAR_TRACKER_REQ_HK_MID: + GENERIC_STAR_TRACKER_ProcessTelemetryRequest(); + break; + + /* + ** All other invalid messages that this app doesn't recognize, + ** increment the command error counter and log as an error event. + */ + default: + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PROCESS_CMD_ERR_EID,CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Invalid command packet, MID = 0x%x", CFE_SB_MsgIdToValue(MsgId)); + break; + } + return; +} + + +/* +** Process ground commands +** TODO: Add additional commands required by the specific component +*/ +void GENERIC_STAR_TRACKER_ProcessGroundCommand(void) +{ + int32 status = OS_SUCCESS; + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t CommandCode = 0; + + /* + ** MsgId is only needed if the command code is not recognized. See default case + */ + CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); + + /* + ** Ground Commands, by definition, have a command code (_CC) associated with them + ** Pull this command code from the message and then process + */ + CFE_MSG_GetFcnCode(GENERIC_STAR_TRACKER_AppData.MsgPtr, &CommandCode); + switch (CommandCode) + { + /* + ** NOOP Command + */ + case GENERIC_STAR_TRACKER_NOOP_CC: + /* + ** First, verify the command length immediately after CC identification + ** Note that VerifyCmdLength handles the command and command error counters + */ + if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) + { + /* Second, send EVS event on successful receipt ground commands*/ + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_NOOP_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: NOOP command received"); + /* Third, do the desired command action if applicable, in the case of NOOP it is no operation */ + } + break; + + /* + ** Reset Counters Command + */ + case GENERIC_STAR_TRACKER_RESET_COUNTERS_CC: + if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_RESET_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: RESET counters command received"); + GENERIC_STAR_TRACKER_ResetCounters(); + } + break; + + /* + ** Enable Command + */ + case GENERIC_STAR_TRACKER_ENABLE_CC: + if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Enable command received"); + GENERIC_STAR_TRACKER_Enable(); + } + break; + + /* + ** Disable Command + */ + case GENERIC_STAR_TRACKER_DISABLE_CC: + if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) + { + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Disable command received"); + GENERIC_STAR_TRACKER_Disable(); + } + break; + + /* + ** TODO: Edit and add more command codes as appropriate for the application + ** Set Configuration Command + ** Note that this is an example of a command that has additional arguments + */ + case GENERIC_STAR_TRACKER_CONFIG_CC: + if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_Config_cmd_t)) == OS_SUCCESS) + { + uint32_t config = ntohl(((GENERIC_STAR_TRACKER_Config_cmd_t*) GENERIC_STAR_TRACKER_AppData.MsgPtr)->DeviceCfg); // command is defined as big-endian... need to convert to host representation + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_CONFIG_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Configuration command received: %u", config); + /* Command device to send HK */ + status = GENERIC_STAR_TRACKER_CommandDevice(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_CFG_CMD, config); + if (status == OS_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + } + } + break; + + /* + ** Invalid Command Codes + */ + default: + /* Increment the error counter upon receipt of an invalid command */ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_ERR_EID, CFE_EVS_EventType_ERROR, + "GENERIC_STAR_TRACKER: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); + break; + } + return; +} + + +/* +** Process Telemetry Request - Triggered in response to a telemetery request +** TODO: Add additional telemetry required by the specific component +*/ +void GENERIC_STAR_TRACKER_ProcessTelemetryRequest(void) +{ + int32 status = OS_SUCCESS; + CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t CommandCode = 0; + + /* MsgId is only needed if the command code is not recognized. See default case */ + CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); + + /* Pull this command code from the message and then process */ + CFE_MSG_GetFcnCode(GENERIC_STAR_TRACKER_AppData.MsgPtr, &CommandCode); + switch (CommandCode) + { + case GENERIC_STAR_TRACKER_REQ_HK_TLM: + GENERIC_STAR_TRACKER_ReportHousekeeping(); + break; + + case GENERIC_STAR_TRACKER_REQ_DATA_TLM: + GENERIC_STAR_TRACKER_ReportDeviceTelemetry(); + break; + + /* + ** Invalid Command Codes + */ + default: + /* Increment the error counter upon receipt of an invalid command */ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DEVICE_TLM_ERR_EID, CFE_EVS_EventType_ERROR, + "GENERIC_STAR_TRACKER: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); + break; + } + return; +} + + +/* +** Report Application Housekeeping +*/ +void GENERIC_STAR_TRACKER_ReportHousekeeping(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) + { + status = GENERIC_STAR_TRACKER_RequestHK(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, (GENERIC_STAR_TRACKER_Device_HK_tlm_t*) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK); + if (status == OS_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, + "GENERIC_STAR_TRACKER: Request device HK reported error %d", status); + } + } + /* Intentionally do not report errors if disabled */ + + /* Time stamp and publish housekeeping telemetry */ + CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt); + CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt, true); + return; +} + + +/* +** Collect and Report Device Telemetry +*/ +void GENERIC_STAR_TRACKER_ReportDeviceTelemetry(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) + { + status = GENERIC_STAR_TRACKER_RequestData(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, (GENERIC_STAR_TRACKER_Device_Data_tlm_t*) &GENERIC_STAR_TRACKER_AppData.DevicePkt.Generic_star_tracker); + if (status == OS_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; + /* Time stamp and publish data telemetry */ + CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.DevicePkt); + CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.DevicePkt, true); + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_REQ_DATA_ERR_EID, CFE_EVS_EventType_ERROR, + "GENERIC_STAR_TRACKER: Request device data reported error %d", status); + } + } + /* Intentionally do not report errors if disabled */ + return; +} + + +/* +** Reset all global counter variables +*/ +void GENERIC_STAR_TRACKER_ResetCounters(void) +{ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount = 0; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandCount = 0; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount = 0; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount = 0; + return; +} + + +/* +** Enable Component +** TODO: Edit for your specific component implementation +*/ +void GENERIC_STAR_TRACKER_Enable(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is disabled */ + if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_DISABLED) + { + /* + ** Initialize hardware interface data + ** TODO: Make specific to your application depending on protocol in use + ** Note that other components provide examples for the different protocols available + */ + GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.deviceString = GENERIC_STAR_TRACKER_CFG_STRING; + GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.handle = GENERIC_STAR_TRACKER_CFG_HANDLE; + GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.isOpen = PORT_CLOSED; + GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.baud = GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ; + GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.access_option = uart_access_flag_RDWR; + + /* Open device specific protocols */ + status = uart_init_port(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart); + if (status == OS_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_ENABLED; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Device enabled"); + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_UART_INIT_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: UART port initialization error %d", status); + } + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_ENABLE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Device enable failed, already enabled"); + } + return; +} + + +/* +** Disable Component +** TODO: Edit for your specific component implementation +*/ +void GENERIC_STAR_TRACKER_Disable(void) +{ + int32 status = OS_SUCCESS; + + /* Check that device is enabled */ + if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) + { + /* Open device specific protocols */ + status = uart_close_port(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart); + if (status == OS_SUCCESS) + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_DISABLED; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Device disabled"); + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_UART_CLOSE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: UART port close error %d", status); + } + } + else + { + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DISABLE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Device disable failed, already disabled"); + } + return; +} + + +/* +** Verify command packet length matches expected +*/ +int32 GENERIC_STAR_TRACKER_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length) +{ + int32 status = OS_SUCCESS; + CFE_SB_MsgId_t msg_id = CFE_SB_INVALID_MSG_ID; + CFE_MSG_FcnCode_t cmd_code = 0; + size_t actual_length = 0; + + CFE_MSG_GetSize(msg, &actual_length); + if (expected_length == actual_length) + { + /* Increment the command counter upon receipt of an invalid command */ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandCount++; + } + else + { + CFE_MSG_GetMsgId(msg, &msg_id); + CFE_MSG_GetFcnCode(msg, &cmd_code); + + CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_LEN_ERR_EID, CFE_EVS_EventType_ERROR, + "Invalid msg length: ID = 0x%X, CC = %d, Len = %d, Expected = %d", + CFE_SB_MsgIdToValue(msg_id), cmd_code, actual_length, expected_length); + + status = OS_ERROR; + + /* Increment the command error counter upon receipt of an invalid command */ + GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; + } + return status; +} diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h new file mode 100644 index 00000000..f28ac4ee --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h @@ -0,0 +1,100 @@ +/******************************************************************************* +** File: generic_star_tracker_app.h +** +** Purpose: +** This is the main header file for the GENERIC_STAR_TRACKER application. +** +*******************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_APP_H_ +#define _GENERIC_STAR_TRACKER_APP_H_ + +/* +** Include Files +*/ +#include "cfe.h" +#include "generic_star_tracker_device.h" +#include "generic_star_tracker_events.h" +#include "generic_star_tracker_platform_cfg.h" +#include "generic_star_tracker_perfids.h" +#include "generic_star_tracker_msg.h" +#include "generic_star_tracker_msgids.h" +#include "generic_star_tracker_version.h" +#include "hwlib.h" + + +/* +** Specified pipe depth - how many messages will be queued in the pipe +*/ +#define GENERIC_STAR_TRACKER_PIPE_DEPTH 32 + + +/* +** Enabled and Disabled Definitions +*/ +#define GENERIC_STAR_TRACKER_DEVICE_DISABLED 0 +#define GENERIC_STAR_TRACKER_DEVICE_ENABLED 1 + + +/* +** GENERIC_STAR_TRACKER global data structure +** The cFE convention is to put all global app data in a single struct. +** This struct is defined in the `generic_star_tracker_app.h` file with one global instance +** in the `.c` file. +*/ +typedef struct +{ + /* + ** Housekeeping telemetry packet + ** Each app defines its own packet which contains its OWN telemetry + */ + GENERIC_STAR_TRACKER_Hk_tlm_t HkTelemetryPkt; /* GENERIC_STAR_TRACKER Housekeeping Telemetry Packet */ + + /* + ** Operational data - not reported in housekeeping + */ + CFE_MSG_Message_t * MsgPtr; /* Pointer to msg received on software bus */ + CFE_SB_PipeId_t CmdPipe; /* Pipe Id for HK command pipe */ + uint32 RunStatus; /* App run status for controlling the application state */ + + /* + ** Device data + ** TODO: Make specific to your application + */ + GENERIC_STAR_TRACKER_Device_tlm_t DevicePkt; /* Device specific data packet */ + + /* + ** Device protocol + ** TODO: Make specific to your application + */ + uart_info_t Generic_star_trackerUart; /* Hardware protocol definition */ + +} GENERIC_STAR_TRACKER_AppData_t; + + +/* +** Exported Data +** Extern the global struct in the header for the Unit Test Framework (UTF). +*/ +extern GENERIC_STAR_TRACKER_AppData_t GENERIC_STAR_TRACKER_AppData; /* GENERIC_STAR_TRACKER App Data */ + + +/* +** +** Local function prototypes. +** +** Note: Except for the entry point (GENERIC_STAR_TRACKER_AppMain), these +** functions are not called from any other source module. +*/ +void ST_AppMain(void); +int32 GENERIC_STAR_TRACKER_AppInit(void); +void GENERIC_STAR_TRACKER_ProcessCommandPacket(void); +void GENERIC_STAR_TRACKER_ProcessGroundCommand(void); +void GENERIC_STAR_TRACKER_ProcessTelemetryRequest(void); +void GENERIC_STAR_TRACKER_ReportHousekeeping(void); +void GENERIC_STAR_TRACKER_ReportDeviceTelemetry(void); +void GENERIC_STAR_TRACKER_ResetCounters(void); +void GENERIC_STAR_TRACKER_Enable(void); +void GENERIC_STAR_TRACKER_Disable(void); +int32 GENERIC_STAR_TRACKER_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length); + +#endif /* _GENERIC_STAR_TRACKER_APP_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c new file mode 100644 index 00000000..8069b255 --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c @@ -0,0 +1,274 @@ +/******************************************************************************* +** File: generic_star_tracker_device.c +** +** Purpose: +** This file contains the source code for the GENERIC_STAR_TRACKER device. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include "generic_star_tracker_device.h" + + +/* +** Generic read data from device +*/ +int32_t GENERIC_STAR_TRACKER_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length) +{ + int32_t status = OS_SUCCESS; + int32_t bytes = 0; + int32_t bytes_available = 0; + uint8_t ms_timeout_counter = 0; + + /* Wait until all data received or timeout occurs */ + bytes_available = uart_bytes_available(device); + while((bytes_available < data_length) && (ms_timeout_counter < GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT)) + { + ms_timeout_counter++; + OS_TaskDelay(1); + bytes_available = uart_bytes_available(device); + } + + if (ms_timeout_counter < GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT) + { + /* Limit bytes available */ + if (bytes_available > data_length) + { + bytes_available = data_length; + } + + /* Read data */ + bytes = uart_read_port(device, read_data, bytes_available); + if (bytes != bytes_available) + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_ReadData: Bytes read != to requested! \n"); + #endif + status = OS_ERROR; + } /* uart_read */ + } + else + { + status = OS_ERROR; + } /* ms_timeout_counter */ + + return status; +} + + +/* +** Generic command to device +** Note that confirming the echoed response is specific to this implementation +*/ +int32_t GENERIC_STAR_TRACKER_CommandDevice(uart_info_t* device, uint8_t cmd_code, uint32_t payload) +{ + int32_t status = OS_SUCCESS; + int32_t bytes = 0; + uint8_t write_data[GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE]; + uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE]; + + /* Prepare command */ + write_data[0] = GENERIC_STAR_TRACKER_DEVICE_HDR_0; + write_data[1] = GENERIC_STAR_TRACKER_DEVICE_HDR_1; + write_data[2] = cmd_code; + write_data[3] = payload >> 24; + write_data[4] = payload >> 16; + write_data[5] = payload >> 8; + write_data[6] = payload; + write_data[7] = GENERIC_STAR_TRACKER_DEVICE_TRAILER_0; + write_data[8] = GENERIC_STAR_TRACKER_DEVICE_TRAILER_1; + + /* Flush any prior data */ + status = uart_flush(device); + if (status == UART_SUCCESS) + { + /* Write data */ + bytes = uart_write_port(device, write_data, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_CommandDevice[%d] = ", bytes); + for (uint32_t i = 0; i < GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE; i++) + { + OS_printf("%02x", write_data[i]); + } + OS_printf("\n"); + #endif + if (bytes == GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE) + { + status = GENERIC_STAR_TRACKER_ReadData(device, read_data, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); + if (status == OS_SUCCESS) + { + /* Confirm echoed response */ + bytes = 0; + while ((bytes < (int32_t) GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE) && (status == OS_SUCCESS)) + { + if (read_data[bytes] != write_data[bytes]) + { + status = OS_ERROR; + } + bytes++; + } + } /* GENERIC_STAR_TRACKER_ReadData */ + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf("GENERIC_STAR_TRACKER_CommandDevice - GENERIC_STAR_TRACKER_ReadData returned %d \n", status); + #endif + } + } + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf("GENERIC_STAR_TRACKER_CommandDevice - uart_write_port returned %d, expected %d \n", bytes, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); + #endif + } /* uart_write */ + } /* uart_flush*/ + return status; +} + + +/* +** Request housekeeping command +*/ +int32_t GENERIC_STAR_TRACKER_RequestHK(uart_info_t* device, GENERIC_STAR_TRACKER_Device_HK_tlm_t* data) +{ + int32_t status = OS_SUCCESS; + uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_HK_SIZE]; + + /* Command device to send HK */ + status = GENERIC_STAR_TRACKER_CommandDevice(device, GENERIC_STAR_TRACKER_DEVICE_REQ_HK_CMD, 0); + if (status == OS_SUCCESS) + { + /* Read HK data */ + status = GENERIC_STAR_TRACKER_ReadData(device, read_data, sizeof(read_data)); + if (status == OS_SUCCESS) + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestHK = "); + for (uint32_t i = 0; i < sizeof(read_data); i++) + { + OS_printf("%02x", read_data[i]); + } + OS_printf("\n"); + #endif + + /* Verify data header and trailer */ + if ((read_data[0] == GENERIC_STAR_TRACKER_DEVICE_HDR_0) && + (read_data[1] == GENERIC_STAR_TRACKER_DEVICE_HDR_1) && + (read_data[14] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_0) && + (read_data[15] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_1) ) + { + data->DeviceCounter = read_data[2] << 24; + data->DeviceCounter |= read_data[3] << 16; + data->DeviceCounter |= read_data[4] << 8; + data->DeviceCounter |= read_data[5]; + + data->DeviceConfig = read_data[6] << 24; + data->DeviceConfig |= read_data[7] << 16; + data->DeviceConfig |= read_data[8] << 8; + data->DeviceConfig |= read_data[9]; + + data->DeviceStatus = read_data[10] << 24; + data->DeviceStatus |= read_data[11] << 16; + data->DeviceStatus |= read_data[12] << 8; + data->DeviceStatus |= read_data[13]; + + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); + OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); + OS_printf(" Config = 0x%08x \n", data->DeviceConfig); + OS_printf(" Status = 0x%08x \n", data->DeviceStatus); + OS_printf(" Trailer = 0x%02x%02x \n", read_data[14], read_data[15]); + #endif + } + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestHK: GENERIC_STAR_TRACKER_ReadData reported error %d \n", status); + #endif + status = OS_ERROR; + } + } /* GENERIC_STAR_TRACKER_ReadData */ + } + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestHK: GENERIC_STAR_TRACKER_CommandDevice reported error %d \n", status); + #endif + } + return status; +} + + +/* +** Request data command +*/ +int32_t GENERIC_STAR_TRACKER_RequestData(uart_info_t* device, GENERIC_STAR_TRACKER_Device_Data_tlm_t* data) +{ + int32_t status = OS_SUCCESS; + uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE]; + + /* Command device to send HK */ + status = GENERIC_STAR_TRACKER_CommandDevice(device, GENERIC_STAR_TRACKER_DEVICE_REQ_DATA_CMD, 0); + if (status == OS_SUCCESS) + { + /* Read HK data */ + status = GENERIC_STAR_TRACKER_ReadData(device, read_data, sizeof(read_data)); + if (status == OS_SUCCESS) + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestData = "); + for (uint32_t i = 0; i < sizeof(read_data); i++) + { + OS_printf("%02x", read_data[i]); + } + OS_printf("\n"); + #endif + + /* Verify data header and trailer */ + if ((read_data[0] == GENERIC_STAR_TRACKER_DEVICE_HDR_0) && + (read_data[1] == GENERIC_STAR_TRACKER_DEVICE_HDR_1) && + (read_data[12] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_0) && + (read_data[13] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_1) ) + { + data->DeviceCounter = read_data[2] << 24; + data->DeviceCounter |= read_data[3] << 16; + data->DeviceCounter |= read_data[4] << 8; + data->DeviceCounter |= read_data[5]; + + data->DeviceDataX = read_data[6] << 8; + data->DeviceDataX |= read_data[7]; + + data->DeviceDataY = read_data[8] << 8; + data->DeviceDataY |= read_data[9]; + + data->DeviceDataZ = read_data[10] << 8; + data->DeviceDataZ |= read_data[11]; + + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); + OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); + OS_printf(" Data X = 0x%04x, %d \n", data->DeviceDataX, data->DeviceDataX); + OS_printf(" Data Y = 0x%04x, %d \n", data->DeviceDataY, data->DeviceDataY); + OS_printf(" Data Z = 0x%04x, %d \n", data->DeviceDataZ, data->DeviceDataZ); + OS_printf(" Trailer = 0x%02x%02x \n", read_data[12], read_data[13]); + #endif + } + } + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestData: Invalid data read! \n"); + #endif + status = OS_ERROR; + } /* GENERIC_STAR_TRACKER_ReadData */ + } + else + { + #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG + OS_printf(" GENERIC_STAR_TRACKER_RequestData: GENERIC_STAR_TRACKER_CommandDevice reported error %d \n", status); + #endif + } + return status; +} diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h new file mode 100644 index 00000000..2f147e2a --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h @@ -0,0 +1,77 @@ +/******************************************************************************* +** File: generic_star_tracker_device.h +** +** Purpose: +** This is the header file for the GENERIC_STAR_TRACKER device. +** +*******************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_DEVICE_H_ +#define _GENERIC_STAR_TRACKER_DEVICE_H_ + +/* +** Required header files. +*/ +#include "device_cfg.h" +#include "hwlib.h" +#include "generic_star_tracker_platform_cfg.h" + + +/* +** Type definitions +** TODO: Make specific to your application +*/ +#define GENERIC_STAR_TRACKER_DEVICE_HDR 0xDEAD +#define GENERIC_STAR_TRACKER_DEVICE_HDR_0 0xDE +#define GENERIC_STAR_TRACKER_DEVICE_HDR_1 0xAD + +#define GENERIC_STAR_TRACKER_DEVICE_NOOP_CMD 0x00 +#define GENERIC_STAR_TRACKER_DEVICE_REQ_HK_CMD 0x01 +#define GENERIC_STAR_TRACKER_DEVICE_REQ_DATA_CMD 0x02 +#define GENERIC_STAR_TRACKER_DEVICE_CFG_CMD 0x03 + +#define GENERIC_STAR_TRACKER_DEVICE_TRAILER 0xBEEF +#define GENERIC_STAR_TRACKER_DEVICE_TRAILER_0 0xBE +#define GENERIC_STAR_TRACKER_DEVICE_TRAILER_1 0xEF + +#define GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN 4 +#define GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE 9 + +/* +** GENERIC_STAR_TRACKER device housekeeping telemetry definition +*/ +typedef struct +{ + uint32_t DeviceCounter; + uint32_t DeviceConfig; + uint32_t DeviceStatus; + +} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_HK_tlm_t; +#define GENERIC_STAR_TRACKER_DEVICE_HK_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_HK_tlm_t ) +#define GENERIC_STAR_TRACKER_DEVICE_HK_SIZE GENERIC_STAR_TRACKER_DEVICE_HK_LNGTH + GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN + + +/* +** GENERIC_STAR_TRACKER device data telemetry definition +*/ +typedef struct +{ + uint32_t DeviceCounter; + uint16_t DeviceDataX; + uint16_t DeviceDataY; + uint16_t DeviceDataZ; + +} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_Data_tlm_t; +#define GENERIC_STAR_TRACKER_DEVICE_DATA_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_Data_tlm_t ) +#define GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE GENERIC_STAR_TRACKER_DEVICE_DATA_LNGTH + GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN + + +/* +** Prototypes +*/ +int32_t GENERIC_STAR_TRACKER_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length); +int32_t GENERIC_STAR_TRACKER_CommandDevice(uart_info_t* device, uint8_t cmd, uint32_t payload); +int32_t GENERIC_STAR_TRACKER_RequestHK(uart_info_t* device, GENERIC_STAR_TRACKER_Device_HK_tlm_t* data); +int32_t GENERIC_STAR_TRACKER_RequestData(uart_info_t* device, GENERIC_STAR_TRACKER_Device_Data_tlm_t* data); + + +#endif /* _GENERIC_STAR_TRACKER_DEVICE_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h new file mode 100644 index 00000000..d51cca05 --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h @@ -0,0 +1,47 @@ +/************************************************************************ +** File: +** generic_star_tracker_events.h +** +** Purpose: +** Define GENERIC_STAR_TRACKER application event IDs +** +*************************************************************************/ + +#ifndef _GENERIC_STAR_TRACKER_EVENTS_H_ +#define _GENERIC_STAR_TRACKER_EVENTS_H_ + +/* Standard app event IDs */ +#define GENERIC_STAR_TRACKER_RESERVED_EID 0 +#define GENERIC_STAR_TRACKER_STARTUP_INF_EID 1 +#define GENERIC_STAR_TRACKER_LEN_ERR_EID 2 +#define GENERIC_STAR_TRACKER_PIPE_ERR_EID 3 +#define GENERIC_STAR_TRACKER_SUB_CMD_ERR_EID 4 +#define GENERIC_STAR_TRACKER_SUB_REQ_HK_ERR_EID 5 +#define GENERIC_STAR_TRACKER_PROCESS_CMD_ERR_EID 6 + +/* Standard command event IDs */ +#define GENERIC_STAR_TRACKER_CMD_ERR_EID 10 +#define GENERIC_STAR_TRACKER_CMD_NOOP_INF_EID 11 +#define GENERIC_STAR_TRACKER_CMD_RESET_INF_EID 12 +#define GENERIC_STAR_TRACKER_CMD_ENABLE_INF_EID 13 +#define GENERIC_STAR_TRACKER_ENABLE_INF_EID 14 +#define GENERIC_STAR_TRACKER_ENABLE_ERR_EID 15 +#define GENERIC_STAR_TRACKER_CMD_DISABLE_INF_EID 16 +#define GENERIC_STAR_TRACKER_DISABLE_INF_EID 17 +#define GENERIC_STAR_TRACKER_DISABLE_ERR_EID 18 + +/* Device specific command event IDs */ +#define GENERIC_STAR_TRACKER_CMD_CONFIG_INF_EID 20 + +/* Standard telemetry event IDs */ +#define GENERIC_STAR_TRACKER_DEVICE_TLM_ERR_EID 30 +#define GENERIC_STAR_TRACKER_REQ_HK_ERR_EID 31 + +/* Device specific telemetry event IDs */ +#define GENERIC_STAR_TRACKER_REQ_DATA_ERR_EID 32 + +/* Hardware protocol event IDs */ +#define GENERIC_STAR_TRACKER_UART_INIT_ERR_EID 40 +#define GENERIC_STAR_TRACKER_UART_CLOSE_ERR_EID 41 + +#endif /* _GENERIC_STAR_TRACKER_EVENTS_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h new file mode 100644 index 00000000..89708fdd --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h @@ -0,0 +1,89 @@ +/******************************************************************************* +** File: +** generic_star_tracker_msg.h +** +** Purpose: +** Define GENERIC_STAR_TRACKER application commands and telemetry messages +** +*******************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_MSG_H_ +#define _GENERIC_STAR_TRACKER_MSG_H_ + +#include "cfe.h" +#include "generic_star_tracker_device.h" + + +/* +** Ground Command Codes +** TODO: Add additional commands required by the specific component +*/ +#define GENERIC_STAR_TRACKER_NOOP_CC 0 +#define GENERIC_STAR_TRACKER_RESET_COUNTERS_CC 1 +#define GENERIC_STAR_TRACKER_ENABLE_CC 2 +#define GENERIC_STAR_TRACKER_DISABLE_CC 3 +#define GENERIC_STAR_TRACKER_CONFIG_CC 4 + + +/* +** Telemetry Request Command Codes +** TODO: Add additional commands required by the specific component +*/ +#define GENERIC_STAR_TRACKER_REQ_HK_TLM 0 +#define GENERIC_STAR_TRACKER_REQ_DATA_TLM 1 + + +/* +** Generic "no arguments" command type definition +*/ +typedef struct +{ + /* Every command requires a header used to identify it */ + CFE_MSG_CommandHeader_t CmdHeader; + +} GENERIC_STAR_TRACKER_NoArgs_cmd_t; + + +/* +** GENERIC_STAR_TRACKER write configuration command +*/ +typedef struct +{ + CFE_MSG_CommandHeader_t CmdHeader; + uint32 DeviceCfg; + +} GENERIC_STAR_TRACKER_Config_cmd_t; + + +/* +** GENERIC_STAR_TRACKER device telemetry definition +*/ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TlmHeader; + GENERIC_STAR_TRACKER_Device_Data_tlm_t Generic_star_tracker; + +} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_tlm_t; +#define GENERIC_STAR_TRACKER_DEVICE_TLM_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_tlm_t ) + + +/* +** GENERIC_STAR_TRACKER housekeeping type definition +*/ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TlmHeader; + uint8 CommandErrorCount; + uint8 CommandCount; + uint8 DeviceErrorCount; + uint8 DeviceCount; + + /* + ** TODO: Edit and add specific telemetry values to this struct + */ + uint8 DeviceEnabled; + GENERIC_STAR_TRACKER_Device_HK_tlm_t DeviceHK; + +} __attribute__((packed)) GENERIC_STAR_TRACKER_Hk_tlm_t; +#define GENERIC_STAR_TRACKER_HK_TLM_LNGTH sizeof ( GENERIC_STAR_TRACKER_Hk_tlm_t ) + +#endif /* _GENERIC_STAR_TRACKER_MSG_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h new file mode 100644 index 00000000..ec3ab848 --- /dev/null +++ b/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h @@ -0,0 +1,19 @@ +/************************************************************************ +** File: +** $Id: generic_star_tracker_app_version.h $ +** +** Purpose: +** The Generic_star_tracker Application header file containing version number +** +*************************************************************************/ + +/* The Generic_star_tracker Application header file containing version number */ +#ifndef _GENERIC_STAR_TRACKER_VERSION_H_ +#define _GENERIC_STAR_TRACKER_VERSION_H_ + +#define GENERIC_STAR_TRACKER_MAJOR_VERSION 1 +#define GENERIC_STAR_TRACKER_MINOR_VERSION 0 +#define GENERIC_STAR_TRACKER_REVISION 0 +#define GENERIC_STAR_TRACKER_MISSION_REV 0 + +#endif diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt new file mode 100644 index 00000000..856a1627 --- /dev/null +++ b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt @@ -0,0 +1,49 @@ +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_NOOP_CC BIG_ENDIAN "Generic_star_tracker NOOP Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_RST_COUNTERS_CC BIG_ENDIAN "Generic_star_tracker Reset Counters Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_ENABLE_CC BIG_ENDIAN "Generic_star_tracker Enable Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 2 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_DISABLE_CC BIG_ENDIAN "Generic_star_tracker Disable Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 3 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_CONFIG_CC BIG_ENDIAN "Generic_star_tracker Configuration Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 5 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 4 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + APPEND_PARAMETER DEVICE_CONFIG 32 UINT MIN_UINT32 MAX_UINT32 0 "Device Configuration" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_REQ_HK BIG_ENDIAN "Generic_star_tracker Request HK Packet Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1936 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 0 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" + +COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_REQ_DATA BIG_ENDIAN "Generic_star_tracker Request Data Packet Command" + APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1936 "CCSDS Packet Identification" + APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" + APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 0 "CCSDS Packet Data Length" + APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" + APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt new file mode 100644 index 00000000..6f96b700 --- /dev/null +++ b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt @@ -0,0 +1,44 @@ +TELEMETRY GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_HK_TLM LITTLE_ENDIAN "GENERIC_STAR_TRACKER_Hk_tlm_t" + APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x0935 "CCSDS Packet Identification" BIG_ENDIAN + APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN + APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN + APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" + APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" + APPEND_ITEM CCSDS_SPARE 32 UINT "" + APPEND_ITEM CMD_ERR_COUNT 8 UINT "Command Error Count" + APPEND_ITEM CMD_COUNT 8 UINT "Command Count" + APPEND_ITEM DEVICE_ERR_COUNT 8 UINT "Device Command Error Count" + APPEND_ITEM DEVICE_COUNT 8 UINT "Device Command Count" + APPEND_ITEM DEVICE_ENABLED 8 UINT "Device Enable Status" + STATE DISABLED 0 + STATE ENABLED 1 + # GENERIC_STAR_TRACKER_Device_HK_tlm_t + APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" + APPEND_ITEM DEVICE_CONFIG 32 UINT "Reported Device Configuration" + APPEND_ITEM DEVICE_STATUS 32 UINT "Reported Device Status" + +TELEMETRY GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_DATA_TLM LITTLE_ENDIAN "GENERIC_STAR_TRACKER_Device_tlm_t" + APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x0936 "CCSDS Packet Identification" BIG_ENDIAN + APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN + APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN + APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" + APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" + APPEND_ITEM CCSDS_SPARE 32 UINT "" + # GENERIC_STAR_TRACKER_Device_Data_tlm_t + APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" + APPEND_ITEM RAW_GENERIC_STAR_TRACKER_X 16 UINT "Raw generic_star_tracker data x component (1-65535)" + APPEND_ITEM RAW_GENERIC_STAR_TRACKER_Y 16 UINT "Raw generic_star_tracker data y component (1-65535)" + APPEND_ITEM RAW_GENERIC_STAR_TRACKER_Z 16 UINT "Raw generic_star_tracker data z component (1-65535)" +# APPEND_ITEM PAD 16 UINT "Because the packed struct it came from has a stride address of 32 and cFS does not serialize" + APPEND_ITEM GENERIC_STAR_TRACKER_X 0 DERIVED "Generic_star_tracker data unit vector x component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_GENERIC_STAR_TRACKER_X") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END + APPEND_ITEM GENERIC_STAR_TRACKER_Y 0 DERIVED "Generic_star_tracker data unit vector y component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_GENERIC_STAR_TRACKER_Y") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END + APPEND_ITEM GENERIC_STAR_TRACKER_Z 0 DERIVED "Generic_star_tracker data unit vector z component (-1.0 to 1.0)" + GENERIC_READ_CONVERSION_START FLOAT 32 + (packet.read("RAW_GENERIC_STAR_TRACKER_Z") - 32768.0)/32767.0 + GENERIC_READ_CONVERSION_END diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt new file mode 100644 index 00000000..f942b7ed --- /dev/null +++ b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt @@ -0,0 +1,10 @@ +# Ignored Parameters +# IGNORE_PARAMETER parameter_name + +# CCSDS +IGNORE_PARAMETER CCSDS_STREAMID +IGNORE_PARAMETER CCSDS_SEQUENCE +IGNORE_PARAMETER CCSDS_LENGTH +IGNORE_PARAMETER CCSDS_SPARE +IGNORE_PARAMETER CCSDS_FC +IGNORE_PARAMETER CCSDS_CHECKSUM diff --git a/components/generic_star_tracker/sim/CMakeLists.txt b/components/generic_star_tracker/sim/CMakeLists.txt new file mode 100644 index 00000000..86771748 --- /dev/null +++ b/components/generic_star_tracker/sim/CMakeLists.txt @@ -0,0 +1,31 @@ +project(generic_star_tracker_sim) + +find_package(ITC_Common REQUIRED QUIET COMPONENTS itc_logger) +find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart) + +include_directories(inc + ${sim_common_SOURCE_DIR}/inc + ${ITC_Common_INCLUDE_DIRS} + ${NOSENGINE_INCLUDE_DIRS}) + +set(generic_star_tracker_sim_src + src/generic_star_tracker_hardware_model.cpp + src/generic_star_tracker_42_data_provider.cpp + src/generic_star_tracker_data_provider.cpp + src/generic_star_tracker_data_point.cpp +) + +# For Code::Blocks and other IDEs +file(GLOB generic_star_tracker_sim_inc inc/*.hpp) + +set(generic_star_tracker_sim_libs + sim_common + ${ITC_Common_LIBRARIES} + ${NOSENGINE_LIBRARIES} +) + +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib") # Pick up .so in install directory + +add_library(generic_star_tracker_sim SHARED ${generic_star_tracker_sim_src} ${generic_star_tracker_sim_inc}) +target_link_libraries(generic_star_tracker_sim ${generic_star_tracker_sim_libs}) +install(TARGETS generic_star_tracker_sim LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp new file mode 100644 index 00000000..1351448b --- /dev/null +++ b/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp @@ -0,0 +1,30 @@ +#ifndef NOS3_GENERIC_STAR_TRACKER42DATAPROVIDER_HPP +#define NOS3_GENERIC_STAR_TRACKER42DATAPROVIDER_HPP + +#include +#include +#include +#include + +namespace Nos3 +{ + /* Standard for a 42 data provider */ + class Generic_star_tracker42DataProvider : public SimData42SocketProvider + { + public: + /* Constructors */ + Generic_star_tracker42DataProvider(const boost::property_tree::ptree& config); + + /* Accessors */ + boost::shared_ptr get_data_point(void) const; + + private: + /* Disallow these */ + ~Generic_star_tracker42DataProvider(void) {}; + Generic_star_tracker42DataProvider& operator=(const Generic_star_tracker42DataProvider&) {return *this;}; + + int16_t _sc; /* Which spacecraft number to parse out of 42 data */ + }; +} + +#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp new file mode 100644 index 00000000..040cdd6d --- /dev/null +++ b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp @@ -0,0 +1,46 @@ +#ifndef NOS3_GENERIC_STAR_TRACKERDATAPOINT_HPP +#define NOS3_GENERIC_STAR_TRACKERDATAPOINT_HPP + +#include +#include + +namespace Nos3 +{ + /* Standard for a data point used transfer data between a data provider and a hardware model */ + class Generic_star_trackerDataPoint : public Sim42DataPoint + { + public: + /* Constructors */ + Generic_star_trackerDataPoint(double count); + Generic_star_trackerDataPoint(int16_t spacecraft, const boost::shared_ptr dp); + + /* Accessors */ + /* Provide the hardware model a way to get the specific data out of the data point */ + std::string to_string(void) const; + double get_generic_star_tracker_data_x(void) const {parse_data_point(); return _generic_star_tracker_data[0];} + double get_generic_star_tracker_data_y(void) const {parse_data_point(); return _generic_star_tracker_data[1];} + double get_generic_star_tracker_data_z(void) const {parse_data_point(); return _generic_star_tracker_data[2];} + bool is_generic_star_tracker_data_valid(void) const {parse_data_point(); return _generic_star_tracker_data_is_valid;} + + private: + /* Disallow these */ + Generic_star_trackerDataPoint(void) {}; + Generic_star_trackerDataPoint(const Generic_star_trackerDataPoint& sdp) : Sim42DataPoint(sdp) {}; + ~Generic_star_trackerDataPoint(void) {}; + + // Private mutators + inline void parse_data_point(void) const {if (_not_parsed) do_parsing();} + void do_parsing(void) const; + + mutable Sim42DataPoint _dp; + int16_t _sc; + // mutable below so parsing can be on demand: + mutable bool _not_parsed; + /* Specific data you need to get from the data provider to the hardware model */ + /* You only get to this data through the accessors above */ + mutable bool _generic_star_tracker_data_is_valid; + mutable double _generic_star_tracker_data[3]; + }; +} + +#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp new file mode 100644 index 00000000..7ec09e95 --- /dev/null +++ b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp @@ -0,0 +1,29 @@ +#ifndef NOS3_GENERIC_STAR_TRACKERDATAPROVIDER_HPP +#define NOS3_GENERIC_STAR_TRACKERDATAPROVIDER_HPP + +#include +#include +#include +#include + +namespace Nos3 +{ + class Generic_star_trackerDataProvider : public SimIDataProvider + { + public: + /* Constructors */ + Generic_star_trackerDataProvider(const boost::property_tree::ptree& config); + + /* Accessors */ + boost::shared_ptr get_data_point(void) const; + + private: + /* Disallow these */ + ~Generic_star_trackerDataProvider(void) {}; + Generic_star_trackerDataProvider& operator=(const Generic_star_trackerDataProvider&) {return *this;}; + + mutable double _request_count; + }; +} + +#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp new file mode 100644 index 00000000..64a4ec63 --- /dev/null +++ b/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp @@ -0,0 +1,61 @@ +#ifndef NOS3_GENERIC_STAR_TRACKERHARDWAREMODEL_HPP +#define NOS3_GENERIC_STAR_TRACKERHARDWAREMODEL_HPP + +/* +** Includes +*/ +#include + +#include +#include + +#include +#include /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ + +#include +#include +#include + + +/* +** Defines +*/ +#define GENERIC_STAR_TRACKER_SIM_SUCCESS 0 +#define GENERIC_STAR_TRACKER_SIM_ERROR 1 + + +/* +** Namespace +*/ +namespace Nos3 +{ + /* Standard for a hardware model */ + class Generic_star_trackerHardwareModel : public SimIHardwareModel + { + public: + /* Constructor and destructor */ + Generic_star_trackerHardwareModel(const boost::property_tree::ptree& config); + ~Generic_star_trackerHardwareModel(void); + + private: + /* Private helper methods */ + void create_generic_star_tracker_hk(std::vector& out_data); + void create_generic_star_tracker_data(std::vector& out_data); + void uart_read_callback(const uint8_t *buf, size_t len); /* Handle data the hardware receives from its protocol bus */ + void command_callback(NosEngine::Common::Message msg); /* Handle backdoor commands and time tick to the simulator */ + + /* Private data members */ + std::unique_ptr _uart_connection; /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ + std::unique_ptr _time_bus; /* Standard */ + + SimIDataProvider* _generic_star_tracker_dp; /* Only needed if the sim has a data provider */ + + /* Internal state data */ + std::uint8_t _enabled; + std::uint32_t _count; + std::uint32_t _config; + std::uint32_t _status; + }; +} + +#endif diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp new file mode 100644 index 00000000..d303b106 --- /dev/null +++ b/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp @@ -0,0 +1,32 @@ +#include + +namespace Nos3 +{ + REGISTER_DATA_PROVIDER(Generic_star_tracker42DataProvider,"GENERIC_STAR_TRACKER_42_PROVIDER"); + + extern ItcLogger::Logger *sim_logger; + + Generic_star_tracker42DataProvider::Generic_star_tracker42DataProvider(const boost::property_tree::ptree& config) : SimData42SocketProvider(config) + { + sim_logger->trace("Generic_star_tracker42DataProvider::Generic_star_tracker42DataProvider: Constructor executed"); + + connect_reader_thread_as_42_socket_client( + config.get("simulator.hardware-model.data-provider.hostname", "localhost"), + config.get("simulator.hardware-model.data-provider.port", 4242) ); + + _sc = config.get("simulator.hardware-model.data-provider.spacecraft", 0); + } + + boost::shared_ptr Generic_star_tracker42DataProvider::get_data_point(void) const + { + sim_logger->trace("Generic_star_tracker42DataProvider::get_data_point: Executed"); + + /* Get the 42 data */ + const boost::shared_ptr dp42 = boost::dynamic_pointer_cast(SimData42SocketProvider::get_data_point()); + + /* Prepare the specific data */ + SimIDataPoint *dp = new Generic_star_trackerDataPoint(_sc, dp42); + + return boost::shared_ptr(dp); + } +} diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp new file mode 100644 index 00000000..fbca9a77 --- /dev/null +++ b/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp @@ -0,0 +1,81 @@ +#include +#include + +namespace Nos3 +{ + extern ItcLogger::Logger *sim_logger; + + Generic_star_trackerDataPoint::Generic_star_trackerDataPoint(double count) + { + sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Defined Constructor executed"); + + /* Do calculations based on provided data */ + _generic_star_tracker_data_is_valid = true; + _generic_star_tracker_data[0] = count * 0.001; + _generic_star_tracker_data[1] = count * 0.002; + _generic_star_tracker_data[2] = count * 0.003; + } + + Generic_star_trackerDataPoint::Generic_star_trackerDataPoint(int16_t spacecraft, const boost::shared_ptr dp) : _dp(*dp), _sc(spacecraft) + { + sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: 42 Constructor executed"); + + /* Initialize data */ + _generic_star_tracker_data_is_valid = false; + _generic_star_tracker_data[0] = _generic_star_tracker_data[1] = _generic_star_tracker_data[2] = 0.0; + } + + void Generic_star_trackerDataPoint::do_parsing(void) const + { + try { + /* + ** Declare 42 telemetry string prefix + ** 42 variables defined in `42/Include/42types.h` + ** 42 data stream defined in `42/Source/IPC/SimWriteToSocket.c` + */ + std::string key; + key.append("SC[").append(std::to_string(_sc)).append("].svb"); // SC[N].svb + + /* Parse 42 telemetry */ + std::string values = _dp.get_value_for_key(key); + + std::vector data; + parse_double_vector(values, data); + + _generic_star_tracker_data[0] = data[0]; + _generic_star_tracker_data[1] = data[1]; + _generic_star_tracker_data[2] = data[2]; + + /* Mark data as valid */ + _generic_star_tracker_data_is_valid = true; + + _not_parsed = false; + + /* Debug print */ + sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Parsed svb = %f %f %f", _generic_star_tracker_data[0], _generic_star_tracker_data[1], _generic_star_tracker_data[2]); + } catch (const std::exception &e) { + sim_logger->error("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Error parsing svb. Error=%s", e.what()); + } + } + + /* Used for printing a representation of the data point */ + std::string Generic_star_trackerDataPoint::to_string(void) const + { + sim_logger->trace("Generic_star_trackerDataPoint::to_string: Executed"); + + std::stringstream ss; + + ss << std::fixed << std::setfill(' '); + ss << "Generic_star_tracker Data Point: Valid: "; + ss << (_generic_star_tracker_data_is_valid ? "Valid" : "INVALID"); + ss << std::setprecision(std::numeric_limits::digits10); /* Full double precision */ + ss << " Generic_star_tracker Data: " + << _generic_star_tracker_data[0] + << " " + << _generic_star_tracker_data[1] + << " " + << _generic_star_tracker_data[2]; + + return ss.str(); + } +} /* namespace Nos3 */ diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp new file mode 100644 index 00000000..280da146 --- /dev/null +++ b/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp @@ -0,0 +1,28 @@ +#include + +namespace Nos3 +{ + REGISTER_DATA_PROVIDER(Generic_star_trackerDataProvider,"GENERIC_STAR_TRACKER_PROVIDER"); + + extern ItcLogger::Logger *sim_logger; + + Generic_star_trackerDataProvider::Generic_star_trackerDataProvider(const boost::property_tree::ptree& config) : SimIDataProvider(config) + { + sim_logger->trace("Generic_star_trackerDataProvider::Generic_star_trackerDataProvider: Constructor executed"); + _request_count = 0; + } + + boost::shared_ptr Generic_star_trackerDataProvider::get_data_point(void) const + { + sim_logger->trace("Generic_star_trackerDataProvider::get_data_point: Executed"); + + /* Prepare the provider data */ + _request_count++; + + /* Request a data point */ + SimIDataPoint *dp = new Generic_star_trackerDataPoint(_request_count); + + /* Return the data point */ + return boost::shared_ptr(dp); + } +} diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp new file mode 100644 index 00000000..25410a23 --- /dev/null +++ b/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp @@ -0,0 +1,326 @@ +#include + +namespace Nos3 +{ + REGISTER_HARDWARE_MODEL(Generic_star_trackerHardwareModel,"GENERIC_STAR_TRACKER"); + + extern ItcLogger::Logger *sim_logger; + + Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel(const boost::property_tree::ptree& config) : SimIHardwareModel(config), + _enabled(GENERIC_STAR_TRACKER_SIM_ERROR), _count(0), _config(0), _status(0) + { + /* Get the NOS engine connection string */ + std::string connection_string = config.get("common.nos-connection-string", "tcp://127.0.0.1:12001"); + sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: NOS Engine connection string: %s.", connection_string.c_str()); + + /* Get a data provider */ + std::string dp_name = config.get("simulator.hardware-model.data-provider.type", "GENERIC_STAR_TRACKER_PROVIDER"); + _generic_star_tracker_dp = SimDataProviderFactory::Instance().Create(dp_name, config); + sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Data provider %s created.", dp_name.c_str()); + + /* Get on a protocol bus */ + /* Note: Initialized defaults in case value not found in config file */ + std::string bus_name = "usart_29"; + int node_port = 29; + if (config.get_child_optional("simulator.hardware-model.connections")) + { + /* Loop through the connections for hardware model */ + BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("simulator.hardware-model.connections")) + { + /* v.second is the child tree (v.first is the name of the child) */ + if (v.second.get("type", "").compare("usart") == 0) + { + /* Configuration found */ + bus_name = v.second.get("bus-name", bus_name); + node_port = v.second.get("node-port", node_port); + break; + } + } + } + _uart_connection.reset(new NosEngine::Uart::Uart(_hub, config.get("simulator.name", "generic_star_tracker_sim"), connection_string, bus_name)); + _uart_connection->open(node_port); + sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Now on UART bus name %s, port %d.", bus_name.c_str(), node_port); + + /* Configure protocol callback */ + _uart_connection->set_read_callback(std::bind(&Generic_star_trackerHardwareModel::uart_read_callback, this, std::placeholders::_1, std::placeholders::_2)); + + /* Get on the command bus*/ + std::string time_bus_name = "command"; + if (config.get_child_optional("hardware-model.connections")) + { + /* Loop through the connections for the hardware model */ + BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("hardware-model.connections")) + { + /* v.first is the name of the child */ + /* v.second is the child tree */ + if (v.second.get("type", "").compare("time") == 0) // + { + time_bus_name = v.second.get("bus-name", "command"); + /* Found it... don't need to go through any more items*/ + break; + } + } + } + _time_bus.reset(new NosEngine::Client::Bus(_hub, connection_string, time_bus_name)); + sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Now on time bus named %s.", time_bus_name.c_str()); + + /* Construction complete */ + sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Construction complete."); + } + + + Generic_star_trackerHardwareModel::~Generic_star_trackerHardwareModel(void) + { + /* Close the protocol bus */ + _uart_connection->close(); + + /* Clean up the data provider */ + delete _generic_star_tracker_dp; + _generic_star_tracker_dp = nullptr; + + /* The bus will clean up the time node */ + } + + + /* Automagically set up by the base class to be called */ + void Generic_star_trackerHardwareModel::command_callback(NosEngine::Common::Message msg) + { + /* Get the data out of the message */ + NosEngine::Common::DataBufferOverlay dbf(const_cast(msg.buffer)); + sim_logger->info("Generic_star_trackerHardwareModel::command_callback: Received command: %s.", dbf.data); + + /* Do something with the data */ + std::string command = dbf.data; + std::string response = "Generic_star_trackerHardwareModel::command_callback: INVALID COMMAND! (Try HELP)"; + boost::to_upper(command); + if (command.compare("HELP") == 0) + { + response = "Generic_star_trackerHardwareModel::command_callback: Valid commands are HELP, ENABLE, DISABLE, STATUS=X, or STOP"; + } + else if (command.compare(0,6,"ENABLE") == 0) + { + _enabled = GENERIC_STAR_TRACKER_SIM_SUCCESS; + response = "Generic_star_trackerHardwareModel::command_callback: Enabled\n"; + } + else if (command.compare(0,7,"DISABLE") == 0) + { + _enabled = GENERIC_STAR_TRACKER_SIM_ERROR; + _count = 0; + _config = 0; + _status = 0; + response = "Generic_star_trackerHardwareModel::command_callback: Disabled"; + } + else if (command.substr(0,7).compare("STATUS=") == 0) + { + try + { + _status = std::stod(command.substr(7)); + response = "Generic_star_trackerHardwareModel::command_callback: Status set"; + } + catch (...) + { + response = "Generic_star_trackerHardwareModel::command_callback: Status invalid"; + } + } + else if (command.compare(0,4,"STOP") == 0) + { + _keep_running = false; + response = "Generic_star_trackerHardwareModel::command_callback: Stopping"; + } + /* TODO: Add anything additional commands here */ + + /* Send a reply */ + sim_logger->info("Generic_star_trackerHardwareModel::command_callback: Sending reply: %s", response.c_str()); + _command_node->send_reply_message_async(msg, response.size(), response.c_str()); + } + + + /* Custom function to prepare the Generic_star_tracker HK telemetry */ + void Generic_star_trackerHardwareModel::create_generic_star_tracker_hk(std::vector& out_data) + { + /* Prepare data size */ + out_data.resize(16, 0x00); + + /* Streaming data header - 0xDEAD */ + out_data[0] = 0xDE; + out_data[1] = 0xAD; + + /* Sequence count */ + out_data[2] = (_count >> 24) & 0x000000FF; + out_data[3] = (_count >> 16) & 0x000000FF; + out_data[4] = (_count >> 8) & 0x000000FF; + out_data[5] = _count & 0x000000FF; + + /* Configuration */ + out_data[6] = (_config >> 24) & 0x000000FF; + out_data[7] = (_config >> 16) & 0x000000FF; + out_data[8] = (_config >> 8) & 0x000000FF; + out_data[9] = _config & 0x000000FF; + + /* Device Status */ + out_data[10] = (_status >> 24) & 0x000000FF; + out_data[11] = (_status >> 16) & 0x000000FF; + out_data[12] = (_status >> 8) & 0x000000FF; + out_data[13] = _status & 0x000000FF; + + /* Streaming data trailer - 0xBEEF */ + out_data[14] = 0xBE; + out_data[15] = 0xEF; + } + + + /* Custom function to prepare the Generic_star_tracker Data */ + void Generic_star_trackerHardwareModel::create_generic_star_tracker_data(std::vector& out_data) + { + boost::shared_ptr data_point = boost::dynamic_pointer_cast(_generic_star_tracker_dp->get_data_point()); + + /* Prepare data size */ + out_data.resize(14, 0x00); + + /* Streaming data header - 0xDEAD */ + out_data[0] = 0xDE; + out_data[1] = 0xAD; + + /* Sequence count */ + out_data[2] = (_count >> 24) & 0x000000FF; + out_data[3] = (_count >> 16) & 0x000000FF; + out_data[4] = (_count >> 8) & 0x000000FF; + out_data[5] = _count & 0x000000FF; + + /* + ** Payload + ** + ** Device is big engian (most significant byte first) + ** Assuming data is valid regardless of dynamic / environmental data + ** Floating poing numbers are extremely problematic + ** (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) + ** Most hardware transmits some type of unsigned integer (e.g. from an ADC), so that's what we've done + ** Scale each of the x, y, z (which are in the range [-1.0, 1.0]) by 32767, + ** and add 32768 so that the result fits in a uint16 + */ + double dx = data_point->get_generic_star_tracker_data_x(); + double dy = data_point->get_generic_star_tracker_data_y(); + double dz = data_point->get_generic_star_tracker_data_z(); + uint16_t x = (uint16_t)(dx*32767.0 + 32768.0); + out_data[6] = (x >> 8) & 0x00FF; + out_data[7] = x & 0x00FF; + uint16_t y = (uint16_t)(dy*32767.0 + 32768.0); + out_data[8] = (y >> 8) & 0x00FF; + out_data[9] = y & 0x00FF; + uint16_t z = (uint16_t)(dz*32767.0 + 32768.0); + out_data[10] = (z >> 8) & 0x00FF; + out_data[11] = z & 0x00FF; + + sim_logger->debug("Generic_star_trackerHardwareModel::create_generic_star_tracker_data: data_point=%f, %f, %f, converted values=%u, %u, %u.", dx, dy, dz, x, y, z); + + /* Streaming data trailer - 0xBEEF */ + out_data[12] = 0xBE; + out_data[13] = 0xEF; + } + + + /* Protocol callback */ + void Generic_star_trackerHardwareModel::uart_read_callback(const uint8_t *buf, size_t len) + { + std::vector out_data; + std::uint8_t valid = GENERIC_STAR_TRACKER_SIM_SUCCESS; + + /* Retrieve data and log in man readable format */ + std::vector in_data(buf, buf + len); + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: REQUEST %s", + SimIHardwareModel::uint8_vector_to_hex_string(in_data).c_str()); + + /* Check simulator is enabled */ + if (_enabled != GENERIC_STAR_TRACKER_SIM_SUCCESS) + { + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Generic_star_tracker sim disabled!"); + valid = GENERIC_STAR_TRACKER_SIM_ERROR; + } + else + { + /* Check if message is incorrect size */ + if (in_data.size() != 9) + { + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Invalid command size of %d received!", in_data.size()); + valid = GENERIC_STAR_TRACKER_SIM_ERROR; + } + else + { + /* Check header - 0xDEAD */ + if ((in_data[0] != 0xDE) || (in_data[1] !=0xAD)) + { + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Header incorrect!"); + valid = GENERIC_STAR_TRACKER_SIM_ERROR; + } + else + { + /* Check trailer - 0xBEEF */ + if ((in_data[7] != 0xBE) || (in_data[8] !=0xEF)) + { + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Trailer incorrect!"); + valid = GENERIC_STAR_TRACKER_SIM_ERROR; + } + else + { + /* Increment count as valid command format received */ + _count++; + } + } + } + + if (valid == GENERIC_STAR_TRACKER_SIM_SUCCESS) + { + /* Process command */ + switch (in_data[2]) + { + case 0: + /* NOOP */ + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: NOOP command received!"); + break; + + case 1: + /* Request HK */ + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Send HK command received!"); + create_generic_star_tracker_hk(out_data); + break; + + case 2: + /* Request data */ + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Send data command received!"); + create_generic_star_tracker_data(out_data); + break; + + case 3: + /* Configuration */ + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Configuration command received!"); + _config = in_data[3] << 24; + _config |= in_data[4] << 16; + _config |= in_data[5] << 8; + _config |= in_data[6]; + break; + + default: + /* Unused command code */ + valid = GENERIC_STAR_TRACKER_SIM_ERROR; + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Unused command %d received!", in_data[2]); + break; + } + } + } + + /* Increment count and echo command since format valid */ + if (valid == GENERIC_STAR_TRACKER_SIM_SUCCESS) + { + _count++; + _uart_connection->write(&in_data[0], in_data.size()); + + /* Send response if existing */ + if (out_data.size() > 0) + { + sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: REPLY %s", + SimIHardwareModel::uint8_vector_to_hex_string(out_data).c_str()); + _uart_connection->write(&out_data[0], out_data.size()); + } + } + } +} diff --git a/components/generic_star_tracker/support/CMakeLists.txt b/components/generic_star_tracker/support/CMakeLists.txt new file mode 100644 index 00000000..4cdc88d0 --- /dev/null +++ b/components/generic_star_tracker/support/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 2.6.4) + +project (generic_star_tracker_checkout) + +if (NOT DEFINED TGTNAME) + message(FATAL_ERROR "TGTNAME must be defined on the cmake command line (e.g. \"-DTGTNAME=cpu1\")") +endif() + +if(${TGTNAME} STREQUAL cpu1) + SET(CMAKE_C_FLAGS_INIT "-m32" CACHE STRING "C Flags required by platform") + SET(CMAKE_C_FLAGS "-m32" CACHE STRING "C Flags required by platform") +endif() + +include(../../ComponentSettings.cmake) + +if(${TGTNAME} STREQUAL cpu1) + find_path(_ITC_CMAKE_MODULES_ + NAMES FindITC_Common.cmake + PATHS ${ITC_CMAKE_MODULES} + ${ITC_DEV_ROOT}/cmake/modules + $ENV{ITC_DEV_ROOT}/cmake/modules + /usr/local/cmake/modules + /usr/cmake/modules) + if(NOT _ITC_CMAKE_MODULES_) + message(WARNING "Unable to find ITC CMake Modules") + endif() + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${_ITC_CMAKE_MODULES_}) + + find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart can i2c spi) +endif() + +include_directories("./") +include_directories("../fsw/platform_inc") +include_directories("../fsw/src") +include_directories("../../../fsw/apps/hwlib/fsw/public_inc") + +set(generic_star_tracker_checkout_src + generic_star_tracker_checkout.c + ../fsw/src/generic_star_tracker_device.c +) + +if(${TGTNAME} STREQUAL cpu1) + include_directories("../../../fsw/apps/hwlib/sim/inc") + set(generic_star_tracker_checkout_src + ${generic_star_tracker_checkout_src} + ../../../fsw/apps/hwlib/sim/src/libuart.c + ../../../fsw/apps/hwlib/sim/src/libcan.c + ../../../fsw/apps/hwlib/sim/src/libi2c.c + ../../../fsw/apps/hwlib/sim/src/libspi.c + ../../../fsw/apps/hwlib/sim/src/nos_link.c + ) + set(generic_star_tracker_checkout_libs + ${ITC_Common_LIBRARIES} + ${NOSENGINE_LIBRARIES} + ) +endif() +if(${TGTNAME} STREQUAL cpu2) + set(generic_star_tracker_checkout_src + ${generic_star_tracker_checkout_src} + ../../../fsw/apps/hwlib/fsw/linux/libuart.c + ) +endif() + +add_executable(generic_star_tracker_checkout ${generic_star_tracker_checkout_src}) +target_link_libraries(generic_star_tracker_checkout ${generic_star_tracker_checkout_libs}) + +if(${TGTNAME} STREQUAL cpu1) + set_target_properties(generic_star_tracker_checkout PROPERTIES COMPILE_FLAGS "-m32 -g" LINK_FLAGS "-m32 -g") +endif() diff --git a/components/generic_star_tracker/support/device_cfg.h b/components/generic_star_tracker/support/device_cfg.h new file mode 100644 index 00000000..17337adb --- /dev/null +++ b/components/generic_star_tracker/support/device_cfg.h @@ -0,0 +1,15 @@ +#ifndef _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ +#define _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ + +/* +** GENERIC_STAR_TRACKER Checkout Configuration +*/ +#define GENERIC_STAR_TRACKER_CFG +/* Note: NOS3 uart requires matching handle and bus number */ +#define GENERIC_STAR_TRACKER_CFG_STRING "/dev/usart_29" +#define GENERIC_STAR_TRACKER_CFG_HANDLE 29 +#define GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ 115200 +#define GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT 250 +#define GENERIC_STAR_TRACKER_CFG_DEBUG + +#endif /* _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ */ diff --git a/components/generic_star_tracker/support/generic_star_tracker_checkout.c b/components/generic_star_tracker/support/generic_star_tracker_checkout.c new file mode 100644 index 00000000..2f19a34f --- /dev/null +++ b/components/generic_star_tracker/support/generic_star_tracker_checkout.c @@ -0,0 +1,278 @@ +/******************************************************************************* +** File: generic_star_tracker_checkout.c +** +** Purpose: +** This checkout can be run without cFS and is used to quickly develop and +** test functions required for a specific component. +** +*******************************************************************************/ + +/* +** Include Files +*/ +#include "generic_star_tracker_checkout.h" + + +/* +** Global Variables +*/ +uart_info_t Generic_star_trackerUart; +GENERIC_STAR_TRACKER_Device_HK_tlm_t Generic_star_trackerHK; +GENERIC_STAR_TRACKER_Device_Data_tlm_t Generic_star_trackerData; + +/* +** Component Functions +*/ +void print_help(void) +{ + printf(PROMPT "command [args]\n" + "---------------------------------------------------------------------\n" + "help - Display help \n" + "exit - Exit app \n" + "noop - No operation command to device \n" + " n - ^ \n" + "hk - Request device housekeeping \n" + " h - ^ \n" + "generic_star_tracker - Request generic_star_tracker data \n" + " s - ^ \n" + "cfg # - Send configuration # \n" + " c # - ^ \n" + "\n" + ); +} + + +int get_command(const char* str) +{ + int status = CMD_UNKNOWN; + char lcmd[MAX_INPUT_TOKEN_SIZE]; + strncpy(lcmd, str, MAX_INPUT_TOKEN_SIZE); + + /* Convert command to lower case */ + to_lower(lcmd); + + if(strcmp(lcmd, "help") == 0) + { + status = CMD_HELP; + } + else if(strcmp(lcmd, "exit") == 0) + { + status = CMD_EXIT; + } + else if(strcmp(lcmd, "noop") == 0) + { + status = CMD_NOOP; + } + else if(strcmp(lcmd, "n") == 0) + { + status = CMD_NOOP; + } + else if(strcmp(lcmd, "hk") == 0) + { + status = CMD_HK; + } + else if(strcmp(lcmd, "h") == 0) + { + status = CMD_HK; + } + else if(strcmp(lcmd, "generic_star_tracker") == 0) + { + status = CMD_GENERIC_STAR_TRACKER; + } + else if(strcmp(lcmd, "s") == 0) + { + status = CMD_GENERIC_STAR_TRACKER; + } + else if(strcmp(lcmd, "cfg") == 0) + { + status = CMD_CFG; + } + else if(strcmp(lcmd, "c") == 0) + { + status = CMD_CFG; + } + return status; +} + + +int process_command(int cc, int num_tokens, char tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]) +{ + int32_t status = OS_SUCCESS; + int32_t exit_status = OS_SUCCESS; + uint32_t config; + + /* Process command */ + switch(cc) + { + case CMD_HELP: + print_help(); + break; + + case CMD_EXIT: + exit_status = OS_ERROR; + break; + + case CMD_NOOP: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = GENERIC_STAR_TRACKER_CommandDevice(&Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_NOOP_CMD, 0); + if (status == OS_SUCCESS) + { + OS_printf("NOOP command success\n"); + } + else + { + OS_printf("NOOP command failed!\n"); + } + } + break; + + case CMD_HK: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = GENERIC_STAR_TRACKER_RequestHK(&Generic_star_trackerUart, &Generic_star_trackerHK); + if (status == OS_SUCCESS) + { + OS_printf("GENERIC_STAR_TRACKER_RequestHK command success\n"); + } + else + { + OS_printf("GENERIC_STAR_TRACKER_RequestHK command failed!\n"); + } + } + break; + + case CMD_GENERIC_STAR_TRACKER: + if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) + { + status = GENERIC_STAR_TRACKER_RequestData(&Generic_star_trackerUart, &Generic_star_trackerData); + if (status == OS_SUCCESS) + { + OS_printf("GENERIC_STAR_TRACKER_RequestData command success\n"); + } + else + { + OS_printf("GENERIC_STAR_TRACKER_RequestData command failed!\n"); + } + } + break; + + case CMD_CFG: + if (check_number_arguments(num_tokens, 1) == OS_SUCCESS) + { + config = atoi(tokens[0]); + status = GENERIC_STAR_TRACKER_CommandDevice(&Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_CFG_CMD, config); + if (status == OS_SUCCESS) + { + OS_printf("Configuration command success with value %u\n", config); + } + else + { + OS_printf("Configuration command failed!\n"); + } + } + break; + + default: + OS_printf("Invalid command format, type 'help' for more info\n"); + break; + } + return exit_status; +} + + +int main(int argc, char *argv[]) +{ + int status = OS_SUCCESS; + char input_buf[MAX_INPUT_BUF]; + char input_tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]; + int num_input_tokens; + int cmd; + char* token_ptr; + uint8_t run_status = OS_SUCCESS; + + /* Open device specific protocols */ + Generic_star_trackerUart.deviceString = GENERIC_STAR_TRACKER_CFG_STRING; + Generic_star_trackerUart.handle = GENERIC_STAR_TRACKER_CFG_HANDLE; + Generic_star_trackerUart.isOpen = PORT_CLOSED; + Generic_star_trackerUart.baud = GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ; + status = uart_init_port(&Generic_star_trackerUart); + if (status == OS_SUCCESS) + { + printf("UART device %s configured with baudrate %d \n", Generic_star_trackerUart.deviceString, Generic_star_trackerUart.baud); + } + else + { + printf("UART device %s failed to initialize! \n", Generic_star_trackerUart.deviceString); + run_status = OS_ERROR; + } + + /* Main loop */ + print_help(); + while(run_status == OS_SUCCESS) + { + num_input_tokens = -1; + cmd = CMD_UNKNOWN; + + /* Read user input */ + printf(PROMPT); + fgets(input_buf, MAX_INPUT_BUF, stdin); + + /* Tokenize line buffer */ + token_ptr = strtok(input_buf, " \t\n"); + while((num_input_tokens < MAX_INPUT_TOKENS) && (token_ptr != NULL)) + { + if(num_input_tokens == -1) + { + /* First token is command */ + cmd = get_command(token_ptr); + } + else + { + strncpy(input_tokens[num_input_tokens], token_ptr, MAX_INPUT_TOKEN_SIZE); + } + token_ptr = strtok(NULL, " \t\n"); + num_input_tokens++; + } + + /* Process command if valid */ + if(num_input_tokens >= 0) + { + /* Process command */ + run_status = process_command(cmd, num_input_tokens, input_tokens); + } + } + + // Close the device + uart_close_port(&Generic_star_trackerUart); + + OS_printf("Cleanly exiting generic_star_tracker application...\n\n"); + return 1; +} + + +/* +** Generic Functions +*/ +int check_number_arguments(int actual, int expected) +{ + int status = OS_SUCCESS; + if (actual != expected) + { + status = OS_ERROR; + OS_printf("Invalid command format, type 'help' for more info\n"); + } + return status; +} + +void to_lower(char* str) +{ + char* ptr = str; + while(*ptr) + { + *ptr = tolower((unsigned char) *ptr); + ptr++; + } + return; +} + diff --git a/components/generic_star_tracker/support/generic_star_tracker_checkout.h b/components/generic_star_tracker/support/generic_star_tracker_checkout.h new file mode 100644 index 00000000..27bc5608 --- /dev/null +++ b/components/generic_star_tracker/support/generic_star_tracker_checkout.h @@ -0,0 +1,68 @@ +/******************************************************************************* +** File: generic_star_tracker_checkout.h +** +** Purpose: +** This is the header file for the GENERIC_STAR_TRACKER checkout. +** +*******************************************************************************/ +#ifndef _GENERIC_STAR_TRACKER_CHECKOUT_H_ +#define _GENERIC_STAR_TRACKER_CHECKOUT_H_ + +/* +** Includes +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hwlib.h" +#include "device_cfg.h" +#include "generic_star_tracker_device.h" + + +/* +** Standard Defines +*/ +#define PROMPT "generic_star_tracker> " +#define MAX_INPUT_BUF 512 +#define MAX_INPUT_TOKENS 64 +#define MAX_INPUT_TOKEN_SIZE 50 +#define TELEM_BUF_LEN 8 + + +/* +** Command Defines +*/ +#define CMD_UNKNOWN -1 +#define CMD_HELP 0 +#define CMD_EXIT 1 +#define CMD_NOOP 2 +#define CMD_HK 3 +#define CMD_GENERIC_STAR_TRACKER 4 +#define CMD_CFG 5 + + +/* +** Prototypes +*/ +void print_help(void); +int get_command(const char* str); +int main(int argc, char *argv[]); + + +/* +** Generic Prototypes +*/ +int check_number_arguments(int actual, int expected); +void to_lower(char* str); + + +#endif /* _GENERIC_STAR_TRACKER_CHECKOUT_H_ */ diff --git a/fsw/nos3_defs/cpu1_cfe_es_startup.scr b/fsw/nos3_defs/cpu1_cfe_es_startup.scr index ec57104d..775aa83d 100644 --- a/fsw/nos3_defs/cpu1_cfe_es_startup.scr +++ b/fsw/nos3_defs/cpu1_cfe_es_startup.scr @@ -26,6 +26,7 @@ CFE_APP, generic_rw, RW_AppMain, RW, CFE_APP, generic_torquer, TORQUER_AppMain, TORQUER, 69, 8192, 0x0, 0; CFE_APP, novatel_oem615, NOVATEL_AppMain, NAV, 70, 8192, 0x0, 0; CFE_APP, sample, SAMPLE_AppMain, SAMPLE, 71, 8192, 0x0, 0; +CFE_APP, generic_st, ST_AppMain, ST, 71, 8192, 0x0, 0; ! CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; diff --git a/fsw/nos3_defs/targets.cmake b/fsw/nos3_defs/targets.cmake index 5c13d43b..13393551 100644 --- a/fsw/nos3_defs/targets.cmake +++ b/fsw/nos3_defs/targets.cmake @@ -115,6 +115,7 @@ list(APPEND MISSION_GLOBAL_APPLIST novatel_oem615 sample generic_adcs + generic_star_tracker ) # Create Application Platform Include List From 4b747efffa6a17f720bd25d17f5cbc8250344d2f Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Mon, 9 Oct 2023 10:37:21 -0400 Subject: [PATCH 025/153] https://github.com/nasa/nos3/issues/166 - Initial mostly working version of the generic star tracker component. --- .gitmodules | 3 + components/generic_star_tracker | 1 + components/generic_star_tracker/.gitignore | 1 - .../generic_star_tracker/CMakeLists.txt | 16 - components/generic_star_tracker/LICENSE | 263 -------- components/generic_star_tracker/README.md | 138 ----- .../generic_star_tracker_perfids.h | 21 - .../generic_star_tracker_msgids.h | 28 - .../generic_star_tracker_platform_cfg.h | 29 - .../fsw/src/generic_star_tracker_app.c | 576 ------------------ .../fsw/src/generic_star_tracker_app.h | 100 --- .../fsw/src/generic_star_tracker_device.c | 274 --------- .../fsw/src/generic_star_tracker_device.h | 77 --- .../fsw/src/generic_star_tracker_events.h | 47 -- .../fsw/src/generic_star_tracker_msg.h | 89 --- .../fsw/src/generic_star_tracker_version.h | 19 - .../cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt | 49 -- .../cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt | 44 -- .../gsw/GENERIC_STAR_TRACKER/target.txt | 10 - .../generic_star_tracker/sim/CMakeLists.txt | 31 - .../generic_star_tracker_42_data_provider.hpp | 30 - .../inc/generic_star_tracker_data_point.hpp | 46 -- .../generic_star_tracker_data_provider.hpp | 29 - .../generic_star_tracker_hardware_model.hpp | 61 -- .../generic_star_tracker_42_data_provider.cpp | 32 - .../src/generic_star_tracker_data_point.cpp | 81 --- .../generic_star_tracker_data_provider.cpp | 28 - .../generic_star_tracker_hardware_model.cpp | 326 ---------- .../support/CMakeLists.txt | 69 --- .../generic_star_tracker/support/device_cfg.h | 15 - .../support/generic_star_tracker_checkout.c | 278 --------- .../support/generic_star_tracker_checkout.h | 68 --- fsw/nos3_defs/tables/to_config.c | 5 +- fsw/nos3_defs/tables/to_lab_sub.c | 3 + gsw/scripts/docker_launch.sh | 1 + sims/cfg/InOut/Inp_IPC.txt | 14 +- sims/cfg/InOut/SC_NOS3.txt | 4 +- sims/cfg/nos3-simulator.xml | 54 +- 38 files changed, 66 insertions(+), 2894 deletions(-) create mode 160000 components/generic_star_tracker delete mode 100644 components/generic_star_tracker/.gitignore delete mode 100644 components/generic_star_tracker/CMakeLists.txt delete mode 100644 components/generic_star_tracker/LICENSE delete mode 100644 components/generic_star_tracker/README.md delete mode 100644 components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h delete mode 100644 components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h delete mode 100644 components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_app.c delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_app.h delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_device.c delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_device.h delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_events.h delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h delete mode 100644 components/generic_star_tracker/fsw/src/generic_star_tracker_version.h delete mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt delete mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt delete mode 100644 components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt delete mode 100644 components/generic_star_tracker/sim/CMakeLists.txt delete mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp delete mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp delete mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp delete mode 100644 components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp delete mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp delete mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp delete mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp delete mode 100644 components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp delete mode 100644 components/generic_star_tracker/support/CMakeLists.txt delete mode 100644 components/generic_star_tracker/support/device_cfg.h delete mode 100644 components/generic_star_tracker/support/generic_star_tracker_checkout.c delete mode 100644 components/generic_star_tracker/support/generic_star_tracker_checkout.h diff --git a/.gitmodules b/.gitmodules index 59e5e009..e3e8df1f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -123,3 +123,6 @@ [submodule "components/generic_adcs"] path = components/generic_adcs url = https://github.com/nasa-itc/generic_adcs.git +[submodule "components/generic_star_tracker"] + path = components/generic_star_tracker + url = https://github.com/nasa-itc/generic_star_tracker.git diff --git a/components/generic_star_tracker b/components/generic_star_tracker new file mode 160000 index 00000000..d2c8e7ec --- /dev/null +++ b/components/generic_star_tracker @@ -0,0 +1 @@ +Subproject commit d2c8e7ec84d5a21e95eed8e42ff624c51e1ca655 diff --git a/components/generic_star_tracker/.gitignore b/components/generic_star_tracker/.gitignore deleted file mode 100644 index cfea098e..00000000 --- a/components/generic_star_tracker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -support/build \ No newline at end of file diff --git a/components/generic_star_tracker/CMakeLists.txt b/components/generic_star_tracker/CMakeLists.txt deleted file mode 100644 index 148cec8a..00000000 --- a/components/generic_star_tracker/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 2.6.4) -project(CFS_GENERIC_STAR_TRACKER_APP C) - -include(../ComponentSettings.cmake) - -include_directories(fsw/public_inc) -include_directories(fsw/mission_inc) -include_directories(fsw/platform_inc) -include_directories(fsw/src) - -include_directories(${hwlib_MISSION_DIR}/fsw/public_inc) - -aux_source_directory(fsw/src APP_SRC_FILES) - -# Create the app module -add_cfe_app(generic_st ${APP_SRC_FILES}) diff --git a/components/generic_star_tracker/LICENSE b/components/generic_star_tracker/LICENSE deleted file mode 100644 index 50a36292..00000000 --- a/components/generic_star_tracker/LICENSE +++ /dev/null @@ -1,263 +0,0 @@ -NASA OPEN SOURCE AGREEMENT VERSION 1.3 - -THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, -REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN -COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT -AS REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT -AGENCY"). THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT -AGENCY, IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT -DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO -USES, REPRODUCES, DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT -SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, -ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN -THIS AGREEMENT. - -Government Agency: NASA -Government Agency Original Software Designation: GSC-17737-1 -Government Agency Original Software Title: - NASA Operational Simulator for Small Satellites -User Registration Requested. Please Visit - https://github.com/nasa/nos3 -Government Agency Point of Contact for Original Software: - John.P.Lucas@nasa.gov - -1. DEFINITIONS - -A. "Contributor" means Government Agency, as the developer of the -Original Software, and any entity that makes a Modification. -B. "Covered Patents" mean patent claims licensable by a Contributor -that are necessarily infringed by the use or sale of its Modification -alone or when combined with the Subject Software. -C. "Display" means the showing of a copy of the Subject Software, -either directly or by means of an image, or any other device. -D. "Distribution" means conveyance or transfer of the Subject -Software, regardless of means, to another. -E. "Larger Work" means computer software that combines Subject -Software, or portions thereof, with software separate from the Subject -Software that is not governed by the terms of this Agreement. -F. "Modification" means any alteration of, including addition to or -deletion from, the substance or structure of either the Original -Software or Subject Software, and includes derivative works, as that -term is defined in the Copyright Statute, 17 USC 101. However, the -act of including Subject Software as part of a Larger Work does not in -and of itself constitute a Modification. -G. "Original Software" means the computer software first released -under this Agreement by Government Agency with Government Agency -designation GSC-17776-1 and entitled Core Flight System Cryptography -Library, including source code, object code and accompanying -documentation, if any. -H. "Recipient" means anyone who acquires the Subject Software under -this Agreement, including all Contributors. -I. "Redistribution" means Distribution of the Subject Software after a -Modification has been made. -J. "Reproduction" means the making of a counterpart, image or copy of -the Subject Software. -K. "Sale" means the exchange of the Subject Software for money or -equivalent value. -L. "Subject Software" means the Original Software, Modifications, or -any respective parts thereof. -M. "Use" means the application or employment of the Subject Software -for any purpose. - -2. GRANT OF RIGHTS - -A. Under Non-Patent Rights: Subject to the terms and conditions of -this Agreement, each Contributor, with respect to its own contribution -to the Subject Software, hereby grants to each Recipient a -non-exclusive, world-wide, royalty-free license to engage in the -following activities pertaining to the Subject Software: - -1. Use -2. Distribution -3. Reproduction -4. Modification -5. Redistribution -6. Display - -B. Under Patent Rights: Subject to the terms and conditions of this -Agreement, each Contributor, with respect to its own contribution to -the Subject Software, hereby grants to each Recipient under Covered -Patents a non-exclusive, world-wide, royalty-free license to engage in -the following activities pertaining to the Subject Software: - -1. Use -2. Distribution -3. Reproduction -4. Sale -5. Offer for Sale - -C. The rights granted under Paragraph B. also apply to the combination -of a Contributor's Modification and the Subject Software if, at the -time the Modification is added by the Contributor, the addition of -such Modification causes the combination to be covered by the Covered -Patents. It does not apply to any other combinations that include a -Modification. - -D. The rights granted in Paragraphs A. and B. allow the Recipient to -sublicense those same rights. Such sublicense must be under the same -terms and conditions of this Agreement. - -3. OBLIGATIONS OF RECIPIENT - -A. Distribution or Redistribution of the Subject Software must be made -under this Agreement except for additions covered under paragraph 3H. - -1. Whenever a Recipient distributes or redistributes the Subject - Software, a copy of this Agreement must be included with each copy - of the Subject Software; and -2. If Recipient distributes or redistributes the Subject Software in - any form other than source code, Recipient must also make the - source code freely available, and must provide with each copy of - the Subject Software information on how to obtain the source code - in a reasonable manner on or through a medium customarily used for - software exchange. - -B. Each Recipient must ensure that the following copyright notice -appears prominently in the Subject Software: - -/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - - This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not - limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness - for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or - any warranty that the software will be error free. - - In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, - contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder. - - ITC Team - NASA IV&V - jstar-development-team@mail.nasa.gov -*/ - -C. Each Contributor must characterize its alteration of the Subject -Software as a Modification and must identify itself as the originator -of its Modification in a manner that reasonably allows subsequent -Recipients to identify the originator of the Modification. In -fulfillment of these requirements, Contributor must include a file -(e.g., a change log file) that describes the alterations made and the -date of the alterations, identifies Contributor as originator of the -alterations, and consents to characterization of the alterations as a -Modification, for example, by including a statement that the -Modification is derived, directly or indirectly, from Original -Software provided by Government Agency. Once consent is granted, it -may not thereafter be revoked. - -D. A Contributor may add its own copyright notice to the Subject -Software. Once a copyright notice has been added to the Subject -Software, a Recipient may not remove it without the express permission -of the Contributor who added the notice. - -E. A Recipient may not make any representation in the Subject Software -or in any promotional, advertising or other material that may be -construed as an endorsement by Government Agency or by any prior -Recipient of any product or service provided by Recipient, or that may -seek to obtain commercial advantage by the fact of Government Agency's -or a prior Recipient's participation in this Agreement. - -F. In an effort to track usage and maintain accurate records of the -Subject Software, each Recipient, upon receipt of the Subject -Software, is requested to register with Government Agency by visiting -the following website: https://github.com/nasa/CryptoLib. Recipient's -name and personal information shall be used for statistical purposes -only. Once a Recipient makes a Modification available, it is requested -that the Recipient inform Government Agency at the web site provided -above how to access the Modification. - -G. Each Contributor represents that that its Modification is believed -to be Contributor's original creation and does not violate any -existing agreements, regulations, statutes or rules, and further that -Contributor has sufficient rights to grant the rights conveyed by this -Agreement. - -H. A Recipient may choose to offer, and to charge a fee for, warranty, -support, indemnity and/or liability obligations to one or more other -Recipients of the Subject Software. A Recipient may do so, however, -only on its own behalf and not on behalf of Government Agency or any -other Recipient. Such a Recipient must make it absolutely clear that -any such warranty, support, indemnity and/or liability obligation is -offered by that Recipient alone. Further, such Recipient agrees to -indemnify Government Agency and every other Recipient for any -liability incurred by them as a result of warranty, support, indemnity -and/or liability offered by such Recipient. - -I. A Recipient may create a Larger Work by combining Subject Software -with separate software not governed by the terms of this agreement and -distribute the Larger Work as a single product. In such case, the -Recipient must make sure Subject Software, or portions thereof, -included in the Larger Work is subject to this Agreement. - -J. Notwithstanding any provisions contained herein, Recipient is -hereby put on notice that export of any goods or technical data from -the United States may require some form of export license from the -U.S. Government. Failure to obtain necessary export licenses may -result in criminal liability under U.S. laws. Government Agency -neither represents that a license shall not be required nor that, if -required, it shall be issued. Nothing granted herein provides any -such export license. - -4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION - -A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY -WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, -INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE -WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM -INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR -FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO -THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, -CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT -OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY -OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. -FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES -REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, -AND DISTRIBUTES IT "AS IS." - -B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS -AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND -SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF -THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, -EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM -PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT -SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED -STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY -PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE -REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL -TERMINATION OF THIS AGREEMENT. - - -5. GENERAL TERMS - -A. Termination: This Agreement and the rights granted hereunder will -terminate automatically if a Recipient fails to comply with these -terms and conditions, and fails to cure such noncompliance within -thirty (30) days of becoming aware of such noncompliance. Upon -termination, a Recipient agrees to immediately cease use and -distribution of the Subject Software. All sublicenses to the Subject -Software properly granted by the breaching Recipient shall survive any -such termination of this Agreement. - -B. Severability: If any provision of this Agreement is invalid or -unenforceable under applicable law, it shall not affect the validity -or enforceability of the remainder of the terms of this Agreement. - -C. Applicable Law: This Agreement shall be subject to United States -federal law only for all purposes, including, but not limited to, -determining the validity of this Agreement, the meaning of its -provisions and the rights, obligations and remedies of the parties. - -D. Entire Understanding: This Agreement constitutes the entire -understanding and agreement of the parties relating to release of the -Subject Software and may not be superseded, modified or amended except -by further written agreement duly executed by the parties. - -E. Binding Authority: By accepting and using the Subject Software -under this Agreement, a Recipient affirms its authority to bind the -Recipient to all terms and conditions of this Agreement and that that -Recipient hereby agrees to all terms and conditions herein. - -F. Point of Contact: Any Recipient contact with Government Agency is -to be directed to the designated representative as follows: - John.P.Lucas@nasa.gov \ No newline at end of file diff --git a/components/generic_star_tracker/README.md b/components/generic_star_tracker/README.md deleted file mode 100644 index b9a654d4..00000000 --- a/components/generic_star_tracker/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# Generic_star_tracker - NOS3 Component -This repository contains the NOS3 Generic_star_tracker Component. -This includes flight software (FSW), ground software (GSW), simulation, and support directories. - -## Component Template -This component template utilizes canned files from the existing [generic_star_tracker component](https://github.com/nasa-itc/generic_star_tracker) to generate a new component to do development in. - -Expected utilization: -* Determine the desired component name -* Create a new submodule for the component via GitHub -* Add the submodule to this project - * `git submodule init` - * `git submodule add -f -b main ./components/` -* Generate the new files - * `./generate_template.sh ` - * Note that must be <= 10 characters by default or you'll need to shorten the software bus pipe name after the fact -* The new files should be placed in the submodule - * `..//` -* Commit the new files to the submodule - * `git add * && git add .gitignore` - * `git commit -m "Initial component template based on version 0.0.0"` -* Add new component to flight software (fsw) in the following files: - * `./fsw/nos3_defs/cpu1_cfe_es_startup.scr` - * `./fsw/nos3_defs/targets.cmake` - * `./fsw/nos3_defs/tables/*` -* Add new component to ground software (gsw) in the following files: - * `./gsw/cosmos/config/system/nos3_system.txt` - * `./gsw/cosmos/config/tools/cmd_tlm_server/nos3_cmd_tlm_server.txt` - * `./gsw/scripts/launch.sh` - -## Overview -In addition to being used by the template generator, the generic_star_tracker component provides an executable example for the user. This generic_star_tracker component is a UART device that accepts multiple commands, including requests for telemetry and data. -The available FSW is for use in the core Flight System (cFS) while the GSW supports COSMOS. -A NOS3 simulation is available which includes both generic_star_tracker and 42 data providers. - - -# Device Communications -The protocol, commands, and responses of the component are captured below. - -## Protocol -The protocol in use is UART 115200 8N1. -The device is speak when spoken too. -All communications with the device require / contain a header of 0xDEAD and a trailer of 0xBEEF. - -## Commands -All commands received by the device are echoed back to the sender to confirm receipt. -Should commmands involve a reply, the device immediately sends the reply after the command echo. -Device commands are all formatted in the same manner and are fixed in size: -* uint16, 0xDEAD -* uint8, command identifier - - (0) Get Housekeeping - - (1) Get Generic_star_tracker - - (2) Set Configuration -* uint32, command payload - - Unused for all but set configuration command -* uint16, 0xBEEF - -## Response -Response formats are as follows: -* Housekeeping - - uint16, 0xDEAD - - uint32, Command Counter - * Increments for each command received - - uint32, Configuration - * Internal configuration number in use by the device - - uint32, Status - * Self reported status of the component where zero is completely healthy and each bit represents different errors - * No means to clear / set status except for a power cycle to the device - - uint16, 0xBEEF -* Generic_star_tracker - - uint16, 0xDEAD - - uint32, Command Counter - * Increments for each command received - - uint16, Data X - * X component of generic_star_tracker data - - uint16, Data Y - * X component of generic_star_tracker data - - uint16, Data Z - * X component of generic_star_tracker data - - uint16, 0xBEEF - - -# Configuration -The various configuration parameters available for each portion of the component are captured below. - -## FSW -Refer to the file [fsw/platform_inc/generic_star_tracker_platform_cfg.h](fsw/platform_inc/generic_star_tracker_platform_cfg.h) for the default -configuration settings, as well as a summary on overriding parameters in mission-specific repositories. - -## Simulation -The default configuration returns data that is X * 0.001, Y * 0.002, and Z * 0.003 the request count after conversions: -``` - - generic_star_tracker_sim - true - libgeneric_star_tracker_sim.so - - GENERIC_STAR_TRACKER - - command - command - generic_star_tracker-sim-command-node - - usart - usart_29 - 29 - - - - GENERIC_STAR_TRACKER_PROVIDER - - - -``` - -## 42 -Optionally the 42 data provider can be configured in the `nos3-simulator.xml`: -``` - - GENERIC_STAR_TRACKER_42_PROVIDER - localhost - 4242 - 5 - 5 - 0 - -``` - - -# Documentation -If this generic_star_tracker application had an ICD and/or test procedure, they would be linked here. - -## Releases -We use [SemVer](http://semver.org/) for versioning. For the versions available, see the tags on this repository. -* v1.0.0 - X/Y/Z - - Updated to be a component repository including FSW, GSW, Sim, and Standalone checkout -* v0.1.0 - 10/9/2021 - - Initial release with version tagging diff --git a/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h b/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h deleted file mode 100644 index b0ba2c9a..00000000 --- a/components/generic_star_tracker/fsw/mission_inc/generic_star_tracker_perfids.h +++ /dev/null @@ -1,21 +0,0 @@ -/******************************************************************************* -** File: -** $Id: generic_star_tracker_perfids.h $ -** -** Purpose: -** Define GENERIC_STAR_TRACKER Performance IDs -** -** Notes: -** -*************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_PERFIDS_H_ -#define _GENERIC_STAR_TRACKER_PERFIDS_H_ - -/* -** define any performance id integer for the app - try to not have this -** id conflict with other apps. Performance IDs are used for cFE performance -** metrics. -*/ -#define GENERIC_STAR_TRACKER_PERF_ID 500 - -#endif /* _GENERIC_STAR_TRACKER_PERFIDS_H_ */ diff --git a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h deleted file mode 100644 index 88bc2fa4..00000000 --- a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_msgids.h +++ /dev/null @@ -1,28 +0,0 @@ -/************************************************************************ -** File: -** $Id: generic_star_tracker_msgids.h $ -** -** Purpose: -** Define GENERIC_STAR_TRACKER Message IDs -** -*************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_MSGIDS_H_ -#define _GENERIC_STAR_TRACKER_MSGIDS_H_ - -/* -** CCSDS V1 Command Message IDs (MID) must be 0x18xx -*/ -#define GENERIC_STAR_TRACKER_CMD_MID 0x1935 - -/* -** This MID is for commands telling the app to publish its telemetry message -*/ -#define GENERIC_STAR_TRACKER_REQ_HK_MID 0x1936 - -/* -** CCSDS V1 Telemetry Message IDs must be 0x08xx -*/ -#define GENERIC_STAR_TRACKER_HK_TLM_MID 0x0935 -#define GENERIC_STAR_TRACKER_DEVICE_TLM_MID 0x0936 - -#endif /* _GENERIC_STAR_TRACKER_MSGIDS_H_ */ diff --git a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h b/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h deleted file mode 100644 index fe026fa8..00000000 --- a/components/generic_star_tracker/fsw/platform_inc/generic_star_tracker_platform_cfg.h +++ /dev/null @@ -1,29 +0,0 @@ -/************************************************************************ -** File: -** $Id: generic_star_tracker_platform_cfg.h $ -** -** Purpose: -** Define generic_star_tracker Platform Configuration Parameters -** -** Notes: -** -*************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ -#define _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ - -/* -** Default GENERIC_STAR_TRACKER Configuration -*/ -#ifndef GENERIC_STAR_TRACKER_CFG - /* Notes: - ** NOS3 uart requires matching handle and bus number - */ - #define GENERIC_STAR_TRACKER_CFG_STRING "usart_29" - #define GENERIC_STAR_TRACKER_CFG_HANDLE 29 - #define GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ 115200 - #define GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT 50 /* Max 255 */ - /* Note: Debug flag disabled (commented out) by default */ - //#define GENERIC_STAR_TRACKER_CFG_DEBUG -#endif - -#endif /* _GENERIC_STAR_TRACKER_PLATFORM_CFG_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c deleted file mode 100644 index 69051fc4..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.c +++ /dev/null @@ -1,576 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_app.c -** -** Purpose: -** This file contains the source code for the GENERIC_STAR_TRACKER application. -** -*******************************************************************************/ - -/* -** Include Files -*/ -#include -#include "generic_star_tracker_app.h" - - -/* -** Global Data -*/ -GENERIC_STAR_TRACKER_AppData_t GENERIC_STAR_TRACKER_AppData; - -/* -** Application entry point and main process loop -*/ -void ST_AppMain(void) -{ - int32 status = OS_SUCCESS; - - /* - ** Create the first Performance Log entry - */ - CFE_ES_PerfLogEntry(GENERIC_STAR_TRACKER_PERF_ID); - - /* - ** Perform application initialization - */ - status = GENERIC_STAR_TRACKER_AppInit(); - if (status != CFE_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; - } - - /* - ** Main loop - */ - while (CFE_ES_RunLoop(&GENERIC_STAR_TRACKER_AppData.RunStatus) == true) - { - /* - ** Performance log exit stamp - */ - CFE_ES_PerfLogExit(GENERIC_STAR_TRACKER_PERF_ID); - - /* - ** Pend on the arrival of the next Software Bus message - ** Note that this is the standard, but timeouts are available - */ - status = CFE_SB_ReceiveBuffer((CFE_SB_Buffer_t **)&GENERIC_STAR_TRACKER_AppData.MsgPtr, GENERIC_STAR_TRACKER_AppData.CmdPipe, CFE_SB_PEND_FOREVER); - - /* - ** Begin performance metrics on anything after this line. This will help to determine - ** where we are spending most of the time during this app execution. - */ - CFE_ES_PerfLogEntry(GENERIC_STAR_TRACKER_PERF_ID); - - /* - ** If the CFE_SB_ReceiveBuffer was successful, then continue to process the command packet - ** If not, then exit the application in error. - ** Note that a SB read error should not always result in an app quitting. - */ - if (status == CFE_SUCCESS) - { - GENERIC_STAR_TRACKER_ProcessCommandPacket(); - } - else - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: SB Pipe Read Error = %d", (int) status); - GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_ERROR; - } - } - - /* - ** Disable component, which cleans up the interface, upon exit - */ - GENERIC_STAR_TRACKER_Disable(); - - /* - ** Performance log exit stamp - */ - CFE_ES_PerfLogExit(GENERIC_STAR_TRACKER_PERF_ID); - - /* - ** Exit the application - */ - CFE_ES_ExitApp(GENERIC_STAR_TRACKER_AppData.RunStatus); -} - - -/* -** Initialize application -*/ -int32 GENERIC_STAR_TRACKER_AppInit(void) -{ - int32 status = OS_SUCCESS; - - GENERIC_STAR_TRACKER_AppData.RunStatus = CFE_ES_RunStatus_APP_RUN; - - /* - ** Register the events - */ - status = CFE_EVS_Register(NULL, 0, CFE_EVS_EventFilter_BINARY); /* as default, no filters are used */ - if (status != CFE_SUCCESS) - { - CFE_ES_WriteToSysLog("GENERIC_STAR_TRACKER: Error registering for event services: 0x%08X\n", (unsigned int) status); - return status; - } - - /* - ** Create the Software Bus command pipe - */ - status = CFE_SB_CreatePipe(&GENERIC_STAR_TRACKER_AppData.CmdPipe, GENERIC_STAR_TRACKER_PIPE_DEPTH, "GENERIC_ST_CMD_PIPE"); - if (status != CFE_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PIPE_ERR_EID, CFE_EVS_EventType_ERROR, - "Error Creating SB Pipe,RC=0x%08X",(unsigned int) status); - return status; - } - - /* - ** Subscribe to ground commands - */ - status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_CMD_MID), GENERIC_STAR_TRACKER_AppData.CmdPipe); - if (status != CFE_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_SUB_CMD_ERR_EID, CFE_EVS_EventType_ERROR, - "Error Subscribing to HK Gnd Cmds, MID=0x%04X, RC=0x%08X", - GENERIC_STAR_TRACKER_CMD_MID, (unsigned int) status); - return status; - } - - /* - ** Subscribe to housekeeping (hk) message requests - */ - status = CFE_SB_Subscribe(CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_REQ_HK_MID), GENERIC_STAR_TRACKER_AppData.CmdPipe); - if (status != CFE_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_SUB_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, - "Error Subscribing to HK Request, MID=0x%04X, RC=0x%08X", - GENERIC_STAR_TRACKER_REQ_HK_MID, (unsigned int) status); - return status; - } - - /* - ** TODO: Subscribe to any other messages here - */ - - - /* - ** Initialize the published HK message - this HK message will contain the - ** telemetry that has been defined in the GENERIC_STAR_TRACKER_HkTelemetryPkt for this app. - */ - CFE_MSG_Init(CFE_MSG_PTR(GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.TlmHeader), - CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_HK_TLM_MID), - GENERIC_STAR_TRACKER_HK_TLM_LNGTH); - - /* - ** Initialize the device packet message - ** This packet is specific to your application - */ - CFE_MSG_Init(CFE_MSG_PTR(GENERIC_STAR_TRACKER_AppData.DevicePkt.TlmHeader), - CFE_SB_ValueToMsgId(GENERIC_STAR_TRACKER_DEVICE_TLM_MID), - GENERIC_STAR_TRACKER_DEVICE_TLM_LNGTH); - - /* - ** TODO: Initialize any other messages that this app will publish - */ - - - /* - ** Always reset all counters during application initialization - */ - GENERIC_STAR_TRACKER_ResetCounters(); - - /* - ** Initialize application data - ** Note that counters are excluded as they were reset in the previous code block - */ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_DISABLED; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceCounter = 0; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceConfig = 0; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK.DeviceStatus = 0; - - /* - ** Send an information event that the app has initialized. - ** This is useful for debugging the loading of individual applications. - */ - status = CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_STARTUP_INF_EID, CFE_EVS_EventType_INFORMATION, - "GENERIC_STAR_TRACKER App Initialized. Version %d.%d.%d.%d", - GENERIC_STAR_TRACKER_MAJOR_VERSION, - GENERIC_STAR_TRACKER_MINOR_VERSION, - GENERIC_STAR_TRACKER_REVISION, - GENERIC_STAR_TRACKER_MISSION_REV); - if (status != CFE_SUCCESS) - { - CFE_ES_WriteToSysLog("GENERIC_STAR_TRACKER: Error sending initialization event: 0x%08X\n", (unsigned int) status); - } - return status; -} - - -/* -** Process packets received on the GENERIC_STAR_TRACKER command pipe -*/ -void GENERIC_STAR_TRACKER_ProcessCommandPacket(void) -{ - CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; - CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); - switch (CFE_SB_MsgIdToValue(MsgId)) - { - /* - ** Ground Commands with command codes fall under the GENERIC_STAR_TRACKER_CMD_MID (Message ID) - */ - case GENERIC_STAR_TRACKER_CMD_MID: - GENERIC_STAR_TRACKER_ProcessGroundCommand(); - break; - - /* - ** All other messages, other than ground commands, add to this case statement. - */ - case GENERIC_STAR_TRACKER_REQ_HK_MID: - GENERIC_STAR_TRACKER_ProcessTelemetryRequest(); - break; - - /* - ** All other invalid messages that this app doesn't recognize, - ** increment the command error counter and log as an error event. - */ - default: - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_PROCESS_CMD_ERR_EID,CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Invalid command packet, MID = 0x%x", CFE_SB_MsgIdToValue(MsgId)); - break; - } - return; -} - - -/* -** Process ground commands -** TODO: Add additional commands required by the specific component -*/ -void GENERIC_STAR_TRACKER_ProcessGroundCommand(void) -{ - int32 status = OS_SUCCESS; - CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; - CFE_MSG_FcnCode_t CommandCode = 0; - - /* - ** MsgId is only needed if the command code is not recognized. See default case - */ - CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); - - /* - ** Ground Commands, by definition, have a command code (_CC) associated with them - ** Pull this command code from the message and then process - */ - CFE_MSG_GetFcnCode(GENERIC_STAR_TRACKER_AppData.MsgPtr, &CommandCode); - switch (CommandCode) - { - /* - ** NOOP Command - */ - case GENERIC_STAR_TRACKER_NOOP_CC: - /* - ** First, verify the command length immediately after CC identification - ** Note that VerifyCmdLength handles the command and command error counters - */ - if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) - { - /* Second, send EVS event on successful receipt ground commands*/ - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_NOOP_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: NOOP command received"); - /* Third, do the desired command action if applicable, in the case of NOOP it is no operation */ - } - break; - - /* - ** Reset Counters Command - */ - case GENERIC_STAR_TRACKER_RESET_COUNTERS_CC: - if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_RESET_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: RESET counters command received"); - GENERIC_STAR_TRACKER_ResetCounters(); - } - break; - - /* - ** Enable Command - */ - case GENERIC_STAR_TRACKER_ENABLE_CC: - if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Enable command received"); - GENERIC_STAR_TRACKER_Enable(); - } - break; - - /* - ** Disable Command - */ - case GENERIC_STAR_TRACKER_DISABLE_CC: - if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_NoArgs_cmd_t)) == OS_SUCCESS) - { - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Disable command received"); - GENERIC_STAR_TRACKER_Disable(); - } - break; - - /* - ** TODO: Edit and add more command codes as appropriate for the application - ** Set Configuration Command - ** Note that this is an example of a command that has additional arguments - */ - case GENERIC_STAR_TRACKER_CONFIG_CC: - if (GENERIC_STAR_TRACKER_VerifyCmdLength(GENERIC_STAR_TRACKER_AppData.MsgPtr, sizeof(GENERIC_STAR_TRACKER_Config_cmd_t)) == OS_SUCCESS) - { - uint32_t config = ntohl(((GENERIC_STAR_TRACKER_Config_cmd_t*) GENERIC_STAR_TRACKER_AppData.MsgPtr)->DeviceCfg); // command is defined as big-endian... need to convert to host representation - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_CONFIG_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Configuration command received: %u", config); - /* Command device to send HK */ - status = GENERIC_STAR_TRACKER_CommandDevice(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_CFG_CMD, config); - if (status == OS_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - } - } - break; - - /* - ** Invalid Command Codes - */ - default: - /* Increment the error counter upon receipt of an invalid command */ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_CMD_ERR_EID, CFE_EVS_EventType_ERROR, - "GENERIC_STAR_TRACKER: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); - break; - } - return; -} - - -/* -** Process Telemetry Request - Triggered in response to a telemetery request -** TODO: Add additional telemetry required by the specific component -*/ -void GENERIC_STAR_TRACKER_ProcessTelemetryRequest(void) -{ - int32 status = OS_SUCCESS; - CFE_SB_MsgId_t MsgId = CFE_SB_INVALID_MSG_ID; - CFE_MSG_FcnCode_t CommandCode = 0; - - /* MsgId is only needed if the command code is not recognized. See default case */ - CFE_MSG_GetMsgId(GENERIC_STAR_TRACKER_AppData.MsgPtr, &MsgId); - - /* Pull this command code from the message and then process */ - CFE_MSG_GetFcnCode(GENERIC_STAR_TRACKER_AppData.MsgPtr, &CommandCode); - switch (CommandCode) - { - case GENERIC_STAR_TRACKER_REQ_HK_TLM: - GENERIC_STAR_TRACKER_ReportHousekeeping(); - break; - - case GENERIC_STAR_TRACKER_REQ_DATA_TLM: - GENERIC_STAR_TRACKER_ReportDeviceTelemetry(); - break; - - /* - ** Invalid Command Codes - */ - default: - /* Increment the error counter upon receipt of an invalid command */ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DEVICE_TLM_ERR_EID, CFE_EVS_EventType_ERROR, - "GENERIC_STAR_TRACKER: Invalid command code for packet, MID = 0x%x, cmdCode = 0x%x", CFE_SB_MsgIdToValue(MsgId), CommandCode); - break; - } - return; -} - - -/* -** Report Application Housekeeping -*/ -void GENERIC_STAR_TRACKER_ReportHousekeeping(void) -{ - int32 status = OS_SUCCESS; - - /* Check that device is enabled */ - if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) - { - status = GENERIC_STAR_TRACKER_RequestHK(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, (GENERIC_STAR_TRACKER_Device_HK_tlm_t*) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceHK); - if (status == OS_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_REQ_HK_ERR_EID, CFE_EVS_EventType_ERROR, - "GENERIC_STAR_TRACKER: Request device HK reported error %d", status); - } - } - /* Intentionally do not report errors if disabled */ - - /* Time stamp and publish housekeeping telemetry */ - CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt); - CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt, true); - return; -} - - -/* -** Collect and Report Device Telemetry -*/ -void GENERIC_STAR_TRACKER_ReportDeviceTelemetry(void) -{ - int32 status = OS_SUCCESS; - - /* Check that device is enabled */ - if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) - { - status = GENERIC_STAR_TRACKER_RequestData(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart, (GENERIC_STAR_TRACKER_Device_Data_tlm_t*) &GENERIC_STAR_TRACKER_AppData.DevicePkt.Generic_star_tracker); - if (status == OS_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; - /* Time stamp and publish data telemetry */ - CFE_SB_TimeStampMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.DevicePkt); - CFE_SB_TransmitMsg((CFE_MSG_Message_t *) &GENERIC_STAR_TRACKER_AppData.DevicePkt, true); - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_REQ_DATA_ERR_EID, CFE_EVS_EventType_ERROR, - "GENERIC_STAR_TRACKER: Request device data reported error %d", status); - } - } - /* Intentionally do not report errors if disabled */ - return; -} - - -/* -** Reset all global counter variables -*/ -void GENERIC_STAR_TRACKER_ResetCounters(void) -{ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount = 0; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandCount = 0; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount = 0; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount = 0; - return; -} - - -/* -** Enable Component -** TODO: Edit for your specific component implementation -*/ -void GENERIC_STAR_TRACKER_Enable(void) -{ - int32 status = OS_SUCCESS; - - /* Check that device is disabled */ - if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_DISABLED) - { - /* - ** Initialize hardware interface data - ** TODO: Make specific to your application depending on protocol in use - ** Note that other components provide examples for the different protocols available - */ - GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.deviceString = GENERIC_STAR_TRACKER_CFG_STRING; - GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.handle = GENERIC_STAR_TRACKER_CFG_HANDLE; - GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.isOpen = PORT_CLOSED; - GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.baud = GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ; - GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart.access_option = uart_access_flag_RDWR; - - /* Open device specific protocols */ - status = uart_init_port(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart); - if (status == OS_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_ENABLED; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_ENABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Device enabled"); - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_UART_INIT_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: UART port initialization error %d", status); - } - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_ENABLE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Device enable failed, already enabled"); - } - return; -} - - -/* -** Disable Component -** TODO: Edit for your specific component implementation -*/ -void GENERIC_STAR_TRACKER_Disable(void) -{ - int32 status = OS_SUCCESS; - - /* Check that device is enabled */ - if (GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled == GENERIC_STAR_TRACKER_DEVICE_ENABLED) - { - /* Open device specific protocols */ - status = uart_close_port(&GENERIC_STAR_TRACKER_AppData.Generic_star_trackerUart); - if (status == OS_SUCCESS) - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceCount++; - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceEnabled = GENERIC_STAR_TRACKER_DEVICE_DISABLED; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DISABLE_INF_EID, CFE_EVS_EventType_INFORMATION, "GENERIC_STAR_TRACKER: Device disabled"); - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_UART_CLOSE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: UART port close error %d", status); - } - } - else - { - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.DeviceErrorCount++; - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_DISABLE_ERR_EID, CFE_EVS_EventType_ERROR, "GENERIC_STAR_TRACKER: Device disable failed, already disabled"); - } - return; -} - - -/* -** Verify command packet length matches expected -*/ -int32 GENERIC_STAR_TRACKER_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length) -{ - int32 status = OS_SUCCESS; - CFE_SB_MsgId_t msg_id = CFE_SB_INVALID_MSG_ID; - CFE_MSG_FcnCode_t cmd_code = 0; - size_t actual_length = 0; - - CFE_MSG_GetSize(msg, &actual_length); - if (expected_length == actual_length) - { - /* Increment the command counter upon receipt of an invalid command */ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandCount++; - } - else - { - CFE_MSG_GetMsgId(msg, &msg_id); - CFE_MSG_GetFcnCode(msg, &cmd_code); - - CFE_EVS_SendEvent(GENERIC_STAR_TRACKER_LEN_ERR_EID, CFE_EVS_EventType_ERROR, - "Invalid msg length: ID = 0x%X, CC = %d, Len = %d, Expected = %d", - CFE_SB_MsgIdToValue(msg_id), cmd_code, actual_length, expected_length); - - status = OS_ERROR; - - /* Increment the command error counter upon receipt of an invalid command */ - GENERIC_STAR_TRACKER_AppData.HkTelemetryPkt.CommandErrorCount++; - } - return status; -} diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h deleted file mode 100644 index f28ac4ee..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_app.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_app.h -** -** Purpose: -** This is the main header file for the GENERIC_STAR_TRACKER application. -** -*******************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_APP_H_ -#define _GENERIC_STAR_TRACKER_APP_H_ - -/* -** Include Files -*/ -#include "cfe.h" -#include "generic_star_tracker_device.h" -#include "generic_star_tracker_events.h" -#include "generic_star_tracker_platform_cfg.h" -#include "generic_star_tracker_perfids.h" -#include "generic_star_tracker_msg.h" -#include "generic_star_tracker_msgids.h" -#include "generic_star_tracker_version.h" -#include "hwlib.h" - - -/* -** Specified pipe depth - how many messages will be queued in the pipe -*/ -#define GENERIC_STAR_TRACKER_PIPE_DEPTH 32 - - -/* -** Enabled and Disabled Definitions -*/ -#define GENERIC_STAR_TRACKER_DEVICE_DISABLED 0 -#define GENERIC_STAR_TRACKER_DEVICE_ENABLED 1 - - -/* -** GENERIC_STAR_TRACKER global data structure -** The cFE convention is to put all global app data in a single struct. -** This struct is defined in the `generic_star_tracker_app.h` file with one global instance -** in the `.c` file. -*/ -typedef struct -{ - /* - ** Housekeeping telemetry packet - ** Each app defines its own packet which contains its OWN telemetry - */ - GENERIC_STAR_TRACKER_Hk_tlm_t HkTelemetryPkt; /* GENERIC_STAR_TRACKER Housekeeping Telemetry Packet */ - - /* - ** Operational data - not reported in housekeeping - */ - CFE_MSG_Message_t * MsgPtr; /* Pointer to msg received on software bus */ - CFE_SB_PipeId_t CmdPipe; /* Pipe Id for HK command pipe */ - uint32 RunStatus; /* App run status for controlling the application state */ - - /* - ** Device data - ** TODO: Make specific to your application - */ - GENERIC_STAR_TRACKER_Device_tlm_t DevicePkt; /* Device specific data packet */ - - /* - ** Device protocol - ** TODO: Make specific to your application - */ - uart_info_t Generic_star_trackerUart; /* Hardware protocol definition */ - -} GENERIC_STAR_TRACKER_AppData_t; - - -/* -** Exported Data -** Extern the global struct in the header for the Unit Test Framework (UTF). -*/ -extern GENERIC_STAR_TRACKER_AppData_t GENERIC_STAR_TRACKER_AppData; /* GENERIC_STAR_TRACKER App Data */ - - -/* -** -** Local function prototypes. -** -** Note: Except for the entry point (GENERIC_STAR_TRACKER_AppMain), these -** functions are not called from any other source module. -*/ -void ST_AppMain(void); -int32 GENERIC_STAR_TRACKER_AppInit(void); -void GENERIC_STAR_TRACKER_ProcessCommandPacket(void); -void GENERIC_STAR_TRACKER_ProcessGroundCommand(void); -void GENERIC_STAR_TRACKER_ProcessTelemetryRequest(void); -void GENERIC_STAR_TRACKER_ReportHousekeeping(void); -void GENERIC_STAR_TRACKER_ReportDeviceTelemetry(void); -void GENERIC_STAR_TRACKER_ResetCounters(void); -void GENERIC_STAR_TRACKER_Enable(void); -void GENERIC_STAR_TRACKER_Disable(void); -int32 GENERIC_STAR_TRACKER_VerifyCmdLength(CFE_MSG_Message_t * msg, uint16 expected_length); - -#endif /* _GENERIC_STAR_TRACKER_APP_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c deleted file mode 100644 index 8069b255..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.c +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_device.c -** -** Purpose: -** This file contains the source code for the GENERIC_STAR_TRACKER device. -** -*******************************************************************************/ - -/* -** Include Files -*/ -#include "generic_star_tracker_device.h" - - -/* -** Generic read data from device -*/ -int32_t GENERIC_STAR_TRACKER_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length) -{ - int32_t status = OS_SUCCESS; - int32_t bytes = 0; - int32_t bytes_available = 0; - uint8_t ms_timeout_counter = 0; - - /* Wait until all data received or timeout occurs */ - bytes_available = uart_bytes_available(device); - while((bytes_available < data_length) && (ms_timeout_counter < GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT)) - { - ms_timeout_counter++; - OS_TaskDelay(1); - bytes_available = uart_bytes_available(device); - } - - if (ms_timeout_counter < GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT) - { - /* Limit bytes available */ - if (bytes_available > data_length) - { - bytes_available = data_length; - } - - /* Read data */ - bytes = uart_read_port(device, read_data, bytes_available); - if (bytes != bytes_available) - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_ReadData: Bytes read != to requested! \n"); - #endif - status = OS_ERROR; - } /* uart_read */ - } - else - { - status = OS_ERROR; - } /* ms_timeout_counter */ - - return status; -} - - -/* -** Generic command to device -** Note that confirming the echoed response is specific to this implementation -*/ -int32_t GENERIC_STAR_TRACKER_CommandDevice(uart_info_t* device, uint8_t cmd_code, uint32_t payload) -{ - int32_t status = OS_SUCCESS; - int32_t bytes = 0; - uint8_t write_data[GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE]; - uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE]; - - /* Prepare command */ - write_data[0] = GENERIC_STAR_TRACKER_DEVICE_HDR_0; - write_data[1] = GENERIC_STAR_TRACKER_DEVICE_HDR_1; - write_data[2] = cmd_code; - write_data[3] = payload >> 24; - write_data[4] = payload >> 16; - write_data[5] = payload >> 8; - write_data[6] = payload; - write_data[7] = GENERIC_STAR_TRACKER_DEVICE_TRAILER_0; - write_data[8] = GENERIC_STAR_TRACKER_DEVICE_TRAILER_1; - - /* Flush any prior data */ - status = uart_flush(device); - if (status == UART_SUCCESS) - { - /* Write data */ - bytes = uart_write_port(device, write_data, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_CommandDevice[%d] = ", bytes); - for (uint32_t i = 0; i < GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE; i++) - { - OS_printf("%02x", write_data[i]); - } - OS_printf("\n"); - #endif - if (bytes == GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE) - { - status = GENERIC_STAR_TRACKER_ReadData(device, read_data, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); - if (status == OS_SUCCESS) - { - /* Confirm echoed response */ - bytes = 0; - while ((bytes < (int32_t) GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE) && (status == OS_SUCCESS)) - { - if (read_data[bytes] != write_data[bytes]) - { - status = OS_ERROR; - } - bytes++; - } - } /* GENERIC_STAR_TRACKER_ReadData */ - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf("GENERIC_STAR_TRACKER_CommandDevice - GENERIC_STAR_TRACKER_ReadData returned %d \n", status); - #endif - } - } - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf("GENERIC_STAR_TRACKER_CommandDevice - uart_write_port returned %d, expected %d \n", bytes, GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE); - #endif - } /* uart_write */ - } /* uart_flush*/ - return status; -} - - -/* -** Request housekeeping command -*/ -int32_t GENERIC_STAR_TRACKER_RequestHK(uart_info_t* device, GENERIC_STAR_TRACKER_Device_HK_tlm_t* data) -{ - int32_t status = OS_SUCCESS; - uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_HK_SIZE]; - - /* Command device to send HK */ - status = GENERIC_STAR_TRACKER_CommandDevice(device, GENERIC_STAR_TRACKER_DEVICE_REQ_HK_CMD, 0); - if (status == OS_SUCCESS) - { - /* Read HK data */ - status = GENERIC_STAR_TRACKER_ReadData(device, read_data, sizeof(read_data)); - if (status == OS_SUCCESS) - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestHK = "); - for (uint32_t i = 0; i < sizeof(read_data); i++) - { - OS_printf("%02x", read_data[i]); - } - OS_printf("\n"); - #endif - - /* Verify data header and trailer */ - if ((read_data[0] == GENERIC_STAR_TRACKER_DEVICE_HDR_0) && - (read_data[1] == GENERIC_STAR_TRACKER_DEVICE_HDR_1) && - (read_data[14] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_0) && - (read_data[15] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_1) ) - { - data->DeviceCounter = read_data[2] << 24; - data->DeviceCounter |= read_data[3] << 16; - data->DeviceCounter |= read_data[4] << 8; - data->DeviceCounter |= read_data[5]; - - data->DeviceConfig = read_data[6] << 24; - data->DeviceConfig |= read_data[7] << 16; - data->DeviceConfig |= read_data[8] << 8; - data->DeviceConfig |= read_data[9]; - - data->DeviceStatus = read_data[10] << 24; - data->DeviceStatus |= read_data[11] << 16; - data->DeviceStatus |= read_data[12] << 8; - data->DeviceStatus |= read_data[13]; - - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); - OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); - OS_printf(" Config = 0x%08x \n", data->DeviceConfig); - OS_printf(" Status = 0x%08x \n", data->DeviceStatus); - OS_printf(" Trailer = 0x%02x%02x \n", read_data[14], read_data[15]); - #endif - } - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestHK: GENERIC_STAR_TRACKER_ReadData reported error %d \n", status); - #endif - status = OS_ERROR; - } - } /* GENERIC_STAR_TRACKER_ReadData */ - } - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestHK: GENERIC_STAR_TRACKER_CommandDevice reported error %d \n", status); - #endif - } - return status; -} - - -/* -** Request data command -*/ -int32_t GENERIC_STAR_TRACKER_RequestData(uart_info_t* device, GENERIC_STAR_TRACKER_Device_Data_tlm_t* data) -{ - int32_t status = OS_SUCCESS; - uint8_t read_data[GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE]; - - /* Command device to send HK */ - status = GENERIC_STAR_TRACKER_CommandDevice(device, GENERIC_STAR_TRACKER_DEVICE_REQ_DATA_CMD, 0); - if (status == OS_SUCCESS) - { - /* Read HK data */ - status = GENERIC_STAR_TRACKER_ReadData(device, read_data, sizeof(read_data)); - if (status == OS_SUCCESS) - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestData = "); - for (uint32_t i = 0; i < sizeof(read_data); i++) - { - OS_printf("%02x", read_data[i]); - } - OS_printf("\n"); - #endif - - /* Verify data header and trailer */ - if ((read_data[0] == GENERIC_STAR_TRACKER_DEVICE_HDR_0) && - (read_data[1] == GENERIC_STAR_TRACKER_DEVICE_HDR_1) && - (read_data[12] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_0) && - (read_data[13] == GENERIC_STAR_TRACKER_DEVICE_TRAILER_1) ) - { - data->DeviceCounter = read_data[2] << 24; - data->DeviceCounter |= read_data[3] << 16; - data->DeviceCounter |= read_data[4] << 8; - data->DeviceCounter |= read_data[5]; - - data->DeviceDataX = read_data[6] << 8; - data->DeviceDataX |= read_data[7]; - - data->DeviceDataY = read_data[8] << 8; - data->DeviceDataY |= read_data[9]; - - data->DeviceDataZ = read_data[10] << 8; - data->DeviceDataZ |= read_data[11]; - - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" Header = 0x%02x%02x \n", read_data[0], read_data[1]); - OS_printf(" Counter = 0x%08x \n", data->DeviceCounter); - OS_printf(" Data X = 0x%04x, %d \n", data->DeviceDataX, data->DeviceDataX); - OS_printf(" Data Y = 0x%04x, %d \n", data->DeviceDataY, data->DeviceDataY); - OS_printf(" Data Z = 0x%04x, %d \n", data->DeviceDataZ, data->DeviceDataZ); - OS_printf(" Trailer = 0x%02x%02x \n", read_data[12], read_data[13]); - #endif - } - } - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestData: Invalid data read! \n"); - #endif - status = OS_ERROR; - } /* GENERIC_STAR_TRACKER_ReadData */ - } - else - { - #ifdef GENERIC_STAR_TRACKER_CFG_DEBUG - OS_printf(" GENERIC_STAR_TRACKER_RequestData: GENERIC_STAR_TRACKER_CommandDevice reported error %d \n", status); - #endif - } - return status; -} diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h deleted file mode 100644 index 2f147e2a..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_device.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_device.h -** -** Purpose: -** This is the header file for the GENERIC_STAR_TRACKER device. -** -*******************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_DEVICE_H_ -#define _GENERIC_STAR_TRACKER_DEVICE_H_ - -/* -** Required header files. -*/ -#include "device_cfg.h" -#include "hwlib.h" -#include "generic_star_tracker_platform_cfg.h" - - -/* -** Type definitions -** TODO: Make specific to your application -*/ -#define GENERIC_STAR_TRACKER_DEVICE_HDR 0xDEAD -#define GENERIC_STAR_TRACKER_DEVICE_HDR_0 0xDE -#define GENERIC_STAR_TRACKER_DEVICE_HDR_1 0xAD - -#define GENERIC_STAR_TRACKER_DEVICE_NOOP_CMD 0x00 -#define GENERIC_STAR_TRACKER_DEVICE_REQ_HK_CMD 0x01 -#define GENERIC_STAR_TRACKER_DEVICE_REQ_DATA_CMD 0x02 -#define GENERIC_STAR_TRACKER_DEVICE_CFG_CMD 0x03 - -#define GENERIC_STAR_TRACKER_DEVICE_TRAILER 0xBEEF -#define GENERIC_STAR_TRACKER_DEVICE_TRAILER_0 0xBE -#define GENERIC_STAR_TRACKER_DEVICE_TRAILER_1 0xEF - -#define GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN 4 -#define GENERIC_STAR_TRACKER_DEVICE_CMD_SIZE 9 - -/* -** GENERIC_STAR_TRACKER device housekeeping telemetry definition -*/ -typedef struct -{ - uint32_t DeviceCounter; - uint32_t DeviceConfig; - uint32_t DeviceStatus; - -} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_HK_tlm_t; -#define GENERIC_STAR_TRACKER_DEVICE_HK_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_HK_tlm_t ) -#define GENERIC_STAR_TRACKER_DEVICE_HK_SIZE GENERIC_STAR_TRACKER_DEVICE_HK_LNGTH + GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN - - -/* -** GENERIC_STAR_TRACKER device data telemetry definition -*/ -typedef struct -{ - uint32_t DeviceCounter; - uint16_t DeviceDataX; - uint16_t DeviceDataY; - uint16_t DeviceDataZ; - -} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_Data_tlm_t; -#define GENERIC_STAR_TRACKER_DEVICE_DATA_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_Data_tlm_t ) -#define GENERIC_STAR_TRACKER_DEVICE_DATA_SIZE GENERIC_STAR_TRACKER_DEVICE_DATA_LNGTH + GENERIC_STAR_TRACKER_DEVICE_HDR_TRL_LEN - - -/* -** Prototypes -*/ -int32_t GENERIC_STAR_TRACKER_ReadData(uart_info_t* device, uint8_t* read_data, uint8_t data_length); -int32_t GENERIC_STAR_TRACKER_CommandDevice(uart_info_t* device, uint8_t cmd, uint32_t payload); -int32_t GENERIC_STAR_TRACKER_RequestHK(uart_info_t* device, GENERIC_STAR_TRACKER_Device_HK_tlm_t* data); -int32_t GENERIC_STAR_TRACKER_RequestData(uart_info_t* device, GENERIC_STAR_TRACKER_Device_Data_tlm_t* data); - - -#endif /* _GENERIC_STAR_TRACKER_DEVICE_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h deleted file mode 100644 index d51cca05..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_events.h +++ /dev/null @@ -1,47 +0,0 @@ -/************************************************************************ -** File: -** generic_star_tracker_events.h -** -** Purpose: -** Define GENERIC_STAR_TRACKER application event IDs -** -*************************************************************************/ - -#ifndef _GENERIC_STAR_TRACKER_EVENTS_H_ -#define _GENERIC_STAR_TRACKER_EVENTS_H_ - -/* Standard app event IDs */ -#define GENERIC_STAR_TRACKER_RESERVED_EID 0 -#define GENERIC_STAR_TRACKER_STARTUP_INF_EID 1 -#define GENERIC_STAR_TRACKER_LEN_ERR_EID 2 -#define GENERIC_STAR_TRACKER_PIPE_ERR_EID 3 -#define GENERIC_STAR_TRACKER_SUB_CMD_ERR_EID 4 -#define GENERIC_STAR_TRACKER_SUB_REQ_HK_ERR_EID 5 -#define GENERIC_STAR_TRACKER_PROCESS_CMD_ERR_EID 6 - -/* Standard command event IDs */ -#define GENERIC_STAR_TRACKER_CMD_ERR_EID 10 -#define GENERIC_STAR_TRACKER_CMD_NOOP_INF_EID 11 -#define GENERIC_STAR_TRACKER_CMD_RESET_INF_EID 12 -#define GENERIC_STAR_TRACKER_CMD_ENABLE_INF_EID 13 -#define GENERIC_STAR_TRACKER_ENABLE_INF_EID 14 -#define GENERIC_STAR_TRACKER_ENABLE_ERR_EID 15 -#define GENERIC_STAR_TRACKER_CMD_DISABLE_INF_EID 16 -#define GENERIC_STAR_TRACKER_DISABLE_INF_EID 17 -#define GENERIC_STAR_TRACKER_DISABLE_ERR_EID 18 - -/* Device specific command event IDs */ -#define GENERIC_STAR_TRACKER_CMD_CONFIG_INF_EID 20 - -/* Standard telemetry event IDs */ -#define GENERIC_STAR_TRACKER_DEVICE_TLM_ERR_EID 30 -#define GENERIC_STAR_TRACKER_REQ_HK_ERR_EID 31 - -/* Device specific telemetry event IDs */ -#define GENERIC_STAR_TRACKER_REQ_DATA_ERR_EID 32 - -/* Hardware protocol event IDs */ -#define GENERIC_STAR_TRACKER_UART_INIT_ERR_EID 40 -#define GENERIC_STAR_TRACKER_UART_CLOSE_ERR_EID 41 - -#endif /* _GENERIC_STAR_TRACKER_EVENTS_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h deleted file mode 100644 index 89708fdd..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_msg.h +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* -** File: -** generic_star_tracker_msg.h -** -** Purpose: -** Define GENERIC_STAR_TRACKER application commands and telemetry messages -** -*******************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_MSG_H_ -#define _GENERIC_STAR_TRACKER_MSG_H_ - -#include "cfe.h" -#include "generic_star_tracker_device.h" - - -/* -** Ground Command Codes -** TODO: Add additional commands required by the specific component -*/ -#define GENERIC_STAR_TRACKER_NOOP_CC 0 -#define GENERIC_STAR_TRACKER_RESET_COUNTERS_CC 1 -#define GENERIC_STAR_TRACKER_ENABLE_CC 2 -#define GENERIC_STAR_TRACKER_DISABLE_CC 3 -#define GENERIC_STAR_TRACKER_CONFIG_CC 4 - - -/* -** Telemetry Request Command Codes -** TODO: Add additional commands required by the specific component -*/ -#define GENERIC_STAR_TRACKER_REQ_HK_TLM 0 -#define GENERIC_STAR_TRACKER_REQ_DATA_TLM 1 - - -/* -** Generic "no arguments" command type definition -*/ -typedef struct -{ - /* Every command requires a header used to identify it */ - CFE_MSG_CommandHeader_t CmdHeader; - -} GENERIC_STAR_TRACKER_NoArgs_cmd_t; - - -/* -** GENERIC_STAR_TRACKER write configuration command -*/ -typedef struct -{ - CFE_MSG_CommandHeader_t CmdHeader; - uint32 DeviceCfg; - -} GENERIC_STAR_TRACKER_Config_cmd_t; - - -/* -** GENERIC_STAR_TRACKER device telemetry definition -*/ -typedef struct -{ - CFE_MSG_TelemetryHeader_t TlmHeader; - GENERIC_STAR_TRACKER_Device_Data_tlm_t Generic_star_tracker; - -} __attribute__((packed)) GENERIC_STAR_TRACKER_Device_tlm_t; -#define GENERIC_STAR_TRACKER_DEVICE_TLM_LNGTH sizeof ( GENERIC_STAR_TRACKER_Device_tlm_t ) - - -/* -** GENERIC_STAR_TRACKER housekeeping type definition -*/ -typedef struct -{ - CFE_MSG_TelemetryHeader_t TlmHeader; - uint8 CommandErrorCount; - uint8 CommandCount; - uint8 DeviceErrorCount; - uint8 DeviceCount; - - /* - ** TODO: Edit and add specific telemetry values to this struct - */ - uint8 DeviceEnabled; - GENERIC_STAR_TRACKER_Device_HK_tlm_t DeviceHK; - -} __attribute__((packed)) GENERIC_STAR_TRACKER_Hk_tlm_t; -#define GENERIC_STAR_TRACKER_HK_TLM_LNGTH sizeof ( GENERIC_STAR_TRACKER_Hk_tlm_t ) - -#endif /* _GENERIC_STAR_TRACKER_MSG_H_ */ diff --git a/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h b/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h deleted file mode 100644 index ec3ab848..00000000 --- a/components/generic_star_tracker/fsw/src/generic_star_tracker_version.h +++ /dev/null @@ -1,19 +0,0 @@ -/************************************************************************ -** File: -** $Id: generic_star_tracker_app_version.h $ -** -** Purpose: -** The Generic_star_tracker Application header file containing version number -** -*************************************************************************/ - -/* The Generic_star_tracker Application header file containing version number */ -#ifndef _GENERIC_STAR_TRACKER_VERSION_H_ -#define _GENERIC_STAR_TRACKER_VERSION_H_ - -#define GENERIC_STAR_TRACKER_MAJOR_VERSION 1 -#define GENERIC_STAR_TRACKER_MINOR_VERSION 0 -#define GENERIC_STAR_TRACKER_REVISION 0 -#define GENERIC_STAR_TRACKER_MISSION_REV 0 - -#endif diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt deleted file mode 100644 index 856a1627..00000000 --- a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_CMD.txt +++ /dev/null @@ -1,49 +0,0 @@ -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_NOOP_CC BIG_ENDIAN "Generic_star_tracker NOOP Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_RST_COUNTERS_CC BIG_ENDIAN "Generic_star_tracker Reset Counters Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_ENABLE_CC BIG_ENDIAN "Generic_star_tracker Enable Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 2 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_DISABLE_CC BIG_ENDIAN "Generic_star_tracker Disable Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 1 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 3 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_CONFIG_CC BIG_ENDIAN "Generic_star_tracker Configuration Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1935 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 5 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 4 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - APPEND_PARAMETER DEVICE_CONFIG 32 UINT MIN_UINT32 MAX_UINT32 0 "Device Configuration" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_REQ_HK BIG_ENDIAN "Generic_star_tracker Request HK Packet Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1936 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 0 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" - -COMMAND GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_REQ_DATA BIG_ENDIAN "Generic_star_tracker Request Data Packet Command" - APPEND_PARAMETER CCSDS_STREAMID 16 UINT MIN_UINT16 MAX_UINT16 0x1936 "CCSDS Packet Identification" - APPEND_PARAMETER CCSDS_SEQUENCE 16 UINT MIN_UINT16 MAX_UINT16 0xC000 "CCSDS Packet Sequence Control" - APPEND_PARAMETER CCSDS_LENGTH 16 UINT MIN_UINT16 MAX_UINT16 0 "CCSDS Packet Data Length" - APPEND_PARAMETER CCSDS_FC 8 UINT MIN_UINT8 MAX_UINT8 1 "CCSDS Command Function Code" - APPEND_PARAMETER CCSDS_CHECKSUM 8 UINT MIN_UINT8 MAX_UINT8 0 "CCSDS Command Checksum" diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt deleted file mode 100644 index 6f96b700..00000000 --- a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/cmd_tlm/GENERIC_STAR_TRACKER_TLM.txt +++ /dev/null @@ -1,44 +0,0 @@ -TELEMETRY GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_HK_TLM LITTLE_ENDIAN "GENERIC_STAR_TRACKER_Hk_tlm_t" - APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x0935 "CCSDS Packet Identification" BIG_ENDIAN - APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN - APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN - APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" - APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" - APPEND_ITEM CCSDS_SPARE 32 UINT "" - APPEND_ITEM CMD_ERR_COUNT 8 UINT "Command Error Count" - APPEND_ITEM CMD_COUNT 8 UINT "Command Count" - APPEND_ITEM DEVICE_ERR_COUNT 8 UINT "Device Command Error Count" - APPEND_ITEM DEVICE_COUNT 8 UINT "Device Command Count" - APPEND_ITEM DEVICE_ENABLED 8 UINT "Device Enable Status" - STATE DISABLED 0 - STATE ENABLED 1 - # GENERIC_STAR_TRACKER_Device_HK_tlm_t - APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" - APPEND_ITEM DEVICE_CONFIG 32 UINT "Reported Device Configuration" - APPEND_ITEM DEVICE_STATUS 32 UINT "Reported Device Status" - -TELEMETRY GENERIC_STAR_TRACKER GENERIC_STAR_TRACKER_DATA_TLM LITTLE_ENDIAN "GENERIC_STAR_TRACKER_Device_tlm_t" - APPEND_ID_ITEM CCSDS_STREAMID 16 UINT 0x0936 "CCSDS Packet Identification" BIG_ENDIAN - APPEND_ITEM CCSDS_SEQUENCE 16 UINT "CCSDS Packet Sequence Control" BIG_ENDIAN - APPEND_ITEM CCSDS_LENGTH 16 UINT "CCSDS Packet Data Length" BIG_ENDIAN - APPEND_ITEM CCSDS_SECONDS 32 UINT "CCSDS Telemetry Secondary Header (seconds)" - APPEND_ITEM CCSDS_SUBSECS 16 UINT "CCSDS Telemetry Secondary Header (subseconds)" - APPEND_ITEM CCSDS_SPARE 32 UINT "" - # GENERIC_STAR_TRACKER_Device_Data_tlm_t - APPEND_ITEM DEVICE_COUNTER 32 UINT "Reported Device Command Counter" - APPEND_ITEM RAW_GENERIC_STAR_TRACKER_X 16 UINT "Raw generic_star_tracker data x component (1-65535)" - APPEND_ITEM RAW_GENERIC_STAR_TRACKER_Y 16 UINT "Raw generic_star_tracker data y component (1-65535)" - APPEND_ITEM RAW_GENERIC_STAR_TRACKER_Z 16 UINT "Raw generic_star_tracker data z component (1-65535)" -# APPEND_ITEM PAD 16 UINT "Because the packed struct it came from has a stride address of 32 and cFS does not serialize" - APPEND_ITEM GENERIC_STAR_TRACKER_X 0 DERIVED "Generic_star_tracker data unit vector x component (-1.0 to 1.0)" - GENERIC_READ_CONVERSION_START FLOAT 32 - (packet.read("RAW_GENERIC_STAR_TRACKER_X") - 32768.0)/32767.0 - GENERIC_READ_CONVERSION_END - APPEND_ITEM GENERIC_STAR_TRACKER_Y 0 DERIVED "Generic_star_tracker data unit vector y component (-1.0 to 1.0)" - GENERIC_READ_CONVERSION_START FLOAT 32 - (packet.read("RAW_GENERIC_STAR_TRACKER_Y") - 32768.0)/32767.0 - GENERIC_READ_CONVERSION_END - APPEND_ITEM GENERIC_STAR_TRACKER_Z 0 DERIVED "Generic_star_tracker data unit vector z component (-1.0 to 1.0)" - GENERIC_READ_CONVERSION_START FLOAT 32 - (packet.read("RAW_GENERIC_STAR_TRACKER_Z") - 32768.0)/32767.0 - GENERIC_READ_CONVERSION_END diff --git a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt b/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt deleted file mode 100644 index f942b7ed..00000000 --- a/components/generic_star_tracker/gsw/GENERIC_STAR_TRACKER/target.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Ignored Parameters -# IGNORE_PARAMETER parameter_name - -# CCSDS -IGNORE_PARAMETER CCSDS_STREAMID -IGNORE_PARAMETER CCSDS_SEQUENCE -IGNORE_PARAMETER CCSDS_LENGTH -IGNORE_PARAMETER CCSDS_SPARE -IGNORE_PARAMETER CCSDS_FC -IGNORE_PARAMETER CCSDS_CHECKSUM diff --git a/components/generic_star_tracker/sim/CMakeLists.txt b/components/generic_star_tracker/sim/CMakeLists.txt deleted file mode 100644 index 86771748..00000000 --- a/components/generic_star_tracker/sim/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -project(generic_star_tracker_sim) - -find_package(ITC_Common REQUIRED QUIET COMPONENTS itc_logger) -find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart) - -include_directories(inc - ${sim_common_SOURCE_DIR}/inc - ${ITC_Common_INCLUDE_DIRS} - ${NOSENGINE_INCLUDE_DIRS}) - -set(generic_star_tracker_sim_src - src/generic_star_tracker_hardware_model.cpp - src/generic_star_tracker_42_data_provider.cpp - src/generic_star_tracker_data_provider.cpp - src/generic_star_tracker_data_point.cpp -) - -# For Code::Blocks and other IDEs -file(GLOB generic_star_tracker_sim_inc inc/*.hpp) - -set(generic_star_tracker_sim_libs - sim_common - ${ITC_Common_LIBRARIES} - ${NOSENGINE_LIBRARIES} -) - -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib") # Pick up .so in install directory - -add_library(generic_star_tracker_sim SHARED ${generic_star_tracker_sim_src} ${generic_star_tracker_sim_inc}) -target_link_libraries(generic_star_tracker_sim ${generic_star_tracker_sim_libs}) -install(TARGETS generic_star_tracker_sim LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp deleted file mode 100644 index 1351448b..00000000 --- a/components/generic_star_tracker/sim/inc/generic_star_tracker_42_data_provider.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NOS3_GENERIC_STAR_TRACKER42DATAPROVIDER_HPP -#define NOS3_GENERIC_STAR_TRACKER42DATAPROVIDER_HPP - -#include -#include -#include -#include - -namespace Nos3 -{ - /* Standard for a 42 data provider */ - class Generic_star_tracker42DataProvider : public SimData42SocketProvider - { - public: - /* Constructors */ - Generic_star_tracker42DataProvider(const boost::property_tree::ptree& config); - - /* Accessors */ - boost::shared_ptr get_data_point(void) const; - - private: - /* Disallow these */ - ~Generic_star_tracker42DataProvider(void) {}; - Generic_star_tracker42DataProvider& operator=(const Generic_star_tracker42DataProvider&) {return *this;}; - - int16_t _sc; /* Which spacecraft number to parse out of 42 data */ - }; -} - -#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp deleted file mode 100644 index 040cdd6d..00000000 --- a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_point.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef NOS3_GENERIC_STAR_TRACKERDATAPOINT_HPP -#define NOS3_GENERIC_STAR_TRACKERDATAPOINT_HPP - -#include -#include - -namespace Nos3 -{ - /* Standard for a data point used transfer data between a data provider and a hardware model */ - class Generic_star_trackerDataPoint : public Sim42DataPoint - { - public: - /* Constructors */ - Generic_star_trackerDataPoint(double count); - Generic_star_trackerDataPoint(int16_t spacecraft, const boost::shared_ptr dp); - - /* Accessors */ - /* Provide the hardware model a way to get the specific data out of the data point */ - std::string to_string(void) const; - double get_generic_star_tracker_data_x(void) const {parse_data_point(); return _generic_star_tracker_data[0];} - double get_generic_star_tracker_data_y(void) const {parse_data_point(); return _generic_star_tracker_data[1];} - double get_generic_star_tracker_data_z(void) const {parse_data_point(); return _generic_star_tracker_data[2];} - bool is_generic_star_tracker_data_valid(void) const {parse_data_point(); return _generic_star_tracker_data_is_valid;} - - private: - /* Disallow these */ - Generic_star_trackerDataPoint(void) {}; - Generic_star_trackerDataPoint(const Generic_star_trackerDataPoint& sdp) : Sim42DataPoint(sdp) {}; - ~Generic_star_trackerDataPoint(void) {}; - - // Private mutators - inline void parse_data_point(void) const {if (_not_parsed) do_parsing();} - void do_parsing(void) const; - - mutable Sim42DataPoint _dp; - int16_t _sc; - // mutable below so parsing can be on demand: - mutable bool _not_parsed; - /* Specific data you need to get from the data provider to the hardware model */ - /* You only get to this data through the accessors above */ - mutable bool _generic_star_tracker_data_is_valid; - mutable double _generic_star_tracker_data[3]; - }; -} - -#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp deleted file mode 100644 index 7ec09e95..00000000 --- a/components/generic_star_tracker/sim/inc/generic_star_tracker_data_provider.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef NOS3_GENERIC_STAR_TRACKERDATAPROVIDER_HPP -#define NOS3_GENERIC_STAR_TRACKERDATAPROVIDER_HPP - -#include -#include -#include -#include - -namespace Nos3 -{ - class Generic_star_trackerDataProvider : public SimIDataProvider - { - public: - /* Constructors */ - Generic_star_trackerDataProvider(const boost::property_tree::ptree& config); - - /* Accessors */ - boost::shared_ptr get_data_point(void) const; - - private: - /* Disallow these */ - ~Generic_star_trackerDataProvider(void) {}; - Generic_star_trackerDataProvider& operator=(const Generic_star_trackerDataProvider&) {return *this;}; - - mutable double _request_count; - }; -} - -#endif diff --git a/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp b/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp deleted file mode 100644 index 64a4ec63..00000000 --- a/components/generic_star_tracker/sim/inc/generic_star_tracker_hardware_model.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef NOS3_GENERIC_STAR_TRACKERHARDWAREMODEL_HPP -#define NOS3_GENERIC_STAR_TRACKERHARDWAREMODEL_HPP - -/* -** Includes -*/ -#include - -#include -#include - -#include -#include /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ - -#include -#include -#include - - -/* -** Defines -*/ -#define GENERIC_STAR_TRACKER_SIM_SUCCESS 0 -#define GENERIC_STAR_TRACKER_SIM_ERROR 1 - - -/* -** Namespace -*/ -namespace Nos3 -{ - /* Standard for a hardware model */ - class Generic_star_trackerHardwareModel : public SimIHardwareModel - { - public: - /* Constructor and destructor */ - Generic_star_trackerHardwareModel(const boost::property_tree::ptree& config); - ~Generic_star_trackerHardwareModel(void); - - private: - /* Private helper methods */ - void create_generic_star_tracker_hk(std::vector& out_data); - void create_generic_star_tracker_data(std::vector& out_data); - void uart_read_callback(const uint8_t *buf, size_t len); /* Handle data the hardware receives from its protocol bus */ - void command_callback(NosEngine::Common::Message msg); /* Handle backdoor commands and time tick to the simulator */ - - /* Private data members */ - std::unique_ptr _uart_connection; /* TODO: Change if your protocol bus is different (e.g. SPI, I2C, etc.) */ - std::unique_ptr _time_bus; /* Standard */ - - SimIDataProvider* _generic_star_tracker_dp; /* Only needed if the sim has a data provider */ - - /* Internal state data */ - std::uint8_t _enabled; - std::uint32_t _count; - std::uint32_t _config; - std::uint32_t _status; - }; -} - -#endif diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp deleted file mode 100644 index d303b106..00000000 --- a/components/generic_star_tracker/sim/src/generic_star_tracker_42_data_provider.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -namespace Nos3 -{ - REGISTER_DATA_PROVIDER(Generic_star_tracker42DataProvider,"GENERIC_STAR_TRACKER_42_PROVIDER"); - - extern ItcLogger::Logger *sim_logger; - - Generic_star_tracker42DataProvider::Generic_star_tracker42DataProvider(const boost::property_tree::ptree& config) : SimData42SocketProvider(config) - { - sim_logger->trace("Generic_star_tracker42DataProvider::Generic_star_tracker42DataProvider: Constructor executed"); - - connect_reader_thread_as_42_socket_client( - config.get("simulator.hardware-model.data-provider.hostname", "localhost"), - config.get("simulator.hardware-model.data-provider.port", 4242) ); - - _sc = config.get("simulator.hardware-model.data-provider.spacecraft", 0); - } - - boost::shared_ptr Generic_star_tracker42DataProvider::get_data_point(void) const - { - sim_logger->trace("Generic_star_tracker42DataProvider::get_data_point: Executed"); - - /* Get the 42 data */ - const boost::shared_ptr dp42 = boost::dynamic_pointer_cast(SimData42SocketProvider::get_data_point()); - - /* Prepare the specific data */ - SimIDataPoint *dp = new Generic_star_trackerDataPoint(_sc, dp42); - - return boost::shared_ptr(dp); - } -} diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp deleted file mode 100644 index fbca9a77..00000000 --- a/components/generic_star_tracker/sim/src/generic_star_tracker_data_point.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -namespace Nos3 -{ - extern ItcLogger::Logger *sim_logger; - - Generic_star_trackerDataPoint::Generic_star_trackerDataPoint(double count) - { - sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Defined Constructor executed"); - - /* Do calculations based on provided data */ - _generic_star_tracker_data_is_valid = true; - _generic_star_tracker_data[0] = count * 0.001; - _generic_star_tracker_data[1] = count * 0.002; - _generic_star_tracker_data[2] = count * 0.003; - } - - Generic_star_trackerDataPoint::Generic_star_trackerDataPoint(int16_t spacecraft, const boost::shared_ptr dp) : _dp(*dp), _sc(spacecraft) - { - sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: 42 Constructor executed"); - - /* Initialize data */ - _generic_star_tracker_data_is_valid = false; - _generic_star_tracker_data[0] = _generic_star_tracker_data[1] = _generic_star_tracker_data[2] = 0.0; - } - - void Generic_star_trackerDataPoint::do_parsing(void) const - { - try { - /* - ** Declare 42 telemetry string prefix - ** 42 variables defined in `42/Include/42types.h` - ** 42 data stream defined in `42/Source/IPC/SimWriteToSocket.c` - */ - std::string key; - key.append("SC[").append(std::to_string(_sc)).append("].svb"); // SC[N].svb - - /* Parse 42 telemetry */ - std::string values = _dp.get_value_for_key(key); - - std::vector data; - parse_double_vector(values, data); - - _generic_star_tracker_data[0] = data[0]; - _generic_star_tracker_data[1] = data[1]; - _generic_star_tracker_data[2] = data[2]; - - /* Mark data as valid */ - _generic_star_tracker_data_is_valid = true; - - _not_parsed = false; - - /* Debug print */ - sim_logger->trace("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Parsed svb = %f %f %f", _generic_star_tracker_data[0], _generic_star_tracker_data[1], _generic_star_tracker_data[2]); - } catch (const std::exception &e) { - sim_logger->error("Generic_star_trackerDataPoint::Generic_star_trackerDataPoint: Error parsing svb. Error=%s", e.what()); - } - } - - /* Used for printing a representation of the data point */ - std::string Generic_star_trackerDataPoint::to_string(void) const - { - sim_logger->trace("Generic_star_trackerDataPoint::to_string: Executed"); - - std::stringstream ss; - - ss << std::fixed << std::setfill(' '); - ss << "Generic_star_tracker Data Point: Valid: "; - ss << (_generic_star_tracker_data_is_valid ? "Valid" : "INVALID"); - ss << std::setprecision(std::numeric_limits::digits10); /* Full double precision */ - ss << " Generic_star_tracker Data: " - << _generic_star_tracker_data[0] - << " " - << _generic_star_tracker_data[1] - << " " - << _generic_star_tracker_data[2]; - - return ss.str(); - } -} /* namespace Nos3 */ diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp deleted file mode 100644 index 280da146..00000000 --- a/components/generic_star_tracker/sim/src/generic_star_tracker_data_provider.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -namespace Nos3 -{ - REGISTER_DATA_PROVIDER(Generic_star_trackerDataProvider,"GENERIC_STAR_TRACKER_PROVIDER"); - - extern ItcLogger::Logger *sim_logger; - - Generic_star_trackerDataProvider::Generic_star_trackerDataProvider(const boost::property_tree::ptree& config) : SimIDataProvider(config) - { - sim_logger->trace("Generic_star_trackerDataProvider::Generic_star_trackerDataProvider: Constructor executed"); - _request_count = 0; - } - - boost::shared_ptr Generic_star_trackerDataProvider::get_data_point(void) const - { - sim_logger->trace("Generic_star_trackerDataProvider::get_data_point: Executed"); - - /* Prepare the provider data */ - _request_count++; - - /* Request a data point */ - SimIDataPoint *dp = new Generic_star_trackerDataPoint(_request_count); - - /* Return the data point */ - return boost::shared_ptr(dp); - } -} diff --git a/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp b/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp deleted file mode 100644 index 25410a23..00000000 --- a/components/generic_star_tracker/sim/src/generic_star_tracker_hardware_model.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#include - -namespace Nos3 -{ - REGISTER_HARDWARE_MODEL(Generic_star_trackerHardwareModel,"GENERIC_STAR_TRACKER"); - - extern ItcLogger::Logger *sim_logger; - - Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel(const boost::property_tree::ptree& config) : SimIHardwareModel(config), - _enabled(GENERIC_STAR_TRACKER_SIM_ERROR), _count(0), _config(0), _status(0) - { - /* Get the NOS engine connection string */ - std::string connection_string = config.get("common.nos-connection-string", "tcp://127.0.0.1:12001"); - sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: NOS Engine connection string: %s.", connection_string.c_str()); - - /* Get a data provider */ - std::string dp_name = config.get("simulator.hardware-model.data-provider.type", "GENERIC_STAR_TRACKER_PROVIDER"); - _generic_star_tracker_dp = SimDataProviderFactory::Instance().Create(dp_name, config); - sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Data provider %s created.", dp_name.c_str()); - - /* Get on a protocol bus */ - /* Note: Initialized defaults in case value not found in config file */ - std::string bus_name = "usart_29"; - int node_port = 29; - if (config.get_child_optional("simulator.hardware-model.connections")) - { - /* Loop through the connections for hardware model */ - BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("simulator.hardware-model.connections")) - { - /* v.second is the child tree (v.first is the name of the child) */ - if (v.second.get("type", "").compare("usart") == 0) - { - /* Configuration found */ - bus_name = v.second.get("bus-name", bus_name); - node_port = v.second.get("node-port", node_port); - break; - } - } - } - _uart_connection.reset(new NosEngine::Uart::Uart(_hub, config.get("simulator.name", "generic_star_tracker_sim"), connection_string, bus_name)); - _uart_connection->open(node_port); - sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Now on UART bus name %s, port %d.", bus_name.c_str(), node_port); - - /* Configure protocol callback */ - _uart_connection->set_read_callback(std::bind(&Generic_star_trackerHardwareModel::uart_read_callback, this, std::placeholders::_1, std::placeholders::_2)); - - /* Get on the command bus*/ - std::string time_bus_name = "command"; - if (config.get_child_optional("hardware-model.connections")) - { - /* Loop through the connections for the hardware model */ - BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, config.get_child("hardware-model.connections")) - { - /* v.first is the name of the child */ - /* v.second is the child tree */ - if (v.second.get("type", "").compare("time") == 0) // - { - time_bus_name = v.second.get("bus-name", "command"); - /* Found it... don't need to go through any more items*/ - break; - } - } - } - _time_bus.reset(new NosEngine::Client::Bus(_hub, connection_string, time_bus_name)); - sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Now on time bus named %s.", time_bus_name.c_str()); - - /* Construction complete */ - sim_logger->info("Generic_star_trackerHardwareModel::Generic_star_trackerHardwareModel: Construction complete."); - } - - - Generic_star_trackerHardwareModel::~Generic_star_trackerHardwareModel(void) - { - /* Close the protocol bus */ - _uart_connection->close(); - - /* Clean up the data provider */ - delete _generic_star_tracker_dp; - _generic_star_tracker_dp = nullptr; - - /* The bus will clean up the time node */ - } - - - /* Automagically set up by the base class to be called */ - void Generic_star_trackerHardwareModel::command_callback(NosEngine::Common::Message msg) - { - /* Get the data out of the message */ - NosEngine::Common::DataBufferOverlay dbf(const_cast(msg.buffer)); - sim_logger->info("Generic_star_trackerHardwareModel::command_callback: Received command: %s.", dbf.data); - - /* Do something with the data */ - std::string command = dbf.data; - std::string response = "Generic_star_trackerHardwareModel::command_callback: INVALID COMMAND! (Try HELP)"; - boost::to_upper(command); - if (command.compare("HELP") == 0) - { - response = "Generic_star_trackerHardwareModel::command_callback: Valid commands are HELP, ENABLE, DISABLE, STATUS=X, or STOP"; - } - else if (command.compare(0,6,"ENABLE") == 0) - { - _enabled = GENERIC_STAR_TRACKER_SIM_SUCCESS; - response = "Generic_star_trackerHardwareModel::command_callback: Enabled\n"; - } - else if (command.compare(0,7,"DISABLE") == 0) - { - _enabled = GENERIC_STAR_TRACKER_SIM_ERROR; - _count = 0; - _config = 0; - _status = 0; - response = "Generic_star_trackerHardwareModel::command_callback: Disabled"; - } - else if (command.substr(0,7).compare("STATUS=") == 0) - { - try - { - _status = std::stod(command.substr(7)); - response = "Generic_star_trackerHardwareModel::command_callback: Status set"; - } - catch (...) - { - response = "Generic_star_trackerHardwareModel::command_callback: Status invalid"; - } - } - else if (command.compare(0,4,"STOP") == 0) - { - _keep_running = false; - response = "Generic_star_trackerHardwareModel::command_callback: Stopping"; - } - /* TODO: Add anything additional commands here */ - - /* Send a reply */ - sim_logger->info("Generic_star_trackerHardwareModel::command_callback: Sending reply: %s", response.c_str()); - _command_node->send_reply_message_async(msg, response.size(), response.c_str()); - } - - - /* Custom function to prepare the Generic_star_tracker HK telemetry */ - void Generic_star_trackerHardwareModel::create_generic_star_tracker_hk(std::vector& out_data) - { - /* Prepare data size */ - out_data.resize(16, 0x00); - - /* Streaming data header - 0xDEAD */ - out_data[0] = 0xDE; - out_data[1] = 0xAD; - - /* Sequence count */ - out_data[2] = (_count >> 24) & 0x000000FF; - out_data[3] = (_count >> 16) & 0x000000FF; - out_data[4] = (_count >> 8) & 0x000000FF; - out_data[5] = _count & 0x000000FF; - - /* Configuration */ - out_data[6] = (_config >> 24) & 0x000000FF; - out_data[7] = (_config >> 16) & 0x000000FF; - out_data[8] = (_config >> 8) & 0x000000FF; - out_data[9] = _config & 0x000000FF; - - /* Device Status */ - out_data[10] = (_status >> 24) & 0x000000FF; - out_data[11] = (_status >> 16) & 0x000000FF; - out_data[12] = (_status >> 8) & 0x000000FF; - out_data[13] = _status & 0x000000FF; - - /* Streaming data trailer - 0xBEEF */ - out_data[14] = 0xBE; - out_data[15] = 0xEF; - } - - - /* Custom function to prepare the Generic_star_tracker Data */ - void Generic_star_trackerHardwareModel::create_generic_star_tracker_data(std::vector& out_data) - { - boost::shared_ptr data_point = boost::dynamic_pointer_cast(_generic_star_tracker_dp->get_data_point()); - - /* Prepare data size */ - out_data.resize(14, 0x00); - - /* Streaming data header - 0xDEAD */ - out_data[0] = 0xDE; - out_data[1] = 0xAD; - - /* Sequence count */ - out_data[2] = (_count >> 24) & 0x000000FF; - out_data[3] = (_count >> 16) & 0x000000FF; - out_data[4] = (_count >> 8) & 0x000000FF; - out_data[5] = _count & 0x000000FF; - - /* - ** Payload - ** - ** Device is big engian (most significant byte first) - ** Assuming data is valid regardless of dynamic / environmental data - ** Floating poing numbers are extremely problematic - ** (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) - ** Most hardware transmits some type of unsigned integer (e.g. from an ADC), so that's what we've done - ** Scale each of the x, y, z (which are in the range [-1.0, 1.0]) by 32767, - ** and add 32768 so that the result fits in a uint16 - */ - double dx = data_point->get_generic_star_tracker_data_x(); - double dy = data_point->get_generic_star_tracker_data_y(); - double dz = data_point->get_generic_star_tracker_data_z(); - uint16_t x = (uint16_t)(dx*32767.0 + 32768.0); - out_data[6] = (x >> 8) & 0x00FF; - out_data[7] = x & 0x00FF; - uint16_t y = (uint16_t)(dy*32767.0 + 32768.0); - out_data[8] = (y >> 8) & 0x00FF; - out_data[9] = y & 0x00FF; - uint16_t z = (uint16_t)(dz*32767.0 + 32768.0); - out_data[10] = (z >> 8) & 0x00FF; - out_data[11] = z & 0x00FF; - - sim_logger->debug("Generic_star_trackerHardwareModel::create_generic_star_tracker_data: data_point=%f, %f, %f, converted values=%u, %u, %u.", dx, dy, dz, x, y, z); - - /* Streaming data trailer - 0xBEEF */ - out_data[12] = 0xBE; - out_data[13] = 0xEF; - } - - - /* Protocol callback */ - void Generic_star_trackerHardwareModel::uart_read_callback(const uint8_t *buf, size_t len) - { - std::vector out_data; - std::uint8_t valid = GENERIC_STAR_TRACKER_SIM_SUCCESS; - - /* Retrieve data and log in man readable format */ - std::vector in_data(buf, buf + len); - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: REQUEST %s", - SimIHardwareModel::uint8_vector_to_hex_string(in_data).c_str()); - - /* Check simulator is enabled */ - if (_enabled != GENERIC_STAR_TRACKER_SIM_SUCCESS) - { - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Generic_star_tracker sim disabled!"); - valid = GENERIC_STAR_TRACKER_SIM_ERROR; - } - else - { - /* Check if message is incorrect size */ - if (in_data.size() != 9) - { - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Invalid command size of %d received!", in_data.size()); - valid = GENERIC_STAR_TRACKER_SIM_ERROR; - } - else - { - /* Check header - 0xDEAD */ - if ((in_data[0] != 0xDE) || (in_data[1] !=0xAD)) - { - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Header incorrect!"); - valid = GENERIC_STAR_TRACKER_SIM_ERROR; - } - else - { - /* Check trailer - 0xBEEF */ - if ((in_data[7] != 0xBE) || (in_data[8] !=0xEF)) - { - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Trailer incorrect!"); - valid = GENERIC_STAR_TRACKER_SIM_ERROR; - } - else - { - /* Increment count as valid command format received */ - _count++; - } - } - } - - if (valid == GENERIC_STAR_TRACKER_SIM_SUCCESS) - { - /* Process command */ - switch (in_data[2]) - { - case 0: - /* NOOP */ - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: NOOP command received!"); - break; - - case 1: - /* Request HK */ - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Send HK command received!"); - create_generic_star_tracker_hk(out_data); - break; - - case 2: - /* Request data */ - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Send data command received!"); - create_generic_star_tracker_data(out_data); - break; - - case 3: - /* Configuration */ - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Configuration command received!"); - _config = in_data[3] << 24; - _config |= in_data[4] << 16; - _config |= in_data[5] << 8; - _config |= in_data[6]; - break; - - default: - /* Unused command code */ - valid = GENERIC_STAR_TRACKER_SIM_ERROR; - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: Unused command %d received!", in_data[2]); - break; - } - } - } - - /* Increment count and echo command since format valid */ - if (valid == GENERIC_STAR_TRACKER_SIM_SUCCESS) - { - _count++; - _uart_connection->write(&in_data[0], in_data.size()); - - /* Send response if existing */ - if (out_data.size() > 0) - { - sim_logger->debug("Generic_star_trackerHardwareModel::uart_read_callback: REPLY %s", - SimIHardwareModel::uint8_vector_to_hex_string(out_data).c_str()); - _uart_connection->write(&out_data[0], out_data.size()); - } - } - } -} diff --git a/components/generic_star_tracker/support/CMakeLists.txt b/components/generic_star_tracker/support/CMakeLists.txt deleted file mode 100644 index 4cdc88d0..00000000 --- a/components/generic_star_tracker/support/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -cmake_minimum_required(VERSION 2.6.4) - -project (generic_star_tracker_checkout) - -if (NOT DEFINED TGTNAME) - message(FATAL_ERROR "TGTNAME must be defined on the cmake command line (e.g. \"-DTGTNAME=cpu1\")") -endif() - -if(${TGTNAME} STREQUAL cpu1) - SET(CMAKE_C_FLAGS_INIT "-m32" CACHE STRING "C Flags required by platform") - SET(CMAKE_C_FLAGS "-m32" CACHE STRING "C Flags required by platform") -endif() - -include(../../ComponentSettings.cmake) - -if(${TGTNAME} STREQUAL cpu1) - find_path(_ITC_CMAKE_MODULES_ - NAMES FindITC_Common.cmake - PATHS ${ITC_CMAKE_MODULES} - ${ITC_DEV_ROOT}/cmake/modules - $ENV{ITC_DEV_ROOT}/cmake/modules - /usr/local/cmake/modules - /usr/cmake/modules) - if(NOT _ITC_CMAKE_MODULES_) - message(WARNING "Unable to find ITC CMake Modules") - endif() - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${_ITC_CMAKE_MODULES_}) - - find_package(NOSENGINE REQUIRED QUIET COMPONENTS common transport client uart can i2c spi) -endif() - -include_directories("./") -include_directories("../fsw/platform_inc") -include_directories("../fsw/src") -include_directories("../../../fsw/apps/hwlib/fsw/public_inc") - -set(generic_star_tracker_checkout_src - generic_star_tracker_checkout.c - ../fsw/src/generic_star_tracker_device.c -) - -if(${TGTNAME} STREQUAL cpu1) - include_directories("../../../fsw/apps/hwlib/sim/inc") - set(generic_star_tracker_checkout_src - ${generic_star_tracker_checkout_src} - ../../../fsw/apps/hwlib/sim/src/libuart.c - ../../../fsw/apps/hwlib/sim/src/libcan.c - ../../../fsw/apps/hwlib/sim/src/libi2c.c - ../../../fsw/apps/hwlib/sim/src/libspi.c - ../../../fsw/apps/hwlib/sim/src/nos_link.c - ) - set(generic_star_tracker_checkout_libs - ${ITC_Common_LIBRARIES} - ${NOSENGINE_LIBRARIES} - ) -endif() -if(${TGTNAME} STREQUAL cpu2) - set(generic_star_tracker_checkout_src - ${generic_star_tracker_checkout_src} - ../../../fsw/apps/hwlib/fsw/linux/libuart.c - ) -endif() - -add_executable(generic_star_tracker_checkout ${generic_star_tracker_checkout_src}) -target_link_libraries(generic_star_tracker_checkout ${generic_star_tracker_checkout_libs}) - -if(${TGTNAME} STREQUAL cpu1) - set_target_properties(generic_star_tracker_checkout PROPERTIES COMPILE_FLAGS "-m32 -g" LINK_FLAGS "-m32 -g") -endif() diff --git a/components/generic_star_tracker/support/device_cfg.h b/components/generic_star_tracker/support/device_cfg.h deleted file mode 100644 index 17337adb..00000000 --- a/components/generic_star_tracker/support/device_cfg.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ -#define _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ - -/* -** GENERIC_STAR_TRACKER Checkout Configuration -*/ -#define GENERIC_STAR_TRACKER_CFG -/* Note: NOS3 uart requires matching handle and bus number */ -#define GENERIC_STAR_TRACKER_CFG_STRING "/dev/usart_29" -#define GENERIC_STAR_TRACKER_CFG_HANDLE 29 -#define GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ 115200 -#define GENERIC_STAR_TRACKER_CFG_MS_TIMEOUT 250 -#define GENERIC_STAR_TRACKER_CFG_DEBUG - -#endif /* _GENERIC_STAR_TRACKER_CHECKOUT_DEVICE_CFG_H_ */ diff --git a/components/generic_star_tracker/support/generic_star_tracker_checkout.c b/components/generic_star_tracker/support/generic_star_tracker_checkout.c deleted file mode 100644 index 2f19a34f..00000000 --- a/components/generic_star_tracker/support/generic_star_tracker_checkout.c +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_checkout.c -** -** Purpose: -** This checkout can be run without cFS and is used to quickly develop and -** test functions required for a specific component. -** -*******************************************************************************/ - -/* -** Include Files -*/ -#include "generic_star_tracker_checkout.h" - - -/* -** Global Variables -*/ -uart_info_t Generic_star_trackerUart; -GENERIC_STAR_TRACKER_Device_HK_tlm_t Generic_star_trackerHK; -GENERIC_STAR_TRACKER_Device_Data_tlm_t Generic_star_trackerData; - -/* -** Component Functions -*/ -void print_help(void) -{ - printf(PROMPT "command [args]\n" - "---------------------------------------------------------------------\n" - "help - Display help \n" - "exit - Exit app \n" - "noop - No operation command to device \n" - " n - ^ \n" - "hk - Request device housekeeping \n" - " h - ^ \n" - "generic_star_tracker - Request generic_star_tracker data \n" - " s - ^ \n" - "cfg # - Send configuration # \n" - " c # - ^ \n" - "\n" - ); -} - - -int get_command(const char* str) -{ - int status = CMD_UNKNOWN; - char lcmd[MAX_INPUT_TOKEN_SIZE]; - strncpy(lcmd, str, MAX_INPUT_TOKEN_SIZE); - - /* Convert command to lower case */ - to_lower(lcmd); - - if(strcmp(lcmd, "help") == 0) - { - status = CMD_HELP; - } - else if(strcmp(lcmd, "exit") == 0) - { - status = CMD_EXIT; - } - else if(strcmp(lcmd, "noop") == 0) - { - status = CMD_NOOP; - } - else if(strcmp(lcmd, "n") == 0) - { - status = CMD_NOOP; - } - else if(strcmp(lcmd, "hk") == 0) - { - status = CMD_HK; - } - else if(strcmp(lcmd, "h") == 0) - { - status = CMD_HK; - } - else if(strcmp(lcmd, "generic_star_tracker") == 0) - { - status = CMD_GENERIC_STAR_TRACKER; - } - else if(strcmp(lcmd, "s") == 0) - { - status = CMD_GENERIC_STAR_TRACKER; - } - else if(strcmp(lcmd, "cfg") == 0) - { - status = CMD_CFG; - } - else if(strcmp(lcmd, "c") == 0) - { - status = CMD_CFG; - } - return status; -} - - -int process_command(int cc, int num_tokens, char tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]) -{ - int32_t status = OS_SUCCESS; - int32_t exit_status = OS_SUCCESS; - uint32_t config; - - /* Process command */ - switch(cc) - { - case CMD_HELP: - print_help(); - break; - - case CMD_EXIT: - exit_status = OS_ERROR; - break; - - case CMD_NOOP: - if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) - { - status = GENERIC_STAR_TRACKER_CommandDevice(&Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_NOOP_CMD, 0); - if (status == OS_SUCCESS) - { - OS_printf("NOOP command success\n"); - } - else - { - OS_printf("NOOP command failed!\n"); - } - } - break; - - case CMD_HK: - if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) - { - status = GENERIC_STAR_TRACKER_RequestHK(&Generic_star_trackerUart, &Generic_star_trackerHK); - if (status == OS_SUCCESS) - { - OS_printf("GENERIC_STAR_TRACKER_RequestHK command success\n"); - } - else - { - OS_printf("GENERIC_STAR_TRACKER_RequestHK command failed!\n"); - } - } - break; - - case CMD_GENERIC_STAR_TRACKER: - if (check_number_arguments(num_tokens, 0) == OS_SUCCESS) - { - status = GENERIC_STAR_TRACKER_RequestData(&Generic_star_trackerUart, &Generic_star_trackerData); - if (status == OS_SUCCESS) - { - OS_printf("GENERIC_STAR_TRACKER_RequestData command success\n"); - } - else - { - OS_printf("GENERIC_STAR_TRACKER_RequestData command failed!\n"); - } - } - break; - - case CMD_CFG: - if (check_number_arguments(num_tokens, 1) == OS_SUCCESS) - { - config = atoi(tokens[0]); - status = GENERIC_STAR_TRACKER_CommandDevice(&Generic_star_trackerUart, GENERIC_STAR_TRACKER_DEVICE_CFG_CMD, config); - if (status == OS_SUCCESS) - { - OS_printf("Configuration command success with value %u\n", config); - } - else - { - OS_printf("Configuration command failed!\n"); - } - } - break; - - default: - OS_printf("Invalid command format, type 'help' for more info\n"); - break; - } - return exit_status; -} - - -int main(int argc, char *argv[]) -{ - int status = OS_SUCCESS; - char input_buf[MAX_INPUT_BUF]; - char input_tokens[MAX_INPUT_TOKENS][MAX_INPUT_TOKEN_SIZE]; - int num_input_tokens; - int cmd; - char* token_ptr; - uint8_t run_status = OS_SUCCESS; - - /* Open device specific protocols */ - Generic_star_trackerUart.deviceString = GENERIC_STAR_TRACKER_CFG_STRING; - Generic_star_trackerUart.handle = GENERIC_STAR_TRACKER_CFG_HANDLE; - Generic_star_trackerUart.isOpen = PORT_CLOSED; - Generic_star_trackerUart.baud = GENERIC_STAR_TRACKER_CFG_BAUDRATE_HZ; - status = uart_init_port(&Generic_star_trackerUart); - if (status == OS_SUCCESS) - { - printf("UART device %s configured with baudrate %d \n", Generic_star_trackerUart.deviceString, Generic_star_trackerUart.baud); - } - else - { - printf("UART device %s failed to initialize! \n", Generic_star_trackerUart.deviceString); - run_status = OS_ERROR; - } - - /* Main loop */ - print_help(); - while(run_status == OS_SUCCESS) - { - num_input_tokens = -1; - cmd = CMD_UNKNOWN; - - /* Read user input */ - printf(PROMPT); - fgets(input_buf, MAX_INPUT_BUF, stdin); - - /* Tokenize line buffer */ - token_ptr = strtok(input_buf, " \t\n"); - while((num_input_tokens < MAX_INPUT_TOKENS) && (token_ptr != NULL)) - { - if(num_input_tokens == -1) - { - /* First token is command */ - cmd = get_command(token_ptr); - } - else - { - strncpy(input_tokens[num_input_tokens], token_ptr, MAX_INPUT_TOKEN_SIZE); - } - token_ptr = strtok(NULL, " \t\n"); - num_input_tokens++; - } - - /* Process command if valid */ - if(num_input_tokens >= 0) - { - /* Process command */ - run_status = process_command(cmd, num_input_tokens, input_tokens); - } - } - - // Close the device - uart_close_port(&Generic_star_trackerUart); - - OS_printf("Cleanly exiting generic_star_tracker application...\n\n"); - return 1; -} - - -/* -** Generic Functions -*/ -int check_number_arguments(int actual, int expected) -{ - int status = OS_SUCCESS; - if (actual != expected) - { - status = OS_ERROR; - OS_printf("Invalid command format, type 'help' for more info\n"); - } - return status; -} - -void to_lower(char* str) -{ - char* ptr = str; - while(*ptr) - { - *ptr = tolower((unsigned char) *ptr); - ptr++; - } - return; -} - diff --git a/components/generic_star_tracker/support/generic_star_tracker_checkout.h b/components/generic_star_tracker/support/generic_star_tracker_checkout.h deleted file mode 100644 index 27bc5608..00000000 --- a/components/generic_star_tracker/support/generic_star_tracker_checkout.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* -** File: generic_star_tracker_checkout.h -** -** Purpose: -** This is the header file for the GENERIC_STAR_TRACKER checkout. -** -*******************************************************************************/ -#ifndef _GENERIC_STAR_TRACKER_CHECKOUT_H_ -#define _GENERIC_STAR_TRACKER_CHECKOUT_H_ - -/* -** Includes -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hwlib.h" -#include "device_cfg.h" -#include "generic_star_tracker_device.h" - - -/* -** Standard Defines -*/ -#define PROMPT "generic_star_tracker> " -#define MAX_INPUT_BUF 512 -#define MAX_INPUT_TOKENS 64 -#define MAX_INPUT_TOKEN_SIZE 50 -#define TELEM_BUF_LEN 8 - - -/* -** Command Defines -*/ -#define CMD_UNKNOWN -1 -#define CMD_HELP 0 -#define CMD_EXIT 1 -#define CMD_NOOP 2 -#define CMD_HK 3 -#define CMD_GENERIC_STAR_TRACKER 4 -#define CMD_CFG 5 - - -/* -** Prototypes -*/ -void print_help(void); -int get_command(const char* str); -int main(int argc, char *argv[]); - - -/* -** Generic Prototypes -*/ -int check_number_arguments(int actual, int expected); -void to_lower(char* str); - - -#endif /* _GENERIC_STAR_TRACKER_CHECKOUT_H_ */ diff --git a/fsw/nos3_defs/tables/to_config.c b/fsw/nos3_defs/tables/to_config.c index 29e15fa5..af9cd704 100644 --- a/fsw/nos3_defs/tables/to_config.c +++ b/fsw/nos3_defs/tables/to_config.c @@ -73,6 +73,7 @@ extern "C" { #include "novatel_oem615_msgids.h" #include "sample_msgids.h" #include "generic_adcs_msgids.h" +#include "generic_star_tracker_msgids.h" /* ** Local Structure Declarations @@ -147,8 +148,8 @@ TO_ConfigTable_t to_ConfigTable = {CFE_SB_MSGID_WRAP_VALUE(GENERIC_MAG_HK_TLM_MID), {0,0}, 32, 0xffff, TO_GROUP_APP | TO_MGROUP_ONE, 0,1}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_MAG_DEVICE_TLM_MID), {0,0}, 32, 0xffff, TO_GROUP_APP | TO_MGROUP_ONE, 0,1}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_ADCS_HK_TLM_MID), {0,0}, 32, 0xffff, TO_GROUP_APP | TO_MGROUP_ONE, 0,1}, - {CFE_SB_MSGID_WRAP_VALUE(TO_UNUSED_ENTRY), {0,0}, 0, 0x0000, TO_GROUP_NONE, 0,0}, - {CFE_SB_MSGID_WRAP_VALUE(TO_UNUSED_ENTRY), {0,0}, 0, 0x0000, TO_GROUP_NONE, 0,0}, + {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_HK_TLM_MID),{0,0}, 32, 0xffff, TO_GROUP_APP | TO_MGROUP_ONE, 0,1}, + {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_DEVICE_TLM_MID),{0,0}, 32, 0xffff, TO_GROUP_APP | TO_MGROUP_ONE, 0,1}, {CFE_SB_MSGID_WRAP_VALUE(TO_UNUSED_ENTRY), {0,0}, 0, 0x0000, TO_GROUP_NONE, 0,0}, {CFE_SB_MSGID_WRAP_VALUE(TO_UNUSED_ENTRY), {0,0}, 0, 0x0000, TO_GROUP_NONE, 0,0}, diff --git a/fsw/nos3_defs/tables/to_lab_sub.c b/fsw/nos3_defs/tables/to_lab_sub.c index 641800ed..948b7c84 100644 --- a/fsw/nos3_defs/tables/to_lab_sub.c +++ b/fsw/nos3_defs/tables/to_lab_sub.c @@ -61,6 +61,7 @@ #include "novatel_oem615_msgids.h" #include "sample_msgids.h" #include "generic_adcs_msgids.h" +#include "generic_star_tracker_msgids.h" /* ** Local Structure Declarations @@ -121,6 +122,8 @@ TO_LAB_Subs_t TO_LAB_Subs = {CFE_SB_MSGID_WRAP_VALUE(GENERIC_ADCS_GNC_MID), {0,0}, 32}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_ADCS_AC_MID), {0,0}, 32}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_ADCS_DO_MID), {0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_HK_TLM_MID),{0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_DEVICE_TLM_MID),{0,0}, 32}, } }; diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 0e0e3d51..3ec676e7 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -111,6 +111,7 @@ do gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME --network-alias=radio_sim -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim echo "" done diff --git a/sims/cfg/InOut/Inp_IPC.txt b/sims/cfg/InOut/Inp_IPC.txt index 0d0a9efe..1436bfba 100644 --- a/sims/cfg/InOut/Inp_IPC.txt +++ b/sims/cfg/InOut/Inp_IPC.txt @@ -1,5 +1,5 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> -15 ! Number of Sockets +16 ! Number of Sockets ********************************** Sample ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode @@ -7,7 +7,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) fortytwo 4242 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) -FALSE ! Echo to stdout +TRUE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 ********************************** RW 0 to 42 ***************************** @@ -162,3 +162,13 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 +********************************** Star Tracker ***************************** +TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) +0 ! AC.ID for ACS mode +"ST.42" ! File name for WRITE or READ +SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) +fortytwo 4282 ! Server Host Name, Port +FALSE ! Allow Blocking (i.e. wait on RX) +TRUE ! Echo to stdout +1 ! Number of TX prefixes +"SC[0].AC.ST" ! Prefix 0 diff --git a/sims/cfg/InOut/SC_NOS3.txt b/sims/cfg/InOut/SC_NOS3.txt index 0eb77bcc..88365b72 100644 --- a/sims/cfg/InOut/SC_NOS3.txt +++ b/sims/cfg/InOut/SC_NOS3.txt @@ -11,7 +11,7 @@ CM ! Pos of CM or ORIGIN, wrt F 0.0 0.0 0.0 ! Vel wrt Formation (m/s), expressed in F *************************** Initial Attitude *************************** LAL ! Ang Vel wrt [NL], Att [QA] wrt [NLF] -0.0 0.0 0.0 ! Ang Vel (deg/sec) +1.0 1.0 1.0 ! Ang Vel (deg/sec) 0.0 0.0 0.0 1.0 ! Quaternion 0.0 0.0 0.0 123 ! Angles (deg) & Euler Sequence *************************** Dynamics Flags *************************** @@ -229,7 +229,7 @@ Z_AXIS ! Boresight Axis X_AXIS, Y_AXIS, or Z_AXIS 0.5 ! Quantization, deg 0 ! Flex Node Index ************************** Star Tracker ********************************* -0 ! Number of Star Trackers +1 ! Number of Star Trackers =============================== ST 0 ==================================== 0.25 ! Sample Time,sec 30.0 20.0 10.0 213 ! Mounting Angles (deg), Seq in Body diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index 87d01c29..caca1fed 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -130,7 +130,7 @@ fortytwo 4242 20 - 1 + 5 0 @@ -154,7 +154,7 @@ fortytwo 4245 20 - 1 + 5 0 0 37 @@ -223,10 +223,10 @@ 00AA - unknown-sim-command-node + star-tracker-command 3.30 0.25 - 0000 + 00AA unknown-sim-command-node @@ -287,7 +287,7 @@ 4277 4278 20 - 1 + 5 0 0 @@ -313,7 +313,7 @@ 4377 4378 20 - 1 + 5 0 1 @@ -339,7 +339,7 @@ 4477 4478 20 - 1 + 5 0 2 @@ -364,7 +364,7 @@ fortytwo 4227 20 - 1 + 5 0 <42-css-scale-factor>1.0 @@ -393,7 +393,7 @@ fortytwo 4279 20 - 1 + 5 3 @@ -425,7 +425,7 @@ fortytwo 9999 20 - 1 + 5 0 0 @@ -450,7 +450,7 @@ fortytwo 4281 20 - 1 + 5 0 @@ -528,7 +528,7 @@ fortytwo 4280 20 - 1 + 5 0 @@ -555,8 +555,36 @@ fortytwo 4234 20 - 1 + 5 + 0 + + + + + + generic_star_tracker_sim + true + libgeneric_star_tracker_sim.so + + GENERIC_STAR_TRACKER + + command + command + star-tracker-command + + usart + usart_10 + 10 + + + + GENERIC_STAR_TRACKER_42_PROVIDER + fortytwo + 4282 + 20 + 5 0 + 0 From 6307d3e5bed16b1ce6b131277f6814669a1125d6 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Mon, 9 Oct 2023 11:52:50 -0400 Subject: [PATCH 026/153] https://github.com/nasa/nos3/issues/166 - Submodule pointer update for data length. --- components/generic_star_tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_star_tracker b/components/generic_star_tracker index d2c8e7ec..99ec8e52 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit d2c8e7ec84d5a21e95eed8e42ff624c51e1ca655 +Subproject commit 99ec8e524e398f15b3af6affd43c5c88dc1dc4c9 From 23f28c4e7041b5fc85378a73c5355c2ebb61250d Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Mon, 9 Oct 2023 14:35:10 -0400 Subject: [PATCH 027/153] https://github.com/nasa/nos3/issues/166 - Add generation of star tracker data packets to scheduler tables. --- fsw/nos3_defs/tables/sch_def_msgtbl.c | 9 +++++---- fsw/nos3_defs/tables/sch_def_schtbl.c | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/fsw/nos3_defs/tables/sch_def_msgtbl.c b/fsw/nos3_defs/tables/sch_def_msgtbl.c index 027dabdf..483776dc 100644 --- a/fsw/nos3_defs/tables/sch_def_msgtbl.c +++ b/fsw/nos3_defs/tables/sch_def_msgtbl.c @@ -58,6 +58,7 @@ #include "novatel_oem615_msgids.h" #include "sample_msgids.h" #include "generic_adcs_msgids.h" +#include "generic_star_tracker_msgids.h" /* ** Message Table entry map... @@ -313,10 +314,10 @@ SCH_MessageEntry_t SCH_DefaultMessageTable[SCH_MAX_MESSAGES] = /* command ID #99 */ { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, - /* command ID #100 */ - { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, - /* command ID #101 */ - { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, + /* command ID #100 - Star Tracker HK */ + { { CFE_MAKE_BIG16(GENERIC_STAR_TRACKER_REQ_HK_MID), CFE_MAKE_BIG16(0xC000), CFE_MAKE_BIG16(0x0001), CFE_MAKE_BIG16(0x0000) } }, + /* command ID #101 - Star Tracker Data */ + { { CFE_MAKE_BIG16(GENERIC_STAR_TRACKER_REQ_HK_MID), CFE_MAKE_BIG16(0xC000), CFE_MAKE_BIG16(0x0001), CFE_MAKE_BIG16(0x0100) } }, /* command ID #102 */ { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, /* command ID #103 */ diff --git a/fsw/nos3_defs/tables/sch_def_schtbl.c b/fsw/nos3_defs/tables/sch_def_schtbl.c index 89b7b398..03d689a0 100644 --- a/fsw/nos3_defs/tables/sch_def_schtbl.c +++ b/fsw/nos3_defs/tables/sch_def_schtbl.c @@ -113,7 +113,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #3 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 2, SCH_GROUP_CFE_HK }, /* EVS HK Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -186,7 +186,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #13 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 3, SCH_GROUP_CFE_HK }, /* SB HK Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -260,7 +260,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #23 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 4, SCH_GROUP_CFE_HK }, /* TIME HK Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -334,7 +334,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #33 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 5, SCH_GROUP_CFE_HK }, /* TBL HK Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -409,7 +409,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #43 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 1, SCH_GROUP_CFE_HK }, /* ES HK Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -482,7 +482,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 81, SCH_GROUP_NONE }, /* MAG Data Request */ /* slot #53 */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -554,7 +554,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 81, SCH_GROUP_NONE }, /* MAG Data Request */ /* slot #63 */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -626,7 +626,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 81, SCH_GROUP_NONE }, /* MAG Data Request */ /* slot #73 */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -698,7 +698,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 81, SCH_GROUP_NONE }, /* MAG Data Request */ /* slot #83 */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -774,7 +774,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 81, SCH_GROUP_NONE }, /* MAG Data Request */ /* slot #93 */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, From ebeda9da49bd653b0d8098c44e74f2d601b26990 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Tue, 10 Oct 2023 13:45:54 -0400 Subject: [PATCH 028/153] https://github.com/nasa/nos3/issues/166 - Submodule update. --- components/generic_star_tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 99ec8e52..9488a463 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 99ec8e524e398f15b3af6affd43c5c88dc1dc4c9 +Subproject commit 9488a46392c18333a86a5d3ca096a3ed210635b3 From 66f2b95687e1356061426d1b4ad3727b4306297a Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Tue, 10 Oct 2023 15:59:35 -0400 Subject: [PATCH 029/153] https://github.com/nasa/nos3/issues/166 - Submodule pointer update. --- components/generic_adcs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_adcs b/components/generic_adcs index 7520ba8f..6cef722b 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 7520ba8fda621cb72dd01182c6427991f47f903e +Subproject commit 6cef722b5708026300c21f61de9320053c0b7cc9 From b16b88426e916d3d23cb116303bd8039c8a2d8d5 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Wed, 11 Oct 2023 13:28:50 -0400 Subject: [PATCH 030/153] https://github.com/nasa/nos3/issues/166 - Reset IPC echoes to default FALSE. --- sims/cfg/InOut/Inp_IPC.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sims/cfg/InOut/Inp_IPC.txt b/sims/cfg/InOut/Inp_IPC.txt index 1436bfba..2dacd956 100644 --- a/sims/cfg/InOut/Inp_IPC.txt +++ b/sims/cfg/InOut/Inp_IPC.txt @@ -7,7 +7,7 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) fortytwo 4242 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) -TRUE ! Echo to stdout +FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 ********************************** RW 0 to 42 ***************************** @@ -169,6 +169,6 @@ TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) fortytwo 4282 ! Server Host Name, Port FALSE ! Allow Blocking (i.e. wait on RX) -TRUE ! Echo to stdout +FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC[0].AC.ST" ! Prefix 0 From 1bc5a927371d5bbce9f1dead23379d83350353d1 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Wed, 11 Oct 2023 13:31:39 -0400 Subject: [PATCH 031/153] https://github.com/nasa/nos3/issues/166 - Submodule update. --- components/generic_adcs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_adcs b/components/generic_adcs index 6cef722b..6c187bb0 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 6cef722b5708026300c21f61de9320053c0b7cc9 +Subproject commit 6c187bb0372d81585f9f2e8fcc5af7a89d28f554 From 8e46a4240f8b4e13d2ce6879f87a613672b4191b Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Sun, 22 Oct 2023 00:03:40 +0000 Subject: [PATCH 032/153] [nasa/nos3#215] Created prepare script and updated cosmos submodule to full project; --- .gitmodules | 3 ++- Makefile | 5 ++++- gsw/ait | 1 - gsw/cosmos | 2 +- gsw/scripts/prepare.sh | 14 ++++++++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) delete mode 160000 gsw/ait create mode 100755 gsw/scripts/prepare.sh diff --git a/.gitmodules b/.gitmodules index 59e5e009..47e2a963 100644 --- a/.gitmodules +++ b/.gitmodules @@ -48,7 +48,8 @@ url = https://github.com/nasa-itc/OrbitInviewPowerPrediction.git [submodule "gsw/cosmos"] path = gsw/cosmos - url = https://github.com/nasa-itc/gsw-cosmos.git + url = https://github.com/OpenC3/cosmos.git + branch = main [submodule "sims/truth_42_sim"] path = sims/truth_42_sim url = https://github.com/nasa-itc/truth_42_sim.git diff --git a/Makefile b/Makefile index d9591a8f..5bd4c3d2 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all build-fsw build-sim checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log real-clean sim stop +LOCALTGTS := all build-fsw build-sim checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log prep real-clean sim stop OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -81,6 +81,9 @@ launch: log: ./gsw/scripts/log.sh +prep: + ./gsw/scripts/prepare.sh + real-clean: $(MAKE) clean ./gsw/scripts/real_clean.sh diff --git a/gsw/ait b/gsw/ait deleted file mode 160000 index 000540c4..00000000 --- a/gsw/ait +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 000540c4766a5608f501e53aa54e17644a2654ec diff --git a/gsw/cosmos b/gsw/cosmos index 06084250..be95d4d5 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 0608425026e4018e762f31cf0a92ed94f4f39bef +Subproject commit be95d4d5d136104f6a72f89f7f440c4d4f29c02d diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh new file mode 100755 index 00000000..10fb97aa --- /dev/null +++ b/gsw/scripts/prepare.sh @@ -0,0 +1,14 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +# COSMOS Installation +cd $GSW_DIR +./openc3.sh run + +# NOS3 Container +$DCALL image pull ivvitc/nos3 From 5ee9323ebfe0adad9b76332d6bd7bf1ebec5e02e Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 24 Oct 2023 07:18:56 -0400 Subject: [PATCH 033/153] [nasa/nos3#215] Added openc3-cosmos submodule and updated env.sh script; --- .gitmodules | 6 +++++- gsw/cosmos | 2 +- gsw/openc3-cosmos | 1 + gsw/scripts/env.sh | 19 ++++++++++--------- 4 files changed, 17 insertions(+), 11 deletions(-) create mode 160000 gsw/openc3-cosmos diff --git a/.gitmodules b/.gitmodules index 47e2a963..00509cba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -48,7 +48,7 @@ url = https://github.com/nasa-itc/OrbitInviewPowerPrediction.git [submodule "gsw/cosmos"] path = gsw/cosmos - url = https://github.com/OpenC3/cosmos.git + url = https://github.com/nasa-itc/gsw-cosmos.git branch = main [submodule "sims/truth_42_sim"] path = sims/truth_42_sim @@ -124,3 +124,7 @@ [submodule "components/generic_adcs"] path = components/generic_adcs url = https://github.com/nasa-itc/generic_adcs.git +[submodule "gsw/openc3-cosmos"] + path = gsw/openc3-cosmos + url = https://github.com/nasa-itc/openc3-cosmos.git + branch = nos3-main diff --git a/gsw/cosmos b/gsw/cosmos index be95d4d5..06084250 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit be95d4d5d136104f6a72f89f7f440c4d4f29c02d +Subproject commit 0608425026e4018e762f31cf0a92ed94f4f39bef diff --git a/gsw/openc3-cosmos b/gsw/openc3-cosmos new file mode 160000 index 00000000..f3f5de2e --- /dev/null +++ b/gsw/openc3-cosmos @@ -0,0 +1 @@ +Subproject commit f3f5de2e9fadcd8d63d35e59c83acb17e4726480 diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index d57f64ae..8560edd8 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -16,23 +16,24 @@ if [ -d $SIM_DIR/bin ]; then fi DATE=$(date "+%Y%m%d%H%M") -OPENC3_PATH="/opt/nos3/cosmos/openc3.sh" +OPENC3_PATH=$BASE_DIR/gsw/openc3-cosmos/openc3.sh NUM_CPUS="$( nproc )" -if [ -f "/etc/redhat-release" ]; then - DCALL="podman" - DFLAGS="podman run --rm --group-add keep-groups -it" - DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" - DCREATE="podman create --rm -it" - DNETWORK="podman network" -else +# Note: Podman not yet supported +#if [ -f "/etc/redhat-release" ]; then +# DCALL="podman" +# DFLAGS="podman run --rm --group-add keep-groups -it" +# DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" +# DCREATE="podman create --rm -it" +# DNETWORK="podman network" +#else DCALL="docker" DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(getent group $(stat -c '%G' $SCRIPT_DIR/env.sh) | cut -d: -f3)" DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" DCREATE="docker create --rm -it" DNETWORK="docker network" -fi +#fi # Debugging #echo "Script directory = " $SCRIPT_DIR From c36ee4b5945e98764b9bcd80115bd7649f78f936 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 25 Oct 2023 22:35:05 -0400 Subject: [PATCH 034/153] [nasa/nos3#215] Updates to prepare to use a local ~/.nos3 directory to place COSMOS and temporary files used to run; --- .gitmodules | 4 ---- Makefile | 5 ++++- gsw/openc3-cosmos | 1 - gsw/scripts/create_cosmos_gem.sh | 9 +++++++++ gsw/scripts/docker_build_fsw.sh | 8 ++++++++ gsw/scripts/docker_build_sim.sh | 8 ++++++++ gsw/scripts/docker_launch.sh | 16 +++++++++++----- gsw/scripts/docker_stop.sh | 2 +- gsw/scripts/env.sh | 12 +++++++++--- gsw/scripts/prepare.sh | 22 ++++++++++++++++++---- gsw/scripts/stop.sh | 4 ++-- gsw/scripts/stop_gsw.sh | 11 +++++++++++ 12 files changed, 81 insertions(+), 21 deletions(-) delete mode 160000 gsw/openc3-cosmos create mode 100644 gsw/scripts/stop_gsw.sh diff --git a/.gitmodules b/.gitmodules index 00509cba..9d197833 100644 --- a/.gitmodules +++ b/.gitmodules @@ -124,7 +124,3 @@ [submodule "components/generic_adcs"] path = components/generic_adcs url = https://github.com/nasa-itc/generic_adcs.git -[submodule "gsw/openc3-cosmos"] - path = gsw/openc3-cosmos - url = https://github.com/nasa-itc/openc3-cosmos.git - branch = nos3-main diff --git a/Makefile b/Makefile index 5bd4c3d2..3fd02c03 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all build-fsw build-sim checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log prep real-clean sim stop +LOCALTGTS := all checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log prep real-clean sim stop stop-gsw OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -94,3 +94,6 @@ sim: stop: ./gsw/scripts/docker_stop.sh ./gsw/scripts/stop.sh + +stop-gsw: + ./gsw/scripts/stop_gsw.sh diff --git a/gsw/openc3-cosmos b/gsw/openc3-cosmos deleted file mode 160000 index f3f5de2e..00000000 --- a/gsw/openc3-cosmos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f3f5de2e9fadcd8d63d35e59c83acb17e4726480 diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index ca9abd9f..96b39d70 100755 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -6,6 +6,15 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + + # Start by changing to a known location cd $GSW_DIR diff --git a/gsw/scripts/docker_build_fsw.sh b/gsw/scripts/docker_build_fsw.sh index 852c7f27..7d1146b2 100755 --- a/gsw/scripts/docker_build_fsw.sh +++ b/gsw/scripts/docker_build_fsw.sh @@ -8,5 +8,13 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + mkdir -p $BASE_DIR/fsw/build $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw diff --git a/gsw/scripts/docker_build_sim.sh b/gsw/scripts/docker_build_sim.sh index f7a85dc1..68ab53c4 100755 --- a/gsw/scripts/docker_build_sim.sh +++ b/gsw/scripts/docker_build_sim.sh @@ -8,5 +8,13 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + mkdir -p $BASE_DIR/sims/build $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 0e0e3d51..bf7f45f3 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -8,6 +8,14 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + echo "Make data folders..." # FSW Side @@ -70,15 +78,13 @@ do echo "" echo $SC_NUM " - Connect COSMOS to spacecraft network..." - $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos 2> /dev/null + $DNETWORK connect $SC_NETNAME openc3-cosmos_openc3-operator_1 --alias cosmos 2> /dev/null echo "" echo $SC_NUM " - 42..." - cd /opt/nos3/42/ - rm -rf NOS3InOut - cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut + cp -r $BASE_DIR/sims/cfg/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* - gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut + gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut echo "" echo $SC_NUM " - Flight Software..." diff --git a/gsw/scripts/docker_stop.sh b/gsw/scripts/docker_stop.sh index 937fc6ee..5c63486f 100755 --- a/gsw/scripts/docker_stop.sh +++ b/gsw/scripts/docker_stop.sh @@ -27,7 +27,7 @@ $DCALL container prune -f > /dev/null 2>&1 $DNETWORK ls --filter=name="nos" | xargs $DNETWORK rm > /dev/null 2>&1 # 42 -rm -rf /opt/nos3/42/NOS3InOut +rm -rf $USER_NOS3_DIR/42/NOS3InOut rm -rf /tmp/gpio* # COSMOS diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 8560edd8..0838668d 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -16,11 +16,15 @@ if [ -d $SIM_DIR/bin ]; then fi DATE=$(date "+%Y%m%d%H%M") -OPENC3_PATH=$BASE_DIR/gsw/openc3-cosmos/openc3.sh - NUM_CPUS="$( nproc )" -# Note: Podman not yet supported +USER_NOS3_DIR=$(cd ~/ && pwd)/.nos3 +OPENC3_DIR=$USER_NOS3_DIR/openc3-cosmos +OPENC3_PATH=$OPENC3_DIR/openc3.sh + +### +### Note: Podman not yet supported +### #if [ -f "/etc/redhat-release" ]; then # DCALL="podman" # DFLAGS="podman run --rm --group-add keep-groups -it" @@ -48,4 +52,6 @@ NUM_CPUS="$( nproc )" #echo "Docker create = " $DCREATE #echo "Docker network = " $DNETWORK #echo "Date = " $DATE +#echo "Local user .nos3 = " $USER_NOS3_DIR +#echo "OpenC3 directory = " $OPENC3_DIR #echo "OpenC3 path = " $OPENC3_PATH diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh index 10fb97aa..3ce85e19 100755 --- a/gsw/scripts/prepare.sh +++ b/gsw/scripts/prepare.sh @@ -6,9 +6,23 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh -# COSMOS Installation -cd $GSW_DIR -./openc3.sh run +echo "Create local user directory..." +mkdir $USER_NOS3_DIR 2> /dev/null +echo " "$USER_NOS3_DIR +mkdir $USER_NOS3_DIR/42 2> /dev/null -# NOS3 Container +echo "Clone openc3-cosmos into local user directory..." +cd $USER_NOS3_DIR +git clone https://github.com/nasa-itc/openc3-cosmos.git --depth 1 -b nos3-main +git reset --hard + +echo "Prepare openc3-cosmos containers..." +cd $OPENC3_DIR +$OPENC3_PATH start + +echo "Set a password in openc3-cosmos via firefox..." +sleep 5 +firefox localhost:2900 & + +echo "Prepare nos3 docker container..." $DCALL image pull ivvitc/nos3 diff --git a/gsw/scripts/stop.sh b/gsw/scripts/stop.sh index 0f0609b9..7e930887 100755 --- a/gsw/scripts/stop.sh +++ b/gsw/scripts/stop.sh @@ -34,7 +34,7 @@ rm -rf $BASE_DIR/fsw/build/exe/cpu1/scratch/* # 42 killall -q 42 -rm -rf /opt/nos3/42/NOS3InOut -rm -rf /tmp/gpio* +#rm -rf /opt/nos3/42/NOS3InOut +#rm -rf /tmp/gpio* exit 0 \ No newline at end of file diff --git a/gsw/scripts/stop_gsw.sh b/gsw/scripts/stop_gsw.sh new file mode 100644 index 00000000..64767e8e --- /dev/null +++ b/gsw/scripts/stop_gsw.sh @@ -0,0 +1,11 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +echo "Stop openc3-cosmos..." +cd $OPENC3_DIR +$OPENC3_PATH stop From edc82d0ebea4eee911a428631582b5e90068798a Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 31 Oct 2023 18:48:21 -0400 Subject: [PATCH 035/153] [nasa/nos3#215] Updated osal and novatel_oem615 submodules; --- components/novatel_oem615 | 2 +- fsw/nos3_defs/cpu1_device_cfg.h | 2 +- fsw/osal | 2 +- gsw/scripts/env.sh | 11 ++++++----- gsw/scripts/prepare.sh | 6 +++--- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/components/novatel_oem615 b/components/novatel_oem615 index 75c93346..e63619d3 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit 75c93346d7349d3d24067bfb79485140deb149fc +Subproject commit e63619d36dced120fc5cb28b4ecac378901178f8 diff --git a/fsw/nos3_defs/cpu1_device_cfg.h b/fsw/nos3_defs/cpu1_device_cfg.h index d7fddb07..3283398c 100644 --- a/fsw/nos3_defs/cpu1_device_cfg.h +++ b/fsw/nos3_defs/cpu1_device_cfg.h @@ -50,7 +50,7 @@ #define GENERIC_RADIO_CFG_PROX_DATA_SIZE 64 #define GENERIC_RADIO_CFG_FSW_IP "nos_fsw" #define GENERIC_RADIO_CFG_DEVICE_IP "radio_sim" -#define GENERIC_RADIO_CFG_DEVICE_DELAY_MS 10 +#define GENERIC_RADIO_CFG_DEVICE_DELAY_MS 250 #define GENERIC_RADIO_CFG_UDP_PROX_TO_FSW 7010 #define GENERIC_RADIO_CFG_UDP_FSW_TO_PROX 7011 #define GENERIC_RADIO_CFG_UDP_FSW_TO_RADIO 5014 diff --git a/fsw/osal b/fsw/osal index 8b046477..ee5a52de 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit 8b046477f047ae371be27f4ee7942fa4f863e7ac +Subproject commit ee5a52dea91fe4e5b593246a6c02d81f3db2a9ef diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index 0838668d..be28caca 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -23,14 +23,15 @@ OPENC3_DIR=$USER_NOS3_DIR/openc3-cosmos OPENC3_PATH=$OPENC3_DIR/openc3.sh ### -### Note: Podman not yet supported +### Notes: +### Podman and/or Docker on RHEL not yet supported ### #if [ -f "/etc/redhat-release" ]; then -# DCALL="podman" -# DFLAGS="podman run --rm --group-add keep-groups -it" +# DCALL="docker" +# DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(getent group $(stat -c '%G' $SCRIPT_DIR/env.sh) | cut -d: -f3)" # DFLAGS_CPUS="$DFLAGS --cpus=$NUM_CPUS" -# DCREATE="podman create --rm -it" -# DNETWORK="podman network" +# DCREATE="docker create --rm -it" +# DNETWORK="docker network" #else DCALL="docker" DFLAGS="docker run --rm -it -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro -u $(id -u $(stat -c '%U' $SCRIPT_DIR/env.sh)):$(getent group $(stat -c '%G' $SCRIPT_DIR/env.sh) | cut -d: -f3)" diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh index 3ce85e19..9c50fa4f 100755 --- a/gsw/scripts/prepare.sh +++ b/gsw/scripts/prepare.sh @@ -20,9 +20,9 @@ echo "Prepare openc3-cosmos containers..." cd $OPENC3_DIR $OPENC3_PATH start +echo "Prepare nos3 docker container..." +$DCALL image pull ivvitc/nos3 + echo "Set a password in openc3-cosmos via firefox..." sleep 5 firefox localhost:2900 & - -echo "Prepare nos3 docker container..." -$DCALL image pull ivvitc/nos3 From 21abe15e3539f8405687f8efe235ebc4eaf5100d Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 31 Oct 2023 23:44:46 +0000 Subject: [PATCH 036/153] [nasa/nos#215] Updated scripts after local deployment attempt; --- gsw/scripts/create_cosmos_gem.sh | 22 +++++++++++----------- gsw/scripts/prepare.sh | 8 +++++++- gsw/scripts/stop_gsw.sh | 0 3 files changed, 18 insertions(+), 12 deletions(-) mode change 100644 => 100755 gsw/scripts/stop_gsw.sh diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index 96b39d70..f0a3dc1e 100755 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -31,11 +31,11 @@ fi # Start generating the plugin mkdir build cd build -$OPENC3_PATH cliroot generate plugin nos3 +$OPENC3_PATH cli generate plugin nos3 if [ ! -d "openc3-cosmos-nos3" ] then echo "" - echo "ERROR: cliroot generate plugin nos3 failed!" + echo "ERROR: cli generate plugin nos3 failed!" echo "" exit 1 fi @@ -123,29 +123,29 @@ echo "" # Build plugin echo "Build plugin..." -$OPENC3_PATH cliroot rake build VERSION=1.0.$DATE +$OPENC3_PATH cli rake build VERSION=1.0.$DATE if [ ! -f "openc3-cosmos-nos3-1.0.$DATE.gem" ] then echo "" - echo "ERROR: cliroot rake build failed!" + echo "ERROR: cli rake build failed!" echo "" exit 1 fi echo "" -# Install plugin -echo "Install plugin..." -cd $GSW_BIN -$OPENC3_PATH cliroot geminstall ./openc3-cosmos-nos3-1.0.$DATE.gem -echo "" +## Install plugin +#echo "Install plugin..." +#cd $GSW_BIN +#$OPENC3_PATH cli geminstall ./openc3-cosmos-nos3-1.0.$DATE.gem +#echo "" # Load plugin echo "Load plugin..." $OPENC3_PATH cliroot load openc3-cosmos-nos3-1.0.$DATE.gem echo "" -# Set permissions on build files -chmod -R 777 $BASE_DIR/gsw/cosmos/build +## Set permissions on build files +#chmod -R 777 $BASE_DIR/gsw/cosmos/build echo "Create COSMOS gem script complete." echo "Note that while this script is complete, COSMOS is likely still be processing behind the scenes!" diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh index 9c50fa4f..7bfd67c0 100755 --- a/gsw/scripts/prepare.sh +++ b/gsw/scripts/prepare.sh @@ -10,19 +10,25 @@ echo "Create local user directory..." mkdir $USER_NOS3_DIR 2> /dev/null echo " "$USER_NOS3_DIR mkdir $USER_NOS3_DIR/42 2> /dev/null +echo "" echo "Clone openc3-cosmos into local user directory..." cd $USER_NOS3_DIR git clone https://github.com/nasa-itc/openc3-cosmos.git --depth 1 -b nos3-main git reset --hard +echo "" echo "Prepare openc3-cosmos containers..." cd $OPENC3_DIR -$OPENC3_PATH start +$OPENC3_PATH run +echo "" echo "Prepare nos3 docker container..." $DCALL image pull ivvitc/nos3 +echo "" echo "Set a password in openc3-cosmos via firefox..." +echo " Refresh webpage if error page shown." +echo "" sleep 5 firefox localhost:2900 & diff --git a/gsw/scripts/stop_gsw.sh b/gsw/scripts/stop_gsw.sh old mode 100644 new mode 100755 From 22b71509bd58798bd44a0ec4d5097bb79422679f Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 1 Nov 2023 17:56:12 -0400 Subject: [PATCH 037/153] [nasa/nos#215] Upgraded to new basebox and added prepare step to readme; --- README.md | 44 ++++++++++++++++++++++++------------ Vagrantfile | 12 +++++----- gsw/scripts/docker_launch.sh | 2 +- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 951660b3..e720bc58 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,13 @@ The best source of documentation can be found at [the wiki](https://github.com/n ### Prerequisites Each of the applications listed below are required prior to performing the installation procedure: -* [Git 2.36+](https://git-scm.com/) -* [Vagrant 2.3.4+](https://www.vagrantup.com/) -* [VirtualBox 7.0+](https://www.virtualbox.org/) +* Option A + * [Git 2.36+](https://git-scm.com/) + * Linux with docker and docker compose installed +* Option B + * [Git 2.36+](https://git-scm.com/) + * [Vagrant 2.3.4+](https://www.vagrantup.com/) + * [VirtualBox 7.0+](https://www.virtualbox.org/) ### Installing 1. Clone the repository `git clone https://github.com/nasa/nos3.git` @@ -17,20 +21,33 @@ Each of the applications listed below are required prior to performing the insta 3. Clone the submodules `git submodule update --init --recursive` 4. Run `vagrant up` and wait to return to a prompt - This can take anywhere from a few minutes to hours depending on internet speeds and host PC specs -5. Login to the nos3 user using the password `nos3123!` and get to work! -6. Try building and running following the instructions below +5. In VirtualBox `Devices > Upgrade Guest Additions...` + - Wait for this to complete +6. Run `vagrant reload` to finish the upgrade +7. Login to the jstar user using the password `jstar123!` and get to work! +8. Try building and running following the instructions below ### Getting started -By default the nos3 repository is shared into the virtual machine at `/home/nos3/Desktop/github-nos3` +By default the nos3 repository is shared into the virtual machine at `/home/jstar/Desktop/github-nos3` 1. Open a terminal 2. Navigate to the nos3 repository - - `cd /home/nos3/Desktop/github-nos3` -2. To build use the `make` command from the nos3 repo -3. To run nos3 use the `make launch` command from the nos3 repo -4. To halt nos3 use the `make stop` command from the nos3 repo + - `cd /home/jstar/Desktop/github-nos3` +3. Prepare the environment with COSMOS and docker containers + - `make prep` +4. Build FSW, GSW, and SIMS + - `make` +5. Run NOS3 including FSW, GSW, and SIMS + - `make launch` +6. Stop NOS3 + - `make stop` + - Note that COSMOS will remaining running in the background until `make stop-gsw` is done ### Directory Layout -* `components` contains the repositories for the hardware component apps; each repository contains the app, an associated sim, and COSMOS command and telemetry tables +* `components` contains the repositories for the hardware component apps + - /fsw - cFS application + - /gsw - OpenC3 COSMOS database + - /sim - NOS3 simulator + - /support - Optional folder containing a standalone checkout application * `fsw` contains the repositories needed to build cFS FSW - /apps - the open source cFS apps - /cfe - the core flight system (cFS) source files @@ -39,8 +56,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/nos3 - /psp - platform support package (PSP), enables use on multiple types of boards - /tools - standard cFS provided tools * `gsw` contains the nos3 ground station files, and other ground based tools - - /ait - Ammos Instrument Toolkit (Untested for 1.05.0) - - /cosmos - COSMOS files + - /cosmos - OpenC3 COSMOS files - /OrbitInviewPowerPrediction - OIPP tool for operators - /scripts - convenience scripts * `sims` contains the nos3 simulators and configuration files @@ -48,7 +64,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/nos3 - /nos_time_driver - time syncronization for all components - /sim_common - common files used by component simulators including the files that define the simulator plugin architecture - /sim_terminal - terminal for testing on NOS Engine busses - - /truth_42_sim - interface between 42 and COSMOS to provide dynamics truth data to COSMOS + - /truth_42_sim - interface between 42 and OpenC3 COSMOS to provide dynamics truth data ### Versioning We use [SemVer](http://semver.org/) for versioning. For the versions available, see the tags on this repository. diff --git a/Vagrantfile b/Vagrantfile index 23c0c3e9..db0a07c7 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -12,19 +12,19 @@ Vagrant.configure("2") do |config| config.vm.box = "nos3/ubuntu" ### Specify version - config.vm.box_version = "20230731" + config.vm.box_version = "20231101" ### Share host NOS3 repository into VM - config.vm.synced_folder ".", "/home/nos3/Desktop/github-nos3", - owner: 'root', group:'vboxsf', automount:'true', + config.vm.synced_folder ".", "/home/jstar/Desktop/github-nos3", + owner: 'jstar', group:'vboxsf', automount:'true', mount_options: ["dmode=0770", "fmode=0770"] ### General configuration config.vm.provider "virtualbox" do |vbox| - vbox.name = "nos3_20230731" + vbox.name = "nos3_20231101" vbox.gui = true ### Enable additional configuration as needed - vbox.cpus = 6 - vbox.memory = "6144" # Should always be > (cpus * 1024) + vbox.cpus = 4 + vbox.memory = "8192" end end diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index bf7f45f3..f590a357 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -89,7 +89,7 @@ do echo $SC_NUM " - Flight Software..." cd $FSW_DIR - gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --cap-add sys_nice ivvitc/nos3 $SCRIPT_DIR/fsw_respawn.sh & + gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --ulimit rtprio=99 --cap-add=sys_nice ivvitc/nos3 $SCRIPT_DIR/fsw_respawn.sh & echo "" # Debugging From 76fa9481d9106990568ea281293d6cf5775376e3 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 3 Nov 2023 15:29:27 -0400 Subject: [PATCH 038/153] https://github.com/nasa/nos3/issues/166 - Update code per suggestions in the pull review. --- components/generic_star_tracker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 9488a463..211aa25c 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 9488a46392c18333a86a5d3ca096a3ed210635b3 +Subproject commit 211aa25c85645602582fa9576cf32595bfd1d522 From 2b7cd234e0554aab6d952931e80e74324302607b Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 3 Nov 2023 15:44:58 -0400 Subject: [PATCH 039/153] https://github.com/nasa/nos3/issues/166 - Update code per suggestions in the pull review. --- fsw/nos3_defs/tables/sch_def_schtbl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fsw/nos3_defs/tables/sch_def_schtbl.c b/fsw/nos3_defs/tables/sch_def_schtbl.c index 03d689a0..724568e1 100644 --- a/fsw/nos3_defs/tables/sch_def_schtbl.c +++ b/fsw/nos3_defs/tables/sch_def_schtbl.c @@ -187,7 +187,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #13 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 3, SCH_GROUP_CFE_HK }, /* SB HK Request */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -261,7 +261,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #23 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 4, SCH_GROUP_CFE_HK }, /* TIME HK Request */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -335,7 +335,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #33 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 5, SCH_GROUP_CFE_HK }, /* TBL HK Request */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -410,7 +410,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #43 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 4, 3, 1, SCH_GROUP_CFE_HK }, /* ES HK Request */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -483,7 +483,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #53 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -555,7 +555,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #63 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -627,7 +627,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #73 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -699,7 +699,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #83 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, @@ -775,7 +775,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /* slot #93 */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,101, SCH_GROUP_NONE }, /* ST Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0,100, SCH_GROUP_NONE }, /* ST Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, From 4eb845d41069661c1c14ae0b1b272c95f8dba564 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 30 Nov 2023 08:49:27 -0500 Subject: [PATCH 040/153] [nasa/nos3#210] Added in comments to document previous OS_Task_Delay implementation to enable faster reverting and testing in the future if it ends up being an issue; --- fsw/osal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/osal b/fsw/osal index ee5a52de..02443940 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit ee5a52dea91fe4e5b593246a6c02d81f3db2a9ef +Subproject commit 0244394010c37a80cb26474a713ac9a64b5cde9c From 1c2416b8690bf8f5e85c0e954f13d33d72e3f12f Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 30 Nov 2023 14:38:01 -0500 Subject: [PATCH 041/153] [nasa/nos3#215] Revert OSAL updates until nos3#210 resolved; --- fsw/osal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/osal b/fsw/osal index 02443940..8b046477 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit 0244394010c37a80cb26474a713ac9a64b5cde9c +Subproject commit 8b046477f047ae371be27f4ee7942fa4f863e7ac From 308e79a76d704bfcd9fa8aa64b4fcad1c23f7ce3 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 14 Dec 2023 07:45:24 -0500 Subject: [PATCH 042/153] [nasa/nos3#223] Shift to use smaller openc3-nos3 repository and build plugins in prep directory; --- .gitignore | 1 + Makefile | 5 ++++- gsw/scripts/create_cosmos_gem.sh | 7 +++---- gsw/scripts/env.sh | 2 +- gsw/scripts/prepare.sh | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index ce44cab0..0f32a7a8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ build *.o support/nos3_install.log tmp +core.* diff --git a/Makefile b/Makefile index 3fd02c03..2d62b6f5 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all checkout clean clean-fsw clean-sim clean-gsw fsw gsw launch log prep real-clean sim stop stop-gsw +LOCALTGTS := all checkout clean clean-fsw clean-sim clean-gsw debug fsw gsw launch log prep real-clean sim stop stop-gsw OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -69,6 +69,9 @@ clean-sim: clean-gsw: rm -rf gsw/cosmos/build +debug: + ./gsw/scripts/docker_debug.sh + fsw: ./gsw/scripts/docker_build_fsw.sh diff --git a/gsw/scripts/create_cosmos_gem.sh b/gsw/scripts/create_cosmos_gem.sh index f0a3dc1e..39aa648e 100755 --- a/gsw/scripts/create_cosmos_gem.sh +++ b/gsw/scripts/create_cosmos_gem.sh @@ -14,9 +14,8 @@ if [ ! -d $USER_NOS3_DIR ]; then exit 1 fi - # Start by changing to a known location -cd $GSW_DIR +cd $OPENC3_DIR # Delete any previous run info rm -rf build @@ -44,13 +43,13 @@ fi mkdir openc3-cosmos-nos3/targets cd openc3-cosmos-nos3/targets targets="" -for i in $(find ../../../../../components -name target.txt) +for i in $(find $BASE_DIR/components -name target.txt) do j=$(dirname $i) cp -r $j . targets="$targets $(basename $j)" done -for i in $(find ../../../config/targets -name target.txt) +for i in $(find $GSW_DIR/config/targets -name target.txt) do j=$(dirname $i) cp -r $j . diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index be28caca..dcc3b417 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -19,7 +19,7 @@ DATE=$(date "+%Y%m%d%H%M") NUM_CPUS="$( nproc )" USER_NOS3_DIR=$(cd ~/ && pwd)/.nos3 -OPENC3_DIR=$USER_NOS3_DIR/openc3-cosmos +OPENC3_DIR=$USER_NOS3_DIR/openc3-nos3 OPENC3_PATH=$OPENC3_DIR/openc3.sh ### diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh index 7bfd67c0..256b4743 100755 --- a/gsw/scripts/prepare.sh +++ b/gsw/scripts/prepare.sh @@ -14,7 +14,7 @@ echo "" echo "Clone openc3-cosmos into local user directory..." cd $USER_NOS3_DIR -git clone https://github.com/nasa-itc/openc3-cosmos.git --depth 1 -b nos3-main +git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main git reset --hard echo "" From bf4e5c46b9bef5125b6bbb9c55b35b282c5ae3f5 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 14 Dec 2023 14:01:52 +0000 Subject: [PATCH 043/153] Initial updates to allow for battery monitoring --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 19874740..8615c388 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 19874740a91a756d348d14c326beabe11aa73f8a +Subproject commit 8615c388fdc6ff2965d99a4197056f3e2ca85b44 From e8f791b9b1b25d2c481f833302503accd298bb12 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Dec 2023 12:03:14 -0500 Subject: [PATCH 044/153] [nasa/nos3#223] Update naming of local cosmos directory and associated networks; --- gsw/scripts/docker_launch.sh | 9 +++++++-- gsw/scripts/env.sh | 2 +- gsw/scripts/prepare.sh | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 0964728c..4cf7c42d 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -78,7 +78,7 @@ do echo "" echo $SC_NUM " - Connect COSMOS to spacecraft network..." - $DNETWORK connect $SC_NETNAME openc3-cosmos_openc3-operator_1 --alias cosmos 2> /dev/null + $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos 2> /dev/null echo "" echo $SC_NUM " - 42..." @@ -114,10 +114,15 @@ do gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 + gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME --network-alias=radio_sim -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim + gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim - gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim + gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + + # Note: Can keep open if desired after a new gnome-profile is manually created + #gnome-terminal --window-with-profile=KeepOpen --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim echo "" done diff --git a/gsw/scripts/env.sh b/gsw/scripts/env.sh index dcc3b417..b3bfff90 100755 --- a/gsw/scripts/env.sh +++ b/gsw/scripts/env.sh @@ -19,7 +19,7 @@ DATE=$(date "+%Y%m%d%H%M") NUM_CPUS="$( nproc )" USER_NOS3_DIR=$(cd ~/ && pwd)/.nos3 -OPENC3_DIR=$USER_NOS3_DIR/openc3-nos3 +OPENC3_DIR=$USER_NOS3_DIR/cosmos OPENC3_PATH=$OPENC3_DIR/openc3.sh ### diff --git a/gsw/scripts/prepare.sh b/gsw/scripts/prepare.sh index 256b4743..44e53ec1 100755 --- a/gsw/scripts/prepare.sh +++ b/gsw/scripts/prepare.sh @@ -14,7 +14,7 @@ echo "" echo "Clone openc3-cosmos into local user directory..." cd $USER_NOS3_DIR -git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main +git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main $USER_NOS3_DIR/cosmos git reset --hard echo "" From da907b99e64d54fadf73a7387c11accf3b983df7 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 19 Dec 2023 17:44:47 +0000 Subject: [PATCH 045/153] Corrections to the various problems with length values being 0 instead of 1 --- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_radio | 2 +- components/sample | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/generic_css b/components/generic_css index a35f8bc2..127c8ef0 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit a35f8bc2e7e78329f9d3e22e5b6ff9f5dcd68c27 +Subproject commit 127c8ef06b3570c314e4f7f39380a546c02be509 diff --git a/components/generic_eps b/components/generic_eps index 19874740..c0de17ae 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 19874740a91a756d348d14c326beabe11aa73f8a +Subproject commit c0de17ae750e37a7eb35a5e2751a9b78eec645ae diff --git a/components/generic_fss b/components/generic_fss index 33f8138d..2811e3f6 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit 33f8138dc77ffe1d8475197456f0f75f923136cd +Subproject commit 2811e3f610c3c3754c0ca6e0c95680fa0e51ef09 diff --git a/components/generic_imu b/components/generic_imu index 85d4e4d1..4bf147f2 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 85d4e4d1ef1a74a45c2270f0a54792dc72dac0a4 +Subproject commit 4bf147f247682918a402e1d058d09405f0963848 diff --git a/components/generic_radio b/components/generic_radio index 80c950c1..a59475b1 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 80c950c1029b767d5ebde960daf1cebec6c48acc +Subproject commit a59475b14e2fa4de3d28f10eedc88381cbac4fa2 diff --git a/components/sample b/components/sample index 843e4822..17a6a328 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 843e4822fe822e980d7fa37c4595d77ab8d98ce7 +Subproject commit 17a6a328a7ca244b5b3a034f884336048d8a0215 From 64bff46157854c1a8141c90725ed714131f53261 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Dec 2023 13:19:33 -0500 Subject: [PATCH 046/153] [nasa/nos3#223] Change sample to use usart_16 to avoid crashing; --- fsw/nos3_defs/cpu1_device_cfg.h | 4 ++-- sims/cfg/nos3-simulator.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fsw/nos3_defs/cpu1_device_cfg.h b/fsw/nos3_defs/cpu1_device_cfg.h index 3283398c..2bcae018 100644 --- a/fsw/nos3_defs/cpu1_device_cfg.h +++ b/fsw/nos3_defs/cpu1_device_cfg.h @@ -37,8 +37,8 @@ ** SAMPLE Configuration */ #define SAMPLE_CFG -#define SAMPLE_CFG_STRING "usart_29" -#define SAMPLE_CFG_HANDLE 29 +#define SAMPLE_CFG_STRING "usart_16" +#define SAMPLE_CFG_HANDLE 16 #define SAMPLE_CFG_BAUDRATE_HZ 115200 #define SAMPLE_CFG_MS_TIMEOUT 50 /* Max 255 */ //#define SAMPLE_CFG_DEBUG diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index caca1fed..8a4c5e11 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -121,8 +121,8 @@ sample-command usart - usart_29 - 29 + usart_16 + 16 From 285e01544ebcc53e7703eba49c00b8df37c31ecb Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Dec 2023 13:22:37 -0500 Subject: [PATCH 047/153] [nasa/nos3#219] Added individual contributer agreement and mention in readme; --- README.md | 3 +++ doc/NOS3_Indv_CLA.pdf | Bin 0 -> 134891 bytes 2 files changed, 3 insertions(+) create mode 100644 doc/NOS3_Indv_CLA.pdf diff --git a/README.md b/README.md index e720bc58..59e4cf09 100644 --- a/README.md +++ b/README.md @@ -75,5 +75,8 @@ This project is licensed under the NOSA (NASA Open Source Agreement) License. # Issues and Features Please report issues and request features on the GitHub tracking system - [NOS3 Issues](https://www.github.com/nasa/nos3/issues). +## Contributions +If you would like to contribute to the repository, please complete the [NOS3_Indv_CLA](./doc/NOS3_Indv_CLA.pdf) form and submit it to gsfc-softwarerequest@mail.nasa.gov with John.P.Lucas@nasa.gov copied. Next please create an issue capturing work to be done noting you intend to work it, a related branch, and submit a pull request when ready and we'll work to get it integrated. + ## Support If this project interests you or if you have any questions, please feel free to contact any developer directly or email `support@nos3.org`. diff --git a/doc/NOS3_Indv_CLA.pdf b/doc/NOS3_Indv_CLA.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3367569e8eedc85a48077ac12610bc519a2e614a GIT binary patch literal 134891 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

QQemxh@HdI{`Ni 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


eXnT6G(oRC=ho^kO5*+Mt}*q@ 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 literal 0 HcmV?d00001 From c4f1bf0b7232abe304139ac1955662c532644204 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 20 Dec 2023 07:42:35 -0500 Subject: [PATCH 048/153] [nasa/nos3#223] Removed only existing 42 InOut files in docker_launch script; --- gsw/scripts/docker_launch.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 4cf7c42d..45b732d7 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -33,10 +33,6 @@ mkdir /tmp/data/inst 2> /dev/null mkdir /tmp/uplink 2> /dev/null cp $BASE_DIR/fsw/build/exe/cpu1/cf/cfe_es_startup.scr /tmp/uplink/tmp0.so 2> /dev/null cp $BASE_DIR/fsw/build/exe/cpu1/cf/sample.so /tmp/uplink/tmp1.so 2> /dev/null -# 42 -cd /opt/nos3/42/ -rm -rf NOS3InOut -cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut echo "Create ground networks..." @@ -82,6 +78,7 @@ do echo "" echo $SC_NUM " - 42..." + rm -rf $USER_NOS3_DIR/42/NOS3InOut cp -r $BASE_DIR/sims/cfg/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut From 46e0ed5a241c9790f83aed8617ca2b33db4cdfed Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 20 Dec 2023 08:15:59 -0500 Subject: [PATCH 049/153] [nasa/nos3#135] Moved sim cfg to top level and updated necessary CMakeLists and launch scripts to accomodate; --- {sims/cfg => cfg}/InOut/ISS_TLE.txt | 0 {sims/cfg => cfg}/InOut/Inp_Cmd.txt | 0 {sims/cfg => cfg}/InOut/Inp_FOV.txt | 0 {sims/cfg => cfg}/InOut/Inp_Graphics.txt | 0 {sims/cfg => cfg}/InOut/Inp_IPC.txt | 0 {sims/cfg => cfg}/InOut/Inp_NOS3.txt | 0 {sims/cfg => cfg}/InOut/Inp_Region.txt | 0 {sims/cfg => cfg}/InOut/Inp_Sim.txt | 0 {sims/cfg => cfg}/InOut/Inp_TDRS.txt | 0 {sims/cfg => cfg}/InOut/Orb_Ellipse.txt | 0 {sims/cfg => cfg}/InOut/Orb_ISS.txt | 0 {sims/cfg => cfg}/InOut/Orb_LEO.txt | 0 {sims/cfg => cfg}/InOut/SC_NOS3.txt | 0 {sims/cfg => cfg}/InOut/TRV.txt | 0 {sims/cfg => cfg}/nos3-simulator.xml | 0 {sims/cfg => cfg}/nos_engine_server_config.json | 0 {sims/cfg => cfg}/sim_log_config.xml | 0 gsw/scripts/docker_launch.sh | 2 +- gsw/scripts/launch.sh | 2 +- sims/CMakeLists.txt | 6 +++--- 20 files changed, 5 insertions(+), 5 deletions(-) rename {sims/cfg => cfg}/InOut/ISS_TLE.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_Cmd.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_FOV.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_Graphics.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_IPC.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_NOS3.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_Region.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_Sim.txt (100%) rename {sims/cfg => cfg}/InOut/Inp_TDRS.txt (100%) rename {sims/cfg => cfg}/InOut/Orb_Ellipse.txt (100%) rename {sims/cfg => cfg}/InOut/Orb_ISS.txt (100%) rename {sims/cfg => cfg}/InOut/Orb_LEO.txt (100%) rename {sims/cfg => cfg}/InOut/SC_NOS3.txt (100%) rename {sims/cfg => cfg}/InOut/TRV.txt (100%) rename {sims/cfg => cfg}/nos3-simulator.xml (100%) rename {sims/cfg => cfg}/nos_engine_server_config.json (100%) rename {sims/cfg => cfg}/sim_log_config.xml (100%) diff --git a/sims/cfg/InOut/ISS_TLE.txt b/cfg/InOut/ISS_TLE.txt similarity index 100% rename from sims/cfg/InOut/ISS_TLE.txt rename to cfg/InOut/ISS_TLE.txt diff --git a/sims/cfg/InOut/Inp_Cmd.txt b/cfg/InOut/Inp_Cmd.txt similarity index 100% rename from sims/cfg/InOut/Inp_Cmd.txt rename to cfg/InOut/Inp_Cmd.txt diff --git a/sims/cfg/InOut/Inp_FOV.txt b/cfg/InOut/Inp_FOV.txt similarity index 100% rename from sims/cfg/InOut/Inp_FOV.txt rename to cfg/InOut/Inp_FOV.txt diff --git a/sims/cfg/InOut/Inp_Graphics.txt b/cfg/InOut/Inp_Graphics.txt similarity index 100% rename from sims/cfg/InOut/Inp_Graphics.txt rename to cfg/InOut/Inp_Graphics.txt diff --git a/sims/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt similarity index 100% rename from sims/cfg/InOut/Inp_IPC.txt rename to cfg/InOut/Inp_IPC.txt diff --git a/sims/cfg/InOut/Inp_NOS3.txt b/cfg/InOut/Inp_NOS3.txt similarity index 100% rename from sims/cfg/InOut/Inp_NOS3.txt rename to cfg/InOut/Inp_NOS3.txt diff --git a/sims/cfg/InOut/Inp_Region.txt b/cfg/InOut/Inp_Region.txt similarity index 100% rename from sims/cfg/InOut/Inp_Region.txt rename to cfg/InOut/Inp_Region.txt diff --git a/sims/cfg/InOut/Inp_Sim.txt b/cfg/InOut/Inp_Sim.txt similarity index 100% rename from sims/cfg/InOut/Inp_Sim.txt rename to cfg/InOut/Inp_Sim.txt diff --git a/sims/cfg/InOut/Inp_TDRS.txt b/cfg/InOut/Inp_TDRS.txt similarity index 100% rename from sims/cfg/InOut/Inp_TDRS.txt rename to cfg/InOut/Inp_TDRS.txt diff --git a/sims/cfg/InOut/Orb_Ellipse.txt b/cfg/InOut/Orb_Ellipse.txt similarity index 100% rename from sims/cfg/InOut/Orb_Ellipse.txt rename to cfg/InOut/Orb_Ellipse.txt diff --git a/sims/cfg/InOut/Orb_ISS.txt b/cfg/InOut/Orb_ISS.txt similarity index 100% rename from sims/cfg/InOut/Orb_ISS.txt rename to cfg/InOut/Orb_ISS.txt diff --git a/sims/cfg/InOut/Orb_LEO.txt b/cfg/InOut/Orb_LEO.txt similarity index 100% rename from sims/cfg/InOut/Orb_LEO.txt rename to cfg/InOut/Orb_LEO.txt diff --git a/sims/cfg/InOut/SC_NOS3.txt b/cfg/InOut/SC_NOS3.txt similarity index 100% rename from sims/cfg/InOut/SC_NOS3.txt rename to cfg/InOut/SC_NOS3.txt diff --git a/sims/cfg/InOut/TRV.txt b/cfg/InOut/TRV.txt similarity index 100% rename from sims/cfg/InOut/TRV.txt rename to cfg/InOut/TRV.txt diff --git a/sims/cfg/nos3-simulator.xml b/cfg/nos3-simulator.xml similarity index 100% rename from sims/cfg/nos3-simulator.xml rename to cfg/nos3-simulator.xml diff --git a/sims/cfg/nos_engine_server_config.json b/cfg/nos_engine_server_config.json similarity index 100% rename from sims/cfg/nos_engine_server_config.json rename to cfg/nos_engine_server_config.json diff --git a/sims/cfg/sim_log_config.xml b/cfg/sim_log_config.xml similarity index 100% rename from sims/cfg/sim_log_config.xml rename to cfg/sim_log_config.xml diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 45b732d7..d9c7a26f 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -79,7 +79,7 @@ do echo $SC_NUM " - 42..." rm -rf $USER_NOS3_DIR/42/NOS3InOut - cp -r $BASE_DIR/sims/cfg/InOut $USER_NOS3_DIR/42/NOS3InOut + cp -r $BASE_DIR/cfg/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut echo "" diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index 2a53fcc4..a360ebab 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -28,7 +28,7 @@ cp $BASE_DIR/fsw/build/exe/cpu1/cf/sample.so /tmp/uplink/tmp1.so 2> /dev/null echo "42..." cd /opt/nos3/42/ rm -rf NOS3InOut -cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut +cp -r $BASE_DIR/cfg/InOut /opt/nos3/42/NOS3InOut gnome-terminal --tab --title="42 Dynamic Simulator" -- /opt/nos3/42/42 NOS3InOut echo "Simulators..." diff --git a/sims/CMakeLists.txt b/sims/CMakeLists.txt index 4e142b13..eb3bba54 100644 --- a/sims/CMakeLists.txt +++ b/sims/CMakeLists.txt @@ -48,8 +48,8 @@ ENDFOREACH() # Install configuration files to bin set(sim_cfg - cfg/nos_engine_server_config.json - cfg/nos3-simulator.xml - cfg/sim_log_config.xml + ../cfg/nos_engine_server_config.json + ../cfg/nos3-simulator.xml + ../cfg/sim_log_config.xml ) install(FILES ${sim_cfg} DESTINATION bin COMPONENT config) From 1d71f7d2019a3b24fd5019b92a6968995a0ef2f8 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 20 Dec 2023 08:33:40 -0500 Subject: [PATCH 050/153] [nasa/nos3#135] Moved ./fsw/nos3_defs into top level cfg folder and updated makefile to support; --- Makefile | 2 ++ {fsw => cfg}/nos3_defs/arch_build_custom.cmake | 0 .../nos3_mission_cfg.h => cfg/nos3_defs/cfe_mission_cfg.h | 0 fsw/nos3_defs/nos3_perfids.h => cfg/nos3_defs/cfe_perfids.h | 0 {fsw => cfg}/nos3_defs/cpu1_cfe_es_startup.scr | 0 {fsw => cfg}/nos3_defs/cpu1_device_cfg.h | 0 {fsw => cfg}/nos3_defs/cpu1_msgids.h | 0 {fsw => cfg}/nos3_defs/cpu1_platform_cfg.h | 0 {fsw => cfg}/nos3_defs/default_osconfig.cmake | 0 {fsw => cfg}/nos3_defs/global_build_options.cmake | 0 {fsw => cfg}/nos3_defs/mission_build_custom.cmake | 0 {fsw => cfg}/nos3_defs/native_osconfig.cmake | 0 {fsw => cfg}/nos3_defs/tables/cf_def_config.c | 0 {fsw => cfg}/nos3_defs/tables/ds_file_tbl.c | 0 {fsw => cfg}/nos3_defs/tables/ds_filter_tbl.c | 0 {fsw => cfg}/nos3_defs/tables/ds_indices.h | 0 {fsw => cfg}/nos3_defs/tables/fm_freespace.c | 0 {fsw => cfg}/nos3_defs/tables/hk_cpy_tbl.c | 0 {fsw => cfg}/nos3_defs/tables/sc_rts001.c | 0 {fsw => cfg}/nos3_defs/tables/sc_rts005.c | 0 {fsw => cfg}/nos3_defs/tables/sch_def_msgtbl.c | 0 {fsw => cfg}/nos3_defs/tables/sch_def_schtbl.c | 0 {fsw => cfg}/nos3_defs/tables/to_config.c | 0 {fsw => cfg}/nos3_defs/tables/to_lab_sub.c | 0 {fsw => cfg}/nos3_defs/targets.cmake | 0 {fsw => cfg}/nos3_defs/toolchain-i386-linux-gnu.cmake | 0 26 files changed, 2 insertions(+) rename {fsw => cfg}/nos3_defs/arch_build_custom.cmake (100%) rename fsw/nos3_defs/nos3_mission_cfg.h => cfg/nos3_defs/cfe_mission_cfg.h (100%) rename fsw/nos3_defs/nos3_perfids.h => cfg/nos3_defs/cfe_perfids.h (100%) rename {fsw => cfg}/nos3_defs/cpu1_cfe_es_startup.scr (100%) rename {fsw => cfg}/nos3_defs/cpu1_device_cfg.h (100%) rename {fsw => cfg}/nos3_defs/cpu1_msgids.h (100%) rename {fsw => cfg}/nos3_defs/cpu1_platform_cfg.h (100%) rename {fsw => cfg}/nos3_defs/default_osconfig.cmake (100%) rename {fsw => cfg}/nos3_defs/global_build_options.cmake (100%) rename {fsw => cfg}/nos3_defs/mission_build_custom.cmake (100%) rename {fsw => cfg}/nos3_defs/native_osconfig.cmake (100%) rename {fsw => cfg}/nos3_defs/tables/cf_def_config.c (100%) rename {fsw => cfg}/nos3_defs/tables/ds_file_tbl.c (100%) rename {fsw => cfg}/nos3_defs/tables/ds_filter_tbl.c (100%) rename {fsw => cfg}/nos3_defs/tables/ds_indices.h (100%) rename {fsw => cfg}/nos3_defs/tables/fm_freespace.c (100%) rename {fsw => cfg}/nos3_defs/tables/hk_cpy_tbl.c (100%) rename {fsw => cfg}/nos3_defs/tables/sc_rts001.c (100%) rename {fsw => cfg}/nos3_defs/tables/sc_rts005.c (100%) rename {fsw => cfg}/nos3_defs/tables/sch_def_msgtbl.c (100%) rename {fsw => cfg}/nos3_defs/tables/sch_def_schtbl.c (100%) rename {fsw => cfg}/nos3_defs/tables/to_config.c (100%) rename {fsw => cfg}/nos3_defs/tables/to_lab_sub.c (100%) rename {fsw => cfg}/nos3_defs/targets.cmake (100%) rename {fsw => cfg}/nos3_defs/toolchain-i386-linux-gnu.cmake (100%) diff --git a/Makefile b/Makefile index 2d62b6f5..0dc5fea9 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,8 @@ FSWBUILDDIR ?= $(CURDIR)/fsw/build SIMBUILDDIR ?= $(CURDIR)/sims/build export CFS_APP_PATH = ../components +export MISSION_DEFS = ../cfg/ +export MISSIONCONFIG = ../cfg/nos3 # The "prep" step requires extra options that are specified via enviroment variables. # Certain special ones should be passed via cache (-D) options to CMake. diff --git a/fsw/nos3_defs/arch_build_custom.cmake b/cfg/nos3_defs/arch_build_custom.cmake similarity index 100% rename from fsw/nos3_defs/arch_build_custom.cmake rename to cfg/nos3_defs/arch_build_custom.cmake diff --git a/fsw/nos3_defs/nos3_mission_cfg.h b/cfg/nos3_defs/cfe_mission_cfg.h similarity index 100% rename from fsw/nos3_defs/nos3_mission_cfg.h rename to cfg/nos3_defs/cfe_mission_cfg.h diff --git a/fsw/nos3_defs/nos3_perfids.h b/cfg/nos3_defs/cfe_perfids.h similarity index 100% rename from fsw/nos3_defs/nos3_perfids.h rename to cfg/nos3_defs/cfe_perfids.h diff --git a/fsw/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr similarity index 100% rename from fsw/nos3_defs/cpu1_cfe_es_startup.scr rename to cfg/nos3_defs/cpu1_cfe_es_startup.scr diff --git a/fsw/nos3_defs/cpu1_device_cfg.h b/cfg/nos3_defs/cpu1_device_cfg.h similarity index 100% rename from fsw/nos3_defs/cpu1_device_cfg.h rename to cfg/nos3_defs/cpu1_device_cfg.h diff --git a/fsw/nos3_defs/cpu1_msgids.h b/cfg/nos3_defs/cpu1_msgids.h similarity index 100% rename from fsw/nos3_defs/cpu1_msgids.h rename to cfg/nos3_defs/cpu1_msgids.h diff --git a/fsw/nos3_defs/cpu1_platform_cfg.h b/cfg/nos3_defs/cpu1_platform_cfg.h similarity index 100% rename from fsw/nos3_defs/cpu1_platform_cfg.h rename to cfg/nos3_defs/cpu1_platform_cfg.h diff --git a/fsw/nos3_defs/default_osconfig.cmake b/cfg/nos3_defs/default_osconfig.cmake similarity index 100% rename from fsw/nos3_defs/default_osconfig.cmake rename to cfg/nos3_defs/default_osconfig.cmake diff --git a/fsw/nos3_defs/global_build_options.cmake b/cfg/nos3_defs/global_build_options.cmake similarity index 100% rename from fsw/nos3_defs/global_build_options.cmake rename to cfg/nos3_defs/global_build_options.cmake diff --git a/fsw/nos3_defs/mission_build_custom.cmake b/cfg/nos3_defs/mission_build_custom.cmake similarity index 100% rename from fsw/nos3_defs/mission_build_custom.cmake rename to cfg/nos3_defs/mission_build_custom.cmake diff --git a/fsw/nos3_defs/native_osconfig.cmake b/cfg/nos3_defs/native_osconfig.cmake similarity index 100% rename from fsw/nos3_defs/native_osconfig.cmake rename to cfg/nos3_defs/native_osconfig.cmake diff --git a/fsw/nos3_defs/tables/cf_def_config.c b/cfg/nos3_defs/tables/cf_def_config.c similarity index 100% rename from fsw/nos3_defs/tables/cf_def_config.c rename to cfg/nos3_defs/tables/cf_def_config.c diff --git a/fsw/nos3_defs/tables/ds_file_tbl.c b/cfg/nos3_defs/tables/ds_file_tbl.c similarity index 100% rename from fsw/nos3_defs/tables/ds_file_tbl.c rename to cfg/nos3_defs/tables/ds_file_tbl.c diff --git a/fsw/nos3_defs/tables/ds_filter_tbl.c b/cfg/nos3_defs/tables/ds_filter_tbl.c similarity index 100% rename from fsw/nos3_defs/tables/ds_filter_tbl.c rename to cfg/nos3_defs/tables/ds_filter_tbl.c diff --git a/fsw/nos3_defs/tables/ds_indices.h b/cfg/nos3_defs/tables/ds_indices.h similarity index 100% rename from fsw/nos3_defs/tables/ds_indices.h rename to cfg/nos3_defs/tables/ds_indices.h diff --git a/fsw/nos3_defs/tables/fm_freespace.c b/cfg/nos3_defs/tables/fm_freespace.c similarity index 100% rename from fsw/nos3_defs/tables/fm_freespace.c rename to cfg/nos3_defs/tables/fm_freespace.c diff --git a/fsw/nos3_defs/tables/hk_cpy_tbl.c b/cfg/nos3_defs/tables/hk_cpy_tbl.c similarity index 100% rename from fsw/nos3_defs/tables/hk_cpy_tbl.c rename to cfg/nos3_defs/tables/hk_cpy_tbl.c diff --git a/fsw/nos3_defs/tables/sc_rts001.c b/cfg/nos3_defs/tables/sc_rts001.c similarity index 100% rename from fsw/nos3_defs/tables/sc_rts001.c rename to cfg/nos3_defs/tables/sc_rts001.c diff --git a/fsw/nos3_defs/tables/sc_rts005.c b/cfg/nos3_defs/tables/sc_rts005.c similarity index 100% rename from fsw/nos3_defs/tables/sc_rts005.c rename to cfg/nos3_defs/tables/sc_rts005.c diff --git a/fsw/nos3_defs/tables/sch_def_msgtbl.c b/cfg/nos3_defs/tables/sch_def_msgtbl.c similarity index 100% rename from fsw/nos3_defs/tables/sch_def_msgtbl.c rename to cfg/nos3_defs/tables/sch_def_msgtbl.c diff --git a/fsw/nos3_defs/tables/sch_def_schtbl.c b/cfg/nos3_defs/tables/sch_def_schtbl.c similarity index 100% rename from fsw/nos3_defs/tables/sch_def_schtbl.c rename to cfg/nos3_defs/tables/sch_def_schtbl.c diff --git a/fsw/nos3_defs/tables/to_config.c b/cfg/nos3_defs/tables/to_config.c similarity index 100% rename from fsw/nos3_defs/tables/to_config.c rename to cfg/nos3_defs/tables/to_config.c diff --git a/fsw/nos3_defs/tables/to_lab_sub.c b/cfg/nos3_defs/tables/to_lab_sub.c similarity index 100% rename from fsw/nos3_defs/tables/to_lab_sub.c rename to cfg/nos3_defs/tables/to_lab_sub.c diff --git a/fsw/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake similarity index 100% rename from fsw/nos3_defs/targets.cmake rename to cfg/nos3_defs/targets.cmake diff --git a/fsw/nos3_defs/toolchain-i386-linux-gnu.cmake b/cfg/nos3_defs/toolchain-i386-linux-gnu.cmake similarity index 100% rename from fsw/nos3_defs/toolchain-i386-linux-gnu.cmake rename to cfg/nos3_defs/toolchain-i386-linux-gnu.cmake From ab078144b960e232ee893828fdb74305087ef321 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 22 Dec 2023 12:12:43 -0500 Subject: [PATCH 051/153] https://github.com/nasa/nos3/issues/222 - Display actual speed up. Add run until X command. Add run X more time command. --- sims/nos_time_driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sims/nos_time_driver b/sims/nos_time_driver index 55238651..e77ed017 160000 --- a/sims/nos_time_driver +++ b/sims/nos_time_driver @@ -1 +1 @@ -Subproject commit 552386510b5180781c20d85e21a42c48308526d3 +Subproject commit e77ed017c99674c4dcb0162f77ff02dc2c7977e4 From 238eae2ddf9ef1f6e65bd9f080daae384e44be79 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 22 Dec 2023 14:57:14 -0500 Subject: [PATCH 052/153] https://github.com/nasa/nos3/issues/222 - Add commands that can be executed from the simulator terminal to control pause/unpause, decrease/increase delay, run seconds and until seconds. --- gsw/scripts/docker_launch.sh | 2 +- sims/cfg/nos3-simulator.xml | 5 +++++ sims/nos_time_driver | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gsw/scripts/docker_launch.sh b/gsw/scripts/docker_launch.sh index 0964728c..f8938e52 100755 --- a/gsw/scripts/docker_launch.sh +++ b/gsw/scripts/docker_launch.sh @@ -123,7 +123,7 @@ done echo "NOS Time Driver..." -sleep 5 +sleep 8 gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE time sleep 1 for (( i=1; i<=$SATNUM; i++ )) diff --git a/sims/cfg/nos3-simulator.xml b/sims/cfg/nos3-simulator.xml index caca1fed..74d055ee 100644 --- a/sims/cfg/nos3-simulator.xml +++ b/sims/cfg/nos3-simulator.xml @@ -27,6 +27,11 @@ command sc1-time-driver + + command + command + time-command + diff --git a/sims/nos_time_driver b/sims/nos_time_driver index e77ed017..4c7bb3a2 160000 --- a/sims/nos_time_driver +++ b/sims/nos_time_driver @@ -1 +1 @@ -Subproject commit e77ed017c99674c4dcb0162f77ff02dc2c7977e4 +Subproject commit 4c7bb3a2dee64cbe905dba7823447bfefb8764cb From 4694ff3777a21e4ac4b22439239994f3630a08fc Mon Sep 17 00:00:00 2001 From: David Date: Thu, 28 Dec 2023 13:30:48 +0000 Subject: [PATCH 053/153] Updates to add a time bus --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 8615c388..d7dd1a2d 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 8615c388fdc6ff2965d99a4197056f3e2ca85b44 +Subproject commit d7dd1a2d6fd95382e9ba8e2a2864077c73065a16 From b860b63769269a7f0789409a9ae3e88415a8dd11 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 2 Jan 2024 12:35:01 -0500 Subject: [PATCH 054/153] [nasa/nos3#135] Moved ./gsw/scrips up to top level and updated Makefile and env.sh with new location; --- Makefile | 24 +++++++++---------- {gsw/scripts => scripts}/checkout.sh | 0 {gsw/scripts => scripts}/create_cosmos_gem.sh | 0 {gsw/scripts => scripts}/docker-compose.yml | 0 {gsw/scripts => scripts}/docker_build_fsw.sh | 0 {gsw/scripts => scripts}/docker_build_sim.sh | 0 .../docker_compose_launch.sh | 0 {gsw/scripts => scripts}/docker_debug.sh | 0 {gsw/scripts => scripts}/docker_launch.sh | 0 {gsw/scripts => scripts}/docker_stop.sh | 0 {gsw/scripts => scripts}/env.sh | 2 +- {gsw/scripts => scripts}/fsw_respawn.sh | 0 {gsw/scripts => scripts}/gsw.sh | 0 {gsw/scripts => scripts}/l0.sh | 0 {gsw/scripts => scripts}/launch.sh | 0 {gsw/scripts => scripts}/log.sh | 0 {gsw/scripts => scripts}/prepare.sh | 0 {gsw/scripts => scripts}/real_clean.sh | 0 {gsw/scripts => scripts}/stop.sh | 0 {gsw/scripts => scripts}/stop_gsw.sh | 0 20 files changed, 13 insertions(+), 13 deletions(-) rename {gsw/scripts => scripts}/checkout.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/create_cosmos_gem.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker-compose.yml (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_build_fsw.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_build_sim.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_compose_launch.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_debug.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_launch.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/docker_stop.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/env.sh (97%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/fsw_respawn.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/gsw.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/l0.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/launch.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/log.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/prepare.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/real_clean.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/stop.sh (100%) mode change 100755 => 100644 rename {gsw/scripts => scripts}/stop_gsw.sh (100%) mode change 100755 => 100644 diff --git a/Makefile b/Makefile index 0dc5fea9..c902d57f 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ build-sim: $(MAKE) --no-print-directory -C $(SIMBUILDDIR) install checkout: - ./gsw/scripts/checkout.sh + ./scripts/checkout.sh clean: $(MAKE) clean-fsw @@ -72,33 +72,33 @@ clean-gsw: rm -rf gsw/cosmos/build debug: - ./gsw/scripts/docker_debug.sh + ./scripts/docker_debug.sh fsw: - ./gsw/scripts/docker_build_fsw.sh + ./scripts/docker_build_fsw.sh gsw: - ./gsw/scripts/create_cosmos_gem.sh + ./scripts/create_cosmos_gem.sh launch: - ./gsw/scripts/docker_launch.sh + ./scripts/docker_launch.sh log: - ./gsw/scripts/log.sh + ./scripts/log.sh prep: - ./gsw/scripts/prepare.sh + ./scripts/prepare.sh real-clean: $(MAKE) clean - ./gsw/scripts/real_clean.sh + ./scripts/real_clean.sh sim: - ./gsw/scripts/docker_build_sim.sh + ./scripts/docker_build_sim.sh stop: - ./gsw/scripts/docker_stop.sh - ./gsw/scripts/stop.sh + ./scripts/docker_stop.sh + ./scripts/stop.sh stop-gsw: - ./gsw/scripts/stop_gsw.sh + ./scripts/stop_gsw.sh diff --git a/gsw/scripts/checkout.sh b/scripts/checkout.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/checkout.sh rename to scripts/checkout.sh diff --git a/gsw/scripts/create_cosmos_gem.sh b/scripts/create_cosmos_gem.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/create_cosmos_gem.sh rename to scripts/create_cosmos_gem.sh diff --git a/gsw/scripts/docker-compose.yml b/scripts/docker-compose.yml old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker-compose.yml rename to scripts/docker-compose.yml diff --git a/gsw/scripts/docker_build_fsw.sh b/scripts/docker_build_fsw.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_build_fsw.sh rename to scripts/docker_build_fsw.sh diff --git a/gsw/scripts/docker_build_sim.sh b/scripts/docker_build_sim.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_build_sim.sh rename to scripts/docker_build_sim.sh diff --git a/gsw/scripts/docker_compose_launch.sh b/scripts/docker_compose_launch.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_compose_launch.sh rename to scripts/docker_compose_launch.sh diff --git a/gsw/scripts/docker_debug.sh b/scripts/docker_debug.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_debug.sh rename to scripts/docker_debug.sh diff --git a/gsw/scripts/docker_launch.sh b/scripts/docker_launch.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_launch.sh rename to scripts/docker_launch.sh diff --git a/gsw/scripts/docker_stop.sh b/scripts/docker_stop.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/docker_stop.sh rename to scripts/docker_stop.sh diff --git a/gsw/scripts/env.sh b/scripts/env.sh old mode 100755 new mode 100644 similarity index 97% rename from gsw/scripts/env.sh rename to scripts/env.sh index b3bfff90..e03cbf82 --- a/gsw/scripts/env.sh +++ b/scripts/env.sh @@ -4,7 +4,7 @@ # SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -BASE_DIR=$(cd `dirname $SCRIPT_DIR`/.. && pwd) +BASE_DIR=$(cd `dirname $SCRIPT_DIR` && pwd) FSW_DIR=$BASE_DIR/fsw/build/exe/cpu1 GSW_BIN=$BASE_DIR/gsw/cosmos/build/openc3-cosmos-nos3 GSW_DIR=$BASE_DIR/gsw/cosmos diff --git a/gsw/scripts/fsw_respawn.sh b/scripts/fsw_respawn.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/fsw_respawn.sh rename to scripts/fsw_respawn.sh diff --git a/gsw/scripts/gsw.sh b/scripts/gsw.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/gsw.sh rename to scripts/gsw.sh diff --git a/gsw/scripts/l0.sh b/scripts/l0.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/l0.sh rename to scripts/l0.sh diff --git a/gsw/scripts/launch.sh b/scripts/launch.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/launch.sh rename to scripts/launch.sh diff --git a/gsw/scripts/log.sh b/scripts/log.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/log.sh rename to scripts/log.sh diff --git a/gsw/scripts/prepare.sh b/scripts/prepare.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/prepare.sh rename to scripts/prepare.sh diff --git a/gsw/scripts/real_clean.sh b/scripts/real_clean.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/real_clean.sh rename to scripts/real_clean.sh diff --git a/gsw/scripts/stop.sh b/scripts/stop.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/stop.sh rename to scripts/stop.sh diff --git a/gsw/scripts/stop_gsw.sh b/scripts/stop_gsw.sh old mode 100755 new mode 100644 similarity index 100% rename from gsw/scripts/stop_gsw.sh rename to scripts/stop_gsw.sh From c61fdb3afa47659a45de4762001ed5940028592c Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 3 Jan 2024 13:32:45 -0500 Subject: [PATCH 055/153] [nasa/nos3#135] Added config step to setup the fsw, 42, and sim configuration files; --- Makefile | 12 +- cfg/InOut/Inp_IPC.txt | 16 +- cfg/nos3-mission.xml | 8 + cfg/nos3_defs/cpu1_cfe_es_startup.scr | 73 ++-- cfg/nos3_defs/targets.cmake | 4 +- cfg/sc-full-config.xml | 68 +++ cfg/sc-minimal-config.xml | 68 +++ cfg/{ => sims}/nos3-simulator.xml | 0 cfg/{ => sims}/nos_engine_server_config.json | 0 cfg/{ => sims}/sim_log_config.xml | 0 scripts/checkout.sh | 0 scripts/config.sh | 18 + scripts/configure.py | 409 +++++++++++++++++++ scripts/create_cosmos_gem.sh | 0 scripts/docker-compose.yml | 0 scripts/docker_build_fsw.sh | 11 + scripts/docker_build_sim.sh | 8 + scripts/docker_compose_launch.sh | 0 scripts/docker_debug.sh | 0 scripts/docker_launch.sh | 9 +- scripts/docker_stop.sh | 0 scripts/env.sh | 0 scripts/fsw_respawn.sh | 0 scripts/gsw.sh | 0 scripts/l0.sh | 0 scripts/launch.sh | 0 scripts/log.sh | 0 scripts/prepare.sh | 0 scripts/real_clean.sh | 0 scripts/stop.sh | 0 scripts/stop_gsw.sh | 0 sims/CMakeLists.txt | 6 +- 32 files changed, 654 insertions(+), 56 deletions(-) create mode 100644 cfg/nos3-mission.xml create mode 100644 cfg/sc-full-config.xml create mode 100644 cfg/sc-minimal-config.xml rename cfg/{ => sims}/nos3-simulator.xml (100%) rename cfg/{ => sims}/nos_engine_server_config.json (100%) rename cfg/{ => sims}/sim_log_config.xml (100%) mode change 100644 => 100755 scripts/checkout.sh create mode 100755 scripts/config.sh create mode 100755 scripts/configure.py mode change 100644 => 100755 scripts/create_cosmos_gem.sh mode change 100644 => 100755 scripts/docker-compose.yml mode change 100644 => 100755 scripts/docker_build_fsw.sh mode change 100644 => 100755 scripts/docker_build_sim.sh mode change 100644 => 100755 scripts/docker_compose_launch.sh mode change 100644 => 100755 scripts/docker_debug.sh mode change 100644 => 100755 scripts/docker_launch.sh mode change 100644 => 100755 scripts/docker_stop.sh mode change 100644 => 100755 scripts/env.sh mode change 100644 => 100755 scripts/fsw_respawn.sh mode change 100644 => 100755 scripts/gsw.sh mode change 100644 => 100755 scripts/l0.sh mode change 100644 => 100755 scripts/launch.sh mode change 100644 => 100755 scripts/log.sh mode change 100644 => 100755 scripts/prepare.sh mode change 100644 => 100755 scripts/real_clean.sh mode change 100644 => 100755 scripts/stop.sh mode change 100644 => 100755 scripts/stop_gsw.sh diff --git a/Makefile b/Makefile index c902d57f..2eb5fdc4 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ FSWBUILDDIR ?= $(CURDIR)/fsw/build SIMBUILDDIR ?= $(CURDIR)/sims/build export CFS_APP_PATH = ../components -export MISSION_DEFS = ../cfg/ -export MISSIONCONFIG = ../cfg/nos3 +export MISSION_DEFS = ../cfg/build/ +export MISSIONCONFIG = ../cfg/build/nos3 # The "prep" step requires extra options that are specified via enviroment variables. # Certain special ones should be passed via cache (-D) options to CMake. @@ -29,7 +29,7 @@ endif # The "LOCALTGTS" defines the top-level targets that are implemented in this makefile # Any other target may also be given, in that case it will simply be passed through. -LOCALTGTS := all checkout clean clean-fsw clean-sim clean-gsw debug fsw gsw launch log prep real-clean sim stop stop-gsw +LOCALTGTS := all checkout clean clean-fsw clean-sim clean-gsw config debug fsw gsw launch log prep real-clean sim stop stop-gsw OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # As this makefile does not build any real files, treat everything as a PHONY target @@ -40,6 +40,7 @@ OTHERTGTS := $(filter-out $(LOCALTGTS),$(MAKECMDGOALS)) # Commands # all: + $(MAKE) config $(MAKE) fsw $(MAKE) sim $(MAKE) gsw @@ -61,8 +62,10 @@ clean: $(MAKE) clean-fsw $(MAKE) clean-sim $(MAKE) clean-gsw + rm -rf cfg/build clean-fsw: + rm -rf cfg/build/nos3_defs rm -rf fsw/build clean-sim: @@ -71,6 +74,9 @@ clean-sim: clean-gsw: rm -rf gsw/cosmos/build +config: + ./scripts/config.sh + debug: ./scripts/docker_debug.sh diff --git a/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt index 2dacd956..c860ef5d 100644 --- a/cfg/InOut/Inp_IPC.txt +++ b/cfg/InOut/Inp_IPC.txt @@ -1,6 +1,6 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> 16 ! Number of Sockets -********************************** Sample ***************************** +********************************** Sample IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "State00.42" ! File name for WRITE or READ @@ -70,7 +70,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 -********************************** Torquer ***************************** +********************************** Torquer IPC ***************************** RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 1 ! AC.ID for ACS mode "Torquer.Rx" ! File name for WRITE or READ @@ -80,7 +80,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 -********************************** IPC 4 ***************************** +********************************** GPS IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "State03.42" ! File name for WRITE or READ @@ -90,7 +90,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 -********************************** CSS ***************************** +********************************** CSS IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "State04.42" ! File name for WRITE or READ @@ -100,7 +100,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC[0].AC.CSS" ! Prefix 0 -********************************** MAG ***************************** +********************************** MAG IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "State05.42" ! File name for WRITE or READ @@ -142,7 +142,7 @@ FALSE ! Echo to stdout "SC[0].Hvb" ! Prefix 4 "SC[0].B[0]" ! Prefix 5 "Orb" ! Prefix 6 -********************************** FSS ***************************** +********************************** FSS IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "FSS.42" ! File name for WRITE or READ @@ -152,7 +152,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 -********************************** GENERIC_IMU ***************************** +********************************** IMU IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "IMU.42" ! File name for WRITE or READ @@ -162,7 +162,7 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC" ! Prefix 0 -********************************** Star Tracker ***************************** +********************************** Star Tracker IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode "ST.42" ! File name for WRITE or READ diff --git a/cfg/nos3-mission.xml b/cfg/nos3-mission.xml new file mode 100644 index 00000000..1216ec61 --- /dev/null +++ b/cfg/nos3-mission.xml @@ -0,0 +1,8 @@ + + 814048200.0 + 1 + sc-full-config.xml + + diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index 775aa83d..1b1092f7 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -8,14 +8,17 @@ CFE_APP, to, TO_AppMain, TO, CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 80, 16384, 0x0, 0; CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 16384, 0x0, 0; +! +! ** The software will not try to parse anything after the first '!' character it sees. ** +! CFE_APP, cf, CF_AppMain, CF, 50, 16384, 0x0, 0; CFE_APP, ds, DS_AppMain, DS, 51, 16384, 0x0, 0; CFE_APP, fm, FM_AppMain, FM, 52, 16384, 0x0, 0; CFE_APP, lc, LC_AppMain, LC, 53, 16384, 0x0, 0; CFE_APP, sc, SC_AppMain, SC, 54, 16384, 0x0, 0; -CFE_APP, arducam, arducam_AppMain, CAM, 60, 8192, 0x0, 0; CFE_APP, generic_adcs, ADCS_AppMain, ADCS, 61, 8192, 0x0, 0; +CFE_APP, arducam, arducam_AppMain, CAM, 60, 8192, 0x0, 0; CFE_APP, generic_css, CSS_AppMain, CSS, 62, 8192, 0x0, 0; CFE_APP, generic_eps, EPS_AppMain, EPS, 63, 8192, 0x0, 0; CFE_APP, generic_fss, FSS_AppMain, FSS, 64, 8192, 0x0, 0; @@ -28,43 +31,35 @@ CFE_APP, novatel_oem615, NOVATEL_AppMain, NAV, CFE_APP, sample, SAMPLE_AppMain, SAMPLE, 71, 8192, 0x0, 0; CFE_APP, generic_st, ST_AppMain, ST, 71, 8192, 0x0, 0; -! +CFE_LIB, cfs_lib, CFS_LibInit, CFS_LIB, 0, 0, 0x0, 0; CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; +CFE_APP, cs, CS_AppMain, CS, 55, 16384, 0x0, 0; +CFE_APP, hk, HK_AppMain, HK, 63, 16384, 0x0, 0; +CFE_APP, hs, HS_AppMain, HS, 56, 16384, 0x0, 0; +CFE_APP, sbn, SBN_AppMain, SBN, 63, 16384, 0x0, 0; +CFE_APP, md, MD_AppMain, MD, 60, 16384, 0x0, 0; +CFE_APP, mm, MM_AppMain, MM, 61, 16384, 0x0, 0; -! -! ** The software will not try to parse anything after the first '!' character it sees. ** -! -! CFE_LIB, cfs_lib, CFS_LibInit, CFS_LIB, 0, 0, 0x0, 0; -! CFE_APP, cs, CS_AppMain, CS, 55, 16384, 0x0, 0; -! CFE_APP, hk, HK_AppMain, HK, 63, 16384, 0x0, 0; -! CFE_APP, hs, HS_AppMain, HS, 56, 16384, 0x0, 0; -! CFE_APP, sbn, SBN_AppMain, SBN, 63, 16384, 0x0, 0; -! CFE_APP, md, MD_AppMain, MD, 60, 16384, 0x0, 0; -! CFE_APP, mm, MM_AppMain, MM, 61, 16384, 0x0, 0; -! -! CFE_LIB, sample_lib, SAMPLE_LibInit, SAMPLE_LIB, 0, 0, 0x0, 0; -! CFE_APP, sample_app, SAMPLE_AppMain, SAMPLE_APP, 51, 16384, 0x0, 0; -! -! Startup script fields: -! 1. Object Type -- CFE_APP for an Application, or CFE_LIB for a library. -! 2. Path/Filename -- This is a cFE Virtual filename, not a vxWorks device/pathname -! 3. Entry Point -- This is the "main" function for Apps. -! 4. CFE Name -- The cFE name for the the APP or Library -! 5. Priority -- This is the Priority of the App, not used for Library -! 6. Stack Size -- This is the Stack size for the App, not used for the Library -! 7. Load Address -- This is the Optional Load Address for the App or Library. Currently not implemented -! so keep it at 0x0. -! 8. Exception Action -- This is the Action the cFE should take if the App has an exception. -! 0 = Just restart the Application -! Non-Zero = Do a cFE Processor Reset -! -! Other Notes: -! 1. The software will not try to parse anything after the first '!' character it sees. That -! is the End of File marker. -! 2. Common Application file extensions: -! Linux = .so ( ci.so ) -! OS X = .bundle ( ci.bundle ) -! Cygwin = .dll ( ci.dll ) -! vxWorks = .o ( ci.o ) -! RTEMS with S-record Loader = .s3r ( ci.s3r ) -! RTEMS with CEXP Loader = .o ( ci.o ) +Startup script fields: +1. Object Type -- CFE_APP for an Application, or CFE_LIB for a library. +2. Path/Filename -- This is a cFE Virtual filename, not a vxWorks device/pathname +3. Entry Point -- This is the "main" function for Apps. +4. CFE Name -- The cFE name for the the APP or Library +5. Priority -- This is the Priority of the App, not used for Library +6. Stack Size -- This is the Stack size for the App, not used for the Library +7. Load Address -- This is the Optional Load Address for the App or Library. Currently not implemented + so keep it at 0x0. +8. Exception Action -- This is the Action the cFE should take if the App has an exception. + 0 = Just restart the Application + Non-Zero = Do a cFE Processor Reset + +Other Notes: +1. The software will not try to parse anything after the first '!' character it sees. That + is the End of File marker. +2. Common Application file extensions: + Linux = .so ( ci.so ) + OS X = .bundle ( ci.bundle ) + Cygwin = .dll ( ci.dll ) + vxWorks = .o ( ci.o ) + RTEMS with S-record Loader = .s3r ( ci.s3r ) + RTEMS with CEXP Loader = .o ( ci.o ) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 13393551..03ee90e2 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -104,6 +104,7 @@ list(APPEND MISSION_GLOBAL_APPLIST # Components # arducam + generic_adcs generic_css generic_eps generic_fss @@ -111,11 +112,10 @@ list(APPEND MISSION_GLOBAL_APPLIST generic_mag generic_reaction_wheel generic_radio + generic_star_tracker generic_torquer novatel_oem615 sample - generic_adcs - generic_star_tracker ) # Create Application Platform Include List diff --git a/cfg/sc-full-config.xml b/cfg/sc-full-config.xml new file mode 100644 index 00000000..32bc3354 --- /dev/null +++ b/cfg/sc-full-config.xml @@ -0,0 +1,68 @@ + + + + true + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + true + + + 0.1 + 1.0 + -1.0 + + \ No newline at end of file diff --git a/cfg/sc-minimal-config.xml b/cfg/sc-minimal-config.xml new file mode 100644 index 00000000..f64a7689 --- /dev/null +++ b/cfg/sc-minimal-config.xml @@ -0,0 +1,68 @@ + + + + true + + + true + + + true + + + true + + + true + + + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + + true + + + 0.1 + 1.0 + -1.0 + + \ No newline at end of file diff --git a/cfg/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml similarity index 100% rename from cfg/nos3-simulator.xml rename to cfg/sims/nos3-simulator.xml diff --git a/cfg/nos_engine_server_config.json b/cfg/sims/nos_engine_server_config.json similarity index 100% rename from cfg/nos_engine_server_config.json rename to cfg/sims/nos_engine_server_config.json diff --git a/cfg/sim_log_config.xml b/cfg/sims/sim_log_config.xml similarity index 100% rename from cfg/sim_log_config.xml rename to cfg/sims/sim_log_config.xml diff --git a/scripts/checkout.sh b/scripts/checkout.sh old mode 100644 new mode 100755 diff --git a/scripts/config.sh b/scripts/config.sh new file mode 100755 index 00000000..d143b3c1 --- /dev/null +++ b/scripts/config.sh @@ -0,0 +1,18 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +# Make flight software configuration directory +mkdir -p $BASE_DIR/cfg/build + +# Copy baseline configurations into build directory +cp -r $BASE_DIR/cfg/InOut $BASE_DIR/cfg/build/ +cp -r $BASE_DIR/cfg/nos3_defs $BASE_DIR/cfg/build/ +cp -r $BASE_DIR/cfg/sims $BASE_DIR/cfg/build/ + +# Configure flight software +python3 $SCRIPT_DIR/configure.py diff --git a/scripts/configure.py b/scripts/configure.py new file mode 100755 index 00000000..d09fa65d --- /dev/null +++ b/scripts/configure.py @@ -0,0 +1,409 @@ +# +# Convenience script for NOS3 development +# Configures NOS3 flight software (FSW) based on mission XML files +# Script assumes run from top level directory of NOS3 repo +# + +import datetime +import xml.etree.ElementTree as ET + +# Parse mission configuration +mission_tree = ET.parse('./cfg/nos3-mission.xml') +mission_root = mission_tree.getroot() +mission_start_time = mission_root.find('start-time').text +print(' start-time:', mission_start_time) +mission_start_time_utc = datetime.datetime(2000, 1, 1, 12, 0) + datetime.timedelta(seconds=float(mission_start_time)) +print(' start-time-utc:', mission_start_time_utc) + +mission_number_spacecraft = mission_root.find('number-spacecraft').text +print(' number-spacecraft:', mission_number_spacecraft) +num_sc = int(mission_number_spacecraft) + +# Check number of spacecraft valid +spacecraft_cfg = [] +if (num_sc < 1): + print('Invalid number of spacecraft in configuration file!') + print('Exiting due to error...') +else: + # Iterate through spacecraft configurations + for x in range(1, int(mission_number_spacecraft) + 1): + sc_str = 'sc-' + str(x) + '-cfg' + sc_cfg = mission_root.find(sc_str).text + #print(' ', sc_str, ':', sc_cfg) + spacecraft_cfg.append(sc_cfg) + + # Open spacecraft configuration + sc_cfg_str = './cfg/' + sc_cfg + sc_tree = ET.parse(sc_cfg_str) + sc_root = sc_tree.getroot() + + # Parse spacecraft configuration + sc_cf_en = sc_root.find('applications/cf/enable').text + sc_ds_en = sc_root.find('applications/ds/enable').text + sc_fm_en = sc_root.find('applications/fm/enable').text + sc_lc_en = sc_root.find('applications/lc/enable').text + sc_sc_en = sc_root.find('applications/sc/enable').text + + sc_adcs_en = sc_root.find('components/adcs/enable').text + sc_cam_en = sc_root.find('components/cam/enable').text + sc_css_en = sc_root.find('components/css/enable').text + sc_eps_en = sc_root.find('components/eps/enable').text + sc_fss_en = sc_root.find('components/fss/enable').text + sc_gps_en = sc_root.find('components/gps/enable').text + sc_imu_en = sc_root.find('components/imu/enable').text + sc_mag_en = sc_root.find('components/mag/enable').text + sc_radio_en = sc_root.find('components/radio/enable').text + sc_rw_en = sc_root.find('components/rw/enable').text + sc_sample_en = sc_root.find('components/sample/enable').text + sc_st_en = sc_root.find('components/st/enable').text + sc_torquer_en = sc_root.find('components/torquer/enable').text + + sc_gui_en = sc_root.find('gui/enable').text + sc_orbit_tipoff_x = sc_root.find('orbit/tipoff_x').text + sc_orbit_tipoff_y = sc_root.find('orbit/tipoff_y').text + sc_orbit_tipoff_z = sc_root.find('orbit/tipoff_z').text + + ### + ### Flight Software - Startup Script + ### + + # Capture lines to be used if enabled in startup script + with open('./cfg/nos3_defs/cpu1_cfe_es_startup.scr', 'r') as fp: + lines = fp.readlines() + + # Initialize variables + sc_startup_eof = 999 + cf_line = "" + ds_line = "" + fm_line = "" + lc_line = "" + sc_line = "" + adcs_line = "" + cam_line = "" + css_line = "" + eps_line = "" + fss_line = "" + gps_line = "" + imu_line = "" + mag_line = "" + radio_line = "" + rw_line = "" + sample_line = "" + st_line = "" + torquer_line = "" + + # Parse lines + for line in lines: + if line.find('!') != -1: + if (lines.index(line)) < sc_startup_eof: + sc_startup_eof = lines.index(line) + if line.find('CF,') != -1: + if (sc_cf_en == 'true'): + cf_line = line + if line.find('DS,') != -1: + if (sc_ds_en == 'true'): + ds_line = line + if line.find('FM,') != -1: + if (sc_fm_en == 'true'): + fm_line = line + if line.find('LC,') != -1: + if (sc_lc_en == 'true'): + lc_line = line + if line.find('SC,') != -1: + if (sc_sc_en == 'true'): + sc_line = line + if line.find('ADCS,') != -1: + if (sc_adcs_en == 'true'): + adcs_line = line + if line.find('CAM,') != -1: + if (sc_cam_en == 'true'): + cam_line = line + if line.find('CSS,') != -1: + if (sc_css_en == 'true'): + css_line = line + if line.find('EPS,') != -1: + if (sc_eps_en == 'true'): + eps_line = line + if line.find('FSS,') != -1: + if (sc_fss_en == 'true'): + fss_line = line + if line.find('IMU,') != -1: + if (sc_imu_en == 'true'): + imu_line = line + if line.find('MAG,') != -1: + if (sc_mag_en == 'true'): + mag_line = line + if line.find('RADIO,') != -1: + if (sc_radio_en == 'true'): + radio_line = line + if line.find('RW,') != -1: + if (sc_rw_en == 'true'): + rw_line = line + if line.find('NAV,') != -1: + if (sc_gps_en == 'true'): + gps_line = line + if line.find('SAMPLE,') != -1: + if (sc_sample_en == 'true'): + sample_line = line + if line.find('ST,') != -1: + if (sc_st_en == 'true'): + st_line = line + if line.find('TORQUER,') != -1: + if (sc_torquer_en == 'true'): + torquer_line = line + + # Modify startup script per spacecraft configuration + lines.insert(sc_startup_eof, "\n") + lines.insert(sc_startup_eof, torquer_line) + lines.insert(sc_startup_eof, st_line) + lines.insert(sc_startup_eof, sample_line) + lines.insert(sc_startup_eof, rw_line) + lines.insert(sc_startup_eof, radio_line) + lines.insert(sc_startup_eof, mag_line) + lines.insert(sc_startup_eof, imu_line) + lines.insert(sc_startup_eof, gps_line) + lines.insert(sc_startup_eof, fss_line) + lines.insert(sc_startup_eof, eps_line) + lines.insert(sc_startup_eof, css_line) + lines.insert(sc_startup_eof, cam_line) + lines.insert(sc_startup_eof, adcs_line) + lines.insert(sc_startup_eof, sc_line) + lines.insert(sc_startup_eof, lc_line) + lines.insert(sc_startup_eof, fm_line) + lines.insert(sc_startup_eof, ds_line) + lines.insert(sc_startup_eof, cf_line) + + # Write startup script file + with open('./cfg/build/nos3_defs/cpu1_cfe_es_startup.scr', 'w') as fp: + lines = "".join(lines) + fp.write(lines) + + ### + ### 42 - InOut Files + ### + + # Inp_Sim.txt + gui_index = 999 + date_index = 999 + time_index = 999 + with open('./cfg/InOut/Inp_Sim.txt', 'r') as fp: + lines = fp.readlines() + for line in lines: + if line.find('Graphics Front End') != -1: + if (lines.index(line)) < gui_index: + gui_index = lines.index(line) + if line.find('Date (UTC)') != -1: + if (lines.index(line)) < date_index: + date_index = lines.index(line) + if line.find('Time (UTC)') != -1: + if (lines.index(line)) < time_index: + time_index = lines.index(line) + + if (sc_gui_en == 'false'): + lines[gui_index] = 'FALSE ! Graphics Front End?\n' + + lines[date_index] = mission_start_time_utc.strftime('%m %d %Y') + ' ! Date (UTC) (Month, Day, Year)\n' + lines[time_index] = mission_start_time_utc.strftime('%H %M %S') + ' ! Time (UTC) (Hr,Min,Sec)\n' + + with open('./cfg/build/InOut/Inp_Sim.txt', 'w') as fp: + lines = "".join(lines) + fp.write(lines) + + # SC_NOS3.txt + tipoff_index = 999 + with open('./cfg/InOut/SC_NOS3.txt', 'r') as fp: + lines = fp.readlines() + for line in lines: + if line.find('Ang Vel (deg/sec)') != -1: + if (lines.index(line)) < tipoff_index: + tipoff_index = lines.index(line) + + lines[tipoff_index] = sc_orbit_tipoff_x + ' ' + sc_orbit_tipoff_y + ' ' + sc_orbit_tipoff_z + ' ! Ang Vel (deg/sec)\n' + + with open('./cfg/build/InOut/SC_NOS3.txt', 'w') as fp: + lines = "".join(lines) + fp.write(lines) + + # Inp_IPC.txt + css_index = 999 + fss_index = 999 + gps_index = 999 + imu_index = 999 + mag_index = 999 + rw0_to_index = 999 + rw0_from_index = 999 + rw1_to_index = 999 + rw1_from_index = 999 + rw2_to_index = 999 + rw2_from_index = 999 + sample_index = 999 + st_index = 999 + torquer_index = 999 + + with open('./cfg/InOut/Inp_IPC.txt', 'r') as fp: + lines = fp.readlines() + for line in lines: + if line.find('CSS IPC') != -1: + if (lines.index(line)) < css_index: + css_index = lines.index(line) + 1 + if line.find('FSS IPC') != -1: + if (lines.index(line)) < fss_index: + fss_index = lines.index(line) + 1 + if line.find('GPS IPC') != -1: + if (lines.index(line)) < gps_index: + gps_index = lines.index(line) + 1 + if line.find('IMU IPC') != -1: + if (lines.index(line)) < imu_index: + imu_index = lines.index(line) + 1 + if line.find('MAG IPC') != -1: + if (lines.index(line)) < mag_index: + mag_index = lines.index(line) + 1 + if line.find('RW 0 to 42') != -1: + if (lines.index(line)) < rw0_to_index: + rw0_to_index = lines.index(line) + 1 + if line.find('RW 0 from 42') != -1: + if (lines.index(line)) < rw0_from_index: + rw0_from_index = lines.index(line) + 1 + if line.find('RW 1 to 42') != -1: + if (lines.index(line)) < rw1_to_index: + rw1_to_index = lines.index(line) + 1 + if line.find('RW 1 from 42') != -1: + if (lines.index(line)) < rw1_from_index: + rw1_from_index = lines.index(line) + 1 + if line.find('RW 2 to 42') != -1: + if (lines.index(line)) < rw2_to_index: + rw2_to_index = lines.index(line) + 1 + if line.find('RW 2 from 42') != -1: + if (lines.index(line)) < rw2_from_index: + rw2_from_index = lines.index(line) + 1 + if line.find('Star Tracker IPC') != -1: + if (lines.index(line)) < st_index: + st_index = lines.index(line) + 1 + if line.find('Torquer IPC') != -1: + if (lines.index(line)) < torquer_index: + torquer_index = lines.index(line) + 1 + + ipc_off = 'OFF ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE)\n' + if (sc_css_en != 'true'): + lines[css_index] = ipc_off + if (sc_fss_en != 'true'): + lines[fss_index] = ipc_off + if (sc_gps_en != 'true'): + lines[gps_index] = ipc_off + if (sc_imu_en != 'true'): + lines[imu_index] = ipc_off + if (sc_mag_en != 'true'): + lines[mag_index] = ipc_off + if (sc_rw_en != 'true'): + lines[rw0_to_index] = ipc_off + lines[rw0_from_index] = ipc_off + lines[rw1_to_index] = ipc_off + lines[rw1_from_index] = ipc_off + lines[rw2_to_index] = ipc_off + lines[rw2_from_index] = ipc_off + if (sc_sample_en != 'true'): + lines[sample_index] = ipc_off + if (sc_st_en != 'true'): + lines[st_index] = ipc_off + if (sc_torquer_en != 'true'): + lines[torquer_index] = ipc_off + + with open('./cfg/build/InOut/Inp_IPC.txt', 'w') as fp: + lines = "".join(lines) + fp.write(lines) + + ### + ### Simulators - nos3-simulator.xml + ### + cam_index = 999 + css_index = 999 + eps_index = 999 + fss_index = 999 + gps_index = 999 + imu_index = 999 + mag_index = 999 + radio_index = 999 + rw0_index = 999 + rw1_index = 999 + rw2_index = 999 + sample_index = 999 + st_index = 999 + torquer_index = 999 + + with open('./cfg/build/sims/nos3-simulator.xml', 'r') as fp: + lines = fp.readlines() + for line in lines: + if line.find('camsim') != -1: + if (lines.index(line)) < cam_index: + cam_index = lines.index(line) + 1 + if line.find('css_sim') != -1: + if (lines.index(line)) < css_index: + css_index = lines.index(line) + 1 + if line.find('eps_sim') != -1: + if (lines.index(line)) < eps_index: + eps_index = lines.index(line) + 1 + if line.find('fss_sim') != -1: + if (lines.index(line)) < fss_index: + fss_index = lines.index(line) + 1 + if line.find('gps') != -1: + if (lines.index(line)) < gps_index: + gps_index = lines.index(line) + 1 + if line.find('imu_sim') != -1: + if (lines.index(line)) < imu_index: + imu_index = lines.index(line) + 1 + if line.find('mag_sim') != -1: + if (lines.index(line)) < mag_index: + mag_index = lines.index(line) + 1 + if line.find('radio_sim') != -1: + if (lines.index(line)) < radio_index: + radio_index = lines.index(line) + 1 + if line.find('reactionwheel-sim0') != -1: + if (lines.index(line)) < rw0_index: + rw0_index = lines.index(line) + 1 + if line.find('reactionwheel-sim1') != -1: + if (lines.index(line)) < rw1_index: + rw1_index = lines.index(line) + 1 + if line.find('reactionwheel-sim2') != -1: + if (lines.index(line)) < rw2_index: + rw2_index = lines.index(line) + 1 + if line.find('sample_sim') != -1: + if (lines.index(line)) < sample_index: + sample_index = lines.index(line) + 1 + if line.find('star_tracker_sim') != -1: + if (lines.index(line)) < st_index: + st_index = lines.index(line) + 1 + if line.find('generic_torquer_sim') != -1: + if (lines.index(line)) < torquer_index: + torquer_index = lines.index(line) + 1 + + sim_disabled = ' false\n' + if (sc_cam_en != 'true'): + lines[css_index] = sim_disabled + if (sc_css_en != 'true'): + lines[css_index] = sim_disabled + if (sc_eps_en != 'true'): + lines[css_index] = sim_disabled + if (sc_fss_en != 'true'): + lines[fss_index] = sim_disabled + if (sc_gps_en != 'true'): + lines[gps_index] = sim_disabled + if (sc_imu_en != 'true'): + lines[imu_index] = sim_disabled + if (sc_mag_en != 'true'): + lines[mag_index] = sim_disabled + if (sc_radio_en != 'true'): + lines[mag_index] = sim_disabled + if (sc_rw_en != 'true'): + lines[rw0_index] = sim_disabled + lines[rw1_index] = sim_disabled + lines[rw2_index] = sim_disabled + if (sc_sample_en != 'true'): + lines[sample_index] = sim_disabled + if (sc_st_en != 'true'): + lines[st_index] = sim_disabled + if (sc_torquer_en != 'true'): + lines[torquer_index] = sim_disabled + + with open('./cfg/build/sims/nos3-simulator.xml', 'w') as fp: + lines = "".join(lines) + fp.write(lines) diff --git a/scripts/create_cosmos_gem.sh b/scripts/create_cosmos_gem.sh old mode 100644 new mode 100755 diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml old mode 100644 new mode 100755 diff --git a/scripts/docker_build_fsw.sh b/scripts/docker_build_fsw.sh old mode 100644 new mode 100755 index 7d1146b2..f6ed6e07 --- a/scripts/docker_build_fsw.sh +++ b/scripts/docker_build_fsw.sh @@ -16,5 +16,16 @@ if [ ! -d $USER_NOS3_DIR ]; then exit 1 fi +# Check that configure build directory exists +if [ ! -d $BASE_DIR/cfg/build ]; then + echo "" + echo " Need to run make config first!" + echo "" + exit 1 +fi + +# Make flight software build directory mkdir -p $BASE_DIR/fsw/build + +# Build $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw diff --git a/scripts/docker_build_sim.sh b/scripts/docker_build_sim.sh old mode 100644 new mode 100755 index 68ab53c4..f6b1f25e --- a/scripts/docker_build_sim.sh +++ b/scripts/docker_build_sim.sh @@ -16,5 +16,13 @@ if [ ! -d $USER_NOS3_DIR ]; then exit 1 fi +# Check that configure build directory exists +if [ ! -d $BASE_DIR/cfg/build ]; then + echo "" + echo " Need to run make config first!" + echo "" + exit 1 +fi + mkdir -p $BASE_DIR/sims/build $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim diff --git a/scripts/docker_compose_launch.sh b/scripts/docker_compose_launch.sh old mode 100644 new mode 100755 diff --git a/scripts/docker_debug.sh b/scripts/docker_debug.sh old mode 100644 new mode 100755 diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh old mode 100644 new mode 100755 index d9c7a26f..bbcc7012 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -16,6 +16,13 @@ if [ ! -d $USER_NOS3_DIR ]; then exit 1 fi +# Check that configure build directory exists +if [ ! -d $BASE_DIR/cfg/build ]; then + echo "" + echo " Need to run make config first!" + echo "" + exit 1 +fi echo "Make data folders..." # FSW Side @@ -79,7 +86,7 @@ do echo $SC_NUM " - 42..." rm -rf $USER_NOS3_DIR/42/NOS3InOut - cp -r $BASE_DIR/cfg/InOut $USER_NOS3_DIR/42/NOS3InOut + cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut echo "" diff --git a/scripts/docker_stop.sh b/scripts/docker_stop.sh old mode 100644 new mode 100755 diff --git a/scripts/env.sh b/scripts/env.sh old mode 100644 new mode 100755 diff --git a/scripts/fsw_respawn.sh b/scripts/fsw_respawn.sh old mode 100644 new mode 100755 diff --git a/scripts/gsw.sh b/scripts/gsw.sh old mode 100644 new mode 100755 diff --git a/scripts/l0.sh b/scripts/l0.sh old mode 100644 new mode 100755 diff --git a/scripts/launch.sh b/scripts/launch.sh old mode 100644 new mode 100755 diff --git a/scripts/log.sh b/scripts/log.sh old mode 100644 new mode 100755 diff --git a/scripts/prepare.sh b/scripts/prepare.sh old mode 100644 new mode 100755 diff --git a/scripts/real_clean.sh b/scripts/real_clean.sh old mode 100644 new mode 100755 diff --git a/scripts/stop.sh b/scripts/stop.sh old mode 100644 new mode 100755 diff --git a/scripts/stop_gsw.sh b/scripts/stop_gsw.sh old mode 100644 new mode 100755 diff --git a/sims/CMakeLists.txt b/sims/CMakeLists.txt index eb3bba54..90b78442 100644 --- a/sims/CMakeLists.txt +++ b/sims/CMakeLists.txt @@ -48,8 +48,8 @@ ENDFOREACH() # Install configuration files to bin set(sim_cfg - ../cfg/nos_engine_server_config.json - ../cfg/nos3-simulator.xml - ../cfg/sim_log_config.xml + ../cfg/build/sims/nos_engine_server_config.json + ../cfg/build/sims/nos3-simulator.xml + ../cfg/build/sims/sim_log_config.xml ) install(FILES ${sim_cfg} DESTINATION bin COMPONENT config) From 97ddc3bdae138682d2d2cd6c5c298da61dd5befd Mon Sep 17 00:00:00 2001 From: Roberto Valenzuela Date: Wed, 3 Jan 2024 23:05:21 -0500 Subject: [PATCH 056/153] Fix typos in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 951660b3..ad4a77ab 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/nos3 - /apps - the open source cFS apps - /cfe - the core flight system (cFS) source files - /nos3_defs - cFS definitions to configure cFS for NOS3 - - /osal - operating system abstraction layer (OSAL), enables building for linux and flight OS + - /osal - operating system abstraction layer (OSAL), enables building for Linux and flight OS - /psp - platform support package (PSP), enables use on multiple types of boards - /tools - standard cFS provided tools * `gsw` contains the nos3 ground station files, and other ground based tools @@ -45,7 +45,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/nos3 - /scripts - convenience scripts * `sims` contains the nos3 simulators and configuration files - /cfg - 42 configuration files and NOS3 top level configuration files - - /nos_time_driver - time syncronization for all components + - /nos_time_driver - time synchronization for all components - /sim_common - common files used by component simulators including the files that define the simulator plugin architecture - /sim_terminal - terminal for testing on NOS Engine busses - /truth_42_sim - interface between 42 and COSMOS to provide dynamics truth data to COSMOS From 691b7383309f64e07f7be8c87b16028334ccd894 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 16 Jan 2024 17:09:09 -0500 Subject: [PATCH 057/153] [nasa/nos3#210] Updated NOS_clock_nanosleep flags; --- fsw/osal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/osal b/fsw/osal index 8b046477..fc9aa16e 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit 8b046477f047ae371be27f4ee7942fa4f863e7ac +Subproject commit fc9aa16ea4f1aaa6ddb20a31b69374bbc858c03a From 8479ea3c4cd665c7b279a72b15cb7bb3980649d8 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 17 Jan 2024 16:45:13 +0000 Subject: [PATCH 058/153] Adding a time bus to the EPS --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index d7dd1a2d..ed62f595 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit d7dd1a2d6fd95382e9ba8e2a2864077c73065a16 +Subproject commit ed62f59593cccecfbfe2d41fca9237b1108c7258 From 79dce4e2169b0ff3a067722346beb6c19d6a2324 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 18 Jan 2024 07:47:21 -0500 Subject: [PATCH 059/153] [nasa/nos3#210] Updated OSAL submodule after PR; --- fsw/osal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/osal b/fsw/osal index fc9aa16e..d45f883b 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit fc9aa16ea4f1aaa6ddb20a31b69374bbc858c03a +Subproject commit d45f883b8aeab458f29c9efc19fa68ee6beda80b From 940ed2979cf8ff7b0b6743f53e228f0059d7d82a Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Jan 2024 17:10:55 +0000 Subject: [PATCH 060/153] Some further alterations/updates to add battery tracking to the EPS --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index ed62f595..dda8fb59 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit ed62f59593cccecfbfe2d41fca9237b1108c7258 +Subproject commit dda8fb5971f3f4cb0472b3c529b20319dcb5fa40 From 0c81f8f7624706c7cc4cbf18ff72c858546a9be6 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 24 Jan 2024 23:00:05 +0000 Subject: [PATCH 061/153] Adjustments to further advance the goal of battery support in the EPS --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index dda8fb59..3be0e49b 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit dda8fb5971f3f4cb0472b3c529b20319dcb5fa40 +Subproject commit 3be0e49be5800a60236548f3c09e6c5ecc77552a From aacf5822f1a775de09ce75eb46ddb953c09750a8 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 30 Jan 2024 07:37:32 -0500 Subject: [PATCH 062/153] [nasa/nos3#221] EPS update battery values appears to be working (counting up) with generic data provider; --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 3be0e49b..2ccc6dda 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 3be0e49be5800a60236548f3c09e6c5ecc77552a +Subproject commit 2ccc6dda9f60da94f7b6d5252e86fcd935987c71 From f2c22b822ccecc169837c91cff8d9cc38b36e47f Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 30 Jan 2024 07:49:38 -0500 Subject: [PATCH 063/153] [nasa/nos3#221] Update to use EPS 42 provider, svb X/YZ appear correct compared to 42 Cam; --- cfg/InOut/Inp_IPC.txt | 12 +++++++++++- cfg/sims/nos3-simulator.xml | 10 +++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt index c860ef5d..e7f7a534 100644 --- a/cfg/InOut/Inp_IPC.txt +++ b/cfg/InOut/Inp_IPC.txt @@ -1,5 +1,5 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> -16 ! Number of Sockets +17 ! Number of Sockets ********************************** Sample IPC ***************************** TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode @@ -172,3 +172,13 @@ FALSE ! Allow Blocking (i.e. wait on RX) FALSE ! Echo to stdout 1 ! Number of TX prefixes "SC[0].AC.ST" ! Prefix 0 +********************************** EPS IPC ***************************** +TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) +0 ! AC.ID for ACS mode +"EPS.42" ! File name for WRITE or READ +SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) +fortytwo 4283 ! Server Host Name, Port +FALSE ! Allow Blocking (i.e. wait on RX) +FALSE ! Echo to stdout +1 ! Number of TX prefixes +"SC" ! Prefix 0 \ No newline at end of file diff --git a/cfg/sims/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml index 5bf4e33a..4c0b08dd 100644 --- a/cfg/sims/nos3-simulator.xml +++ b/cfg/sims/nos3-simulator.xml @@ -211,8 +211,16 @@ 10 - + + + GENERIC_EPS_42_PROVIDER + fortytwo + 4283 + 20 + 5 + 0 From 046c309f63e843582b555812c3c409024ddc88c7 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 1 Feb 2024 16:16:06 +0000 Subject: [PATCH 064/153] Adding back the battery watthrs to the simulator so as to better track the state of things --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 2ccc6dda..ee2f1576 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 2ccc6dda9f60da94f7b6d5252e86fcd935987c71 +Subproject commit ee2f1576476434c162db9e7c4fe526aeb6b3f513 From ba26002b6eef7c59699f62975313856a2ea0c0b1 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Thu, 1 Feb 2024 14:40:58 -0500 Subject: [PATCH 065/153] 239-SYNOPSIS-INTEGRATION-WIP --- .gitmodules | 4 ++++ components/ComponentSettings.cmake | 4 ++-- components/syn | 1 + fsw/nos3_defs/arch_build_custom.cmake | 8 ++++---- fsw/nos3_defs/cpu1_cfe_es_startup.scr | 2 +- fsw/nos3_defs/tables/sch_def_msgtbl.c | 4 +++- fsw/nos3_defs/tables/sch_def_schtbl.c | 2 +- fsw/nos3_defs/tables/to_lab_sub.c | 5 +++++ fsw/nos3_defs/targets.cmake | 1 + gsw/scripts/launch.sh | 1 + 10 files changed, 23 insertions(+), 9 deletions(-) create mode 160000 components/syn diff --git a/.gitmodules b/.gitmodules index 7c6df900..f5b19b42 100644 --- a/.gitmodules +++ b/.gitmodules @@ -127,3 +127,7 @@ [submodule "components/generic_star_tracker"] path = components/generic_star_tracker url = https://github.com/nasa-itc/generic_star_tracker.git +[submodule "components/syn"] + path = components/syn + url = git@aetd-git.gsfc.nasa.gov:itc/jpl/synopsis/syn_component/syn_nos3.git + branch = main diff --git a/components/ComponentSettings.cmake b/components/ComponentSettings.cmake index ae83d11f..66ac76f1 100644 --- a/components/ComponentSettings.cmake +++ b/components/ComponentSettings.cmake @@ -10,7 +10,7 @@ set(ITC_C_FLAGS "${ITC_C_FLAGS}" "-Wall" "-Wextra" #"-Wpedantic" # should discuss this - "-Werror" + #"-Werror" #"-Werror=format" "-Wformat=2" #"-Wcast-align" # should discuss this @@ -29,7 +29,7 @@ set(ITC_C_FLAGS "${ITC_C_FLAGS}" "-Wfloat-equal" "-Wno-packed" # should discuss this "-Wno-unused-parameter" # should discuss this - "-Wno-unused-variable" # should discuss this + #"-Wno-unused-variable" # should discuss this "-Wvariadic-macros" "-Wvla" "-Wstrict-overflow" diff --git a/components/syn b/components/syn new file mode 160000 index 00000000..88f1c683 --- /dev/null +++ b/components/syn @@ -0,0 +1 @@ +Subproject commit 88f1c6838ddca53f82bff31700ae03d3c6e370f8 diff --git a/fsw/nos3_defs/arch_build_custom.cmake b/fsw/nos3_defs/arch_build_custom.cmake index a17258df..e2af60d2 100644 --- a/fsw/nos3_defs/arch_build_custom.cmake +++ b/fsw/nos3_defs/arch_build_custom.cmake @@ -26,13 +26,13 @@ # and uses the same warning options that are applied at the mission level. # add_compile_options( - -std=c99 # Target the C99 standard (without gcc extensions) - -pedantic # Issue all the warnings demanded by strict ISO C + #-std=c99 # Target the C99 standard (without gcc extensions) + #-pedantic # Issue all the warnings demanded by strict ISO C -Wall # Warn about most questionable operations - -Wstrict-prototypes # Warn about missing prototypes + #-Wstrict-prototypes # Warn about missing prototypes -Wwrite-strings # Warn if not treating string literals as "const" -Wpointer-arith # Warn about suspicious pointer operations - -Werror # Treat warnings as errors (code should be clean) + #-Werror # Treat warnings as errors (code should be clean) -Wno-address-of-packed-member # Build Specific -DBYTE_ORDER_LE diff --git a/fsw/nos3_defs/cpu1_cfe_es_startup.scr b/fsw/nos3_defs/cpu1_cfe_es_startup.scr index 775aa83d..ba8806a3 100644 --- a/fsw/nos3_defs/cpu1_cfe_es_startup.scr +++ b/fsw/nos3_defs/cpu1_cfe_es_startup.scr @@ -4,7 +4,7 @@ CFE_LIB, io_lib, IO_LibInit, IO_LIB, CFE_APP, sch, SCH_AppMain, SCH, 40, 16384, 0x0, 0; CFE_APP, ci, CI_AppMain, CI, 41, 16384, 0x0, 0; CFE_APP, to, TO_AppMain, TO, 42, 16384, 0x0, 0; - +CFE_APP, syn, SYN_AppMain, SYN, 60, 8192, 0x0, 0; CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 80, 16384, 0x0, 0; CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 16384, 0x0, 0; diff --git a/fsw/nos3_defs/tables/sch_def_msgtbl.c b/fsw/nos3_defs/tables/sch_def_msgtbl.c index 483776dc..fc37581c 100644 --- a/fsw/nos3_defs/tables/sch_def_msgtbl.c +++ b/fsw/nos3_defs/tables/sch_def_msgtbl.c @@ -60,6 +60,8 @@ #include "generic_adcs_msgids.h" #include "generic_star_tracker_msgids.h" +#include "syn_msgids.h" + /* ** Message Table entry map... ** @@ -224,7 +226,7 @@ SCH_MessageEntry_t SCH_DefaultMessageTable[SCH_MAX_MESSAGES] = /* command ID #56 - Sample Data */ { { CFE_MAKE_BIG16(SAMPLE_REQ_HK_MID), CFE_MAKE_BIG16(0xC000), CFE_MAKE_BIG16(0x0001), CFE_MAKE_BIG16(0x0100) } }, /* command ID #57 */ - { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, + { { CFE_MAKE_BIG16(SYN_REQ_HK_MID), CFE_MAKE_BIG16(0xC000), CFE_MAKE_BIG16(0x0001), CFE_MAKE_BIG16(0x0000) } }, /* command ID #58 */ { { CFE_MAKE_BIG16(SCH_UNUSED_MID) } }, /* command ID #59 */ diff --git a/fsw/nos3_defs/tables/sch_def_schtbl.c b/fsw/nos3_defs/tables/sch_def_schtbl.c index 724568e1..a7ef5c78 100644 --- a/fsw/nos3_defs/tables/sch_def_schtbl.c +++ b/fsw/nos3_defs/tables/sch_def_schtbl.c @@ -351,7 +351,7 @@ SCH_ScheduleEntry_t SCH_DefaultScheduleTable[SCH_TABLE_ENTRIES] = /*{ SCH_DISABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 24, SCH_GROUP_MD_WAKEUP }, */ /* MD Wakeup */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 5, 0, 55, SCH_GROUP_CFE_HK }, /* Sample HK Request */ { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 56, SCH_GROUP_CFE_HK }, /* Sample Data Request */ - { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, + { SCH_ENABLED, SCH_ACTIVITY_SEND_MSG, 1, 0, 57, SCH_GROUP_CFE_HK }, /* SYN_APP Data Request */ { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, { SCH_UNUSED, 0, 0, 0, 0, SCH_GROUP_NONE}, diff --git a/fsw/nos3_defs/tables/to_lab_sub.c b/fsw/nos3_defs/tables/to_lab_sub.c index 948b7c84..9c082dc7 100644 --- a/fsw/nos3_defs/tables/to_lab_sub.c +++ b/fsw/nos3_defs/tables/to_lab_sub.c @@ -63,6 +63,8 @@ #include "generic_adcs_msgids.h" #include "generic_star_tracker_msgids.h" +#include "syn_msgids.h" + /* ** Local Structure Declarations */ @@ -82,6 +84,7 @@ TO_LAB_Subs_t TO_LAB_Subs = {CFE_SB_MSGID_WRAP_VALUE(CF_CONFIG_TLM_MID), {0,0}, 4}, {CFE_SB_MSGID_WRAP_VALUE(CF_HK_TLM_MID), {0,0}, 4}, {CFE_SB_MSGID_WRAP_VALUE(FM_HK_TLM_MID), {0,0}, 4}, + {CFE_SB_MSGID_WRAP_VALUE(FM_DIR_LIST_TLM_MID), {0,0}, 4}, {CFE_SB_MSGID_WRAP_VALUE(SC_HK_TLM_MID), {0,0}, 4}, {CFE_SB_MSGID_WRAP_VALUE(DS_HK_TLM_MID), {0,0}, 4}, {CFE_SB_MSGID_WRAP_VALUE(LC_HK_TLM_MID), {0,0}, 4}, @@ -125,6 +128,8 @@ TO_LAB_Subs_t TO_LAB_Subs = {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_HK_TLM_MID),{0,0}, 32}, {CFE_SB_MSGID_WRAP_VALUE(GENERIC_STAR_TRACKER_DEVICE_TLM_MID),{0,0}, 32}, + {CFE_SB_MSGID_WRAP_VALUE(SYN_HK_TLM_MID), {0,0}, 32}, + } }; diff --git a/fsw/nos3_defs/targets.cmake b/fsw/nos3_defs/targets.cmake index 13393551..604d8753 100644 --- a/fsw/nos3_defs/targets.cmake +++ b/fsw/nos3_defs/targets.cmake @@ -116,6 +116,7 @@ list(APPEND MISSION_GLOBAL_APPLIST sample generic_adcs generic_star_tracker + syn ) # Create Application Platform Include List diff --git a/gsw/scripts/launch.sh b/gsw/scripts/launch.sh index 2a53fcc4..e5907a46 100755 --- a/gsw/scripts/launch.sh +++ b/gsw/scripts/launch.sh @@ -51,6 +51,7 @@ gnome-terminal --tab --title='RW 2 Sim' -- $SIM_BIN/nos3-single-simula gnome-terminal --tab --title='Sample Sim' -- $SIM_BIN/nos3-single-simulator sample_sim gnome-terminal --tab --title='Torquer Sim' -- $SIM_BIN/nos3-single-simulator generic_torquer_sim gnome-terminal --tab --title="NOS Time Driver" -- $SIM_BIN/nos3-single-simulator time +gnome-terminal --tab --title="SYNOPSIS Sim" -- $SIM_BIN/nos3-single-simulator synopsis #echo "CryptoLib..." #mkdir $BASE_DIR/components/cryptolib/build/ From 393976e32835dcba7e522377ad6af11ef2070670 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Thu, 1 Feb 2024 15:00:43 -0500 Subject: [PATCH 066/153] 239-SYNOPSIS-INTEGRATION --- gsw/cosmos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsw/cosmos b/gsw/cosmos index 06084250..781ff886 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 0608425026e4018e762f31cf0a92ed94f4f39bef +Subproject commit 781ff88628ccec936fa7a413e7c54920f8362425 From 4c03b1da3a1b3b8f6ed4518d44a66f6ca112b2e8 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 5 Feb 2024 17:38:07 +0000 Subject: [PATCH 067/153] [nasa/nos3#221] Final updates to change the battery voltage depending on the charge of the battery, as well as corrections to the numbers to make them at least plausible. --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index ee2f1576..95ed6953 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit ee2f1576476434c162db9e7c4fe526aeb6b3f513 +Subproject commit 95ed6953e0507036fe4b2aaf7debb3706ed8623c From 2d6cd74158d7fbc7fca588ed914934f964770c7a Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Tue, 6 Feb 2024 11:57:32 -0500 Subject: [PATCH 068/153] [nasa/nos3#239] Update Submodule - Path updates, CC updates, ReadmeUpdate, Removal of Strings in CC --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index 88f1c683..b42b7343 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 88f1c6838ddca53f82bff31700ae03d3c6e370f8 +Subproject commit b42b73438e7c60c3ade1e1ac1df7831dfd9c18e3 From e48640bb15d04127c27d12ce00d1ffaf432ca186 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Tue, 6 Feb 2024 12:05:02 -0500 Subject: [PATCH 069/153] [nasa/nos3#239] Comment Cleanup and Updates - Submodule update --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index b42b7343..e2b5d7d9 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit b42b73438e7c60c3ade1e1ac1df7831dfd9c18e3 +Subproject commit e2b5d7d95e5e5e69eae3e0c5a03416dff4d7db77 From 963d526ed7e4afcffdafeec042926b56e6401ff8 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 7 Feb 2024 17:33:07 +0000 Subject: [PATCH 070/153] [nasa/nos3#221] Defining a value which I had previously overlooked --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 95ed6953..2ee4d414 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 95ed6953e0507036fe4b2aaf7debb3706ed8623c +Subproject commit 2ee4d4140ed32c9f11c08e7e1919be7785e74865 From 59a121b637cf291afb546a828c0efd15f08c5310 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 7 Feb 2024 12:43:48 -0500 Subject: [PATCH 071/153] [nasa/nos3#239] Removed CmakeLists version in synopsis submodule to resolve symlinking issue while in VM shared folders; --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index e2b5d7d9..84d229d5 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit e2b5d7d95e5e5e69eae3e0c5a03416dff4d7db77 +Subproject commit 84d229d5b69ea3374dd2b486a41cb283f18c51b8 From b043b496ac0caf5b85f94859a933bc7cfe5bbf44 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Wed, 7 Feb 2024 15:07:28 -0500 Subject: [PATCH 072/153] [nasa/nos3#239] Update Submodule - Cleanup for merge. --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index 84d229d5..aa979e4b 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 84d229d5b69ea3374dd2b486a41cb283f18c51b8 +Subproject commit aa979e4ba0247a62f0d7ecf81863e7464e7bd025 From fbc9da3771794841d9f9097c47ca96efef065818 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Wed, 7 Feb 2024 15:50:19 -0500 Subject: [PATCH 073/153] [nasa/nos3#239] Removed syn_device - unnecessary. Removed remaining Uart calls. Updated Cmake to reinclude components.cmake --- components/ComponentSettings.cmake | 4 ++-- components/syn | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/ComponentSettings.cmake b/components/ComponentSettings.cmake index 66ac76f1..1281f6b0 100644 --- a/components/ComponentSettings.cmake +++ b/components/ComponentSettings.cmake @@ -9,7 +9,7 @@ set(ITC_C_FLAGS "${ITC_C_FLAGS}" #"-std=c99" "-Wall" "-Wextra" - #"-Wpedantic" # should discuss this + "-Wpedantic" # should discuss this #"-Werror" #"-Werror=format" "-Wformat=2" @@ -40,7 +40,7 @@ set(ITC_C_FLAGS "${ITC_C_FLAGS}" #"-fsanitize=address" #"-fstack-check" #"-Weverything" - #"-pedantic-errors" + "-pedantic-errors" ) #if(${TGTNAME} STREQUAL cpu1) diff --git a/components/syn b/components/syn index aa979e4b..d2f0bf82 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit aa979e4ba0247a62f0d7ecf81863e7464e7bd025 +Subproject commit d2f0bf82626697d6df10371340ab124a705e1535 From 3b5e9ff9be14d59eca5bd4de36403a9e169be1cb Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Thu, 8 Feb 2024 11:49:22 -0500 Subject: [PATCH 074/153] [nasa/nos3#239] Removed unnecessary device telemetry calls. - Update SYN Submodule --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index d2f0bf82..419f54dc 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit d2f0bf82626697d6df10371340ab124a705e1535 +Subproject commit 419f54dcf73743b095489678a0b8402b41e58601 From d2dc128df72bd9ef766f8a12523ac686722579af Mon Sep 17 00:00:00 2001 From: David Date: Thu, 8 Feb 2024 17:05:33 +0000 Subject: [PATCH 075/153] [nasa/nos3#221] Adding in the current and voltage values to the .xml configuration file --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 2ee4d414..5adce0a2 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 2ee4d4140ed32c9f11c08e7e1919be7785e74865 +Subproject commit 5adce0a21bab8b98987ef853c03471e35b610d5c From 987e7d4356c05cc4d3d2f202862c10086135b97a Mon Sep 17 00:00:00 2001 From: David Date: Thu, 15 Feb 2024 17:00:48 +0000 Subject: [PATCH 076/153] [nasa/nos3#221] Update to use _sim_microseconds_per_tick instead of a fixed value for calculating power draw/generation --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index 5adce0a2..c07e1f3a 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 5adce0a21bab8b98987ef853c03471e35b610d5c +Subproject commit c07e1f3aad7122ae825e8820187d861466813963 From 2265e8a1d16fc7f114cfe2370e9b7e5e504f88e2 Mon Sep 17 00:00:00 2001 From: Ice Date: Thu, 15 Feb 2024 13:43:33 -0500 Subject: [PATCH 077/153] [NOS3#234] Initial Igniter GUI Commit --- cfg/gui/cfg_gui.ui | 1156 +++++++++++++++++++++++++++++++++++++ cfg/gui/cfg_gui.ui.nIFTUJ | 1112 +++++++++++++++++++++++++++++++++++ cfg/gui/cfg_gui_main.py | 332 +++++++++++ cfg/gui/cfg_gui_ui.py | 399 +++++++++++++ 4 files changed, 2999 insertions(+) create mode 100644 cfg/gui/cfg_gui.ui create mode 100644 cfg/gui/cfg_gui.ui.nIFTUJ create mode 100644 cfg/gui/cfg_gui_main.py create mode 100644 cfg/gui/cfg_gui_ui.py diff --git a/cfg/gui/cfg_gui.ui b/cfg/gui/cfg_gui.ui new file mode 100644 index 00000000..09550594 --- /dev/null +++ b/cfg/gui/cfg_gui.ui @@ -0,0 +1,1156 @@ + + + Form + + + + 0 + 0 + 658 + 655 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + + Form + + + + + 0 + 0 + 661 + 661 + + + + QTabWidget::Rounded + + + 0 + + + + Config + + + + + 130 + 20 + 421 + 26 + + + + Qt::AlignCenter + + + true + + + None + + + + + + 550 + 20 + 94 + 26 + + + + Browse... + + + + + + 10 + 20 + 121 + 21 + + + + Current Config: + + + + + + 10 + 260 + 631 + 321 + + + + Spacecraft Config + + + + + 0 + 20 + 631 + 301 + + + + + + + + 0 + 0 + + + + true + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 613 + 297 + + + + + 0 + 0 + + + + + QLayout::SetDefaultConstraint + + + + + + + + + + + 150 + -1 + 48 + 21 + + + + 1 + + + + + + + 10 + 60 + 631 + 181 + + + + Master Config + + + + + 0 + 20 + 631 + 161 + + + + + + + false + + + + + + + + + + 220 + 590 + 94 + 26 + + + + Save + + + + + + 330 + 590 + 94 + 26 + + + + Save As... + + + + + + Build + + + + + 10 + 120 + 631 + 491 + + + + Console Output + + + Qt::AlignCenter + + + false + + + false + + + + + 0 + 20 + 631 + 471 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 110 + 20 + 421 + 81 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 79 + 0 + 341 + 80 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 340 + 80 + + + + + + + FSW + + + + + + + FSW + + + + + + + GSW + + + + + + + SIM + + + + + + + SIM + + + + + + + GSW + + + + + + + All + + + + + + + All + + + + + + + + + + 0 + 0 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Build + + + Qt::AlignCenter + + + + + + + + + + 0 + 40 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Clean + + + Qt::AlignCenter + + + + + + + + + + + Launch + + + + + 10 + 10 + 631 + 611 + + + + + + + + + 10 + 570 + 611 + 31 + + + + + 45 + + + + + Play + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg + + + + + + + Pause + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg + + + + + + + + + 10 + 10 + 611 + 41 + + + + + + + Launch + + + + + + + Stop + + + + + + + + + 10 + 60 + 611 + 451 + + + + NOS3 Time Driver + + + Qt::AlignCenter + + + false + + + false + + + + + 0 + 20 + 611 + 431 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 190 + 520 + 261 + 41 + + + + + + + + + + + + + Run For + + + + + Run Until + + + + + + + + + + + Qt::AlignCenter + + + + + + + + + + + + diff --git a/cfg/gui/cfg_gui.ui.nIFTUJ b/cfg/gui/cfg_gui.ui.nIFTUJ new file mode 100644 index 00000000..6af78023 --- /dev/null +++ b/cfg/gui/cfg_gui.ui.nIFTUJ @@ -0,0 +1,1112 @@ + + + Form + + + + 0 + 0 + 655 + 655 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + + Form + + + + + 0 + 0 + 661 + 661 + + + + QTabWidget::Rounded + + + 0 + + + + Config + + + + + 130 + 20 + 421 + 26 + + + + Qt::AlignCenter + + + true + + + None + + + + + + 550 + 20 + 94 + 26 + + + + Browse... + + + + + + 10 + 20 + 121 + 21 + + + + Current Config: + + + + + + 10 + 300 + 631 + 281 + + + + Spacecraft Config + + + + + 0 + 20 + 631 + 261 + + + + + + + QTextEdit::NoWrap + + + false + + + + + + + + + 150 + -1 + 48 + 21 + + + + 1 + + + + + + + 10 + 60 + 631 + 231 + + + + Master Config + + + + + 0 + 20 + 631 + 211 + + + + + + + false + + + + + + + + + + 220 + 590 + 94 + 26 + + + + Save + + + + + + 330 + 590 + 94 + 26 + + + + Save As... + + + + + + Build + + + + + 10 + 120 + 631 + 491 + + + + Console Output + + + false + + + false + + + + + 0 + 20 + 631 + 471 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 110 + 20 + 421 + 81 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 79 + 0 + 341 + 80 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 340 + 80 + + + + + + + FSW + + + + + + + FSW + + + + + + + GSW + + + + + + + SIM + + + + + + + SIM + + + + + + + GSW + + + + + + + All + + + + + + + All + + + + + + + + + + 0 + 0 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Build + + + Qt::AlignCenter + + + + + + + + + + 0 + 40 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Clean + + + Qt::AlignCenter + + + + + + + + + + + Launch + + + + + 10 + 10 + 631 + 611 + + + + + + + + + 10 + 570 + 611 + 31 + + + + + 45 + + + + + Play + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg + + + + + + + Pause + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg + + + + + + + + + 10 + 10 + 611 + 41 + + + + + + + Launch + + + + + + + Stop + + + + + + + + + 10 + 60 + 611 + 451 + + + + Console Output + + + false + + + false + + + + + 0 + 20 + 611 + 431 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 200 + 530 + 93 + 26 + + + + + Run For + + + + + Run Until + + + + + + + 290 + 530 + 181 + 26 + + + + + + + Qt::AlignCenter + + + + + + + + + diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py new file mode 100644 index 00000000..c52c629e --- /dev/null +++ b/cfg/gui/cfg_gui_main.py @@ -0,0 +1,332 @@ +from pathlib import Path +from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout +from PySide6.QtCore import QProcess, QDateTime +from PySide6.QtGui import QTextCharFormat + +import sys, re, xmltodict, datetime, threading +import xml.etree.ElementTree as ET + +from cfg_gui_ui import Ui_Form + +class cfg_gui(QWidget): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.ui = Ui_Form() + self.ui.setupUi(self) + self.setFixedSize(655, 655) + self.setWindowTitle("NOS3 Igniter - Version 0.0.1") + + self.dateTimeEdit = QDateTimeEdit() + self.scConfigs = {} # Stores child configs {'filename' : "filetext"} + self.prevButtonPressed = None # Tracks the last button pressed, used in buttonColor() + self.defaultStyleSheet = self.ui.pushButton_buildAll.styleSheet() # Saves default stylesheet to return button color to normal, buttonColor() + self.setup = 0 # Allows for switchConfig() to initially be called without calling saveText() + self.configNumTrack = 0 # Tracks the index of the previous SC config when switching to another index + + # Config Tab + self.ui.pushButton_browse.clicked.connect(self.browseConfig) + self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) + self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) + self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) + + # Build Tab + self.ui.pushButton_buildAll.clicked.connect(lambda: self.build("all", self.ui.pushButton_buildAll)) + self.ui.pushButton_fswBuild.clicked.connect(lambda: self.build("fsw", self.ui.pushButton_fswBuild)) + self.ui.pushButton_gswBuild.clicked.connect(lambda: self.build("gsw", self.ui.pushButton_gswBuild)) + self.ui.pushButton_simBuild.clicked.connect(lambda: self.build("sim", self.ui.pushButton_simBuild)) + self.ui.pushButton_cleanAll.clicked.connect(lambda: self.clean("all", self.ui.pushButton_cleanAll)) + self.ui.pushButton_fswClean.clicked.connect(lambda: self.clean("fsw", self.ui.pushButton_fswClean)) + self.ui.pushButton_gswClean.clicked.connect(lambda: self.clean("gsw", self.ui.pushButton_gswClean)) + self.ui.pushButton_simClean.clicked.connect(lambda: self.clean("sim", self.ui.pushButton_simClean)) + + # Launch Tab + self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) + self.ui.pushButton_stop.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make stop")) + self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) + self.ui.pushButton_launch.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make launch")) + self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) + + # Replaces the textbox on launch tab with a date/time box and vice versa + def run_ForUntil(self): + index = self.ui.comboBox_run.currentIndex() + if index == 0: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.ui.lineEdit_secondsEntry) + self.ui.lineEdit_secondsEntry.setPlaceholderText("") + elif index == 1: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.ui.lineEdit_secondsEntry) + self.ui.lineEdit_secondsEntry.setPlaceholderText("Seconds") + elif index == 2: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.currentTime = datetime.datetime.now() + self.dateTimeEdit.setMinimumDateTime(QDateTime(self.currentTime.year, self.currentTime.month, self.currentTime.day, self.currentTime.hour, self.currentTime.minute, self.currentTime.second, 0, 0)) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.dateTimeEdit) + + # Overwrites the currently saved text for the currently selected spacecraft config when edited + def saveText(self, layout:QLayout, config_value:int): + child = self.scConfigs[config_value] + text = child + filename = text.split('\n')[0] + childXml = text.split('\n', 2)[2] + childXml = xmltodict.parse(childXml) + + applications = ['cf', 'ds', 'fm', 'lc', 'sc'] + components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'torquer'] + + i = 0 + while layout.itemAt(i) != None: + widget = layout.itemAt(i).widget() + if isinstance(widget, QCheckBox): + #print(child.text()) + text = widget.text().split(' ')[0] + if text in applications: + childXml['sc-1-config']['applications'][text]['enable'] = str(widget.isChecked()).lower() + elif text in components: + childXml['sc-1-config']['components'][text]['enable'] = str(widget.isChecked()).lower() + elif text == 'gui': + childXml['sc-1-config'][text]['enable'] = str(widget.isChecked()).lower() + elif isinstance(widget, QDoubleSpinBox): + #print(child.prefix()) + prefix = widget.prefix().split(' ')[0] + childXml['sc-1-config']['orbit'][prefix] = str(widget.value()) + i += 1 + + combined = filename + '\n\n' + xmltodict.unparse(childXml) + self.scConfigs[config_value] = combined + + # Saves the master/child XML's edited in the GUI + def saveXML(self, saveType:str): + # saveType = "save" (overwrite) or "saveAs" (new) + + if saveType == "saveAs": + savePath, _ = QFileDialog.getSaveFileName(None, 'Directory', './cfg/custom') + elif saveType == "save": + savePath = self.config_path + + # Grab master and save to xml + masterXml = xmltodict.parse(self.ui.textEdit_masterConfig.toPlainText()) + self.convert2xml(masterXml, savePath) + + # TODO: Now handle children, currently placeholder until checkboxes are added (update in progress) + self.saveText(self.layout_, self.ui.spinBox_configNumber.value()-1) + + for child in self.scConfigs: + text = str(self.scConfigs[child]) + filename = text.split('\n')[0].split(' ')[1] + childXml = text.split('\n', 2)[2] + childXml = xmltodict.parse(childXml) + + # save under same directory as masterXml using filename parsed from textEdit + self.convert2xml(childXml, savePath.rsplit('/', 1)[0]+f'/{filename}') + + # Loads the child config into the Spacecraft Config textbox + def switchConfig(self, value:int): + # value : index of spacecraft config in the order listed in the master XML + # Note: Parameter indexing starts at 1 + + # save edits made to config before viewing next one + if self.setup == 1: + self.saveText(self.layout_, self.configNumTrack) + self.configNumTrack = value-1 + + self.setup = 1 + self.ui.scrollArea.setWidgetResizable(True) + self.ui.scrollAreaWidgetContents.setLayout(QVBoxLayout().layout()) + self.layout_ = self.ui.scrollAreaWidgetContents.layout() + self.layout_.setSpacing(12) + + # remove all items from SC Config window when switching index + while self.layout_.itemAt(0) != None: + child = self.layout_.itemAt(0).widget().setParent(None) + + + value = value-1 + if value in self.scConfigs: + fileName = self.scConfigs[value].split('\n')[0] + childXML = self.scConfigs[value].split('\n')[2::] + childXML = ''.join(childXML) + childDict = xmltodict.parse(childXML) + + policy = self.ui.scrollAreaWidgetContents.sizePolicy() + + for child in childDict: + configTag = QLabel() + configTag.setText((fileName)) + configTag.setMinimumHeight(18) + self.layout_.addWidget(configTag) + for child2 in childDict[child]: + tag = QLabel() + tag.setText(child2.upper()+": ") + format = QTextCharFormat() + format.setFontUnderline(True) + tag.setFont(format.font()) + tag.setMinimumHeight(18) + self.layout_.addWidget(tag) + if child2 in ['applications', 'components']: + for child3 in childDict[child][child2]: + enableTag = QCheckBox() + enableTag.setText(child3 + " enable ") + enableTag.setChecked(childDict[child][child2][child3]['enable'] == 'true') + enableTag.setMinimumHeight(18) + enableTag.sizePolicy().setVerticalPolicy(QSizePolicy.Expanding) + self.layout_.addWidget(enableTag) + elif child2 == 'gui': + enableTag = QCheckBox() + enableTag.setText(child2 + " enable ") + enableTag.setChecked(childDict[child][child2]['enable'] == 'true') + self.layout_.addWidget(enableTag) + elif child2 == 'orbit': + for child3 in childDict[child][child2]: + orbitSpinBox = QDoubleSpinBox() + orbitSpinBox.setMinimum(-99.00) + orbitSpinBox.setMaximum(99.00) + orbitSpinBox.setValue(float(childDict[child][child2][child3])) + orbitSpinBox.setPrefix(f'{child3} = ') + self.layout_.addWidget(orbitSpinBox) + else: + tag = QLabel() + tag.setText("*ERROR*\n\nMake sure you chose a master configuration file\n\n*ERROR*") + self.layout_.addWidget(tag) + + # Converts a dictionary to XML file, saved under the given filename/path + def convert2xml(self, attrDict:dict, fileName:[str, Path]): + # ensure file is saved as xml + if fileName[-4::] != ".xml": + fileName += ".xml" + + # unparse dictionary to xml + with open(fileName, "w") as f: + xmltodict.unparse(attrDict, f, pretty=True) + f.close() + + # Opens file selection menu and calls parseXML() on the selected file + def browseConfig(self): + self.config_path, _ = QFileDialog.getOpenFileName(None, 'File', './cfg', "XML Files [ *.xml ]") + if self.config_path != "": + self.config_name = self.config_path.split("/")[-1] + self.ui.lineEdit_curConfig.setText(self.config_name) + self.parseXml(self.config_path) + + # Parses Master and child XML files from the given file, updates text boxes accordingly + def parseXml(self, config_path): + + # Master + with open(config_path, 'r') as f: + self.ui.textEdit_masterConfig.setText(f.read()) + f.close() + + i = 1 + childDict = {} + root = ET.parse(config_path).getroot() + for child in root: + if child.tag == "number-spacecraft": + self.ui.spinBox_configNumber.setMaximum(int(child.text)) + if re.match("sc-[0-9]+-cfg", child.tag): + childDict[child.tag] = child.text + i+=1 + + # Children + config_dir = str(config_path.rsplit('/', 1)[0]) + for i, child in enumerate(childDict): + if Path(f'{config_dir}/{childDict[child]}').is_file(): + filePath = f'{config_dir}/{childDict[child]}' + elif Path(f'./cfg/{childDict[child]}').is_file(): + filePath = f'./cfg/{childDict[child]}' + elif Path(f'./cfg/custom/{childDict[child]}').is_file(): + filePath = f'./cfg/custom/{childDict[child]}' + else: + raise FileNotFoundError(childDict[child]) + + with open(filePath, 'r') as f: + self.scConfigs[i] = f'Filename: {childDict[child]}\n\n{f.read()}' + f.close() + + # Update Spacecraft Config Text + self.switchConfig(1) + + # Starts a Bash process to execute args, redirects output to given textbox, not used for now + def startBashProcess(self, textbox:QTextEdit, args:list): + process = QProcess() + process.start("bash", [item for item in args]) + + process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) + process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) + + process.waitForFinished() + process.close() + + # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() + def gnome_terminal(self, textbox:QTextEdit, command:str): + process = QProcess() + print(command) + process.startCommand(f'gnome-terminal -- {command}') + + process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) + process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) + + process.waitForFinished(msecs=-1) + textbox.append(f'>> {command}...') + #process.close() + + # Placeholder clean command + def clean(self, software:str, button:QPushButton): + textbox = self.ui.textEdit_buildConsole + if software == 'all': + command = f'make clean' + else: + command = f'make clean-{software}' + + self.buttonColor(button) + t1 = threading.Thread(target=self.thread_Bash(textbox, button, command), name='t1') + t1.start() + + # Placeholder build command, assumes make prep already ran, same with clean commands + def build(self, software:str, button:QPushButton): + textbox = self.ui.textEdit_buildConsole + command = f'make {software}' + + self.buttonColor(button) + t1 = threading.Thread(target=self.thread_Bash(textbox, button, command), name='t1') + t1.start() + + # Button/Bash function wrapper for threads + def thread_Bash(self, textbox:QTextEdit, button:QPushButton, command:str): + self.disableButtons(button) + self.gnome_terminal(textbox, command) + self.enableButtons(button) + + # Changes the color of the most recently pressed button to green + def buttonColor(self, button:QPushButton): + if self.prevButtonPressed is not None: + self.prevButtonPressed.setStyleSheet(self.defaultStyleSheet) + button.setStyleSheet('QPushButton {background-color: green;}') + self.prevButtonPressed = button + + # Disable build/clean buttons while another is being ran + def disableButtons(self, button:QPushButton): + index = self.ui.gridLayout_buildCleanButtons.count()-1 + while index >= 0: + widget = self.ui.gridLayout_buildCleanButtons.itemAt(index).widget() + if widget != button: + widget.setDisabled(1) + index -= 1 + + # Enable build/clean buttons after process is done running + def enableButtons(self, button:QPushButton): + index = self.ui.gridLayout_buildCleanButtons.count()-1 + while index >= 0: + widget = self.ui.gridLayout_buildCleanButtons.itemAt(index).widget() + if widget != button: + widget.setEnabled(1) + index -= 1 + + +def main(): + app = QApplication(sys.argv) + win = cfg_gui() + win.show() + sys.exit(app.exec()) + +main() \ No newline at end of file diff --git a/cfg/gui/cfg_gui_ui.py b/cfg/gui/cfg_gui_ui.py new file mode 100644 index 00000000..913952bb --- /dev/null +++ b/cfg/gui/cfg_gui_ui.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'cfg_gui.ui' +## +## Created by: Qt User Interface Compiler version 6.6.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout, + QGroupBox, QHBoxLayout, QLabel, QLineEdit, + QPushButton, QScrollArea, QSizePolicy, QSpinBox, + QTabWidget, QTextEdit, QVBoxLayout, QWidget) + +class Ui_Form(object): + def setupUi(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(655, 655) + palette = QPalette() + brush = QBrush(QColor(0, 0, 0, 255)) + brush.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.WindowText, brush) + brush1 = QBrush(QColor(255, 255, 255, 255)) + brush1.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Button, brush1) + palette.setBrush(QPalette.Active, QPalette.Light, brush1) + palette.setBrush(QPalette.Active, QPalette.Midlight, brush1) + brush2 = QBrush(QColor(127, 127, 127, 255)) + brush2.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Dark, brush2) + brush3 = QBrush(QColor(170, 170, 170, 255)) + brush3.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Mid, brush3) + palette.setBrush(QPalette.Active, QPalette.Text, brush) + palette.setBrush(QPalette.Active, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Active, QPalette.ButtonText, brush) + palette.setBrush(QPalette.Active, QPalette.Base, brush1) + palette.setBrush(QPalette.Active, QPalette.Window, brush1) + palette.setBrush(QPalette.Active, QPalette.Shadow, brush) + palette.setBrush(QPalette.Active, QPalette.AlternateBase, brush1) + brush4 = QBrush(QColor(255, 255, 220, 255)) + brush4.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Active, QPalette.ToolTipText, brush) + brush5 = QBrush(QColor(0, 0, 0, 127)) + brush5.setStyle(Qt.SolidPattern) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Active, QPalette.PlaceholderText, brush5) +#endif + palette.setBrush(QPalette.Active, QPalette.Accent, brush1) + palette.setBrush(QPalette.Inactive, QPalette.WindowText, brush) + palette.setBrush(QPalette.Inactive, QPalette.Button, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Light, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Midlight, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Dark, brush2) + palette.setBrush(QPalette.Inactive, QPalette.Mid, brush3) + palette.setBrush(QPalette.Inactive, QPalette.Text, brush) + palette.setBrush(QPalette.Inactive, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) + palette.setBrush(QPalette.Inactive, QPalette.Base, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Window, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Shadow, brush) + palette.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush1) + palette.setBrush(QPalette.Inactive, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Inactive, QPalette.ToolTipText, brush) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Inactive, QPalette.PlaceholderText, brush5) +#endif + palette.setBrush(QPalette.Inactive, QPalette.Accent, brush1) + palette.setBrush(QPalette.Disabled, QPalette.WindowText, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Button, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Light, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Midlight, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Dark, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Mid, brush3) + palette.setBrush(QPalette.Disabled, QPalette.Text, brush2) + palette.setBrush(QPalette.Disabled, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Disabled, QPalette.ButtonText, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Base, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Window, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Shadow, brush) + palette.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush1) + palette.setBrush(QPalette.Disabled, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Disabled, QPalette.ToolTipText, brush) + brush6 = QBrush(QColor(127, 127, 127, 127)) + brush6.setStyle(Qt.SolidPattern) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Disabled, QPalette.PlaceholderText, brush6) +#endif + palette.setBrush(QPalette.Disabled, QPalette.Accent, brush1) + Form.setPalette(palette) + self.tabWidget = QTabWidget(Form) + self.tabWidget.setObjectName(u"tabWidget") + self.tabWidget.setGeometry(QRect(0, 0, 661, 661)) + self.tabWidget.setTabShape(QTabWidget.Rounded) + self.tab = QWidget() + self.tab.setObjectName(u"tab") + self.lineEdit_curConfig = QLineEdit(self.tab) + self.lineEdit_curConfig.setObjectName(u"lineEdit_curConfig") + self.lineEdit_curConfig.setGeometry(QRect(130, 20, 421, 26)) + self.lineEdit_curConfig.setAlignment(Qt.AlignCenter) + self.lineEdit_curConfig.setReadOnly(True) + self.pushButton_browse = QPushButton(self.tab) + self.pushButton_browse.setObjectName(u"pushButton_browse") + self.pushButton_browse.setGeometry(QRect(550, 20, 94, 26)) + self.label_curConfig = QLabel(self.tab) + self.label_curConfig.setObjectName(u"label_curConfig") + self.label_curConfig.setGeometry(QRect(10, 20, 121, 21)) + self.groupBox_scConfig = QGroupBox(self.tab) + self.groupBox_scConfig.setObjectName(u"groupBox_scConfig") + self.groupBox_scConfig.setGeometry(QRect(10, 260, 631, 321)) + self.horizontalLayoutWidget_6 = QWidget(self.groupBox_scConfig) + self.horizontalLayoutWidget_6.setObjectName(u"horizontalLayoutWidget_6") + self.horizontalLayoutWidget_6.setGeometry(QRect(0, 20, 631, 301)) + self.horizontalLayout_6 = QHBoxLayout(self.horizontalLayoutWidget_6) + self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.scrollArea = QScrollArea(self.horizontalLayoutWidget_6) + self.scrollArea.setObjectName(u"scrollArea") + self.scrollArea.setAutoFillBackground(True) + self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + self.scrollArea.setWidgetResizable(False) + self.scrollAreaWidgetContents = QWidget() + self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 627, 297)) + self.scrollArea.setWidget(self.scrollAreaWidgetContents) + + self.horizontalLayout_6.addWidget(self.scrollArea, 0, Qt.AlignTop) + + self.spinBox_configNumber = QSpinBox(self.groupBox_scConfig) + self.spinBox_configNumber.setObjectName(u"spinBox_configNumber") + self.spinBox_configNumber.setGeometry(QRect(150, -1, 48, 21)) + self.spinBox_configNumber.setMinimum(1) + self.groupBox_masterConfig = QGroupBox(self.tab) + self.groupBox_masterConfig.setObjectName(u"groupBox_masterConfig") + self.groupBox_masterConfig.setGeometry(QRect(10, 60, 631, 181)) + self.horizontalLayoutWidget_5 = QWidget(self.groupBox_masterConfig) + self.horizontalLayoutWidget_5.setObjectName(u"horizontalLayoutWidget_5") + self.horizontalLayoutWidget_5.setGeometry(QRect(0, 20, 631, 161)) + self.horizontalLayout_5 = QHBoxLayout(self.horizontalLayoutWidget_5) + self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.textEdit_masterConfig = QTextEdit(self.horizontalLayoutWidget_5) + self.textEdit_masterConfig.setObjectName(u"textEdit_masterConfig") + self.textEdit_masterConfig.setReadOnly(False) + + self.horizontalLayout_5.addWidget(self.textEdit_masterConfig) + + self.pushButton_save = QPushButton(self.tab) + self.pushButton_save.setObjectName(u"pushButton_save") + self.pushButton_save.setGeometry(QRect(220, 590, 94, 26)) + self.pushButton_saveAs = QPushButton(self.tab) + self.pushButton_saveAs.setObjectName(u"pushButton_saveAs") + self.pushButton_saveAs.setGeometry(QRect(330, 590, 94, 26)) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QWidget() + self.tab_2.setObjectName(u"tab_2") + self.groupBox_8 = QGroupBox(self.tab_2) + self.groupBox_8.setObjectName(u"groupBox_8") + self.groupBox_8.setGeometry(QRect(10, 120, 631, 491)) + self.groupBox_8.setAlignment(Qt.AlignCenter) + self.groupBox_8.setFlat(False) + self.groupBox_8.setCheckable(False) + self.textEdit_buildConsole = QTextEdit(self.groupBox_8) + self.textEdit_buildConsole.setObjectName(u"textEdit_buildConsole") + self.textEdit_buildConsole.setGeometry(QRect(0, 20, 631, 471)) + palette1 = QPalette() + palette1.setBrush(QPalette.Active, QPalette.Text, brush1) + palette1.setBrush(QPalette.Active, QPalette.Base, brush) + palette1.setBrush(QPalette.Inactive, QPalette.Text, brush1) + palette1.setBrush(QPalette.Inactive, QPalette.Base, brush) + self.textEdit_buildConsole.setPalette(palette1) + self.textEdit_buildConsole.setReadOnly(True) + self.frame_2 = QFrame(self.tab_2) + self.frame_2.setObjectName(u"frame_2") + self.frame_2.setGeometry(QRect(110, 20, 421, 81)) + self.frame_2.setFrameShape(QFrame.StyledPanel) + self.frame_2.setFrameShadow(QFrame.Raised) + self.frame = QFrame(self.frame_2) + self.frame.setObjectName(u"frame") + self.frame.setGeometry(QRect(79, 0, 341, 80)) + self.frame.setFrameShape(QFrame.StyledPanel) + self.frame.setFrameShadow(QFrame.Raised) + self.gridLayoutWidget_2 = QWidget(self.frame) + self.gridLayoutWidget_2.setObjectName(u"gridLayoutWidget_2") + self.gridLayoutWidget_2.setGeometry(QRect(0, 0, 340, 80)) + self.gridLayout_buildCleanButtons = QGridLayout(self.gridLayoutWidget_2) + self.gridLayout_buildCleanButtons.setObjectName(u"gridLayout_buildCleanButtons") + self.gridLayout_buildCleanButtons.setContentsMargins(0, 0, 0, 0) + self.pushButton_fswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_fswClean.setObjectName(u"pushButton_fswClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswClean, 1, 1, 1, 1) + + self.pushButton_fswBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_fswBuild.setObjectName(u"pushButton_fswBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswBuild, 0, 1, 1, 1) + + self.pushButton_gswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_gswClean.setObjectName(u"pushButton_gswClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswClean, 1, 2, 1, 1) + + self.pushButton_simClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_simClean.setObjectName(u"pushButton_simClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simClean, 1, 0, 1, 1) + + self.pushButton_simBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_simBuild.setObjectName(u"pushButton_simBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simBuild, 0, 0, 1, 1) + + self.pushButton_gswBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_gswBuild.setObjectName(u"pushButton_gswBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswBuild, 0, 2, 1, 1) + + self.pushButton_buildAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_buildAll.setObjectName(u"pushButton_buildAll") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_buildAll, 0, 3, 1, 1) + + self.pushButton_cleanAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_cleanAll.setObjectName(u"pushButton_cleanAll") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cleanAll, 1, 3, 1, 1) + + self.frame_3 = QFrame(self.frame_2) + self.frame_3.setObjectName(u"frame_3") + self.frame_3.setGeometry(QRect(0, 0, 81, 41)) + self.frame_3.setFrameShape(QFrame.StyledPanel) + self.frame_3.setFrameShadow(QFrame.Raised) + self.verticalLayoutWidget = QWidget(self.frame_3) + self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") + self.verticalLayoutWidget.setGeometry(QRect(0, 0, 81, 41)) + self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.label_4 = QLabel(self.verticalLayoutWidget) + self.label_4.setObjectName(u"label_4") + self.label_4.setAlignment(Qt.AlignCenter) + + self.verticalLayout.addWidget(self.label_4) + + self.frame_4 = QFrame(self.frame_2) + self.frame_4.setObjectName(u"frame_4") + self.frame_4.setGeometry(QRect(0, 40, 81, 41)) + self.frame_4.setFrameShape(QFrame.StyledPanel) + self.frame_4.setFrameShadow(QFrame.Raised) + self.verticalLayoutWidget_2 = QWidget(self.frame_4) + self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2") + self.verticalLayoutWidget_2.setGeometry(QRect(0, 0, 81, 41)) + self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.label_5 = QLabel(self.verticalLayoutWidget_2) + self.label_5.setObjectName(u"label_5") + self.label_5.setAlignment(Qt.AlignCenter) + + self.verticalLayout_2.addWidget(self.label_5) + + self.tabWidget.addTab(self.tab_2, "") + self.tab_3 = QWidget() + self.tab_3.setObjectName(u"tab_3") + self.groupBox_control = QGroupBox(self.tab_3) + self.groupBox_control.setObjectName(u"groupBox_control") + self.groupBox_control.setGeometry(QRect(10, 10, 631, 611)) + self.horizontalLayoutWidget = QWidget(self.groupBox_control) + self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget") + self.horizontalLayoutWidget.setGeometry(QRect(10, 570, 611, 31)) + self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget) + self.horizontalLayout.setSpacing(45) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.pushButton_play = QPushButton(self.horizontalLayoutWidget) + self.pushButton_play.setObjectName(u"pushButton_play") + icon = QIcon() + icon.addFile(u"../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg", QSize(), QIcon.Normal, QIcon.Off) + self.pushButton_play.setIcon(icon) + + self.horizontalLayout.addWidget(self.pushButton_play) + + self.pushButton_pause = QPushButton(self.horizontalLayoutWidget) + self.pushButton_pause.setObjectName(u"pushButton_pause") + icon1 = QIcon() + icon1.addFile(u"../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg", QSize(), QIcon.Normal, QIcon.Off) + self.pushButton_pause.setIcon(icon1) + + self.horizontalLayout.addWidget(self.pushButton_pause) + + self.horizontalLayoutWidget_2 = QWidget(self.groupBox_control) + self.horizontalLayoutWidget_2.setObjectName(u"horizontalLayoutWidget_2") + self.horizontalLayoutWidget_2.setGeometry(QRect(10, 10, 611, 41)) + self.horizontalLayout_2 = QHBoxLayout(self.horizontalLayoutWidget_2) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.pushButton_launch = QPushButton(self.horizontalLayoutWidget_2) + self.pushButton_launch.setObjectName(u"pushButton_launch") + + self.horizontalLayout_2.addWidget(self.pushButton_launch) + + self.pushButton_stop = QPushButton(self.horizontalLayoutWidget_2) + self.pushButton_stop.setObjectName(u"pushButton_stop") + + self.horizontalLayout_2.addWidget(self.pushButton_stop) + + self.groupBox_9 = QGroupBox(self.groupBox_control) + self.groupBox_9.setObjectName(u"groupBox_9") + self.groupBox_9.setGeometry(QRect(10, 60, 611, 451)) + self.groupBox_9.setAlignment(Qt.AlignCenter) + self.groupBox_9.setFlat(False) + self.groupBox_9.setCheckable(False) + self.textEdit_launchConsole = QTextEdit(self.groupBox_9) + self.textEdit_launchConsole.setObjectName(u"textEdit_launchConsole") + self.textEdit_launchConsole.setGeometry(QRect(0, 20, 611, 431)) + palette2 = QPalette() + palette2.setBrush(QPalette.Active, QPalette.Text, brush1) + palette2.setBrush(QPalette.Active, QPalette.Base, brush) + palette2.setBrush(QPalette.Inactive, QPalette.Text, brush1) + palette2.setBrush(QPalette.Inactive, QPalette.Base, brush) + self.textEdit_launchConsole.setPalette(palette2) + self.textEdit_launchConsole.setReadOnly(True) + self.horizontalLayoutWidget_3 = QWidget(self.groupBox_control) + self.horizontalLayoutWidget_3.setObjectName(u"horizontalLayoutWidget_3") + self.horizontalLayoutWidget_3.setGeometry(QRect(190, 520, 261, 41)) + self.horizontalLayout_runForUntil = QHBoxLayout(self.horizontalLayoutWidget_3) + self.horizontalLayout_runForUntil.setObjectName(u"horizontalLayout_runForUntil") + self.horizontalLayout_runForUntil.setContentsMargins(0, 0, 0, 0) + self.comboBox_run = QComboBox(self.horizontalLayoutWidget_3) + self.comboBox_run.addItem("") + self.comboBox_run.addItem("") + self.comboBox_run.addItem("") + self.comboBox_run.setObjectName(u"comboBox_run") + + self.horizontalLayout_runForUntil.addWidget(self.comboBox_run) + + self.lineEdit_secondsEntry = QLineEdit(self.horizontalLayoutWidget_3) + self.lineEdit_secondsEntry.setObjectName(u"lineEdit_secondsEntry") + self.lineEdit_secondsEntry.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_runForUntil.addWidget(self.lineEdit_secondsEntry) + + self.tabWidget.addTab(self.tab_3, "") + + self.retranslateUi(Form) + + self.tabWidget.setCurrentIndex(0) + + + QMetaObject.connectSlotsByName(Form) + # setupUi + + def retranslateUi(self, Form): + Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) + self.lineEdit_curConfig.setPlaceholderText(QCoreApplication.translate("Form", u"None", None)) + self.pushButton_browse.setText(QCoreApplication.translate("Form", u"Browse...", None)) + self.label_curConfig.setText(QCoreApplication.translate("Form", u"Current Config:", None)) + self.groupBox_scConfig.setTitle(QCoreApplication.translate("Form", u"Spacecraft Config", None)) + self.groupBox_masterConfig.setTitle(QCoreApplication.translate("Form", u"Master Config", None)) + self.pushButton_save.setText(QCoreApplication.translate("Form", u"Save", None)) + self.pushButton_saveAs.setText(QCoreApplication.translate("Form", u"Save As...", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Form", u"Config", None)) + self.groupBox_8.setTitle(QCoreApplication.translate("Form", u"Console Output", None)) + self.pushButton_fswClean.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_fswBuild.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_gswClean.setText(QCoreApplication.translate("Form", u"GSW", None)) + self.pushButton_simClean.setText(QCoreApplication.translate("Form", u"SIM", None)) + self.pushButton_simBuild.setText(QCoreApplication.translate("Form", u"SIM", None)) + self.pushButton_gswBuild.setText(QCoreApplication.translate("Form", u"GSW", None)) + self.pushButton_buildAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.pushButton_cleanAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.label_4.setText(QCoreApplication.translate("Form", u"Build", None)) + self.label_5.setText(QCoreApplication.translate("Form", u"Clean", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("Form", u"Build", None)) + self.groupBox_control.setTitle("") + self.pushButton_play.setText(QCoreApplication.translate("Form", u"Play", None)) + self.pushButton_pause.setText(QCoreApplication.translate("Form", u"Pause", None)) + self.pushButton_launch.setText(QCoreApplication.translate("Form", u"Launch", None)) + self.pushButton_stop.setText(QCoreApplication.translate("Form", u"Stop", None)) + self.groupBox_9.setTitle(QCoreApplication.translate("Form", u"NOS3 Time Driver", None)) + self.comboBox_run.setItemText(0, "") + self.comboBox_run.setItemText(1, QCoreApplication.translate("Form", u"Run For", None)) + self.comboBox_run.setItemText(2, QCoreApplication.translate("Form", u"Run Until", None)) + + self.lineEdit_secondsEntry.setText("") + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("Form", u"Launch", None)) + # retranslateUi + From c369cac349fcc75aea28b3dc437660edf84c18b4 Mon Sep 17 00:00:00 2001 From: "NDC\\rjbrown6" Date: Thu, 15 Feb 2024 15:57:06 -0500 Subject: [PATCH 078/153] [nasa/nos3#239] Migration to OS Github --- .gitmodules | 2 +- components/syn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f5b19b42..320c8544 100644 --- a/.gitmodules +++ b/.gitmodules @@ -129,5 +129,5 @@ url = https://github.com/nasa-itc/generic_star_tracker.git [submodule "components/syn"] path = components/syn - url = git@aetd-git.gsfc.nasa.gov:itc/jpl/synopsis/syn_component/syn_nos3.git + url = git@github.com:nasa-itc/syn.git branch = main diff --git a/components/syn b/components/syn index 419f54dc..1294aee8 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 419f54dcf73743b095489678a0b8402b41e58601 +Subproject commit 1294aee808331ae44116427b8a5bf11c5ed4f4eb From db30aca64c8ec0e77bdb7966642ce811066e6e4a Mon Sep 17 00:00:00 2001 From: David Date: Fri, 16 Feb 2024 14:20:41 +0000 Subject: [PATCH 079/153] [nasa/nos3#221] Commit to point to the 'dev' branch of the EPS submodule --- components/generic_eps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/generic_eps b/components/generic_eps index c07e1f3a..2b7db574 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit c07e1f3aad7122ae825e8820187d861466813963 +Subproject commit 2b7db5749398c3f7e85137e9f6b097551c9a5254 From 558215a3ebb9078eee4796a924aa94415391e892 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 19 Feb 2024 13:24:56 -0500 Subject: [PATCH 080/153] [nasa/nos3#226] Update submodules to latest dev; --- components/generic_css | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_radio | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- fsw/osal | 2 +- sims/nos_time_driver | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/generic_css b/components/generic_css index a35f8bc2..f0548bae 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit a35f8bc2e7e78329f9d3e22e5b6ff9f5dcd68c27 +Subproject commit f0548baed468d97a96970a9df5c9597290bd0b06 diff --git a/components/generic_fss b/components/generic_fss index 33f8138d..c9d7f7dd 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit 33f8138dc77ffe1d8475197456f0f75f923136cd +Subproject commit c9d7f7dd3ba1cbb33a1bfe653d3f1d1e354a4838 diff --git a/components/generic_imu b/components/generic_imu index 85d4e4d1..95b78abf 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 85d4e4d1ef1a74a45c2270f0a54792dc72dac0a4 +Subproject commit 95b78abf527eba1862de251e1b7bfbe09e742f79 diff --git a/components/generic_radio b/components/generic_radio index 80c950c1..f5a1a9a1 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 80c950c1029b767d5ebde960daf1cebec6c48acc +Subproject commit f5a1a9a1b95a8da29184cab80fae8709d47a4d8f diff --git a/components/novatel_oem615 b/components/novatel_oem615 index e63619d3..53c73c1d 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit e63619d36dced120fc5cb28b4ecac378901178f8 +Subproject commit 53c73c1d85f9015d92242368ebc0853f6b7f0e8b diff --git a/components/sample b/components/sample index 843e4822..744d049d 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 843e4822fe822e980d7fa37c4595d77ab8d98ce7 +Subproject commit 744d049da704252d8615e6f0e96dba77a25f0443 diff --git a/fsw/osal b/fsw/osal index 8b046477..d45f883b 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit 8b046477f047ae371be27f4ee7942fa4f863e7ac +Subproject commit d45f883b8aeab458f29c9efc19fa68ee6beda80b diff --git a/sims/nos_time_driver b/sims/nos_time_driver index 55238651..ddfe0917 160000 --- a/sims/nos_time_driver +++ b/sims/nos_time_driver @@ -1 +1 @@ -Subproject commit 552386510b5180781c20d85e21a42c48308526d3 +Subproject commit ddfe09172ebd84fc0a23b6fba7d140652c5de17e From 1c5c26e92853561dafab6fe447bc6a7e648948ae Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 19 Feb 2024 15:10:38 -0500 Subject: [PATCH 081/153] [nasa/nos3#226] Added environmental variables for DBOX version in all scripts; --- scripts/checkout.sh | 12 +++++----- scripts/docker_build_fsw.sh | 2 +- scripts/docker_build_sim.sh | 2 +- scripts/docker_debug.sh | 2 +- scripts/docker_launch.sh | 44 ++++++++++++++++++------------------- scripts/env.sh | 3 +++ scripts/prepare.sh | 2 +- 7 files changed, 35 insertions(+), 32 deletions(-) diff --git a/scripts/checkout.sh b/scripts/checkout.sh index ccc00227..8cc3d7fb 100755 --- a/scripts/checkout.sh +++ b/scripts/checkout.sh @@ -24,17 +24,17 @@ echo "" #rm -rf NOS3InOut #cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut #xhost +local:* -#gnome-terminal --window-with-profile=KeepOpen --title="42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut +#gnome-terminal --window-with-profile=KeepOpen --title="42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t $DBOX /opt/nos3/42/42 NOS3InOut #echo "" echo "NOS Core..." -gnome-terminal --tab --title="NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json -gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE time -gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE stdio-terminal +gnome-terminal --tab --title="NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN $DBOX /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json +gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE time +gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE stdio-terminal echo "Checkout..." # Rename for your simulator under test to allow checkout -gnome-terminal --tab --title="Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim +gnome-terminal --tab --title="Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim # Example manual build for sample checkout: # cd ./components/sample/support @@ -44,6 +44,6 @@ gnome-terminal --tab --title="Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --na # make # Rename for your checkout under test to allow checkout -gnome-terminal --title="Sample Sim" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR ivvitc/nos3 ./components/sample/support/build/sample_checkout +gnome-terminal --title="Sample Sim" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR $DBOX ./components/sample/support/build/sample_checkout echo "" diff --git a/scripts/docker_build_fsw.sh b/scripts/docker_build_fsw.sh index f6ed6e07..0c29df0a 100755 --- a/scripts/docker_build_fsw.sh +++ b/scripts/docker_build_fsw.sh @@ -28,4 +28,4 @@ fi mkdir -p $BASE_DIR/fsw/build # Build -$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-fsw +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_fsw" -w $BASE_DIR $DBOX make -j$NUM_CPUS build-fsw diff --git a/scripts/docker_build_sim.sh b/scripts/docker_build_sim.sh index f6b1f25e..a80856f0 100755 --- a/scripts/docker_build_sim.sh +++ b/scripts/docker_build_sim.sh @@ -25,4 +25,4 @@ if [ ! -d $BASE_DIR/cfg/build ]; then fi mkdir -p $BASE_DIR/sims/build -$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR ivvitc/nos3 make -j$NUM_CPUS build-sim +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_sim" -w $BASE_DIR $DBOX make -j$NUM_CPUS build-sim diff --git a/scripts/docker_debug.sh b/scripts/docker_debug.sh index 95df27c3..501657cf 100755 --- a/scripts/docker_debug.sh +++ b/scripts/docker_debug.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/fsw/build -$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR --name "nos3_debug" ivvitc/nos3 bash +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR --name "nos3_debug" $DBOX bash diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index c18897d5..387d5422 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -53,8 +53,8 @@ echo "" echo "Create NOS interfaces..." export GND_CFG_FILE="-f nos3-simulator.xml" -gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE stdio-terminal -gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_udp_terminal" --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE udp-terminal +gnome-terminal --tab --title="NOS Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_terminal" --network=nos3_core -w $SIM_BIN $DBOX ./nos3-single-simulator $GND_CFG_FILE stdio-terminal +gnome-terminal --tab --title="NOS UDP Terminal" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name "nos_udp_terminal" --network=nos3_core -w $SIM_BIN $DBOX ./nos3-single-simulator $GND_CFG_FILE udp-terminal echo "" @@ -88,12 +88,12 @@ do rm -rf $USER_NOS3_DIR/42/NOS3InOut cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* - gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t ivvitc/nos3 /opt/nos3/42/42 NOS3InOut + gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t $DBOX /opt/nos3/42/42 NOS3InOut echo "" echo $SC_NUM " - Flight Software..." cd $FSW_DIR - gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --ulimit rtprio=99 --cap-add=sys_nice ivvitc/nos3 $SCRIPT_DIR/fsw_respawn.sh & + gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --ulimit rtprio=99 --cap-add=sys_nice $DBOX $SCRIPT_DIR/fsw_respawn.sh & echo "" # Debugging @@ -101,39 +101,39 @@ do echo $SC_NUM " - Simulators..." cd $SIM_BIN - gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json - gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE truth42sim + gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN $DBOX /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json + gnome-terminal --tab --title=$SC_NUM" - 42 Truth Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_truth42sim" -h truth42sim --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE truth42sim $DNETWORK connect $SC_NETNAME nos_terminal $DNETWORK connect $SC_NETNAME nos_udp_terminal # Component simulators - gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE camsim - gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_css_sim - gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim - gnome-terminal --tab --title=$SC_NUM" - FSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_fss_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_fss_sim - gnome-terminal --tab --title=$SC_NUM" - GPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_gps_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE gps - gnome-terminal --tab --title=$SC_NUM" - IMU Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_imu_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_imu_sim - gnome-terminal --tab --title=$SC_NUM" - MAG Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_mag_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_mag_sim - gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 - gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 - gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 + gnome-terminal --tab --title=$SC_NUM" - CAM Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_cam_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE camsim + gnome-terminal --tab --title=$SC_NUM" - CSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_css_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_css_sim + gnome-terminal --tab --title=$SC_NUM" - EPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_eps_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_eps_sim + gnome-terminal --tab --title=$SC_NUM" - FSS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_fss_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_fss_sim + gnome-terminal --tab --title=$SC_NUM" - GPS Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_gps_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE gps + gnome-terminal --tab --title=$SC_NUM" - IMU Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_imu_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_imu_sim + gnome-terminal --tab --title=$SC_NUM" - MAG Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_mag_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_mag_sim + gnome-terminal --tab --title=$SC_NUM" - RW 0 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim0" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim0 + gnome-terminal --tab --title=$SC_NUM" - RW 1 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim1" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim1 + gnome-terminal --tab --title=$SC_NUM" - RW 2 Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_rw_sim2" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic-reactionwheel-sim2 - gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME --network-alias=radio_sim -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim + gnome-terminal --tab --title=$SC_NUM" - Radio Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_radio_sim" -h radio_sim --network=$SC_NETNAME --network-alias=radio_sim -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_radio_sim - gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim - gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim - gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim + gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim + gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim # Note: Can keep open if desired after a new gnome-profile is manually created - #gnome-terminal --window-with-profile=KeepOpen --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $SC_CFG_FILE sample_sim + #gnome-terminal --window-with-profile=KeepOpen --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim echo "" done echo "NOS Time Driver..." sleep 8 -gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=nos3_core -w $SIM_BIN ivvitc/nos3 ./nos3-single-simulator $GND_CFG_FILE time +gnome-terminal --tab --title="NOS Time Driver" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name nos_time_driver --network=nos3_core -w $SIM_BIN $DBOX ./nos3-single-simulator $GND_CFG_FILE time sleep 1 for (( i=1; i<=$SATNUM; i++ )) do diff --git a/scripts/env.sh b/scripts/env.sh index e03cbf82..ce708ce6 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,6 +40,9 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi +DBOX="ivvitc/nos3" +#DBOX="ivvitc/nos3-64:latest" + # Debugging #echo "Script directory = " $SCRIPT_DIR #echo "Base directory = " $BASE_DIR diff --git a/scripts/prepare.sh b/scripts/prepare.sh index 44e53ec1..e3eab3cc 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -24,7 +24,7 @@ $OPENC3_PATH run echo "" echo "Prepare nos3 docker container..." -$DCALL image pull ivvitc/nos3 +$DCALL image pull $DBOX echo "" echo "Set a password in openc3-cosmos via firefox..." From f78cde7b5e88f36c26ec243b8a9739bea7bde813 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 20 Feb 2024 09:18:08 -0500 Subject: [PATCH 082/153] [nasa/nos3#226] Building without werror or 42 GUIFLAG, resolved issue with configure.py and sample_index; --- cfg/nos3_defs/targets.cmake | 2 +- cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake | 34 +++++++++++++++++++ components/generic_eps | 2 +- components/generic_imu | 2 +- components/generic_radio | 2 +- components/generic_star_tracker | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- scripts/configure.py | 3 ++ scripts/docker_debug.sh | 2 +- scripts/docker_launch.sh | 2 +- scripts/env.sh | 4 +-- scripts/prepare.sh | 7 ++++ sims/CMakeLists.txt | 4 +-- sims/MissionSettings.cmake | 10 +++--- sims/nos_time_driver | 2 +- sims/sim_common | 2 +- sims/truth_42_sim | 2 +- 18 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 03ee90e2..72003adb 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -137,7 +137,7 @@ SET(MISSION_CPUNAMES cpu1) SET(cpu1_PROCESSORID 1) SET(cpu1_APPLIST) # Note: Using all ${MISSION_GLOBAL_APPLIST} automatically SET(cpu1_FILELIST cfe_es_startup.scr) -SET(cpu1_SYSTEM i386-linux-gnu) +SET(cpu1_SYSTEM amd64-linux-gnu) # USER Supplied #SET(cpu2_PROCESSORID 2) diff --git a/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake new file mode 100644 index 00000000..a062e7fc --- /dev/null +++ b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake @@ -0,0 +1,34 @@ +# This example toolchain file describes the cross compiler to use for +# the target architecture indicated in the configuration file. + +# Basic cross system configuration +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_SYSTEM_PROCESSOR amd64) + +# Specify the cross compiler executables +# Typically these would be installed in a home directory or somewhere +# in /opt. However in this example the system compiler is used. +SET(CMAKE_C_COMPILER "/usr/bin/gcc") +SET(CMAKE_CXX_COMPILER "/usr/bin/g++") + +# Configure the find commands +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + +# These variable settings are specific to cFE/OSAL and determines which +# abstraction layers are built when using this toolchain +SET(CFE_SYSTEM_PSPNAME "nos-linux") +SET(OSAL_SYSTEM_OSTYPE "nos") + +#SET(CMAKE_C_FLAGS_INIT "" CACHE STRING "C Flags required by platform") +#SET(CMAKE_SHARED_LINKER_FLAGS "-pg") + +# Build Specific +add_definitions(-DBYTE_ORDER_LE) +add_definitions(-D_LINUX_OS_) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +set(CI_TRANSPORT udp) +set(TO_TRANSPORT udp) diff --git a/components/generic_eps b/components/generic_eps index 2b7db574..88b5e5c4 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 2b7db5749398c3f7e85137e9f6b097551c9a5254 +Subproject commit 88b5e5c42353c3c44f1444cbe8b6ee0ece081406 diff --git a/components/generic_imu b/components/generic_imu index 95b78abf..a871d46e 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 95b78abf527eba1862de251e1b7bfbe09e742f79 +Subproject commit a871d46e33579dc497e4211d6a282980a56e9532 diff --git a/components/generic_radio b/components/generic_radio index f5a1a9a1..0fcf722a 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit f5a1a9a1b95a8da29184cab80fae8709d47a4d8f +Subproject commit 0fcf722a7a63837e0c8f2686dbd8faf6d536d3d3 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 211aa25c..05803784 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 211aa25c85645602582fa9576cf32595bfd1d522 +Subproject commit 058037847c27d0574c83df96e0eab0b0e6aab9e7 diff --git a/components/novatel_oem615 b/components/novatel_oem615 index 53c73c1d..b8335916 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit 53c73c1d85f9015d92242368ebc0853f6b7f0e8b +Subproject commit b833591696c0430f0f2343b3a29b8c77a538456d diff --git a/components/sample b/components/sample index 744d049d..bdffc647 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 744d049da704252d8615e6f0e96dba77a25f0443 +Subproject commit bdffc6470ae053a7a78393d440a78a3b74547436 diff --git a/scripts/configure.py b/scripts/configure.py index d09fa65d..7694698d 100755 --- a/scripts/configure.py +++ b/scripts/configure.py @@ -276,6 +276,9 @@ if line.find('RW 2 from 42') != -1: if (lines.index(line)) < rw2_from_index: rw2_from_index = lines.index(line) + 1 + if line.find('Sample IPC') != -1: + if (lines.index(line)) < sample_index: + sample_index = lines.index(line) + 1 if line.find('Star Tracker IPC') != -1: if (lines.index(line)) < st_index: st_index = lines.index(line) + 1 diff --git a/scripts/docker_debug.sh b/scripts/docker_debug.sh index 501657cf..87c541a7 100755 --- a/scripts/docker_debug.sh +++ b/scripts/docker_debug.sh @@ -9,4 +9,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) source $SCRIPT_DIR/env.sh mkdir -p $BASE_DIR/fsw/build -$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -w $BASE_DIR --name "nos3_debug" $DBOX bash +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $BASE_DIR --name "nos3_debug" $DBOX bash diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 387d5422..e0fe92ad 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -88,7 +88,7 @@ do rm -rf $USER_NOS3_DIR/42/NOS3InOut cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut xhost +local:* - gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t $DBOX /opt/nos3/42/42 NOS3InOut + gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR:$USER_NOS3_DIR -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w $USER_NOS3_DIR/42 -t $DBOX $USER_NOS3_DIR/42/42 NOS3InOut echo "" echo $SC_NUM " - Flight Software..." diff --git a/scripts/env.sh b/scripts/env.sh index ce708ce6..728371fa 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,8 +40,8 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -DBOX="ivvitc/nos3" -#DBOX="ivvitc/nos3-64:latest" +#DBOX="ivvitc/nos3" +DBOX="ivvitc/nos3-64:latest" # Debugging #echo "Script directory = " $SCRIPT_DIR diff --git a/scripts/prepare.sh b/scripts/prepare.sh index e3eab3cc..d9ea9293 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -27,6 +27,13 @@ echo "Prepare nos3 docker container..." $DCALL image pull $DBOX echo "" +echo "Prepare 42..." +cd $USER_NOS3_DIR +git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main +cd $USER_NOS3_DIR/42 +sed 's/#GLUT_OR_GLFW = _USE_GLUT_/GLUT_OR_GLFW = _USE_GLUT_/' -i $USER_NOS3_DIR/42/Makefile +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make + echo "Set a password in openc3-cosmos via firefox..." echo " Refresh webpage if error page shown." echo "" diff --git a/sims/CMakeLists.txt b/sims/CMakeLists.txt index 90b78442..9eea63e5 100644 --- a/sims/CMakeLists.txt +++ b/sims/CMakeLists.txt @@ -24,8 +24,8 @@ set(CXX_11 ON) STRING(REGEX REPLACE "--std=c\\+\\+98" "" ITC_CXX_FLAGS ${ITC_CXX_FLAGS}) #Remove the C++98 Flag if it exists endif(ITC_CXX_FLAGS) set(ITC_CXX_FLAGS "${ITC_CXX_FLAGS} --std=c++11") - set(CMAKE_CXX_FLAGS "-m32 -Wl,--disable-new-dtags -Werror -Wall -Wextra -pedantic -Wno-vla -Wwrite-strings -Wpointer-arith -Wcast-align") - set(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--disable-new-dtags") + set(CMAKE_CXX_FLAGS "-Wl,--disable-new-dtags -Werror -Wall -Wextra -pedantic -Wno-vla -Wwrite-strings -Wpointer-arith -Wcast-align") + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--disable-new-dtags") endif(CXX_11) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) diff --git a/sims/MissionSettings.cmake b/sims/MissionSettings.cmake index 511300d5..e3b41e2c 100644 --- a/sims/MissionSettings.cmake +++ b/sims/MissionSettings.cmake @@ -5,12 +5,12 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) endif() -set(ARCHITECTURE_STRING "i386") +set(ARCHITECTURE_STRING "amd64") set(ITC_C_FLAGS "") #Used for C set(ITC_CCXX_FLAGS "") #Works for both C/C++ set(CLANG_OVERRIDE "") -set(BOOST_LIBRARYDIR /usr/lib/i386-linux-gnu) +set(BOOST_LIBRARYDIR /usr/lib/amd64-linux-gnu) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") message(STATUS "Clang detected. MissionSettings will invoke GCC Compile Flags") @@ -29,9 +29,9 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG_OVERRIDE) set(ITC_CCXX_FLAGS "${ITC_CCXX_FLAGS} -fdiagnostics-show-option") message(STATUS "Setting compiler options...") - set(ITC_CCXX_FLAGS "${ITC_CCXX_FLAGS} -fPIC") - set(CMAKE_SHARED_LINKER_FLAGS "-fpic") - set(CMAKE_EXE_LINKER_FLAGS "-fpic") + #set(ITC_CCXX_FLAGS "${ITC_CCXX_FLAGS} -fPIC") + #set(CMAKE_SHARED_LINKER_FLAGS "-fpic") + #set(CMAKE_EXE_LINKER_FLAGS "-fpic") CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY) diff --git a/sims/nos_time_driver b/sims/nos_time_driver index ddfe0917..13a30e82 160000 --- a/sims/nos_time_driver +++ b/sims/nos_time_driver @@ -1 +1 @@ -Subproject commit ddfe09172ebd84fc0a23b6fba7d140652c5de17e +Subproject commit 13a30e8278d5f64e9cb70d3b86e234a2d499590d diff --git a/sims/sim_common b/sims/sim_common index 73426293..e005f237 160000 --- a/sims/sim_common +++ b/sims/sim_common @@ -1 +1 @@ -Subproject commit 73426293555550bea01a7b8b05e3cc21b0f93c4f +Subproject commit e005f237803cd0081800f3018780b53366953ec3 diff --git a/sims/truth_42_sim b/sims/truth_42_sim index 3abce84a..e1b1e265 160000 --- a/sims/truth_42_sim +++ b/sims/truth_42_sim @@ -1 +1 @@ -Subproject commit 3abce84acce56c0999d24db212624e0917096e2c +Subproject commit e1b1e2657345d44be82fb72b0706ce8f178f1fd1 From 4fe9e0883726ae5c412a5ff7eb9404d45ecd9a4a Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 21 Feb 2024 19:39:15 -0500 Subject: [PATCH 083/153] [nasa/nos3#239] Updated configuration.py to support SYN and updated submodule in attempt to resolve FetchContent issue; --- cfg/nos3_defs/cpu1_cfe_es_startup.scr | 3 ++- cfg/nos3_defs/targets.cmake | 5 ----- cfg/sc-full-config.xml | 3 +++ cfg/sc-minimal-config.xml | 3 +++ components/syn | 2 +- scripts/configure.py | 5 +++++ 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index d69f1b93..8b4e018c 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -4,7 +4,7 @@ CFE_LIB, io_lib, IO_LibInit, IO_LIB, CFE_APP, sch, SCH_AppMain, SCH, 40, 16384, 0x0, 0; CFE_APP, ci, CI_AppMain, CI, 41, 16384, 0x0, 0; CFE_APP, to, TO_AppMain, TO, 42, 16384, 0x0, 0; -CFE_APP, syn, SYN_AppMain, SYN, 60, 8192, 0x0, 0; + CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 80, 16384, 0x0, 0; CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 16384, 0x0, 0; @@ -30,6 +30,7 @@ CFE_APP, generic_torquer, TORQUER_AppMain, TORQUER, CFE_APP, novatel_oem615, NOVATEL_AppMain, NAV, 70, 8192, 0x0, 0; CFE_APP, sample, SAMPLE_AppMain, SAMPLE, 71, 8192, 0x0, 0; CFE_APP, generic_st, ST_AppMain, ST, 71, 8192, 0x0, 0; +CFE_APP, syn, SYN_AppMain, SYN, 72, 8192, 0x0, 0; CFE_LIB, cfs_lib, CFS_LibInit, CFS_LIB, 0, 0, 0x0, 0; CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 4c9d3439..b3718a50 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -116,12 +116,7 @@ list(APPEND MISSION_GLOBAL_APPLIST generic_torquer novatel_oem615 sample -<<<<<<< HEAD:fsw/nos3_defs/targets.cmake - generic_adcs - generic_star_tracker syn -======= ->>>>>>> origin/dev:cfg/nos3_defs/targets.cmake ) # Create Application Platform Include List diff --git a/cfg/sc-full-config.xml b/cfg/sc-full-config.xml index 32bc3354..c2213c53 100644 --- a/cfg/sc-full-config.xml +++ b/cfg/sc-full-config.xml @@ -53,6 +53,9 @@ true + + true + true diff --git a/cfg/sc-minimal-config.xml b/cfg/sc-minimal-config.xml index f64a7689..07b9d3ab 100644 --- a/cfg/sc-minimal-config.xml +++ b/cfg/sc-minimal-config.xml @@ -53,6 +53,9 @@ false + + false + false diff --git a/components/syn b/components/syn index 1294aee8..0d721234 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 1294aee808331ae44116427b8a5bf11c5ed4f4eb +Subproject commit 0d721234fb8d1ff7cfde9ce411713e5025bd875c diff --git a/scripts/configure.py b/scripts/configure.py index d09fa65d..1e8b7dc4 100755 --- a/scripts/configure.py +++ b/scripts/configure.py @@ -56,6 +56,7 @@ sc_rw_en = sc_root.find('components/rw/enable').text sc_sample_en = sc_root.find('components/sample/enable').text sc_st_en = sc_root.find('components/st/enable').text + sc_syn_en = sc_root.find('components/syn/enable').text sc_torquer_en = sc_root.find('components/torquer/enable').text sc_gui_en = sc_root.find('gui/enable').text @@ -148,6 +149,9 @@ if line.find('ST,') != -1: if (sc_st_en == 'true'): st_line = line + if line.find('SYN,') != -1: + if (sc_syn_en == 'true'): + syn_line = line if line.find('TORQUER,') != -1: if (sc_torquer_en == 'true'): torquer_line = line @@ -155,6 +159,7 @@ # Modify startup script per spacecraft configuration lines.insert(sc_startup_eof, "\n") lines.insert(sc_startup_eof, torquer_line) + lines.insert(sc_startup_eof, syn_line) lines.insert(sc_startup_eof, st_line) lines.insert(sc_startup_eof, sample_line) lines.insert(sc_startup_eof, rw_line) From b91ad65dfaf7d855ba6227792b09e7fedc215457 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 21 Feb 2024 20:11:37 -0500 Subject: [PATCH 084/153] [nasa/nos3#226] Updated 42 prep to use the nos3-1.6.2 branch; --- scripts/docker_launch.sh | 1 + scripts/env.sh | 1 - scripts/prepare.sh | 9 +++++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index e0fe92ad..4539a4e7 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -94,6 +94,7 @@ do echo $SC_NUM " - Flight Software..." cd $FSW_DIR gnome-terminal --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --ulimit rtprio=99 --cap-add=sys_nice $DBOX $SCRIPT_DIR/fsw_respawn.sh & + #gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - NOS3 Flight Software" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_nos_fsw" -h nos_fsw --network=$SC_NETNAME -w $FSW_DIR --sysctl fs.mqueue.msg_max=10000 --ulimit rtprio=99 --cap-add=sys_nice $DBOX $FSW_DIR/core-cpu1 -R PO & echo "" # Debugging diff --git a/scripts/env.sh b/scripts/env.sh index 728371fa..06fad19a 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,7 +40,6 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -#DBOX="ivvitc/nos3" DBOX="ivvitc/nos3-64:latest" # Debugging diff --git a/scripts/prepare.sh b/scripts/prepare.sh index d9ea9293..f598887a 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -11,28 +11,33 @@ mkdir $USER_NOS3_DIR 2> /dev/null echo " "$USER_NOS3_DIR mkdir $USER_NOS3_DIR/42 2> /dev/null echo "" +echo "" echo "Clone openc3-cosmos into local user directory..." cd $USER_NOS3_DIR git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main $USER_NOS3_DIR/cosmos git reset --hard echo "" +echo "" echo "Prepare openc3-cosmos containers..." cd $OPENC3_DIR $OPENC3_PATH run echo "" +echo "" echo "Prepare nos3 docker container..." $DCALL image pull $DBOX echo "" +echo "" echo "Prepare 42..." cd $USER_NOS3_DIR -git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main +git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-1.6.2 cd $USER_NOS3_DIR/42 -sed 's/#GLUT_OR_GLFW = _USE_GLUT_/GLUT_OR_GLFW = _USE_GLUT_/' -i $USER_NOS3_DIR/42/Makefile $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make +echo "" +echo "" echo "Set a password in openc3-cosmos via firefox..." echo " Refresh webpage if error page shown." From 46e9ed27357891342179430682dbc917ef967b60 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 22 Feb 2024 19:35:20 -0500 Subject: [PATCH 085/153] [nasa/nos3#239] Updated syn submodule after missing commit hash was realized; --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index 0d721234..098a30a6 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 0d721234fb8d1ff7cfde9ce411713e5025bd875c +Subproject commit 098a30a624ef7f1f471b764a5e4d545a8c09e763 From 05f36c9f22b04fe45716e0f77a1e2da3040e7966 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 23 Feb 2024 12:15:27 -0500 Subject: [PATCH 086/153] [nasa/nos3#134] - Move the arducam CMakeLists.txt inside the fsw directory. --- cfg/nos3_defs/targets.cmake | 3 ++- components/arducam | 2 +- fsw/cfe | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index b3718a50..2564a9a0 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -103,7 +103,7 @@ list(APPEND MISSION_GLOBAL_APPLIST # # Components # - arducam + arducam/fsw generic_adcs generic_css generic_eps @@ -123,6 +123,7 @@ list(APPEND MISSION_GLOBAL_APPLIST FOREACH(X ${MISSION_GLOBAL_APPLIST}) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/platform_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/public_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) ENDFOREACH(X) diff --git a/components/arducam b/components/arducam index bafb309d..28f8675b 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit bafb309d18cf649cf451929381fb7e7b4e0e0dbb +Subproject commit 28f8675b73afebae137b7346d6ad39358edf9d13 diff --git a/fsw/cfe b/fsw/cfe index 6d96c6e8..82f80e48 160000 --- a/fsw/cfe +++ b/fsw/cfe @@ -1 +1 @@ -Subproject commit 6d96c6e856a654f7c96e66a87b003aa01ff96874 +Subproject commit 82f80e48681ebb5c14b07a0491a0ef6383513675 From 964a7819be95313cd6ebf2ca31ead4afd7abf759 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 23 Feb 2024 14:38:58 -0500 Subject: [PATCH 087/153] [nasa/nos3#134] - Move the CMakeLists.txt inside the fsw directory: generic_adcs, generic_css, generic_eps, generic_fss, generic_imu, generic_mag, generic_radio, generic_reaction_wheel, generic_star_tracker, generic_torquer, novatel_oem615, sample. --- cfg/nos3_defs/targets.cmake | 25 +++++++++++++------------ components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_radio | 2 +- components/generic_reaction_wheel | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- 13 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 2564a9a0..afb92361 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -104,18 +104,18 @@ list(APPEND MISSION_GLOBAL_APPLIST # Components # arducam/fsw - generic_adcs - generic_css - generic_eps - generic_fss - generic_imu - generic_mag - generic_reaction_wheel - generic_radio - generic_star_tracker - generic_torquer - novatel_oem615 - sample + generic_adcs/fsw + generic_css/fsw + generic_eps/fsw + generic_fss/fsw + generic_imu/fsw + generic_mag/fsw + generic_reaction_wheel/fsw + generic_radio/fsw + generic_star_tracker/fsw + generic_torquer/fsw + novatel_oem615/fsw + sample/fsw syn ) @@ -126,6 +126,7 @@ FOREACH(X ${MISSION_GLOBAL_APPLIST}) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/public_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/src) ENDFOREACH(X) # FT_INSTALL_SUBDIR indicates where the black box test data files (lua scripts) should diff --git a/components/generic_adcs b/components/generic_adcs index 6c187bb0..0fef4a96 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 6c187bb0372d81585f9f2e8fcc5af7a89d28f554 +Subproject commit 0fef4a968394c218c6a5f15246a880e064587344 diff --git a/components/generic_css b/components/generic_css index f0548bae..592e7790 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit f0548baed468d97a96970a9df5c9597290bd0b06 +Subproject commit 592e77902c82a4ba893f19e8162dfa003f5150f4 diff --git a/components/generic_eps b/components/generic_eps index 2b7db574..392df9fc 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 2b7db5749398c3f7e85137e9f6b097551c9a5254 +Subproject commit 392df9fc3ddbf175b2acbe1a7ad28e58b8499d40 diff --git a/components/generic_fss b/components/generic_fss index c9d7f7dd..4e7a74a1 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit c9d7f7dd3ba1cbb33a1bfe653d3f1d1e354a4838 +Subproject commit 4e7a74a10f24a0f542b74045b25a4305b38efb7e diff --git a/components/generic_imu b/components/generic_imu index 95b78abf..71b336a4 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 95b78abf527eba1862de251e1b7bfbe09e742f79 +Subproject commit 71b336a4be3a8141e12d8bc93a17901d58388a62 diff --git a/components/generic_mag b/components/generic_mag index 37b4eb61..38d08cf0 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit 37b4eb6108cad3a856ee65c3d0ee9239de7d9c24 +Subproject commit 38d08cf0e4a5dee7bb787f4cdb0bc81dd6195b90 diff --git a/components/generic_radio b/components/generic_radio index f5a1a9a1..4fe58478 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit f5a1a9a1b95a8da29184cab80fae8709d47a4d8f +Subproject commit 4fe5847885848df3af03b71e4a0679cc6dbdd786 diff --git a/components/generic_reaction_wheel b/components/generic_reaction_wheel index 7962a302..8e283c55 160000 --- a/components/generic_reaction_wheel +++ b/components/generic_reaction_wheel @@ -1 +1 @@ -Subproject commit 7962a3021e839fef9b8b8222166358cba9d4619a +Subproject commit 8e283c55c8600608150b35b97166b57ea8f8499e diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 211aa25c..4b4998fb 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 211aa25c85645602582fa9576cf32595bfd1d522 +Subproject commit 4b4998fb09815768a55478c4d51650eb6103bb6f diff --git a/components/generic_torquer b/components/generic_torquer index a561060a..cbd7df18 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit a561060ad1b988402b5175b3cb9674dc6568b1bf +Subproject commit cbd7df182ff3c40c5b6398312d12e167291c5244 diff --git a/components/novatel_oem615 b/components/novatel_oem615 index e63619d3..b6b495c0 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit e63619d36dced120fc5cb28b4ecac378901178f8 +Subproject commit b6b495c00879b8886b28091d7a14549029fc9a75 diff --git a/components/sample b/components/sample index 744d049d..14330da5 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 744d049da704252d8615e6f0e96dba77a25f0443 +Subproject commit 14330da56ecc80700df088cfc1fba1ff2a284443 From 5a467467f25ee75ca189c0bfc876d5a6984dd363 Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Fri, 23 Feb 2024 15:06:26 -0500 Subject: [PATCH 088/153] [nasa/nos3#134] - Move the CMakeLists.txt inside the fsw directory: syn. --- cfg/nos3_defs/targets.cmake | 2 +- components/syn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index afb92361..448f8deb 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -116,7 +116,7 @@ list(APPEND MISSION_GLOBAL_APPLIST generic_torquer/fsw novatel_oem615/fsw sample/fsw - syn + syn/fsw ) # Create Application Platform Include List diff --git a/components/syn b/components/syn index 098a30a6..c85e06e3 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 098a30a624ef7f1f471b764a5e4d545a8c09e763 +Subproject commit c85e06e319eaf20da5aa8ba4ad549b5e0b6c4d45 From 2fdd74773db42ec9778dc9011896e94d05059e6a Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 29 Feb 2024 17:23:44 -0500 Subject: [PATCH 089/153] [nasa/nos3#134] Update submodules after merge requests and resolve configure.py error for syn false; --- components/arducam | 2 +- components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_radio | 2 +- components/generic_reaction_wheel | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- components/syn | 2 +- fsw/cfe | 2 +- gsw/cosmos | 2 +- scripts/configure.py | 1 + sims/truth_42_sim | 2 +- 18 files changed, 18 insertions(+), 17 deletions(-) diff --git a/components/arducam b/components/arducam index 28f8675b..d8ae6d79 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit 28f8675b73afebae137b7346d6ad39358edf9d13 +Subproject commit d8ae6d799588b7272f53eccff8b55b8e2e8291d3 diff --git a/components/generic_adcs b/components/generic_adcs index 0fef4a96..8f8ae811 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 0fef4a968394c218c6a5f15246a880e064587344 +Subproject commit 8f8ae8116321451f05371b64ff52e91e91007b4b diff --git a/components/generic_css b/components/generic_css index 592e7790..5c1fa189 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit 592e77902c82a4ba893f19e8162dfa003f5150f4 +Subproject commit 5c1fa189b32e56bcd4406bd9e470b32a1e3bc98f diff --git a/components/generic_eps b/components/generic_eps index 392df9fc..12fa740e 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 392df9fc3ddbf175b2acbe1a7ad28e58b8499d40 +Subproject commit 12fa740efd8729d9efe6face57de7b65002f3bfb diff --git a/components/generic_fss b/components/generic_fss index 4e7a74a1..0b7c04a1 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit 4e7a74a10f24a0f542b74045b25a4305b38efb7e +Subproject commit 0b7c04a1afce8be9177439bd06f59858a396f1ca diff --git a/components/generic_imu b/components/generic_imu index 71b336a4..5a2004ea 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 71b336a4be3a8141e12d8bc93a17901d58388a62 +Subproject commit 5a2004eab08f7fa794c5516fbc97d6a21deedc6b diff --git a/components/generic_mag b/components/generic_mag index 38d08cf0..cf3bc666 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit 38d08cf0e4a5dee7bb787f4cdb0bc81dd6195b90 +Subproject commit cf3bc666a52ca998dc6ba9260877b1a10c163922 diff --git a/components/generic_radio b/components/generic_radio index 4fe58478..9b5c389a 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 4fe5847885848df3af03b71e4a0679cc6dbdd786 +Subproject commit 9b5c389a8d583dc8ccc12f0fb1b42d2f5bf480fe diff --git a/components/generic_reaction_wheel b/components/generic_reaction_wheel index 8e283c55..69cde78d 160000 --- a/components/generic_reaction_wheel +++ b/components/generic_reaction_wheel @@ -1 +1 @@ -Subproject commit 8e283c55c8600608150b35b97166b57ea8f8499e +Subproject commit 69cde78d913cfb3ee13de6e3f25eda4059fa9f72 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 4b4998fb..29763241 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 4b4998fb09815768a55478c4d51650eb6103bb6f +Subproject commit 29763241d5b8bd66e0dfbf7099c501f2e9e71b64 diff --git a/components/generic_torquer b/components/generic_torquer index cbd7df18..94db987e 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit cbd7df182ff3c40c5b6398312d12e167291c5244 +Subproject commit 94db987e309588d52eab8fd44407a43b47bbc7af diff --git a/components/novatel_oem615 b/components/novatel_oem615 index b6b495c0..6f9519a1 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit b6b495c00879b8886b28091d7a14549029fc9a75 +Subproject commit 6f9519a17c2680ebf26348f0a108d1f0e760c8fa diff --git a/components/sample b/components/sample index 14330da5..b07046ee 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 14330da56ecc80700df088cfc1fba1ff2a284443 +Subproject commit b07046eeb5f6622efce9344c738bafbb537600a9 diff --git a/components/syn b/components/syn index c85e06e3..78be29d8 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit c85e06e319eaf20da5aa8ba4ad549b5e0b6c4d45 +Subproject commit 78be29d8b3710452581b25821c5993238493106d diff --git a/fsw/cfe b/fsw/cfe index 82f80e48..79c22d9e 160000 --- a/fsw/cfe +++ b/fsw/cfe @@ -1 +1 @@ -Subproject commit 82f80e48681ebb5c14b07a0491a0ef6383513675 +Subproject commit 79c22d9edfe425f39efc782bb168aefe8db5ddf7 diff --git a/gsw/cosmos b/gsw/cosmos index 781ff886..14a27fd4 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 781ff88628ccec936fa7a413e7c54920f8362425 +Subproject commit 14a27fd4951afc42c152cfa7760b056f9252d0f9 diff --git a/scripts/configure.py b/scripts/configure.py index 1e8b7dc4..27d5dcfa 100755 --- a/scripts/configure.py +++ b/scripts/configure.py @@ -91,6 +91,7 @@ rw_line = "" sample_line = "" st_line = "" + syn_line = "" torquer_line = "" # Parse lines diff --git a/sims/truth_42_sim b/sims/truth_42_sim index 3abce84a..e1b1e265 160000 --- a/sims/truth_42_sim +++ b/sims/truth_42_sim @@ -1 +1 @@ -Subproject commit 3abce84acce56c0999d24db212624e0917096e2c +Subproject commit e1b1e2657345d44be82fb72b0706ce8f178f1fd1 From 76fd5bf173f819a7e9d4eeaee4cc63fffe8ef856 Mon Sep 17 00:00:00 2001 From: Kevin Bruce Date: Mon, 4 Mar 2024 11:25:07 -0500 Subject: [PATCH 090/153] [nasa/nos3#136] Updated Component Perf-IDs to be unique --- components/generic_eps | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_star_tracker | 2 +- components/syn | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/generic_eps b/components/generic_eps index 12fa740e..87d74658 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 12fa740efd8729d9efe6face57de7b65002f3bfb +Subproject commit 87d7465827a21144afab58551ca765f401625de6 diff --git a/components/generic_imu b/components/generic_imu index 5a2004ea..16bb3615 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 5a2004eab08f7fa794c5516fbc97d6a21deedc6b +Subproject commit 16bb36150998f605a9b3612d24b790b4185c6991 diff --git a/components/generic_mag b/components/generic_mag index cf3bc666..c41cef68 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit cf3bc666a52ca998dc6ba9260877b1a10c163922 +Subproject commit c41cef686c68ce7f5211093145dc7940b20e4f30 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 29763241..2a275a2b 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 29763241d5b8bd66e0dfbf7099c501f2e9e71b64 +Subproject commit 2a275a2b0c91db1777a6f28a3ab0ea6184c09b5f diff --git a/components/syn b/components/syn index 78be29d8..f18d9fae 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 78be29d8b3710452581b25821c5993238493106d +Subproject commit f18d9fae9484ac17fff1e73bf00b1bdc4f2784fa From f337cb9bd30022aee87b0758a5320b93484336aa Mon Sep 17 00:00:00 2001 From: Kevin Bruce Date: Mon, 4 Mar 2024 11:30:06 -0500 Subject: [PATCH 091/153] [nasa/nos3#136] Updated app perf_ids to be unique --- fsw/apps/sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/apps/sc b/fsw/apps/sc index c9a5fb1b..1ae91874 160000 --- a/fsw/apps/sc +++ b/fsw/apps/sc @@ -1 +1 @@ -Subproject commit c9a5fb1b9cc822d2251f5d5c6eaa6c02635774bd +Subproject commit 1ae9187404c5230fc6eb7856183b8db23f056799 From 55aea80b58a9a88876b33e584f6ce074529c5214 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Mon, 4 Mar 2024 19:33:58 -0500 Subject: [PATCH 092/153] [nasa/nos3#226] Updates to build 64-bit fsw; --- cfg/nos3_defs/cpu1_cfe_es_startup.scr | 40 +++++++++++++-------------- components/arducam | 2 +- components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_radio | 2 +- components/generic_reaction_wheel | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- fsw/apps/ci | 2 +- fsw/apps/hwlib | 2 +- fsw/apps/sch | 2 +- fsw/apps/to | 2 +- fsw/osal | 2 +- 19 files changed, 38 insertions(+), 38 deletions(-) diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index 1b1092f7..3e2616a4 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -3,33 +3,33 @@ CFE_LIB, io_lib, IO_LibInit, IO_LIB, CFE_APP, sch, SCH_AppMain, SCH, 40, 16384, 0x0, 0; CFE_APP, ci, CI_AppMain, CI, 41, 16384, 0x0, 0; -CFE_APP, to, TO_AppMain, TO, 42, 16384, 0x0, 0; +CFE_APP, to, TO_AppMain, TO, 42, 32768, 0x0, 0; CFE_APP, ci_lab, CI_Lab_AppMain, CI_LAB_APP, 80, 16384, 0x0, 0; -CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 16384, 0x0, 0; +CFE_APP, to_lab, TO_LAB_AppMain, TO_LAB_APP, 81, 32768, 0x0, 0; ! ! ** The software will not try to parse anything after the first '!' character it sees. ** ! -CFE_APP, cf, CF_AppMain, CF, 50, 16384, 0x0, 0; -CFE_APP, ds, DS_AppMain, DS, 51, 16384, 0x0, 0; -CFE_APP, fm, FM_AppMain, FM, 52, 16384, 0x0, 0; -CFE_APP, lc, LC_AppMain, LC, 53, 16384, 0x0, 0; -CFE_APP, sc, SC_AppMain, SC, 54, 16384, 0x0, 0; +CFE_APP, cf, CF_AppMain, CF, 50, 32768, 0x0, 0; +CFE_APP, ds, DS_AppMain, DS, 51, 32768, 0x0, 0; +CFE_APP, fm, FM_AppMain, FM, 52, 32768, 0x0, 0; +CFE_APP, lc, LC_AppMain, LC, 53, 32768, 0x0, 0; +CFE_APP, sc, SC_AppMain, SC, 54, 32768, 0x0, 0; -CFE_APP, generic_adcs, ADCS_AppMain, ADCS, 61, 8192, 0x0, 0; -CFE_APP, arducam, arducam_AppMain, CAM, 60, 8192, 0x0, 0; -CFE_APP, generic_css, CSS_AppMain, CSS, 62, 8192, 0x0, 0; -CFE_APP, generic_eps, EPS_AppMain, EPS, 63, 8192, 0x0, 0; -CFE_APP, generic_fss, FSS_AppMain, FSS, 64, 8192, 0x0, 0; -CFE_APP, generic_imu, IMU_AppMain, IMU, 65, 8192, 0x0, 0; -CFE_APP, generic_mag, MAG_AppMain, MAG, 66, 8192, 0x0, 0; -CFE_APP, generic_radio, RADIO_AppMain, RADIO, 67, 8192, 0x0, 0; -CFE_APP, generic_rw, RW_AppMain, RW, 68, 8192, 0x0, 0; -CFE_APP, generic_torquer, TORQUER_AppMain, TORQUER, 69, 8192, 0x0, 0; -CFE_APP, novatel_oem615, NOVATEL_AppMain, NAV, 70, 8192, 0x0, 0; -CFE_APP, sample, SAMPLE_AppMain, SAMPLE, 71, 8192, 0x0, 0; -CFE_APP, generic_st, ST_AppMain, ST, 71, 8192, 0x0, 0; +CFE_APP, generic_adcs, ADCS_AppMain, ADCS, 60, 32768, 0x0, 0; +CFE_APP, arducam, arducam_AppMain, CAM, 61, 32768, 0x0, 0; +CFE_APP, generic_css, CSS_AppMain, CSS, 62, 32768, 0x0, 0; +CFE_APP, generic_eps, EPS_AppMain, EPS, 63, 32768, 0x0, 0; +CFE_APP, generic_fss, FSS_AppMain, FSS, 64, 32768, 0x0, 0; +CFE_APP, generic_imu, IMU_AppMain, IMU, 65, 32768, 0x0, 0; +CFE_APP, generic_mag, MAG_AppMain, MAG, 66, 32768, 0x0, 0; +CFE_APP, generic_radio, RADIO_AppMain, RADIO, 67, 32768, 0x0, 0; +CFE_APP, generic_rw, RW_AppMain, RW, 68, 32768, 0x0, 0; +CFE_APP, generic_torquer, TORQUER_AppMain, TORQUER, 69, 32768, 0x0, 0; +CFE_APP, novatel_oem615, NOVATEL_AppMain, NAV, 70, 32768, 0x0, 0; +CFE_APP, sample, SAMPLE_AppMain, SAMPLE, 71, 32768, 0x0, 0; +CFE_APP, generic_st, ST_AppMain, ST, 71, 32768, 0x0, 0; CFE_LIB, cfs_lib, CFS_LibInit, CFS_LIB, 0, 0, 0x0, 0; CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; diff --git a/components/arducam b/components/arducam index bafb309d..0b9de156 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit bafb309d18cf649cf451929381fb7e7b4e0e0dbb +Subproject commit 0b9de1567ed64259d2422f3f864ee0c8ee8a273c diff --git a/components/generic_adcs b/components/generic_adcs index 6c187bb0..0291f5e4 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 6c187bb0372d81585f9f2e8fcc5af7a89d28f554 +Subproject commit 0291f5e4b85acd21a65f9f19a1855939f745b058 diff --git a/components/generic_css b/components/generic_css index f0548bae..00a2b37b 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit f0548baed468d97a96970a9df5c9597290bd0b06 +Subproject commit 00a2b37b3687d499eb3038bb0eff97113196b854 diff --git a/components/generic_eps b/components/generic_eps index 88b5e5c4..956440ac 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 88b5e5c42353c3c44f1444cbe8b6ee0ece081406 +Subproject commit 956440ac7c2862b35197d0bcdbeda6118de9ea52 diff --git a/components/generic_fss b/components/generic_fss index c9d7f7dd..9baa0448 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit c9d7f7dd3ba1cbb33a1bfe653d3f1d1e354a4838 +Subproject commit 9baa0448291d641c21e69b466225ee77b1c4c58e diff --git a/components/generic_imu b/components/generic_imu index a871d46e..4de10fb5 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit a871d46e33579dc497e4211d6a282980a56e9532 +Subproject commit 4de10fb5e913741c9e7074ff7fa4587876bc87e8 diff --git a/components/generic_mag b/components/generic_mag index 37b4eb61..954e7590 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit 37b4eb6108cad3a856ee65c3d0ee9239de7d9c24 +Subproject commit 954e75900bad34de0865a733cbaa3f35eb58d970 diff --git a/components/generic_radio b/components/generic_radio index 0fcf722a..ab85deb6 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 0fcf722a7a63837e0c8f2686dbd8faf6d536d3d3 +Subproject commit ab85deb6d5b0170669e2255044bb447d2f38c795 diff --git a/components/generic_reaction_wheel b/components/generic_reaction_wheel index 7962a302..9eaa9a97 160000 --- a/components/generic_reaction_wheel +++ b/components/generic_reaction_wheel @@ -1 +1 @@ -Subproject commit 7962a3021e839fef9b8b8222166358cba9d4619a +Subproject commit 9eaa9a9731440f266559819174645a4b2c0a1bec diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 05803784..a3a3d65c 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 058037847c27d0574c83df96e0eab0b0e6aab9e7 +Subproject commit a3a3d65cd684c065b20ae1c6af10584b90d9d798 diff --git a/components/generic_torquer b/components/generic_torquer index a561060a..94947273 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit a561060ad1b988402b5175b3cb9674dc6568b1bf +Subproject commit 94947273ea5fb1b4e54f5115e509ad93b7522275 diff --git a/components/novatel_oem615 b/components/novatel_oem615 index b8335916..c3fbb7fc 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit b833591696c0430f0f2343b3a29b8c77a538456d +Subproject commit c3fbb7fc05f25fbe7d3da3ec154d5d70383839d3 diff --git a/components/sample b/components/sample index bdffc647..77fc6595 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit bdffc6470ae053a7a78393d440a78a3b74547436 +Subproject commit 77fc6595266525dd14ccf62880e75e3073c566b0 diff --git a/fsw/apps/ci b/fsw/apps/ci index 23686e1d..1db1c31b 160000 --- a/fsw/apps/ci +++ b/fsw/apps/ci @@ -1 +1 @@ -Subproject commit 23686e1de648afb98be7a3fed7bbe7b17e85775a +Subproject commit 1db1c31bf22d8feec8761217bbd49207691a4a91 diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index 405f028a..8b9402ed 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit 405f028a35c31585c2e07bb8d8ac85bca476ca21 +Subproject commit 8b9402edbd12fbda1fb96415a778e66b66d2a564 diff --git a/fsw/apps/sch b/fsw/apps/sch index c81ff8b7..220f962a 160000 --- a/fsw/apps/sch +++ b/fsw/apps/sch @@ -1 +1 @@ -Subproject commit c81ff8b751f40c33ceaaf1e26b463b19b0471203 +Subproject commit 220f962abd1a69512d29b172fdd57c056b265b9f diff --git a/fsw/apps/to b/fsw/apps/to index 471e41ca..5ea7e9ef 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 471e41ca5dd395c037dfe31f562cba5e06943d96 +Subproject commit 5ea7e9efdb7062f69c89aa2c1d913cc125c072c7 diff --git a/fsw/osal b/fsw/osal index d45f883b..19a19def 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit d45f883b8aeab458f29c9efc19fa68ee6beda80b +Subproject commit 19a19def07ea0d4f8c00a3071650517d2fe3b858 From 1501074fd8f6a5510e59580fb4c25f852d492b91 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 6 Mar 2024 10:14:52 -0500 Subject: [PATCH 093/153] [nasa/nos3#136] Updated submodules after merges; --- components/generic_eps | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_star_tracker | 2 +- components/syn | 2 +- fsw/apps/sc | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/generic_eps b/components/generic_eps index 87d74658..50769495 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 87d7465827a21144afab58551ca765f401625de6 +Subproject commit 507694958be6fade74cabe7698efa9db5cc2ef76 diff --git a/components/generic_imu b/components/generic_imu index 16bb3615..5a015635 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 16bb36150998f605a9b3612d24b790b4185c6991 +Subproject commit 5a015635463cf62369836405b3e300d96a22aac0 diff --git a/components/generic_mag b/components/generic_mag index c41cef68..1d964c69 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit c41cef686c68ce7f5211093145dc7940b20e4f30 +Subproject commit 1d964c6918cc2ab5d1f387152fc60a6de340e960 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 2a275a2b..73031098 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 2a275a2b0c91db1777a6f28a3ab0ea6184c09b5f +Subproject commit 73031098ae145ec94b063cc69036e01001be3288 diff --git a/components/syn b/components/syn index f18d9fae..22f30d3f 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit f18d9fae9484ac17fff1e73bf00b1bdc4f2784fa +Subproject commit 22f30d3fca8dd9db7780be0f3d155358ab684a98 diff --git a/fsw/apps/sc b/fsw/apps/sc index 1ae91874..37e919b7 160000 --- a/fsw/apps/sc +++ b/fsw/apps/sc @@ -1 +1 @@ -Subproject commit 1ae9187404c5230fc6eb7856183b8db23f056799 +Subproject commit 37e919b76b1a34fc93917d636dfc5f238de72945 From 9386fc3e7f0b703bcbc1b44316ce06f5b127f04c Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 6 Mar 2024 17:58:59 -0500 Subject: [PATCH 094/153] [nasa/nos3#226] Updates to use specific nos3-64:20240306 container and various submodules after merges; --- cfg/nos3_defs/targets.cmake | 28 +++++++++++++++------------- components/arducam | 2 +- components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_radio | 2 +- components/generic_reaction_wheel | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- fsw/apps/ci | 2 +- fsw/apps/hwlib | 2 +- fsw/apps/sch | 2 +- fsw/apps/to | 2 +- fsw/cfe | 2 +- fsw/osal | 2 +- scripts/env.sh | 2 +- sims/nos_time_driver | 2 +- sims/sim_common | 2 +- 23 files changed, 37 insertions(+), 35 deletions(-) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 72003adb..97862819 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -103,27 +103,29 @@ list(APPEND MISSION_GLOBAL_APPLIST # # Components # - arducam - generic_adcs - generic_css - generic_eps - generic_fss - generic_imu - generic_mag - generic_reaction_wheel - generic_radio - generic_star_tracker - generic_torquer - novatel_oem615 - sample + arducam/fsw + generic_adcs/fsw + generic_css/fsw + generic_eps/fsw + generic_fss/fsw + generic_imu/fsw + generic_mag/fsw + generic_reaction_wheel/fsw + generic_radio/fsw + generic_star_tracker/fsw + generic_torquer/fsw + novatel_oem615/fsw + sample/fsw ) # Create Application Platform Include List FOREACH(X ${MISSION_GLOBAL_APPLIST}) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/platform_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/public_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/src) ENDFOREACH(X) # FT_INSTALL_SUBDIR indicates where the black box test data files (lua scripts) should diff --git a/components/arducam b/components/arducam index 0b9de156..88e946d5 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit 0b9de1567ed64259d2422f3f864ee0c8ee8a273c +Subproject commit 88e946d54da6e0ed5e2084fd46e8476ff473b3c2 diff --git a/components/generic_adcs b/components/generic_adcs index 0291f5e4..e5f9931b 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 0291f5e4b85acd21a65f9f19a1855939f745b058 +Subproject commit e5f9931bb8332edbddf333d5e2aaa0c3955ca560 diff --git a/components/generic_css b/components/generic_css index 00a2b37b..d9c6f3ec 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit 00a2b37b3687d499eb3038bb0eff97113196b854 +Subproject commit d9c6f3ec9f198436aaac936952934b32598f8a68 diff --git a/components/generic_eps b/components/generic_eps index 956440ac..6eccddc3 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 956440ac7c2862b35197d0bcdbeda6118de9ea52 +Subproject commit 6eccddc35d57368d9ada312158457be7ccd94b00 diff --git a/components/generic_fss b/components/generic_fss index 9baa0448..5bff1273 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit 9baa0448291d641c21e69b466225ee77b1c4c58e +Subproject commit 5bff12731e8c280b8180578bca667b02a01c04ef diff --git a/components/generic_imu b/components/generic_imu index 4de10fb5..66366658 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 4de10fb5e913741c9e7074ff7fa4587876bc87e8 +Subproject commit 6636665872e75220f95394a9cedaa437d0755e16 diff --git a/components/generic_mag b/components/generic_mag index 954e7590..4bea80d9 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit 954e75900bad34de0865a733cbaa3f35eb58d970 +Subproject commit 4bea80d98166e9ea90b1681c89f8f1653da56917 diff --git a/components/generic_radio b/components/generic_radio index ab85deb6..4f6e4565 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit ab85deb6d5b0170669e2255044bb447d2f38c795 +Subproject commit 4f6e45659d99eadd5750c2f4be4c7cae3b572a51 diff --git a/components/generic_reaction_wheel b/components/generic_reaction_wheel index 9eaa9a97..5c25a8b4 160000 --- a/components/generic_reaction_wheel +++ b/components/generic_reaction_wheel @@ -1 +1 @@ -Subproject commit 9eaa9a9731440f266559819174645a4b2c0a1bec +Subproject commit 5c25a8b49a0de2a720d92ec86863f682eba8e192 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index a3a3d65c..077c6919 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit a3a3d65cd684c065b20ae1c6af10584b90d9d798 +Subproject commit 077c691987c6d4eec21e2e96651a6b46ebed1127 diff --git a/components/generic_torquer b/components/generic_torquer index 94947273..854ceaca 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit 94947273ea5fb1b4e54f5115e509ad93b7522275 +Subproject commit 854ceaca8b66d820e2473b933565551994ddfb94 diff --git a/components/novatel_oem615 b/components/novatel_oem615 index c3fbb7fc..1e0b761f 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit c3fbb7fc05f25fbe7d3da3ec154d5d70383839d3 +Subproject commit 1e0b761f07dc6da39f1692a3313b35bd23635d15 diff --git a/components/sample b/components/sample index 77fc6595..03957624 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 77fc6595266525dd14ccf62880e75e3073c566b0 +Subproject commit 0395762428be4369a1da8878d19d80827876921a diff --git a/fsw/apps/ci b/fsw/apps/ci index 1db1c31b..60f15751 160000 --- a/fsw/apps/ci +++ b/fsw/apps/ci @@ -1 +1 @@ -Subproject commit 1db1c31bf22d8feec8761217bbd49207691a4a91 +Subproject commit 60f15751722dc6cc8a77f62f98d9d4f40ead330b diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index 8b9402ed..7f4fc717 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit 8b9402edbd12fbda1fb96415a778e66b66d2a564 +Subproject commit 7f4fc7177f7819d034d237c2a8a26a3cca319a98 diff --git a/fsw/apps/sch b/fsw/apps/sch index 220f962a..3c4af159 160000 --- a/fsw/apps/sch +++ b/fsw/apps/sch @@ -1 +1 @@ -Subproject commit 220f962abd1a69512d29b172fdd57c056b265b9f +Subproject commit 3c4af159bb4032311103332cb50bb752d1b57abe diff --git a/fsw/apps/to b/fsw/apps/to index 5ea7e9ef..42bf2418 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 5ea7e9efdb7062f69c89aa2c1d913cc125c072c7 +Subproject commit 42bf24186615e524a188efb7c067f34e44e75171 diff --git a/fsw/cfe b/fsw/cfe index 6d96c6e8..79c22d9e 160000 --- a/fsw/cfe +++ b/fsw/cfe @@ -1 +1 @@ -Subproject commit 6d96c6e856a654f7c96e66a87b003aa01ff96874 +Subproject commit 79c22d9edfe425f39efc782bb168aefe8db5ddf7 diff --git a/fsw/osal b/fsw/osal index 19a19def..570ad091 160000 --- a/fsw/osal +++ b/fsw/osal @@ -1 +1 @@ -Subproject commit 19a19def07ea0d4f8c00a3071650517d2fe3b858 +Subproject commit 570ad0913daf57ad2a62c92f6a0daef5a94f72ba diff --git a/scripts/env.sh b/scripts/env.sh index 06fad19a..0fb42b28 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,7 +40,7 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -DBOX="ivvitc/nos3-64:latest" +DBOX="ivvitc/nos3-64:20240306" # Debugging #echo "Script directory = " $SCRIPT_DIR diff --git a/sims/nos_time_driver b/sims/nos_time_driver index 13a30e82..da2d3b09 160000 --- a/sims/nos_time_driver +++ b/sims/nos_time_driver @@ -1 +1 @@ -Subproject commit 13a30e8278d5f64e9cb70d3b86e234a2d499590d +Subproject commit da2d3b09c2b1868090b99fbf2507fd24f04043a7 diff --git a/sims/sim_common b/sims/sim_common index e005f237..5c804f64 160000 --- a/sims/sim_common +++ b/sims/sim_common @@ -1 +1 @@ -Subproject commit e005f237803cd0081800f3018780b53366953ec3 +Subproject commit 5c804f64834e41f02c0660275daca9778f065c24 From 065dc8f9abd6baa0c69e996a3f7d09d5004162e1 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 6 Mar 2024 18:25:12 -0500 Subject: [PATCH 095/153] [nasa/nos3#226] Updates to build 64-bit after merge issue and resolved syn submodule; --- cfg/nos3_defs/targets.cmake | 2 +- components/syn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index 448f8deb..ddc442dd 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -140,7 +140,7 @@ SET(MISSION_CPUNAMES cpu1) SET(cpu1_PROCESSORID 1) SET(cpu1_APPLIST) # Note: Using all ${MISSION_GLOBAL_APPLIST} automatically SET(cpu1_FILELIST cfe_es_startup.scr) -SET(cpu1_SYSTEM i386-linux-gnu) +SET(cpu1_SYSTEM amd64-linux-gnu) # USER Supplied #SET(cpu2_PROCESSORID 2) diff --git a/components/syn b/components/syn index 22f30d3f..eb48367d 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 22f30d3fca8dd9db7780be0f3d155358ab684a98 +Subproject commit eb48367d575d65a070661bc6142d29ed5de1de70 From ee715fdba5a982c1dd5d03f235cf3bc7a35c9e97 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 6 Mar 2024 19:30:07 -0500 Subject: [PATCH 096/153] [nasa/nos3#264] Added configure check for openc3 vs. cosmos, confirmed openc3 still functional; --- Makefile | 2 +- cfg/nos3-mission.xml | 1 + scripts/configure.py | 23 +++++++++++++++++- scripts/docker_launch.sh | 10 ++------ scripts/{gsw.sh => gsw_cosmos_build.sh} | 2 +- scripts/gsw_cosmos_launch.sh | 23 ++++++++++++++++++ ...eate_cosmos_gem.sh => gsw_openc3_build.sh} | 2 +- scripts/gsw_openc3_launch.sh | 24 +++++++++++++++++++ 8 files changed, 75 insertions(+), 12 deletions(-) rename scripts/{gsw.sh => gsw_cosmos_build.sh} (85%) mode change 100755 => 100644 create mode 100644 scripts/gsw_cosmos_launch.sh rename scripts/{create_cosmos_gem.sh => gsw_openc3_build.sh} (97%) mode change 100755 => 100644 create mode 100644 scripts/gsw_openc3_launch.sh diff --git a/Makefile b/Makefile index 2eb5fdc4..0852ced2 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ fsw: ./scripts/docker_build_fsw.sh gsw: - ./scripts/create_cosmos_gem.sh + ./cfg/build/gsw_build.sh launch: ./scripts/docker_launch.sh diff --git a/cfg/nos3-mission.xml b/cfg/nos3-mission.xml index 1216ec61..351c9081 100644 --- a/cfg/nos3-mission.xml +++ b/cfg/nos3-mission.xml @@ -1,5 +1,6 @@ 814048200.0 + openc3 1 sc-full-config.xml + - prox @@ -540,8 +541,8 @@ GENERIC_IMU_42_PROVIDER fortytwo 4280 - 20 - 5 + 30 + 1 0 @@ -567,8 +568,8 @@ GENERIC_MAG_42_PROVIDER fortytwo 4234 - 20 - 5 + 30 + 1 0
@@ -594,8 +595,8 @@ GENERIC_STAR_TRACKER_42_PROVIDER fortytwo 4282 - 20 - 5 + 30 + 1 0 0 diff --git a/components/cryptolib b/components/cryptolib index 9fe8788c..174e896c 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit 9fe8788cb487e5d883f4c8db68b607197cdc089f +Subproject commit 174e896c0f1587f4b4a0b0ed21d567a6ba2496d6 diff --git a/gsw/cosmos b/gsw/cosmos index 3b229c95..979bbf4d 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 3b229c951b122320c7b0ac6618cc9e7c25ba3c07 +Subproject commit 979bbf4d73e60e4a69ef310b6567524bae78d2a7 diff --git a/scripts/docker_build_cryptolib.sh b/scripts/docker_build_cryptolib.sh new file mode 100644 index 00000000..63126da2 --- /dev/null +++ b/scripts/docker_build_cryptolib.sh @@ -0,0 +1,31 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + +# Check that configure build directory exists +if [ ! -d $BASE_DIR/cfg/build ]; then + echo "" + echo " Need to run make config first!" + echo "" + exit 1 +fi + +# Make ground software build directory +mkdir -p $BASE_DIR/gsw/build + +# Build +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_cryptolib" -w $BASE_DIR $DBOX make -j$NUM_CPUS build-cryptolib diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 5243c866..1eb1eb05 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -127,8 +127,7 @@ do gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim - # Note: Can keep open if desired after a new gnome-profile is manually created - #gnome-terminal --window-with-profile=KeepOpen --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim + gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone echo "" done diff --git a/scripts/env.sh b/scripts/env.sh index 0fb42b28..6bf3791a 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,7 +40,7 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -DBOX="ivvitc/nos3-64:20240306" +DBOX="ivvitc/nos3-64:dev" # Debugging #echo "Script directory = " $SCRIPT_DIR From a53e01d3897af21c30dbfd1d069e60e4e6e6f903 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Mar 2024 08:29:25 -0400 Subject: [PATCH 108/153] [nasa/nos3#204] Added additional enable_TO_and_verify() function prior to each CFDP test and included rm /tmp/nos3 in the make clean-gsw command; --- Makefile | 1 + gsw/cosmos | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0852ced2..c8c74906 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,7 @@ clean-sim: clean-gsw: rm -rf gsw/cosmos/build + rm -rf /tmp/nos3 config: ./scripts/config.sh diff --git a/gsw/cosmos b/gsw/cosmos index 3b229c95..4f239cae 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 3b229c951b122320c7b0ac6618cc9e7c25ba3c07 +Subproject commit 4f239caed384a689693d191ebaaf83ab2811d5ff From 0eefab48b372e90d18b442910e75e3c0172f8091 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Mar 2024 08:48:59 -0400 Subject: [PATCH 109/153] [nasa/nos3#263] Updated the syn submodule after merge requests; --- components/syn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/syn b/components/syn index 0d5d7b0e..dcf625c3 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit 0d5d7b0e22e59ebe12c67833e003fbf1e3511a79 +Subproject commit dcf625c30879d129aaa25a36789cf676cce59973 From 5f75da352e8662b8bbecadb9987d47ca295ef904 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Mar 2024 09:05:33 -0400 Subject: [PATCH 110/153] [nasa/nos3#207] Updated the prepare.sh script to use the nos3-main branch after merge request; --- scripts/prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prepare.sh b/scripts/prepare.sh index 76de2deb..ac9cf8a1 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -34,7 +34,7 @@ echo "" echo "Prepare 42..." cd $USER_NOS3_DIR -git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3#207 +git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main cd $USER_NOS3_DIR/42 $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make echo "" From 19beabd79c04d9199f0738ac795a5ad574ecbb2a Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Mar 2024 19:47:13 -0400 Subject: [PATCH 111/153] [nasa/nos3#204] Updates after submodule merge requests; --- fsw/apps/cf | 2 +- fsw/apps/ci | 2 +- fsw/apps/fm | 2 +- gsw/cosmos | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fsw/apps/cf b/fsw/apps/cf index d431880e..13e98e12 160000 --- a/fsw/apps/cf +++ b/fsw/apps/cf @@ -1 +1 @@ -Subproject commit d431880e28045bba6f27c8f4a0ad48869ceb1145 +Subproject commit 13e98e12e565b90f577537ec1be3ad4557178fe8 diff --git a/fsw/apps/ci b/fsw/apps/ci index 10c30a77..285dcb4d 160000 --- a/fsw/apps/ci +++ b/fsw/apps/ci @@ -1 +1 @@ -Subproject commit 10c30a772c718bc38f3f522fcab137135603e61c +Subproject commit 285dcb4dfe7cce82d5d5846d78d920e06805a75c diff --git a/fsw/apps/fm b/fsw/apps/fm index 464ea617..e7410e59 160000 --- a/fsw/apps/fm +++ b/fsw/apps/fm @@ -1 +1 @@ -Subproject commit 464ea6170ea7b40140649d028afb4101519489a0 +Subproject commit e7410e593f12f05a834c646ea8241e4c98c2a4a3 diff --git a/gsw/cosmos b/gsw/cosmos index 4f239cae..1f388ad5 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 4f239caed384a689693d191ebaaf83ab2811d5ff +Subproject commit 1f388ad56475e541265aeb3c98a702355d71107c From 0c956283f9a9edb5a36fc963132444e98fa9068d Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 19 Mar 2024 20:05:56 -0400 Subject: [PATCH 112/153] [nasa/nos3#251] Updates after submodule merges; --- components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_radio | 2 +- components/generic_reaction_wheel | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- gsw/cosmos | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/generic_adcs b/components/generic_adcs index 23fef334..2755e61e 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 23fef334ded0da354a0198643ed3656edc2af735 +Subproject commit 2755e61e66d847aada2bce545e537ea5606d9e27 diff --git a/components/generic_css b/components/generic_css index 054d983d..1bbba058 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit 054d983d3995dfcecc421819cf9a8de4251eeaaf +Subproject commit 1bbba058117e2c8a3bf17229a1102eab7a67bee4 diff --git a/components/generic_eps b/components/generic_eps index 29a7b7cd..2c6d147e 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 29a7b7cd613797bfdbb32a2c657f80899e1c82c8 +Subproject commit 2c6d147eb6b7c4b6e43298ff8c4d743da9002d38 diff --git a/components/generic_fss b/components/generic_fss index 701208f9..a20aaa5f 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit 701208f95dbfc289ca77f29d5b934558c839a1da +Subproject commit a20aaa5f0a4bd3c6ed9b76e088a172ac17f05847 diff --git a/components/generic_imu b/components/generic_imu index efcff32e..6d1058e3 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit efcff32ec91e19a654ea6fb9aaf47307bbbebbaf +Subproject commit 6d1058e370f09ead713f03a8cee10d308549059c diff --git a/components/generic_mag b/components/generic_mag index 54e4c687..a67fdade 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit 54e4c687e0ab8ce14b5308876f5882536e748f44 +Subproject commit a67fdadea4663bebc308d88c974438c677aab8ba diff --git a/components/generic_radio b/components/generic_radio index 9c6484bc..f721f9b7 160000 --- a/components/generic_radio +++ b/components/generic_radio @@ -1 +1 @@ -Subproject commit 9c6484bc77457e61a3f2995a0afdb6a79ef25d85 +Subproject commit f721f9b7a838d03fc5c4498316e1743ff1c455c8 diff --git a/components/generic_reaction_wheel b/components/generic_reaction_wheel index 502b59eb..838cc687 160000 --- a/components/generic_reaction_wheel +++ b/components/generic_reaction_wheel @@ -1 +1 @@ -Subproject commit 502b59ebd81a6c412b07d3b9fbf66286575e4d9d +Subproject commit 838cc687594bb77a5fa456c593c77c73edb7bf69 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index de163a6b..6fb52ab3 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit de163a6b6c7e515c05b695e9fd5eeb38f5b1e2ff +Subproject commit 6fb52ab329c5ca783dcff2b904da1a3b3e19c876 diff --git a/components/generic_torquer b/components/generic_torquer index ae8ceded..fda1fb7c 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit ae8ceded3677a71d6711b6ef32227525bb5ec56f +Subproject commit fda1fb7c323b5e66707e4c7acd8cc45d6213654f diff --git a/components/novatel_oem615 b/components/novatel_oem615 index 2036e729..8d526247 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit 2036e7291a5e1ea1e26f14f4c13df1a7bd092fa1 +Subproject commit 8d526247d049ba1ec45f0eb108daff7f9e8e8003 diff --git a/components/sample b/components/sample index 63a053be..5382e509 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 63a053beb3ab647639ec1d0b6a20bd961cad0548 +Subproject commit 5382e5097253ed661f715caf6d9f046087454c3c diff --git a/gsw/cosmos b/gsw/cosmos index 93efa443..7cdfad92 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 93efa44324eb134d48c92e20c7fd4ae6bc1629dd +Subproject commit 7cdfad92bafdebadc5b415e1b4ef323f2790dda7 From 73e2c3712b3811328af28447ac3b1f4430f44a41 Mon Sep 17 00:00:00 2001 From: Kevin Bruce <77984549+kevincbruce@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:45:51 -0400 Subject: [PATCH 113/153] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43404dbe..a2db7360 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Each of the applications listed below are required prior to performing the insta 3. Clone the submodules `git submodule update --init --recursive` 4. Run `vagrant up` and wait to return to a prompt - This can take anywhere from a few minutes to hours depending on internet speeds and host PC specs +_It may also be wise at around this stage to shutdown the VM once it starts and to allocate it more resources if possible, preferably at least 4 cores and 8 GB of RAM, preferably more._ 5. In VirtualBox `Devices > Upgrade Guest Additions...` - Wait for this to complete 6. Run `vagrant reload` to finish the upgrade @@ -45,7 +46,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/jsta ### Directory Layout * `components` contains the repositories for the hardware component apps - /fsw - cFS application - - /gsw - OpenC3 COSMOS database + - /gsw - OpenC3 (or Ball Aerospace) COSMOS database - /sim - NOS3 simulator - /support - Optional folder containing a standalone checkout application * `fsw` contains the repositories needed to build cFS FSW @@ -56,7 +57,7 @@ By default the nos3 repository is shared into the virtual machine at `/home/jsta - /psp - platform support package (PSP), enables use on multiple types of boards - /tools - standard cFS provided tools * `gsw` contains the nos3 ground station files, and other ground based tools - - /cosmos - OpenC3 COSMOS files + - /cosmos - OpenC3 (or Ball Aerospace) COSMOS files - /OrbitInviewPowerPrediction - OIPP tool for operators - /scripts - convenience scripts * `sims` contains the nos3 simulators and configuration files From 69db2833123ad4279dfc339a36daa5c764c01ef3 Mon Sep 17 00:00:00 2001 From: Kevin Bruce <77984549+kevincbruce@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:47:57 -0400 Subject: [PATCH 114/153] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2db7360..ac21e10f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Each of the applications listed below are required prior to performing the insta 3. Clone the submodules `git submodule update --init --recursive` 4. Run `vagrant up` and wait to return to a prompt - This can take anywhere from a few minutes to hours depending on internet speeds and host PC specs -_It may also be wise at around this stage to shutdown the VM once it starts and to allocate it more resources if possible, preferably at least 4 cores and 8 GB of RAM, preferably more._ +_It may also be wise at around this stage to shutdown the VM once it starts and to allocate it more resources if possible, preferably at least 4 cores and 8 GB of RAM, preferably 8 cores and 16 GB of RAM._ 5. In VirtualBox `Devices > Upgrade Guest Additions...` - Wait for this to complete 6. Run `vagrant reload` to finish the upgrade From b4d2f4dd01f5676b0a87bfdc26abc201b55a450c Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 27 Mar 2024 08:49:01 -0400 Subject: [PATCH 115/153] [nasa/nos3#202] TC clear and encrypted working again after submodule updates, disabled debug CI prints; --- components/cryptolib | 2 +- fsw/apps/ci | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/cryptolib b/components/cryptolib index 174e896c..56e99b94 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit 174e896c0f1587f4b4a0b0ed21d567a6ba2496d6 +Subproject commit 56e99b94ed9eba44b812a0b1279b584641fe1c5a diff --git a/fsw/apps/ci b/fsw/apps/ci index 10c30a77..153db705 160000 --- a/fsw/apps/ci +++ b/fsw/apps/ci @@ -1 +1 @@ -Subproject commit 10c30a772c718bc38f3f522fcab137135603e61c +Subproject commit 153db705202edec3391c7b0dab11be0cd9cb128d From e90175c8ee3bbafc8a6635c752f078f4a1c23a4e Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 28 Mar 2024 10:54:40 -0400 Subject: [PATCH 116/153] [nasa/nos3#202] Updates in attempt to get both TC and TM initialized - failing still; --- cfg/nos3_defs/cpu1_cfe_es_startup.scr | 2 +- components/cryptolib | 2 +- fsw/apps/io_lib | 2 +- fsw/apps/to | 2 +- gsw/cosmos | 2 +- scripts/docker_launch.sh | 7 ++++--- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index 2b1520f7..7a21cddb 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -1,6 +1,6 @@ +CFE_LIB, crypto, Crypto_SC_Init, CRYPTO, 0, 0, 0x0, 0; CFE_LIB, hwlib, hwlib_Init, HW_LIB, 0, 0, 0x0, 0; CFE_LIB, io_lib, IO_LibInit, IO_LIB, 0, 0, 0x0, 0; -CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; CFE_APP, sch, SCH_AppMain, SCH, 40, 16384, 0x0, 0; CFE_APP, ci, CI_AppMain, CI, 41, 16384, 0x0, 0; diff --git a/components/cryptolib b/components/cryptolib index 56e99b94..a344ffdd 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit 56e99b94ed9eba44b812a0b1279b584641fe1c5a +Subproject commit a344ffdd75c3275c756688da38fa73e303d1e518 diff --git a/fsw/apps/io_lib b/fsw/apps/io_lib index 31a03167..92cf7e1e 160000 --- a/fsw/apps/io_lib +++ b/fsw/apps/io_lib @@ -1 +1 @@ -Subproject commit 31a0316787506cc664c4771f4f61cf6030351afb +Subproject commit 92cf7e1eed42205365992c3a988438f0a8051b77 diff --git a/fsw/apps/to b/fsw/apps/to index 42bf2418..28aaae22 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 42bf24186615e524a188efb7c067f34e44e75171 +Subproject commit 28aaae22688c442cdb15de99dd9670ff4eae1108 diff --git a/gsw/cosmos b/gsw/cosmos index 979bbf4d..5daf14f4 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 979bbf4d73e60e4a69ef310b6567524bae78d2a7 +Subproject commit 5daf14f454f5da88b9d7b4b6599378526b78b931 diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 1eb1eb05..a5a8cc19 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -85,6 +85,10 @@ do $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos echo "" + echo $SC_NUM " - CryptoLib..." + gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone + echo "" + echo $SC_NUM " - 42..." rm -rf $USER_NOS3_DIR/42/NOS3InOut cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut @@ -126,9 +130,6 @@ do gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim - - gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone - echo "" done echo "NOS Time Driver..." From 35c8c9fdf7d32050e264bd0309b5486e45353650 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 2 Apr 2024 15:52:51 -0400 Subject: [PATCH 117/153] [nos3#202] Debugging TM clear mode now; --- components/cryptolib | 2 +- fsw/apps/io_lib | 2 +- fsw/apps/to | 2 +- gsw/cosmos | 2 +- scripts/docker_launch.sh | 9 +++++---- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/components/cryptolib b/components/cryptolib index a344ffdd..30e457d6 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit a344ffdd75c3275c756688da38fa73e303d1e518 +Subproject commit 30e457d62bdbc561f622a8d620121e4fd556af30 diff --git a/fsw/apps/io_lib b/fsw/apps/io_lib index 92cf7e1e..f9c841b4 160000 --- a/fsw/apps/io_lib +++ b/fsw/apps/io_lib @@ -1 +1 @@ -Subproject commit 92cf7e1eed42205365992c3a988438f0a8051b77 +Subproject commit f9c841b42dec4b485cb02dbf5a682e974461606c diff --git a/fsw/apps/to b/fsw/apps/to index 28aaae22..5741c305 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 28aaae22688c442cdb15de99dd9670ff4eae1108 +Subproject commit 5741c3051b3ee0ccea0526bba7482d7cefe10a5f diff --git a/gsw/cosmos b/gsw/cosmos index 5daf14f4..fd47c51d 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit 5daf14f454f5da88b9d7b4b6599378526b78b931 +Subproject commit fd47c51da784167318bee3a2bc8533ab11628a03 diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index a5a8cc19..38149b8a 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -85,10 +85,6 @@ do $DNETWORK connect $SC_NETNAME cosmos_openc3-operator_1 --alias cosmos echo "" - echo $SC_NUM " - CryptoLib..." - gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone - echo "" - echo $SC_NUM " - 42..." rm -rf $USER_NOS3_DIR/42/NOS3InOut cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut @@ -105,6 +101,10 @@ do # Debugging # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually + echo $SC_NUM " - CryptoLib..." + gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone + echo "" + echo $SC_NUM " - Simulators..." cd $SIM_BIN gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN $DBOX /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json @@ -130,6 +130,7 @@ do gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim + echo "" done echo "NOS Time Driver..." From 0e98f8543793a51d1089f7cf1c758a6ce0d938d2 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 4 Apr 2024 16:34:59 +0000 Subject: [PATCH 118/153] Added .gitignore file --- cfg/gui/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 cfg/gui/.gitignore diff --git a/cfg/gui/.gitignore b/cfg/gui/.gitignore new file mode 100644 index 00000000..cb8a7669 --- /dev/null +++ b/cfg/gui/.gitignore @@ -0,0 +1,3 @@ +*.ui +*.ui.* +__pycache__ \ No newline at end of file From 8263e9bc7db72939f620301375aef57ff8fe65c3 Mon Sep 17 00:00:00 2001 From: Ice Date: Thu, 11 Apr 2024 10:56:53 -0400 Subject: [PATCH 119/153] QOL and Bug Fixes --- cfg/gui/cfg_gui_main.py | 119 ++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 30 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index c52c629e..67722e05 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -1,5 +1,5 @@ from pathlib import Path -from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout +from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout, QMessageBox from PySide6.QtCore import QProcess, QDateTime from PySide6.QtGui import QTextCharFormat @@ -8,6 +8,10 @@ from cfg_gui_ui import Ui_Form + +# TODO: Update master xml sc-x-cfg filename if modified in sc config (in progress) + + class cfg_gui(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -17,8 +21,9 @@ def __init__(self, *args, **kwargs): self.setFixedSize(655, 655) self.setWindowTitle("NOS3 Igniter - Version 0.0.1") + # globals self.dateTimeEdit = QDateTimeEdit() - self.scConfigs = {} # Stores child configs {'filename' : "filetext"} + self.scConfigs = {} # Stores child configs {'index' : "filetext"} self.prevButtonPressed = None # Tracks the last button pressed, used in buttonColor() self.defaultStyleSheet = self.ui.pushButton_buildAll.styleSheet() # Saves default stylesheet to return button color to normal, buttonColor() self.setup = 0 # Allows for switchConfig() to initially be called without calling saveText() @@ -64,22 +69,32 @@ def run_ForUntil(self): self.dateTimeEdit.setMinimumDateTime(QDateTime(self.currentTime.year, self.currentTime.month, self.currentTime.day, self.currentTime.hour, self.currentTime.minute, self.currentTime.second, 0, 0)) self.ui.horizontalLayout_runForUntil.insertWidget(1, self.dateTimeEdit) - # Overwrites the currently saved text for the currently selected spacecraft config when edited + # Updates the currently saved xml dictionary (not actual xml file) for the currently selected spacecraft config when edited. TODO: change name of function def saveText(self, layout:QLayout, config_value:int): - child = self.scConfigs[config_value] - text = child + text = self.scConfigs[config_value] filename = text.split('\n')[0] - childXml = text.split('\n', 2)[2] - childXml = xmltodict.parse(childXml) + childXml = xmltodict.parse(text.split('\n', 2)[2]) + # TODO: change to dynamically pull apps/components from xml file or directory applications = ['cf', 'ds', 'fm', 'lc', 'sc'] components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'torquer'] i = 0 while layout.itemAt(i) != None: widget = layout.itemAt(i).widget() - if isinstance(widget, QCheckBox): - #print(child.text()) + + # Handle filename + if isinstance(widget, QTextEdit): + widget:QTextEdit + filename = widget.toPlainText() + if "Filename:" not in filename: + filename = f'Filename: {filename}' + if "Filename: " not in filename: + filename = f'Filename: {filename.split(":")[1]}' + + # Handle checkboxes + elif isinstance(widget, QCheckBox): + widget:QCheckBox text = widget.text().split(' ')[0] if text in applications: childXml['sc-1-config']['applications'][text]['enable'] = str(widget.isChecked()).lower() @@ -87,10 +102,14 @@ def saveText(self, layout:QLayout, config_value:int): childXml['sc-1-config']['components'][text]['enable'] = str(widget.isChecked()).lower() elif text == 'gui': childXml['sc-1-config'][text]['enable'] = str(widget.isChecked()).lower() + + # Handle orbits elif isinstance(widget, QDoubleSpinBox): - #print(child.prefix()) + widget:QDoubleSpinBox prefix = widget.prefix().split(' ')[0] childXml['sc-1-config']['orbit'][prefix] = str(widget.value()) + + # Increment index i += 1 combined = filename + '\n\n' + xmltodict.unparse(childXml) @@ -101,7 +120,7 @@ def saveXML(self, saveType:str): # saveType = "save" (overwrite) or "saveAs" (new) if saveType == "saveAs": - savePath, _ = QFileDialog.getSaveFileName(None, 'Directory', './cfg/custom') + savePath, _ = QFileDialog.getSaveFileName(None, 'Directory', './cfg') elif saveType == "save": savePath = self.config_path @@ -109,7 +128,7 @@ def saveXML(self, saveType:str): masterXml = xmltodict.parse(self.ui.textEdit_masterConfig.toPlainText()) self.convert2xml(masterXml, savePath) - # TODO: Now handle children, currently placeholder until checkboxes are added (update in progress) + # Now handle children self.saveText(self.layout_, self.ui.spinBox_configNumber.value()-1) for child in self.scConfigs: @@ -121,6 +140,8 @@ def saveXML(self, saveType:str): # save under same directory as masterXml using filename parsed from textEdit self.convert2xml(childXml, savePath.rsplit('/', 1)[0]+f'/{filename}') + self.reloadConfig(self.config_path) + # Loads the child config into the Spacecraft Config textbox def switchConfig(self, value:int): # value : index of spacecraft config in the order listed in the master XML @@ -130,8 +151,10 @@ def switchConfig(self, value:int): if self.setup == 1: self.saveText(self.layout_, self.configNumTrack) self.configNumTrack = value-1 + else: + self.setup = 1 - self.setup = 1 + # setup layout to add item to self.ui.scrollArea.setWidgetResizable(True) self.ui.scrollAreaWidgetContents.setLayout(QVBoxLayout().layout()) self.layout_ = self.ui.scrollAreaWidgetContents.layout() @@ -141,21 +164,22 @@ def switchConfig(self, value:int): while self.layout_.itemAt(0) != None: child = self.layout_.itemAt(0).widget().setParent(None) - + # Now parse the xml and convert to widgets value = value-1 if value in self.scConfigs: fileName = self.scConfigs[value].split('\n')[0] childXML = self.scConfigs[value].split('\n')[2::] childXML = ''.join(childXML) childDict = xmltodict.parse(childXML) - - policy = self.ui.scrollAreaWidgetContents.sizePolicy() + # child = sc-xxx-cfg for child in childDict: - configTag = QLabel() + configTag = QTextEdit() configTag.setText((fileName)) - configTag.setMinimumHeight(18) + configTag.setMinimumHeight(30) self.layout_.addWidget(configTag) + + # child2 = applications | components | gui | orbit for child2 in childDict[child]: tag = QLabel() tag.setText(child2.upper()+": ") @@ -164,7 +188,10 @@ def switchConfig(self, value:int): tag.setFont(format.font()) tag.setMinimumHeight(18) self.layout_.addWidget(tag) + if child2 in ['applications', 'components']: + + # child 3 = cf | ds | ... | adcs | cam | ... for child3 in childDict[child][child2]: enableTag = QCheckBox() enableTag.setText(child3 + " enable ") @@ -172,12 +199,16 @@ def switchConfig(self, value:int): enableTag.setMinimumHeight(18) enableTag.sizePolicy().setVerticalPolicy(QSizePolicy.Expanding) self.layout_.addWidget(enableTag) + elif child2 == 'gui': enableTag = QCheckBox() enableTag.setText(child2 + " enable ") enableTag.setChecked(childDict[child][child2]['enable'] == 'true') self.layout_.addWidget(enableTag) + elif child2 == 'orbit': + + # child3 = tipoff_x/y/z for child3 in childDict[child][child2]: orbitSpinBox = QDoubleSpinBox() orbitSpinBox.setMinimum(-99.00) @@ -186,12 +217,13 @@ def switchConfig(self, value:int): orbitSpinBox.setPrefix(f'{child3} = ') self.layout_.addWidget(orbitSpinBox) else: + # No SC configs in master XML file, or selected a SC XML as master tag = QLabel() tag.setText("*ERROR*\n\nMake sure you chose a master configuration file\n\n*ERROR*") self.layout_.addWidget(tag) # Converts a dictionary to XML file, saved under the given filename/path - def convert2xml(self, attrDict:dict, fileName:[str, Path]): + def convert2xml(self, attrDict:dict, fileName:str): # ensure file is saved as xml if fileName[-4::] != ".xml": fileName += ".xml" @@ -203,39 +235,63 @@ def convert2xml(self, attrDict:dict, fileName:[str, Path]): # Opens file selection menu and calls parseXML() on the selected file def browseConfig(self): + + # Clear SC Config window when selecting a new master config + if "layout_" in self.__dict__: + while self.layout_.itemAt(0) != None: + self.layout_.itemAt(0).widget().setParent(None) + self.config_path, _ = QFileDialog.getOpenFileName(None, 'File', './cfg', "XML Files [ *.xml ]") if self.config_path != "": self.config_name = self.config_path.split("/")[-1] self.ui.lineEdit_curConfig.setText(self.config_name) self.parseXml(self.config_path) + # Reloads the whole config after clicking save, allows you to change "sc-x-cfg" xml file + def reloadConfig(self, config_path): + if "layout_" in self.__dict__: + while self.layout_.itemAt(0) != None: + self.layout_.itemAt(0).widget().setParent(None) + + if config_path != "": + config_name = config_path.split("/")[-1] + self.ui.lineEdit_curConfig.setText(config_name) + self.parseXml(config_path) + + self.ui.spinBox_configNumber.setValue(1) + # Parses Master and child XML files from the given file, updates text boxes accordingly def parseXml(self, config_path): - # Master + # Read Master with open(config_path, 'r') as f: self.ui.textEdit_masterConfig.setText(f.read()) f.close() + # Parse number of SC and SC filenames from master i = 1 + self.sc_cfg_files = [] childDict = {} - root = ET.parse(config_path).getroot() - for child in root: + self.master_root = ET.parse(config_path).getroot() + for child in self.master_root: if child.tag == "number-spacecraft": self.ui.spinBox_configNumber.setMaximum(int(child.text)) if re.match("sc-[0-9]+-cfg", child.tag): childDict[child.tag] = child.text + + # Check for duplicate xml's + if child.text in self.sc_cfg_files: + QMessageBox.critical(self, "Error", "Using duplicate Spacecraft Config Files, Changes will not be saved correctly") + print("Duplicate SC Config file") + + self.sc_cfg_files.append(child.text) i+=1 - # Children + # Read Children config_dir = str(config_path.rsplit('/', 1)[0]) for i, child in enumerate(childDict): if Path(f'{config_dir}/{childDict[child]}').is_file(): filePath = f'{config_dir}/{childDict[child]}' - elif Path(f'./cfg/{childDict[child]}').is_file(): - filePath = f'./cfg/{childDict[child]}' - elif Path(f'./cfg/custom/{childDict[child]}').is_file(): - filePath = f'./cfg/custom/{childDict[child]}' else: raise FileNotFoundError(childDict[child]) @@ -243,7 +299,7 @@ def parseXml(self, config_path): self.scConfigs[i] = f'Filename: {childDict[child]}\n\n{f.read()}' f.close() - # Update Spacecraft Config Text + # Update Spacecraft Config Text to first SC config listed in master config self.switchConfig(1) # Starts a Bash process to execute args, redirects output to given textbox, not used for now @@ -285,7 +341,10 @@ def clean(self, software:str, button:QPushButton): # Placeholder build command, assumes make prep already ran, same with clean commands def build(self, software:str, button:QPushButton): textbox = self.ui.textEdit_buildConsole - command = f'make {software}' + if software == 'all': + command = f'make' + else: + command = f'make {software}' self.buttonColor(button) t1 = threading.Thread(target=self.thread_Bash(textbox, button, command), name='t1') @@ -297,7 +356,7 @@ def thread_Bash(self, textbox:QTextEdit, button:QPushButton, command:str): self.gnome_terminal(textbox, command) self.enableButtons(button) - # Changes the color of the most recently pressed button to green + # Changes the color of the most recently pressed button to green and the last pressed button to default def buttonColor(self, button:QPushButton): if self.prevButtonPressed is not None: self.prevButtonPressed.setStyleSheet(self.defaultStyleSheet) From 9e774bfe6cda854f7e503aa213a36de966ee53ca Mon Sep 17 00:00:00 2001 From: Ice Date: Thu, 11 Apr 2024 14:49:03 -0400 Subject: [PATCH 120/153] Removed Bash Process function and calls to it --- cfg/gui/cfg_gui_main.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 67722e05..84e99fe1 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -46,9 +46,9 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_simClean.clicked.connect(lambda: self.clean("sim", self.ui.pushButton_simClean)) # Launch Tab - self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) + #self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) self.ui.pushButton_stop.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make stop")) - self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) + #self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) self.ui.pushButton_launch.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make launch")) self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) @@ -303,20 +303,20 @@ def parseXml(self, config_path): self.switchConfig(1) # Starts a Bash process to execute args, redirects output to given textbox, not used for now - def startBashProcess(self, textbox:QTextEdit, args:list): - process = QProcess() - process.start("bash", [item for item in args]) + #def startBashProcess(self, textbox:QTextEdit, args:list): + #process = QProcess() + #process.start("bash", [item for item in args]) - process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) - process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) + #process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) + #process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) - process.waitForFinished() - process.close() + #process.waitForFinished() + #process.close() # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() def gnome_terminal(self, textbox:QTextEdit, command:str): process = QProcess() - print(command) + #print(command) process.startCommand(f'gnome-terminal -- {command}') process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) From d6ce6a55b24d5d2dd8916e6afaf9f1673d21c308 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Mon, 15 Apr 2024 13:57:46 -0400 Subject: [PATCH 121/153] Modified terminals to stay open after executing command --- cfg/gui/cfg_gui_main.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 84e99fe1..bbf6983f 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -47,8 +47,10 @@ def __init__(self, *args, **kwargs): # Launch Tab #self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) + self.ui.pushButton_play.setDisabled(1) self.ui.pushButton_stop.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make stop")) #self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) + self.ui.pushButton_pause.setDisabled(1) self.ui.pushButton_launch.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make launch")) self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) @@ -77,7 +79,7 @@ def saveText(self, layout:QLayout, config_value:int): # TODO: change to dynamically pull apps/components from xml file or directory applications = ['cf', 'ds', 'fm', 'lc', 'sc'] - components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'torquer'] + components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'syn', 'torquer'] i = 0 while layout.itemAt(i) != None: @@ -302,29 +304,16 @@ def parseXml(self, config_path): # Update Spacecraft Config Text to first SC config listed in master config self.switchConfig(1) - # Starts a Bash process to execute args, redirects output to given textbox, not used for now - #def startBashProcess(self, textbox:QTextEdit, args:list): - #process = QProcess() - #process.start("bash", [item for item in args]) - - #process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) - #process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) - - #process.waitForFinished() - #process.close() - # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() def gnome_terminal(self, textbox:QTextEdit, command:str): process = QProcess() - #print(command) - process.startCommand(f'gnome-terminal -- {command}') + process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; read line" ') process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) process.waitForFinished(msecs=-1) textbox.append(f'>> {command}...') - #process.close() # Placeholder clean command def clean(self, software:str, button:QPushButton): From 75fb4f21d842a97399cb92cc656a2ce88eb88116 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Mon, 15 Apr 2024 14:29:34 -0400 Subject: [PATCH 122/153] Added Igniter to make prep --- scripts/prepare.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/prepare.sh b/scripts/prepare.sh index ac9cf8a1..69bca9e4 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -39,3 +39,10 @@ cd $USER_NOS3_DIR/42 $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make echo "" echo "" + +echo "Prepare Igniter..." +pip3 install pyside6 +cd $BASE_DIR +python3 $BASE_DIR/cfg/gui/cfg_gui_main.py & +echo "" +echo "" From 834edfcef52f10ec2f727750f270cb3f90bbfe9e Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Mon, 15 Apr 2024 14:52:38 -0400 Subject: [PATCH 123/153] Added a 'Done' echo to let you know when the terminal is safe to close --- cfg/gui/cfg_gui_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index bbf6983f..870f2d7e 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -307,7 +307,7 @@ def parseXml(self, config_path): # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() def gnome_terminal(self, textbox:QTextEdit, command:str): process = QProcess() - process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; read line" ') + process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; echo Done; read line" ') process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) From 7796987a2e1149237fbcd1ffd3e24e28a6de82d3 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 18 Apr 2024 09:34:33 -0400 Subject: [PATCH 124/153] [nasa/nos3#279] Updated Igniter Dependencies --- scripts/prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prepare.sh b/scripts/prepare.sh index 69bca9e4..d73ae7b3 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -41,7 +41,7 @@ echo "" echo "" echo "Prepare Igniter..." -pip3 install pyside6 +pip3 install pyside6 xmltodict cd $BASE_DIR python3 $BASE_DIR/cfg/gui/cfg_gui_main.py & echo "" From c5467e2b110d04e69d5391ae2f61cfbd3fe4f079 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 18 Apr 2024 09:41:40 -0400 Subject: [PATCH 125/153] [nasa/nos3#279] Added ability to make igniter --- Makefile | 3 +++ scripts/igniter_launch.sh | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 scripts/igniter_launch.sh diff --git a/Makefile b/Makefile index c8c74906..f449bd85 100644 --- a/Makefile +++ b/Makefile @@ -109,3 +109,6 @@ stop: stop-gsw: ./scripts/stop_gsw.sh + +igniter: + ./scripts/igniter_launch.sh diff --git a/scripts/igniter_launch.sh b/scripts/igniter_launch.sh new file mode 100644 index 00000000..bbe225d1 --- /dev/null +++ b/scripts/igniter_launch.sh @@ -0,0 +1,13 @@ +#!/bin/bash -i +# +# Convenience script for NOS# development + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh +echo "" +echo "" + +cd $BASE_DIR +python3 $BASE_DIR/cfg/gui/cfg_gui_main.py & +echo "" +echo "" \ No newline at end of file From 7e13f23359410955b58cf1139180557ad8e8657f Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 18 Apr 2024 10:32:54 -0400 Subject: [PATCH 126/153] Updated TODO's, Comments --- cfg/gui/cfg_gui_main.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 870f2d7e..e8a30b0c 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -2,15 +2,12 @@ from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout, QMessageBox from PySide6.QtCore import QProcess, QDateTime from PySide6.QtGui import QTextCharFormat - +from cfg_gui_ui import Ui_Form import sys, re, xmltodict, datetime, threading import xml.etree.ElementTree as ET -from cfg_gui_ui import Ui_Form - - # TODO: Update master xml sc-x-cfg filename if modified in sc config (in progress) - +# TODO: disableButtons(), enableButtons() not working as intended due to the gnome-terminal handling the command externally class cfg_gui(QWidget): def __init__(self, *args, **kwargs): @@ -45,7 +42,7 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_gswClean.clicked.connect(lambda: self.clean("gsw", self.ui.pushButton_gswClean)) self.ui.pushButton_simClean.clicked.connect(lambda: self.clean("sim", self.ui.pushButton_simClean)) - # Launch Tab + # Launch Tab (Time Driver controls disabled) #self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) self.ui.pushButton_play.setDisabled(1) self.ui.pushButton_stop.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make stop")) @@ -77,7 +74,7 @@ def saveText(self, layout:QLayout, config_value:int): filename = text.split('\n')[0] childXml = xmltodict.parse(text.split('\n', 2)[2]) - # TODO: change to dynamically pull apps/components from xml file or directory + # TODO: change to dynamically pull apps/components from xml file or directory, but how? applications = ['cf', 'ds', 'fm', 'lc', 'sc'] components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'syn', 'torquer'] @@ -307,6 +304,8 @@ def parseXml(self, config_path): # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() def gnome_terminal(self, textbox:QTextEdit, command:str): process = QProcess() + + # `read line` is to hold the terminal open after execution, allows errors to be seen process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; echo Done; read line" ') process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) @@ -324,7 +323,7 @@ def clean(self, software:str, button:QPushButton): command = f'make clean-{software}' self.buttonColor(button) - t1 = threading.Thread(target=self.thread_Bash(textbox, button, command), name='t1') + t1 = threading.Thread(target=self.thread_gnome(textbox, button, command), name='t1') t1.start() # Placeholder build command, assumes make prep already ran, same with clean commands @@ -336,11 +335,11 @@ def build(self, software:str, button:QPushButton): command = f'make {software}' self.buttonColor(button) - t1 = threading.Thread(target=self.thread_Bash(textbox, button, command), name='t1') + t1 = threading.Thread(target=self.thread_gnome(textbox, button, command), name='t1') t1.start() # Button/Bash function wrapper for threads - def thread_Bash(self, textbox:QTextEdit, button:QPushButton, command:str): + def thread_gnome(self, textbox:QTextEdit, button:QPushButton, command:str): self.disableButtons(button) self.gnome_terminal(textbox, command) self.enableButtons(button) From 2acafb8ed9223a3e4f383813f91143b8c267717f Mon Sep 17 00:00:00 2001 From: Zemerick Date: Sun, 21 Apr 2024 19:24:55 -0400 Subject: [PATCH 127/153] fixed the link to the NASA Contributor's PDF Form --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 951660b3..06078d9e 100644 --- a/README.md +++ b/README.md @@ -59,5 +59,12 @@ This project is licensed under the NOSA (NASA Open Source Agreement) License. # Issues and Features Please report issues and request features on the GitHub tracking system - [NOS3 Issues](https://www.github.com/nasa/nos3/issues). +## Contributions +If you would like to contribute to the repository, please complete this [NASA Form][def] + and submit it to gsfc-softwarerequest@mail.nasa.gov with John.P.Lucas@nasa.gov CC'ed. Next, please create an issue describing the work to be performed noting that you intend to work it, create a related branch, and submit a pull request when ready. When complete, we will review and work to get it integrated. + ## Support If this project interests you or if you have any questions, please feel free to contact any developer directly or email `support@nos3.org`. + + +[def]: https://github.com/nasa/nos3/files/14578604/NOS3_Invd_CLA.pdf "NOS3 NASA Contributor Form PDF" \ No newline at end of file From d06c08ee2f33456b58fc4097f005d18e18a0be7b Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 23 Apr 2024 07:38:41 -0400 Subject: [PATCH 128/153] [nasa/nos3#202] TM clear mode appears functional, but breaks FECF on TC side (cryptolib error -12) once started; --- components/cryptolib | 2 +- fsw/apps/to | 2 +- scripts/docker_launch.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/cryptolib b/components/cryptolib index 30e457d6..f62cf1b4 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit 30e457d62bdbc561f622a8d620121e4fd556af30 +Subproject commit f62cf1b428016cbf33c66fe8875bbb2cff369dd4 diff --git a/fsw/apps/to b/fsw/apps/to index 5741c305..a3b534de 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit 5741c3051b3ee0ccea0526bba7482d7cefe10a5f +Subproject commit a3b534dedd2e212d0eb2a500b2eac67cd30c497a diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 38149b8a..5d1caec7 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -102,7 +102,7 @@ do # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually echo $SC_NUM " - CryptoLib..." - gnome-terminal --window-with-profile=KeepOpen --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone + gnome-terminal --tab --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone echo "" echo $SC_NUM " - Simulators..." From 9280ebf2fb9c367d59d891f7cc6f0fffb9a860ce Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 25 Apr 2024 09:16:38 -0400 Subject: [PATCH 129/153] [nasa/nos3#202] Removed badFECF option in CryptoLib - likely was getting set due to an issue elsewhere; --- components/cryptolib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/cryptolib b/components/cryptolib index f62cf1b4..393b6214 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit f62cf1b428016cbf33c66fe8875bbb2cff369dd4 +Subproject commit 393b621486a5dcd9474065bfb39e88c77099f21f From e2ca5db0acca880de618b296d8d32c204b2c95d0 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 25 Apr 2024 10:06:27 -0400 Subject: [PATCH 130/153] Disabled components that don't currently work --- cfg/gui/cfg_gui_main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index e8a30b0c..ef662a2d 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -49,7 +49,9 @@ def __init__(self, *args, **kwargs): #self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) self.ui.pushButton_pause.setDisabled(1) self.ui.pushButton_launch.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make launch")) - self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) + #self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) + self.ui.comboBox_run.setDisabled(1) + self.ui.lineEdit_secondsEntry.setDisabled(1) # Replaces the textbox on launch tab with a date/time box and vice versa def run_ForUntil(self): From d6330b8eb351c9a5c2a6e7e4a71f269006f0d1d4 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 25 Apr 2024 10:45:48 -0400 Subject: [PATCH 131/153] Added default config to load on start --- cfg/gui/cfg_gui_main.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index ef662a2d..5148400a 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -5,9 +5,10 @@ from cfg_gui_ui import Ui_Form import sys, re, xmltodict, datetime, threading import xml.etree.ElementTree as ET +import os # TODO: Update master xml sc-x-cfg filename if modified in sc config (in progress) -# TODO: disableButtons(), enableButtons() not working as intended due to the gnome-terminal handling the command externally +# TODO: disableButtons(), enableButtons() not working as intended due to the gnome-terminal thread handling the commands externally class cfg_gui(QWidget): def __init__(self, *args, **kwargs): @@ -53,6 +54,9 @@ def __init__(self, *args, **kwargs): self.ui.comboBox_run.setDisabled(1) self.ui.lineEdit_secondsEntry.setDisabled(1) + # Load Default Config + self.reloadConfig(f'{os.path.dirname(os.path.abspath(__file__))}/../nos3-mission.xml') + # Replaces the textbox on launch tab with a date/time box and vice versa def run_ForUntil(self): index = self.ui.comboBox_run.currentIndex() @@ -353,7 +357,7 @@ def buttonColor(self, button:QPushButton): button.setStyleSheet('QPushButton {background-color: green;}') self.prevButtonPressed = button - # Disable build/clean buttons while another is being ran + # Disable build/clean buttons while another is being ran (not working) def disableButtons(self, button:QPushButton): index = self.ui.gridLayout_buildCleanButtons.count()-1 while index >= 0: @@ -362,7 +366,7 @@ def disableButtons(self, button:QPushButton): widget.setDisabled(1) index -= 1 - # Enable build/clean buttons after process is done running + # Enable build/clean buttons after process is done running (not working) def enableButtons(self, button:QPushButton): index = self.ui.gridLayout_buildCleanButtons.count()-1 while index >= 0: From 5f4539247ad316c3deaa710422d437a305856bd2 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 25 Apr 2024 12:13:22 -0400 Subject: [PATCH 132/153] [nasa/nos3#282] Added include APPLICATION_PLATFORM_INC_LIST to the DS CMakeList.txt to allow easy reconfiguration per targets in use for build; --- cfg/nos3_defs/tables/ds_filter_tbl.c | 9 +++++---- fsw/apps/ds | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cfg/nos3_defs/tables/ds_filter_tbl.c b/cfg/nos3_defs/tables/ds_filter_tbl.c index c595d42a..de5a3afd 100644 --- a/cfg/nos3_defs/tables/ds_filter_tbl.c +++ b/cfg/nos3_defs/tables/ds_filter_tbl.c @@ -45,11 +45,12 @@ #include "cfe_msgids.h" #include "ds_msgids.h" +#include "sample_msgids.h" + /* #include "ci_lab_msgids.h" */ /* #include "to_lab_msgids.h" */ /* #include "cs_msgids.h" */ -/* #include "ds_msgids.h" */ /* #include "fm_msgids.h" */ /* #include "hk_msgids.h" */ /* #include "hs_msgids.h" */ @@ -196,11 +197,11 @@ DS_FilterTable_t DS_FilterTable = { {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}}}, /* Packet Index 014 */ - {/* .MessageID = */ CFE_SB_MSGID_RESERVED, + {/* .MessageID = */ CFE_SB_MSGID_WRAP_VALUE(SAMPLE_REQ_HK_MID), /* .Filter = */ {/* File table index, filter type, N, X, O */ - {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, - {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, + {FILE_ALL_APP_HK_PKTS, DS_BY_COUNT, 1, 1, 0}, + {FILE_ALL_APP_TLM_PKTS, DS_BY_COUNT, 1, 1, 0}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}}}, /* Packet Index 015 */ diff --git a/fsw/apps/ds b/fsw/apps/ds index 2a6c6a2d..3f5eeeea 160000 --- a/fsw/apps/ds +++ b/fsw/apps/ds @@ -1 +1 @@ -Subproject commit 2a6c6a2df5b2f00915a06f0a5ac30b9c327c725d +Subproject commit 3f5eeeea37ebcf464945d1d2204f57409beb6ab0 From 6766d1eb28912c9f59434b58efbfae5e32a76718 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Thu, 25 Apr 2024 14:13:54 -0400 Subject: [PATCH 133/153] [nasa/nos3#282] Updated DS submodule after pull request; --- fsw/apps/ds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/apps/ds b/fsw/apps/ds index 3f5eeeea..3f273f6a 160000 --- a/fsw/apps/ds +++ b/fsw/apps/ds @@ -1 +1 @@ -Subproject commit 3f5eeeea37ebcf464945d1d2204f57409beb6ab0 +Subproject commit 3f273f6a552c1fb408b989ac0d78743452d3dbc3 From 03acc1eba83ca34d6d6c6d69341e9fd91909c3da Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 26 Apr 2024 07:24:11 -0400 Subject: [PATCH 134/153] [nasa/nos3#288] Added additional folders to APPLICATION_PLATFORM_INC_LIST and defaulted to using top level *_app.h file for RTS; --- cfg/nos3_defs/tables/sc_rts005.c | 13 +++++++++---- cfg/nos3_defs/targets.cmake | 7 ++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/cfg/nos3_defs/tables/sc_rts005.c b/cfg/nos3_defs/tables/sc_rts005.c index e2da32b8..a1d85837 100644 --- a/cfg/nos3_defs/tables/sc_rts005.c +++ b/cfg/nos3_defs/tables/sc_rts005.c @@ -8,10 +8,9 @@ #include "sc_msg.h" /* defines SC message structures */ /* Command Includes */ -#include "generic_radio_msg.h" -#include "generic_radio_msgids.h" -#include "sample_msg.h" -#include "sample_msgids.h" +#include "cam_app.h" +#include "generic_radio_app.h" +#include "sample_app.h" /* Custom table structure, modify as needed to add desired commands */ typedef struct @@ -20,6 +19,8 @@ typedef struct SAMPLE_Config_cmd_t cmd1; SC_RtsEntryHeader_t hdr2; GENERIC_RADIO_Proximity_cmd_t cmd2; + SC_RtsEntryHeader_t hdr3; + CAM_NoArgsCmd_t cmd3; } SC_RtsStruct005_t; /* Define the union to size the table correctly */ @@ -45,6 +46,10 @@ SC_RtsTable005_t SC_Rts005 = { .cmd2.CmdHeader = CFE_MSG_CMD_HDR_INIT(GENERIC_RADIO_CMD_MID, SC_MEMBER_SIZE(cmd2), GENERIC_RADIO_PROXIMITY_CC, 0x00), .cmd2.SCID = 0, .cmd2.Payload = {0x18, 0xA9, 0xC0, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00}, + + /* 3 - CAM NOOP */ + .hdr3.TimeTag = 1, + .cmd3.CmdHeader = CFE_MSG_CMD_HDR_INIT(CAM_CMD_MID, SC_MEMBER_SIZE(cmd3), CAM_NOOP_CC, 0x00), } }; diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index ddc442dd..26bfe3ae 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -121,12 +121,17 @@ list(APPEND MISSION_GLOBAL_APPLIST # Create Application Platform Include List FOREACH(X ${MISSION_GLOBAL_APPLIST}) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/mission_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/mission_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/public_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/public_inc) - LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/src) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) ENDFOREACH(X) # FT_INSTALL_SUBDIR indicates where the black box test data files (lua scripts) should From c028f2b211ccc011c96d59451c88c5b2b3977d3e Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Fri, 26 Apr 2024 09:58:43 -0400 Subject: [PATCH 135/153] [nasa/nos3#234] Added build config button --- cfg/gui/cfg_gui.ui | 89 ++++++++++++++++-------------- cfg/gui/cfg_gui_main.py | 1 + cfg/gui/cfg_gui_ui.py | 117 +++++++++++++++++++++++----------------- 3 files changed, 118 insertions(+), 89 deletions(-) diff --git a/cfg/gui/cfg_gui.ui b/cfg/gui/cfg_gui.ui index 09550594..51651542 100644 --- a/cfg/gui/cfg_gui.ui +++ b/cfg/gui/cfg_gui.ui @@ -492,10 +492,10 @@ - QTabWidget::Rounded + QTabWidget::TabShape::Rounded - 0 + 1 @@ -511,7 +511,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter true @@ -568,7 +568,7 @@ - + @@ -580,10 +580,10 @@ true - Qt::ScrollBarAlwaysOn + Qt::ScrollBarPolicy::ScrollBarAlwaysOn - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff true @@ -593,8 +593,8 @@ 0 0 - 613 - 297 + 84 + 28 @@ -605,7 +605,7 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint @@ -703,7 +703,7 @@ Console Output - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter false @@ -773,96 +773,103 @@ - 110 + 10 20 - 421 + 641 81 - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised 79 0 - 341 + 561 80 - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised 0 0 - 340 + 561 80 - - + + - FSW + All - + + + + All + + + + FSW - - + + - GSW + CFG - + SIM - + SIM - + GSW - - + + - All + FSW - + - All + GSW @@ -879,10 +886,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -900,7 +907,7 @@ Build - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -917,10 +924,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -938,7 +945,7 @@ Clean - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -1039,7 +1046,7 @@ NOS3 Time Driver - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter false @@ -1141,7 +1148,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 5148400a..07d3650f 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -35,6 +35,7 @@ def __init__(self, *args, **kwargs): # Build Tab self.ui.pushButton_buildAll.clicked.connect(lambda: self.build("all", self.ui.pushButton_buildAll)) + self.ui.pushButton_cfgBuild.clicked.connect(lambda: self.build("config", self.ui.pushButton_cfgBuild)) self.ui.pushButton_fswBuild.clicked.connect(lambda: self.build("fsw", self.ui.pushButton_fswBuild)) self.ui.pushButton_gswBuild.clicked.connect(lambda: self.build("gsw", self.ui.pushButton_gswBuild)) self.ui.pushButton_simBuild.clicked.connect(lambda: self.build("sim", self.ui.pushButton_simBuild)) diff --git a/cfg/gui/cfg_gui_ui.py b/cfg/gui/cfg_gui_ui.py index 913952bb..aac8d2a6 100644 --- a/cfg/gui/cfg_gui_ui.py +++ b/cfg/gui/cfg_gui_ui.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'cfg_gui.ui' ## -## Created by: Qt User Interface Compiler version 6.6.1 +## Created by: Qt User Interface Compiler version 6.7.0 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -16,15 +16,16 @@ QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout, - QGroupBox, QHBoxLayout, QLabel, QLineEdit, - QPushButton, QScrollArea, QSizePolicy, QSpinBox, - QTabWidget, QTextEdit, QVBoxLayout, QWidget) + QGroupBox, QHBoxLayout, QLabel, QLayout, + QLineEdit, QPushButton, QScrollArea, QSizePolicy, + QSpinBox, QTabWidget, QTextEdit, QVBoxLayout, + QWidget) class Ui_Form(object): def setupUi(self, Form): if not Form.objectName(): Form.setObjectName(u"Form") - Form.resize(655, 655) + Form.resize(658, 655) palette = QPalette() brush = QBrush(QColor(0, 0, 0, 255)) brush.setStyle(Qt.SolidPattern) @@ -101,13 +102,13 @@ def setupUi(self, Form): self.tabWidget = QTabWidget(Form) self.tabWidget.setObjectName(u"tabWidget") self.tabWidget.setGeometry(QRect(0, 0, 661, 661)) - self.tabWidget.setTabShape(QTabWidget.Rounded) + self.tabWidget.setTabShape(QTabWidget.TabShape.Rounded) self.tab = QWidget() self.tab.setObjectName(u"tab") self.lineEdit_curConfig = QLineEdit(self.tab) self.lineEdit_curConfig.setObjectName(u"lineEdit_curConfig") self.lineEdit_curConfig.setGeometry(QRect(130, 20, 421, 26)) - self.lineEdit_curConfig.setAlignment(Qt.AlignCenter) + self.lineEdit_curConfig.setAlignment(Qt.AlignmentFlag.AlignCenter) self.lineEdit_curConfig.setReadOnly(True) self.pushButton_browse = QPushButton(self.tab) self.pushButton_browse.setObjectName(u"pushButton_browse") @@ -126,15 +127,29 @@ def setupUi(self, Form): self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) self.scrollArea = QScrollArea(self.horizontalLayoutWidget_6) self.scrollArea.setObjectName(u"scrollArea") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) + self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setAutoFillBackground(True) - self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) - self.scrollArea.setWidgetResizable(False) + self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) + self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 627, 297)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 84, 28)) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth()) + self.scrollAreaWidgetContents.setSizePolicy(sizePolicy1) + self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.verticalLayout_3.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) self.scrollArea.setWidget(self.scrollAreaWidgetContents) - self.horizontalLayout_6.addWidget(self.scrollArea, 0, Qt.AlignTop) + self.horizontalLayout_6.addWidget(self.scrollArea, 0, Qt.AlignmentFlag.AlignTop) self.spinBox_configNumber = QSpinBox(self.groupBox_scConfig) self.spinBox_configNumber.setObjectName(u"spinBox_configNumber") @@ -167,7 +182,7 @@ def setupUi(self, Form): self.groupBox_8 = QGroupBox(self.tab_2) self.groupBox_8.setObjectName(u"groupBox_8") self.groupBox_8.setGeometry(QRect(10, 120, 631, 491)) - self.groupBox_8.setAlignment(Qt.AlignCenter) + self.groupBox_8.setAlignment(Qt.AlignmentFlag.AlignCenter) self.groupBox_8.setFlat(False) self.groupBox_8.setCheckable(False) self.textEdit_buildConsole = QTextEdit(self.groupBox_8) @@ -182,65 +197,70 @@ def setupUi(self, Form): self.textEdit_buildConsole.setReadOnly(True) self.frame_2 = QFrame(self.tab_2) self.frame_2.setObjectName(u"frame_2") - self.frame_2.setGeometry(QRect(110, 20, 421, 81)) - self.frame_2.setFrameShape(QFrame.StyledPanel) - self.frame_2.setFrameShadow(QFrame.Raised) + self.frame_2.setGeometry(QRect(10, 20, 641, 81)) + self.frame_2.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_2.setFrameShadow(QFrame.Shadow.Raised) self.frame = QFrame(self.frame_2) self.frame.setObjectName(u"frame") - self.frame.setGeometry(QRect(79, 0, 341, 80)) - self.frame.setFrameShape(QFrame.StyledPanel) - self.frame.setFrameShadow(QFrame.Raised) + self.frame.setGeometry(QRect(79, 0, 561, 80)) + self.frame.setFrameShape(QFrame.Shape.StyledPanel) + self.frame.setFrameShadow(QFrame.Shadow.Raised) self.gridLayoutWidget_2 = QWidget(self.frame) self.gridLayoutWidget_2.setObjectName(u"gridLayoutWidget_2") - self.gridLayoutWidget_2.setGeometry(QRect(0, 0, 340, 80)) + self.gridLayoutWidget_2.setGeometry(QRect(0, 0, 561, 80)) self.gridLayout_buildCleanButtons = QGridLayout(self.gridLayoutWidget_2) self.gridLayout_buildCleanButtons.setObjectName(u"gridLayout_buildCleanButtons") self.gridLayout_buildCleanButtons.setContentsMargins(0, 0, 0, 0) - self.pushButton_fswClean = QPushButton(self.gridLayoutWidget_2) - self.pushButton_fswClean.setObjectName(u"pushButton_fswClean") + self.pushButton_cleanAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_cleanAll.setObjectName(u"pushButton_cleanAll") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswClean, 1, 1, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cleanAll, 1, 0, 1, 1) + + self.pushButton_buildAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_buildAll.setObjectName(u"pushButton_buildAll") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_buildAll, 0, 0, 1, 1) self.pushButton_fswBuild = QPushButton(self.gridLayoutWidget_2) self.pushButton_fswBuild.setObjectName(u"pushButton_fswBuild") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswBuild, 0, 1, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswBuild, 0, 2, 1, 1) - self.pushButton_gswClean = QPushButton(self.gridLayoutWidget_2) - self.pushButton_gswClean.setObjectName(u"pushButton_gswClean") + self.pushButton_cfgBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_cfgBuild.setObjectName(u"pushButton_cfgBuild") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswClean, 1, 2, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cfgBuild, 0, 1, 1, 1) self.pushButton_simClean = QPushButton(self.gridLayoutWidget_2) self.pushButton_simClean.setObjectName(u"pushButton_simClean") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simClean, 1, 0, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simClean, 1, 4, 1, 1) self.pushButton_simBuild = QPushButton(self.gridLayoutWidget_2) self.pushButton_simBuild.setObjectName(u"pushButton_simBuild") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simBuild, 0, 0, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simBuild, 0, 4, 1, 1) self.pushButton_gswBuild = QPushButton(self.gridLayoutWidget_2) self.pushButton_gswBuild.setObjectName(u"pushButton_gswBuild") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswBuild, 0, 2, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswBuild, 0, 3, 1, 1) - self.pushButton_buildAll = QPushButton(self.gridLayoutWidget_2) - self.pushButton_buildAll.setObjectName(u"pushButton_buildAll") + self.pushButton_fswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_fswClean.setObjectName(u"pushButton_fswClean") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_buildAll, 0, 3, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswClean, 1, 2, 1, 1) - self.pushButton_cleanAll = QPushButton(self.gridLayoutWidget_2) - self.pushButton_cleanAll.setObjectName(u"pushButton_cleanAll") + self.pushButton_gswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_gswClean.setObjectName(u"pushButton_gswClean") - self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cleanAll, 1, 3, 1, 1) + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswClean, 1, 3, 1, 1) self.frame_3 = QFrame(self.frame_2) self.frame_3.setObjectName(u"frame_3") self.frame_3.setGeometry(QRect(0, 0, 81, 41)) - self.frame_3.setFrameShape(QFrame.StyledPanel) - self.frame_3.setFrameShadow(QFrame.Raised) + self.frame_3.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_3.setFrameShadow(QFrame.Shadow.Raised) self.verticalLayoutWidget = QWidget(self.frame_3) self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") self.verticalLayoutWidget.setGeometry(QRect(0, 0, 81, 41)) @@ -249,15 +269,15 @@ def setupUi(self, Form): self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.label_4 = QLabel(self.verticalLayoutWidget) self.label_4.setObjectName(u"label_4") - self.label_4.setAlignment(Qt.AlignCenter) + self.label_4.setAlignment(Qt.AlignmentFlag.AlignCenter) self.verticalLayout.addWidget(self.label_4) self.frame_4 = QFrame(self.frame_2) self.frame_4.setObjectName(u"frame_4") self.frame_4.setGeometry(QRect(0, 40, 81, 41)) - self.frame_4.setFrameShape(QFrame.StyledPanel) - self.frame_4.setFrameShadow(QFrame.Raised) + self.frame_4.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_4.setFrameShadow(QFrame.Shadow.Raised) self.verticalLayoutWidget_2 = QWidget(self.frame_4) self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2") self.verticalLayoutWidget_2.setGeometry(QRect(0, 0, 81, 41)) @@ -266,7 +286,7 @@ def setupUi(self, Form): self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.label_5 = QLabel(self.verticalLayoutWidget_2) self.label_5.setObjectName(u"label_5") - self.label_5.setAlignment(Qt.AlignCenter) + self.label_5.setAlignment(Qt.AlignmentFlag.AlignCenter) self.verticalLayout_2.addWidget(self.label_5) @@ -318,7 +338,7 @@ def setupUi(self, Form): self.groupBox_9 = QGroupBox(self.groupBox_control) self.groupBox_9.setObjectName(u"groupBox_9") self.groupBox_9.setGeometry(QRect(10, 60, 611, 451)) - self.groupBox_9.setAlignment(Qt.AlignCenter) + self.groupBox_9.setAlignment(Qt.AlignmentFlag.AlignCenter) self.groupBox_9.setFlat(False) self.groupBox_9.setCheckable(False) self.textEdit_launchConsole = QTextEdit(self.groupBox_9) @@ -347,7 +367,7 @@ def setupUi(self, Form): self.lineEdit_secondsEntry = QLineEdit(self.horizontalLayoutWidget_3) self.lineEdit_secondsEntry.setObjectName(u"lineEdit_secondsEntry") - self.lineEdit_secondsEntry.setAlignment(Qt.AlignCenter) + self.lineEdit_secondsEntry.setAlignment(Qt.AlignmentFlag.AlignCenter) self.horizontalLayout_runForUntil.addWidget(self.lineEdit_secondsEntry) @@ -355,7 +375,7 @@ def setupUi(self, Form): self.retranslateUi(Form) - self.tabWidget.setCurrentIndex(0) + self.tabWidget.setCurrentIndex(1) QMetaObject.connectSlotsByName(Form) @@ -372,14 +392,15 @@ def retranslateUi(self, Form): self.pushButton_saveAs.setText(QCoreApplication.translate("Form", u"Save As...", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Form", u"Config", None)) self.groupBox_8.setTitle(QCoreApplication.translate("Form", u"Console Output", None)) - self.pushButton_fswClean.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_cleanAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.pushButton_buildAll.setText(QCoreApplication.translate("Form", u"All", None)) self.pushButton_fswBuild.setText(QCoreApplication.translate("Form", u"FSW", None)) - self.pushButton_gswClean.setText(QCoreApplication.translate("Form", u"GSW", None)) + self.pushButton_cfgBuild.setText(QCoreApplication.translate("Form", u"CFG", None)) self.pushButton_simClean.setText(QCoreApplication.translate("Form", u"SIM", None)) self.pushButton_simBuild.setText(QCoreApplication.translate("Form", u"SIM", None)) self.pushButton_gswBuild.setText(QCoreApplication.translate("Form", u"GSW", None)) - self.pushButton_buildAll.setText(QCoreApplication.translate("Form", u"All", None)) - self.pushButton_cleanAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.pushButton_fswClean.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_gswClean.setText(QCoreApplication.translate("Form", u"GSW", None)) self.label_4.setText(QCoreApplication.translate("Form", u"Build", None)) self.label_5.setText(QCoreApplication.translate("Form", u"Clean", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("Form", u"Build", None)) From 85e7dcdf7a05303a8053f5aef4e9786962c463f0 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Fri, 26 Apr 2024 10:44:18 -0400 Subject: [PATCH 136/153] [nasa/nos3#234] Added JSTAR and Nos3 branding --- cfg/gui/cfg_gui.ui | 41 ++++++++++++++++++++++-- cfg/gui/cfg_gui_main.py | 6 +++- cfg/gui/cfg_gui_ui.py | 15 +++++++-- cfg/gui/resources/JSTAR-transparent.png | Bin 0 -> 96293 bytes cfg/gui/resources/nos3.png | Bin 0 -> 53018 bytes 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 cfg/gui/resources/JSTAR-transparent.png create mode 100644 cfg/gui/resources/nos3.png diff --git a/cfg/gui/cfg_gui.ui b/cfg/gui/cfg_gui.ui index 51651542..51c2dea8 100644 --- a/cfg/gui/cfg_gui.ui +++ b/cfg/gui/cfg_gui.ui @@ -495,7 +495,7 @@ QTabWidget::TabShape::Rounded - 1 + 0 @@ -593,8 +593,8 @@ 0 0 - 84 - 28 + 613 + 68 @@ -685,6 +685,41 @@ Save As... + + + + 30 + 585 + 161 + 41 + + + + + + + true + + + + + + 450 + 585 + 171 + 41 + + + + + + + true + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter + + diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 07d3650f..cc52e5ea 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -1,7 +1,7 @@ from pathlib import Path from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout, QMessageBox from PySide6.QtCore import QProcess, QDateTime -from PySide6.QtGui import QTextCharFormat +from PySide6.QtGui import QTextCharFormat, QPixmap from cfg_gui_ui import Ui_Form import sys, re, xmltodict, datetime, threading import xml.etree.ElementTree as ET @@ -32,6 +32,10 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) + pixmap = QPixmap('resources/JSTAR-transparent.png') + self.ui.label_jstarLogo.setPixmap(pixmap) + pixmap = QPixmap('resources/nos3.png') + self.ui.label_nos3Logo.setPixmap(pixmap) # Build Tab self.ui.pushButton_buildAll.clicked.connect(lambda: self.build("all", self.ui.pushButton_buildAll)) diff --git a/cfg/gui/cfg_gui_ui.py b/cfg/gui/cfg_gui_ui.py index aac8d2a6..5d31b05f 100644 --- a/cfg/gui/cfg_gui_ui.py +++ b/cfg/gui/cfg_gui_ui.py @@ -138,7 +138,7 @@ def setupUi(self, Form): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 84, 28)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 613, 68)) sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) @@ -176,6 +176,15 @@ def setupUi(self, Form): self.pushButton_saveAs = QPushButton(self.tab) self.pushButton_saveAs.setObjectName(u"pushButton_saveAs") self.pushButton_saveAs.setGeometry(QRect(330, 590, 94, 26)) + self.label_nos3Logo = QLabel(self.tab) + self.label_nos3Logo.setObjectName(u"label_nos3Logo") + self.label_nos3Logo.setGeometry(QRect(30, 585, 161, 41)) + self.label_nos3Logo.setScaledContents(True) + self.label_jstarLogo = QLabel(self.tab) + self.label_jstarLogo.setObjectName(u"label_jstarLogo") + self.label_jstarLogo.setGeometry(QRect(450, 585, 171, 41)) + self.label_jstarLogo.setScaledContents(True) + self.label_jstarLogo.setAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") @@ -375,7 +384,7 @@ def setupUi(self, Form): self.retranslateUi(Form) - self.tabWidget.setCurrentIndex(1) + self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(Form) @@ -390,6 +399,8 @@ def retranslateUi(self, Form): self.groupBox_masterConfig.setTitle(QCoreApplication.translate("Form", u"Master Config", None)) self.pushButton_save.setText(QCoreApplication.translate("Form", u"Save", None)) self.pushButton_saveAs.setText(QCoreApplication.translate("Form", u"Save As...", None)) + self.label_nos3Logo.setText("") + self.label_jstarLogo.setText("") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Form", u"Config", None)) self.groupBox_8.setTitle(QCoreApplication.translate("Form", u"Console Output", None)) self.pushButton_cleanAll.setText(QCoreApplication.translate("Form", u"All", None)) diff --git a/cfg/gui/resources/JSTAR-transparent.png b/cfg/gui/resources/JSTAR-transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..35568dba98b5e141573b36e17dd2be40dbbfdd60 GIT binary patch literal 96293 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 `oG4xP-kb@n%u;=vLp4sf?)Hs0e)brLpFo=t7 z&WPEOalqnC3hAxVj21=PknE*)O-?PqwVGRb=t`tOQ$X33j4pkaOy+IihPio9VtuT& z{+Azn5;#2Uh2V$pL6iAZEb%l!Kh@g}BfGZz%K)z2@q%*>sy#rhbXai|k9NRkY#??+<8l7b2TZ=Z}`G-Bs^0g|I6P8l}^uvAMS36qmL;DX%07{9&1 znR%VKFD>0x#>AoTNhK3Bgs%}JxcsV6JOR1CG*^sU*?;ZvnRX&g%_q#Gbwj52Tb5{p#^}lN^!E zirFudPhS4^zmIdcm!)v4SJ^VcEO_Rk)xVnF+lyxuiBj)C~ioIRBtR~6Pqd$yBmi^<($MS z^8D3(UM}ZksB7)xX%B8?J=KH<6*^|48d+UJV3G+G`+M2l`-bCkX<$-2*30+7^ z%FFO$2*Q95#w5mOXjE8E^4s)i#69hOALYUOf-J&t91UI&G$!@=9zihl7iPdl7qr>^ zB4M?$@yV=^(ZR(DkwrNs@T`T@ zk|S2+9N>+W^nMYqOMJ*EWka_pcre}IBO3#}7;A8Crs1t((e=jRp_$cJ$yIg56u&#y zW6_24%ZE6KRF=H^7w+X|Qd{_P5G51u`GGyN02qH%M8B)hl$L62nUgM_WtcTy^jA_| zt&g8yz@)~g*;V1g1bwWCZ#*}YnMFf}j1l~$%zFOzm*9vMp0jw)6U<38(L)jGu0xtg z0K1cXl!N+F65IR!ma?*!SiRr-0^i+v82?YIyrQsn z{d*FDNLUftJA){nF2c$pOp~uv-$LD}u&6Kt7-=2uWmQ%v_`Xc;%Slb<>vq@7Pp-uP z=W!=I-98&LK_`1I#_vjoHB7TTLUp*}+M8`Y`wF93UP9Z&5mocv!kN<_Y$$^G;T(R= z1zt~;r`x?|lN5RD=Z#mbwYtLs{kG&ld6H7ZmKLLlACt~M3GvNby}=_8kp*(;%?K;Qo6u=R4v#IN90Lm=Wt<2U~BA%`;bgiz^c9!%2tn zmG=}uE+g{GQr%Bz8!c^1y8@EX!$Bv8alwcRvEn)BqpYHO@SCH86j{`ES>^0sf%MjR z%1{xI;Fkw|W7nUaR%lP3{4}tYKU;I{7(NJpN^CUYcnR6+b^GaclGD=VJDJbWvtY1w zg6};g^0tRpE*blPgR;wRaav>N(W;KT61cF5H${u6Z~RFdPx)QSqzf98cw^81Tz6h4q=<|EqXxSvTR#`BRM)G>)~w~AI5)dWtyjl($txHuav3?P~ROcx73QZSodRRi!yrNoX)be5c#!(bE{DWe@6$)v3$|@3F z`qDCO06era-H`*5C(|yBH1M{7xN;>8y_+T8u!YY+%RNvO2go=dXy$5PA;DrAxJitD zUWg|m^DLJm2rZP}8?UuQJ`50nXExrOn5x&DH@aT+F3=oG?6lyM z1xS`7f7tdH)c|suhdd8vy+UFPUC>77`&g3vw$K`B_|4$F+;&+&f7nkJs(G(TZ}%b^ zqJP00@8hxh>HD{skcQ16lW)X31 zBk52cD;#QhYw5b9#UZzG~*Gm6VBdy&7b@ol7Z`2 z8%_EXUA6}v1q$({+ZeV?oRje=d=Ew+D1>jw(#;A&QRqwfW!wD_FSwCvdmr^dO8r_fVkw1cPmE z@Xm1WQ_pFi0#cxSN!tQi+{cYJYCF5Ux1m5QM4Y%F$b8~0*(j$Ff;?6AzfC4WQf7Ug z+id<`-+RCGJz+b1k`+OyZ#b0B%D(*(&3!|u%SxHKv@j0o4YPG!#9#e#c+`s0PlXien# zTNJ4lHY?PkpgZSFkk4W+fgw;QTV0ZnZi4wGeYkm8^W17~N3L%?RLYXyz@t-CC}L&&v*)Auy%dBJca& zYrHK%I#lYY1Y4@!(Xa$dM$7N4-e#4QKLs_UDPGPWzfr<>i_bHP8M!ulj z{8)~h)bKaSh@0Q_lgg%z-@hSegDKpH>*5h|u(OAyq~M?X%g;lV5De>>EnRt8E%Cy` zAebkUVnM$g3DB;_sEKpthsHk`ReLxxWhoD)If5RaZDk6UocBv@Q|e6j7r3j#`z{)61-+yVEzLxj{W;SE~;>*3G3kPxs{rVDYC|=MjB&AWj#ZXm(xJp805$g)*-oL*8q(u|pEEVi_jyz1YSbi6^ z7=#5suC5TyLoP*gmroaLyeCOp6+w^7&H)v=6WxC%+elE=zlFFTta9uQQr2+liP7P# zwOriEOsfe^-KwfhN%N{hqr&Q+qFC{ls;wbKklu9Bt{BLth%GB7jOh?deI{&2C zM4IxZTceW_(M??M>x3WKrUHX6tQ~GZ|Kt87%M+&w~XVG9cHki_oh4KviqCxAiaGy}7a%ch=|-|a4P#@NuJq2~aW4Gf=Gf~od{LGORtbThi!`YY|76_7 zo};tGV8hPmq&5On8tXfobI@n?4=Kl}_q`i(nDpO6BMp)_9lEX$voS&`Uoy-D)oIEZ;{6s6!O3bAg3ePcc%Wk5j*Sr1)O$o0?YL;eY3c zP{uVIIg=n`z4*91?C=@reI&Be9vu9<+G~uPmoeRl?xFK@SAghjb?D8~QhG7Wm$KCWg-~N8FvYX5AmubFPl&XTkE zSqc-EU$C*~#vG@y42ChFSt-Bar(1Nt;~#4Q#EXCaN5kO)9KwO45S?t`-XND=cl>mW z4kMc@rF=NRm6jp(UMF1VEJc`5Q8eJLKY(Fb-0~mVHkg+b{Tm{+7Ub9eC-vKJn8-@2 z^+ZWxJ!QHwlGaCrIZiyAacod7cPKUC3Sie(8;o;;D@B79|3lb4fLX{zib62<&i0$k z(a&&PX@@Iy-EuSM$bs^@96{p5*lk`CTKCZ}V^NRaFDa+6Fab+kmhEnFnN5~2Lllv5 zJ;z~I&h_`5ZzcTMLB#O~% zJAG|43-27GXW5;SP*_aAzwNAav>y^{<=xd0%6-y=}w3F~~v2FrA!QQw;D zAh*?oE2ajVQk6_f?SYZ?t(#JH!ME=+l-Qv!jf>Ts#uTZCnb=B{D~BaJm@HIHEyP{d zu=T|DuJtqA22L?1;sqRnr4@%xwNfSmqB7+RC#?9e6ULAS971AnU&7}Qd%Hd<5!bne zuU0rRyA6AF`w|yVo)m8k>2U$?UulsiM*9=|{%DXT&kLUQ&)GDKs~2RRw47bMLKLJ8 z!N6bVdZik>=>9>Yy>jN@fv0{le_R6e_#e@`+ovx>`V*2g9|u;#6}riFz1}+5=XN10 z*3|!~iTX&`S2ms=!Lq#3dZt6B*+RuRD^-t~Zf#n6arkY^KM&B4S13AGO5Yj7`E@Ac z=-`DAH7~^3A2>}OI%F9zRoGNdwc2~s>~IZ-G;Dw2il(I9@`uU9d{bW68t|>{#Gq~N zl)z~xGb0sFBpD(u6>;M+zji(_!>ktXRI9Jg9X|}~!HE)UJke9CcV^)Ei96p?I7&VI zVYOrHs6JS1&Qlv!-|KBqu!XGel_HM3%1xgs_jhp%y?=wk_rcFC4sWx^o zRDziRisCTuI388r-}^`4PR;s%AV*0#$A=j7y|kOvB-&2qdmKn} z{qW9pf7MRsBA(_w2%mM5h}d8HSEXr)@dM znn6UBwACj|vlB|jV_1kcHbo921&b=*FZLAle{@-_cA=8wI84I`HC8BeU=wO`wILsp zP0&kk>>PwE620`UD$2|{RyJ?sbV7248vm%gA)y-6AAhX#l1GI%q7pBc9+ zTeQ~FRHJw`yiP-)@44aCNK znN3XyxXxdG?ZE&BU_-%Vn6N;f^XX@5LZl+?O>v7X?Xv)8&K*!u(k)xX3$0e9^w2GA z)<6DtjoJt^scRn#4)74;0OeAY)SxfCVOrnRY_{44@2*oCxb%VLw-Q6OJ2o5~mFSs) zZ)-N06wrr!c$M>l1W)X&ehu|Xv)RiK>ttGZ+5jOdL?h5JC-<**ev~A~l#N-Vv^mMy8V8N6-85t?s+_oxC^7>93uf z$a}{3Cay_f?v*`4L5Lz1;DBjDpGMkH8PFf2^nMWzR~eyp;^g5lnLvjeNqQ6WzXNt}>&n2-X2HBBdHZtaTyb0NVJ>D_`|{ zR~HBxbV?B^FKQ<}8W%77?}W@v+$&v{zZ8^`?(Wn+r`gLe6SvguBk~SwG<4q!?&|v< zda?8xnJ|7`8Wd(|x~)Z|4+++3<64GizRT+8J@v()wCbQg!V+H(E2;~m;Mo-nl62U5 ze3dA3Zm7vXNQBE7v%zIZi~8{nw0p_O#6nG}_Gc1{qb;UXP#Iz=80|M;7u#4-hPXZtVI<)(U@(89C5{axE8B3RFg`_?BNfERkyLwb1Byj$qPIur)`l{e_|+XVqxQ)rxBaibDl2;JY^}k{x%r-v&ENiF{hW zZ=hKDz~bbrG&ko8CxdwCOrJ+cY!j$uPMGEsK?CQs_$_^{j#HWFX_oIidI&6|Z52UA zcb7)m_{nRZ+(Detp7%FI(cZ7bRCZsDqGrXAUHPaTdRGzH-i!a9lc<=efwy3@(nz0Q zLpXqzG^2XD*i7lNKKNLsNDOGE;;suJ?ksabvDIF$|J5GS7fkf?Z!baCImRCy`J96e z*}9+I><|}vuxI-KU*DAg&UdBK8!uF!`duk4Y$GpTVVNK7-^C_d4k;)HQkW&>w|;l5E(YD{?>06>(f;u8_qPK^)7JZ|r_DLZy2x z#&oVwN-7cuj3pviM?H0RV>XfSQGlJ=t~5Q(S1%{`uH<|4`XlHjQ8S5 zX#J^2v#sG3VFuh&BWP|=@N1^5N_5<*EH7Ky_jAxjxw36L{;W|F?}m=;j?s7hnv2lz z4}{Esbj|lkqG^i>8@&P)aj7=#D5crOMG5-_FsHBx3Nvz;N?Ieejtjwsc0*vrT%F;1{{cFvq+-#3J^$WVaWpsvHDd7>* ztkmQaVDbq<9GOGL0N+tXxhp@1le+@o3RhvYA12oWN`19o z3wo+PO*_x7s+#&9%{ayBxJcnP^B*mo9Q~w~))AJm9y3wqR39hg=n%CvdJQ-(Wx)Rp zDgprG7zsJ!+OYu9u9kFcc-TNz(67PEVww<1WcDV`3zWxlKrV+rBiZ!0vC z7XRYCC8ezCXWrxS&^y=pYd8Yt%|Nv^R<)9SBn6soNp=4%3dC9IRB3OW+nD}LT@7$` zWH3zJtN8>9aGI}?d74ZNZf=pnpd4>ge8R>C^fO7S+a*ssG*UZv5%ZLN#R6rWM;PW~ zp^;#jl6;w9N#xK}7GNSW`e^No6iZ%hz757)AC@Jidtp@Zb&*=!%bK59PfRvEe*F(I zn$iQij;NIQA4Ua)U{PrjFOk&>p4}@O^!iq9W!iiA%WI~z$;9HF1UjWQ0L6PYB zdvXI@h+M}=XQdKf^b4x=aZh>6iZwFaHF#)*cdA6zUapPRo!@M!6m-_9W((oS+dDAq zlm8A|crJ{~l=<3+o~(n86S+a!ctYs`ZxQ%-1&8yzwikj(JRCX;xeM;HuU?z9I$-X- zONkcb^@KwspMxBM$i%GMm`R2{Y|P46KvihJU@^VGthcd6Uw6BzJTY|)xiLR2)aH-C zHfE=#Izkqn(R;;$F~~*hir{p3)EIk)>btP}a{h^MK+7Y-&n{E*TnI?>eHCC?B$$Av{C9wZkYMXgTKrU1wpq$ z%diU_)Pb6AFWXg07?U08+hh_CV=<$<;jpu7GoHF+UwNybScETU`bX_HlfMTP??~5dDp$_8MsPG7&_*vgm3vZ zy59P)_4mY&>_bSifgdfu|3H<$k(=2%yNFE`S#9E5)LIwGpoe~Imu!6cv~#t(FWy0Y z9WVE0Bcklvw>9UsGJE%_72` z20U(JF2*K!TmCerVs6*R!?ueW0MfZKl`e?FRtV>b*4Ysk#A_FUP{uNnDzA?U*Mv2bC+I@?3ycHDbV_798Q3OW-XC)4l%0 zLCK@_5^WDpj8J?Ez=F$5_qSGwqkSo})rnZ=8;ckq+LZQYoAngF!TD`m_|kFbQFe96 zQsC5|&#>;7^(OS_7&|BRA?Lq{LmR3CUZL(7o64b_9h<)9q~y2x*pZQlBovwY#|0h% z%eLhjy*=x{m3N9O){n$22B~xJR8mbeAl8n=>vw3%LUa*X zWH<}FBVpyw^;HLtrb2evy>Rsvj2=!|gpYB@kF?q_L4u-=zI zG@9aKd|&fyE(qBmQ@+~C#~w8FKbT~UwVR`v`Q_Gse+#PPZGPv`qvA?pP0zJv!&mFO zl9Dq|zKvnm-Kxn8Dc=lIPERIO%@NO!!HO+r9)}(tS4P~+W zE}|%fx)NSHm5BORJ!hriEGF*PwPB6UNe7LfgfY~l4jXQ`L}gItjI!^ zb8V<8-LfAbm*oae)~^p45ch0wu=eyY3QID7EJJx+J zR6Oki4r72ct9360!H>x+Dk2o&3_7~u;(MVm$2TZu<(}iVp!9nX(Wp!nf6BnM;#M4# z#O&Rl4v>W6FOoD2DVpar<~=vd)MU#dCOJhudHT4Qf%{W6g~)SYo~4HY4l|+TJla$# z4(3n3*ZESrqx%iaB_mbo5IJ;B9=1-8W^;46ERt8GY@$b}C67}58sdtlQt@s?hPZd! zaY_xxaryXsS{GMcvNJNi@_O?>ieuw@U5<)7Sn+=ts^Of2R4Fr60^g>~Z!jh2T`Q;|t)!CAx#VG0amI=6HD$h^d=hKz` zI@O5}xt0`Xn6M~G%pDNDhEQFZ1@Kk;J-jd2?MXukFP@cebUH5zu^skJcguaSbouej zWoGicKkGFYWLM(@zjdXD!cO8{g9&;(&&GD_G~wUSEmYjtp8pin7EOXMs)j+UB@xR+ zoP6_>sXJgb?9Vr~8;IJxMclo(7gDhWfvCFz2s-Gg+B+cQ@GUVSr}4Y7YedW9~xn;N36(h_^K_eRmHD z(qFlC)`$TEikR^%+2VPjBTPZ8n~#L(6n%kcAxw8NUZ1X?W~);DDZTf(X`I5bX5{qO zo9uRKoV^n}a}A0BE`+rHqU#%k6|pNscsnYNLQI2U*X5MyE<5i_<4XSU+K8~HqMWa8 zSoVAePZtBj^mI?4;l3}L`oX?GYzu0ocfPI9Q{}p3y=MFP4ZFc4 zmlqp7crk~Z)1=I^Cp4m!iVT6+JQWeIHSj(<>2Ap^6YD#VH zKdn_y=IFu=I}kqF(tcE*+t9Bp1wINn-)g3DKZzygdd=?eEq{0I`H+In*%tb}F{BfS zPPVb|-F%;0(An_zGU>V7HaBon<ySQO{$XC2&a^XKX`-iaFS5-sOS)*I*b3=96pyM>KjbQ9Ni?2yt&dHjF6MBj#1V4XX1;Y(W=zKdz z7SB{x6H+IogVnjmo=!I^&UNoEmw)EJO9gywelOtJEE|v5fI_H%fFtFxo?*Kd_;jaN zWexe$r9aPC|MGZ5qvXixs?4~AQt8wmdBrr<=1QQ_I_fCLr1xI3ocXiij1U&QdkwR) z8em0TQTY5ijn`5~X7_v_VXUR!Qn>f@P>#Xh#BU&%y~})VO%ZSFqkOsq+N>~L(8D%t z+2ptFB;fLW_HHbvHZBT;4=oYMV3wCMc^ZZZrSye?aU8YI(9T??xa+=9cqQu!ZO2|A? z)B#f%HEh&L45ebzUfAegU79W07!#s9vmro%L%GZ)mod4{o^I>@xYVP|t8p$6rQ`#C zePgY|&X=vu4^v*~3%a=D}^=fw)<#$x#e5Fzh ze^5A0$QXb1DRUgw=YkoEdFZ52R&MCxyo8+i>=<`*-G94kVpB_-|CPCcJa$N()coW# zdv4gAqNpnff>jHxQ>rvWhNcL}Ij5R=7jTg4?g|g6+w#LXJ^&jr`dkBeckW-*%Xh0%Ik*Xsv-;86iWX#R#9rvGm9osv9-c3o9QD24v?Od_qr$Rx0J< zkj}K$wuu2Bh&YQ3}Rhk)c=c?%%%Usrno~;dwc8g{XYdRVGk}SJ4 zm-w)#{K^#)n!=sYg84Qk-+-`?t}+7qopI}THPB$y8bxDJs{xkjor9}2E(rh1bGuz0 z^3{?(%1(|n<(kowWQZYg2nAX^6P>m1*BT{k>bdP=g46ns z6zN@O7B^q#$9p`&53qsfgDY|t@yW=p9p@8iZ5xxpk0qO8z`!h%-qnT zcf9AtXZzk&{&iMT9nFZV@Q)m979RLL<^GI{b>H=wCJ{zb&wjK){(gmZ+j&(yON2+& zDOhN{mIj`snjsz!v2;etnYkS0ZpkGCM`Iu|41!qe?R>qXE@JBG8oFc2P2}pJwjk&d zw(@0tihP+Du{5^e*lG~!ZN$SR2x8KDD?+8Ns%trjgg|KMxPTz-h-G~iLN;0Zd>A~e zGfMyc=M^v^Qn3ksld30Zstt|V)8ZNVTb@h6@`umqYpXp1&QF!b^w5qEa_8mPQ*A1w z7#Q)>DYubGjN&hv@NWhD@9zTiB)j1Ga4*eeZHOB$Bo|4ME!i@sq5~qVQD#Ye=}ARp zJJqo0?Lc9)YowFJG;?k%Nk-o@us8rn9Fgq;b*BsGW8pPw|ManC-Fs}Rhe+Ir4T2Jo z(Cpu<2C04e&_TCST6SsrS6RbC^lI0?9qhXI>S|8g{qGh1VZ`_4)lc1_mqRC$r=5p4 zy-&fnA#1&hi_>6(d%lv|%FNCzx>yrFw6P>qJ{FvJKTtmUH@vKIz3XlBSSs@T1=rD! zkmmfvZ5{Eq3WBz{mc0+IKCOuKecunS3P17N0et;|P}Z&p3Foo@>W~`)WO&R18+b)M zHgdrk5F#$lSzZtVy?q_8J7a$fGb@g@s zlI7ZCnl8`d=(eKeT)o3wi^CO>zRgYy%j=?8jN%5TrvhLj@5M=25y3*0{cXl(xWB2t z_V6|}6C+VoH3(VSMAvO2^HaUq#b9DD4YU~vUVM+(DGkv&Hw>bV+LR&hvw`mN3VTv< zYZM5=BOniqa$I1s>+NAllsp*F?^^2w=egN)ulyUA7@?}^fz!?_S0d|Z#3>jUb+8bp zELq7a#~G+W@;2B&kgx2!nx~@H6q1?P{{kvO)xIRdWy|KNzx%ce1(6VXH9{mr+#Z*n zKmCT07fd9$_LhU&$6u{K=$dg8mwxyC|LqqFHHFdyg@VFnU^{WJ-J~$?w?ZLEBxDo> zm)qsQE-U9D@we?bmWgI(oO1Y6^JfjaAO~-=T1|T4wQo8M7<%Ih8f^-;?}(@mrhgiE z-iO2r+=|co2z1Aeo4PNjX38 zz`eh?`>ye)?9~`bo_O)gOBODAY{)lXeSeJW8el~mp;QbwT zAk68)79sKO;g*&GWl|~-J+58fU;q3YTKXuPAXxP@y^1N` z3Dn!8OhPju5i5m81r~r`3a+~e4%lzc)wj->c5a)N;h(B=&2N9=t-D>)|J_X`iJd_U zgD1iz*?j-x$A93*Toxft5n_hLIlu>|$*Of0Bj7vh;O#e-w%ltc@>_N8y(;@ELR=M; za&({CB*fz<%)9%E<*yC&^)R@M2y$hHBS1XieNrhQ7Fwg4xg69RvYE@{!2p15*BK5y zE|`|%4Cvo|!pJMyPp`K|ZRdrGi+Qu*S50{2o%g>uofmMDibV$dPxX}TzLJ%#|pM(uT@)Z%_TyNVMI~Hi0HDsub+fA z2kia%{JGbj+O#Rz#5t!6o_wdrJ@?F?_WNJOEv-l+C`lwi$8nKrpp%e@47;u?$Su`T zJj}#9C%1I6tJL`7SE?*ff&2M5htN0-?brE+(Sy#ru{s!Ec=`43e7frQ6MP7BMtp+r zJ<6nlq&YEi`2Yps2>8huFt-#6LOwtLyfg2da&7Nx2qCxxSmo`<4ZQIcJ+6NLr(ZYh zuNxsqdf58%NxW4)S*`6@IU&|WMO+!*@|X+6lpiV>AvS58Eq{2NHgm z;_9H4WBb-7A?|kB4X=H=`p46l9swJZ3UGNH6R_Ck5#k^#HlGNwc)3J=Rr+fflaeAD zhh*t`XT-?f6GshfKP|_)c#F-!fqwQq%dWlq?x)6qQ4q$+MscDPOpFRM9|)G1HcW7A z)D=@94UrMKR4HlBSi94YeCobi2jx8>e)hH19j>}&_KHn50X=Mqq#8G#1Ow$Hss7GS zLd?MN8H7*>%s3dtfx`~m^Mj=eC*&O=?r_2ARp0#gk3$G80*9e=2`6K;6q6I5+NzHL ze$Z>&1;RGMvM299=&*fjpCDA$s$3z&NFZ^ZLfL|y@Gt`nEHpCll5qIJd#}F#u1O~& zDaLz1d$AQyyx!xn#m|oV>6btDP1;-|S_qhzWm{2lxPrYK*F(wG_oe8m#f>3^83q0 zSb5L7kd4TSbQA(YjCDX9e8x>GKYV-+jli>n$ngH5S$t@>Ww`;qvHalN!5n_B3lhaDk=I zuDM|R#HkMe*BddSLCp3bTG$vim16l$15hKums+%G@oODsEs)J#LL;wK|4uef7dNJWE2p;2Hg6s4v1Y($7LxG4??gg>u2v7!VeReOvGT${9_Jwah00%pWk__>#mvj&}X0j=VaY1r07DShcKB0E!H$B ziI;+9pqI2v9u!G-9Q?CRKW5pzxAp5*rHkb7PDqFckDR&!!cD;89x%>1|Obj-&3h4#PX@W<3coKfuGm}hacAZgJlaR=M^EIeed(5@4kQWtw0+= zX#%UQg@6m!3!L<8Uhyi2AI&;#8jfS=Lr!@d`u4eC`uJg8#?|QsQzy?ALL4{;NewUo z=5dIc5#bcXnFG-Rbc&efG6)I@~yA*5W_^E-Cc5 z3A%+28!76?vS})m3S^2P8{(Xb5ThTlkHJoKUB{$43Q6CV4j`zjb~bpo-Z*T~h36ml zKy|U$*8YkRZwsLu{(Ef^;wM*p)a|ulRyJzxwryTpw=X1E5tJE}H5**Rzy5~My^~1?R2%=fw z`)K0N#F8TVaOwsTHQ}+|JuvS5>+BPs+93$>o2xqv8#Qf(s}+KS)fF*nX(=l8t!?bU03IniSg@Rm;ov%Jl_`2 zuC5Vq@$b~Q+Wwv3(>;LUIYV-}u9Z#beBtepoQ4y3XVFX;*#$|1j0W9(1zXd{! z3%f4bhEghIEC$zrC)cy9M_xQ>aNmxTYrE-+5Z5-M^?1J8BE+{p@XVB%vld;ehnj*5 z2H3s_M8{--Jc$seWDt@Nrz?M7_X5*1#)oTlmszA9N*JBds*Scwtd9l1SLXS}2()fv}~6X%VoK3Gd9)k9_KZnM3kF zLj2}u9fpmXkwJ(xA(@bb7?WfwB-NGK@})nV>a=6FaPln?V%$B*I4?(ti4AS`-7T*O zG1>)o>fC$XUw`A6QYfNt80m2w8$w|de4L=ww%rIAC~dQgVXxhreE;@}Is0t)iK=m6 zE)in+uB00utOQCuste4IfvG3qloJkn_MzKvxNuumUCW+ded)|ucTN9ueQfu5f;kVDhj5=T55are_z8?YJAI zAx?uuiSn6MzD;6Wm`5u!Q; zLu2mzdAA*T?7=&)-j2sGXAi+-yNS0xe8)rcpXk@5Su11XMhB7(fk?POd=R)^DNr4K zESY!eiEWlWFl)?3IeRlzY}gB#5n}WY)i6SwNr)@huH`f#mX-AarwPo2=lFq&5#l@~ z#LvC6rqh6-@V$gYt5Gz7l`-Hgn&}q-U z|H1biD763pUEhY!*I+pVFfij#t;&9SY zN4&h?{;SWb$)J;~$08}7^}w@N&%S-$l#tazb3Fr0qkzYg2{0{AlFlX`iE92yCmgu! zq1$#uLab*H;y^>3QK?Q4;?#0oR>@e(Vo7Gwq)NALg%IbVWMce`d3Voy^x1)-@J`@( zSP;P$<#RE69>2Q@W|wER4|4S_u3Ec1&w*&f0w=Z}7Ckuglv9pw`Bv4A-2T0Ci4X@> z4so34D8$9;jub0YN^PvhWC?f8#UdsSoOo=T<@eun4JO)cQ>TOD=xZN-*KX?6nKS3o$B%DxqOiRSI<}j4^Motn@Gg z&YeBA!!ZZ#zN)(C$=n}_cK1#L-e3D$;t-F80VtNXwne2olu3xv_QKr-$H44r_yaps z5xl~v{$_+2`x8HOFag&uBg6xH{cG~5A)OT=R)o0r3Gq4IMt}5w|5tKUETMrX?7Hyb zbVLO=Nr*ApCa;@IE)$g!Vw4CAPN9R3ktig^l!HbXcy1gb1_w8>p5Joggg)ImA2Gis z15d6WJLRgG?IAY~VEY586+n}aR+T!t&5T_&jNQg1{ zoub{V_@V)@eH*}#MV2r^Y(Pvzh!r6Q07ZyvpAa8-fww`f61 z>+DU>ffHjU^|afU-F)}G4-XB8o9LcT!S-CRaD9$={wXIMymZ0rQ4NC-qwg&i>?rdT zl?h3>sG7Y^Mu?@AlZ+5cLM*2E)bej8A$Fk6zAZm^=JBa{kyQ7|e||pX;vQFi?vh3% z76%AL3c+Vd0EUwu7L75`I#xx9xAOtSX9t(PT{{V3ox*|pH2dJW$Ll`fGN%Y}YW@lA zHv?V1gp`7*Ti_%eh**}$p)d`U>?GjQOFPe+Fsj?=s*+;yMsluwyk_0uufF{5xhtN3 zxyN4{H}2(OT-vwcoKuf``mULyt4)ZPzwp7urWGk}fBGS{lGwfExzBstH2sddi(_5^ zBj_j*L31HtCx;qbbWz62e(};cSRpg(wudQmj-Z=HJ2`#Kgd{vi%S)c~-IFFJeelDozZD(83Ti2K=&4}WSuX7uDI7}IltVH14* zEGP(t>1FL(J@Me;5l22C-tkGtvE%1IXUWAf#2jGaM2gRCY64>KVJaCAV}_W-WQa{T zy+Q4Fp51t40OH#hJhjUEXh&^E!jPSn#jUTCc^nQ9KM$VyyYs?`sYb5C$B%T>S?vbmLjC#q%DHFIdMn_JCL_ntbblBh?cT5=DZDzb* zrc`ck$Gdylj~O@V3Db~sER?Qcs(tyzZMLjfIQYm{nb`43$1yk0f6kT!AjZj`P;Rv9 zs!X7;yX6+DiHtCp-*dA_$sIS*55hmy8^v>=t z|7>MAK2Y^6?))Va3W|gp(F82p;BrdI1jL0LMouXevR&dRzK!gSllVK&YPs3{WIaE4 zeT!1?>pBp_1faQW)v{?Z@kpPHMT}F(k1CmO>FoQs3bm^3VqU)oQ0k*Xt z23>RB@;jysDHkZ_&jDk~=B*!g{{5HlPaiwH`|L!<{ZMVcwDao@BZf_SPSI;9vX%vZ z?azhG>K#|! zCg&ZA4Do><3Wnq!@g+|p2g&u8FN`1ZJA|PDpRABJ!DNs@0)-$rLVd^m_I-7v`_9OOZJ3sv8g6prJye=GObs{FCm$X0kspX4D9r4!9FYWlGQ|;D;K$qI8ICgTekTJ8+Ra*^$g)Nf_r%?Dv?;|;uV1*{jXRwWkUDyiF;xJQU?&1 zv~clkmc>FV*65~aOmMkugU&+Gt;;3L@0>BP+@Ls-u`W&9?|fQt#;DOZ>V}Pg zAH4*G!qTDMuVg*9(R*?;{5-3#ip3~qGLXuKykhQ*Yl{R2sK6`-Br1Ud1?HMn(=NZT zRs9{MiBDP1Ndw}tL@UM4jRzq9`0KwKb?-g$GfD*@MwUH3g!n%s+)K7s{Vw!ez064} z0pdc_OU}DQR+n(V!g+x(tY{aRHx#fB$R=I0YEi4!Eoy#{V#8S}-TC0tzt6btx=}A% zRH}8+1+AXAZ}Ig;Fh$G>VnARt9)>vT8R9e`PVT@AAG>(Nj<>$( zX*mdp0US9D47WpF_dt(^mFx^LUo5K6$-W+k^5FF@R_*ND#?CkN2yoJh#MLYXSG zb;MQ`A1#0w?-+HQ(b7IcS0I$X54v`0`{CG@v{Vag?76g>qG?5__R0Aoxd7w>tb9E0O}LA^@=tL3`!Ox$Q4J`^1C`*e7b- zj`$4Znn0xh*hs^Y49+1IsvjOj#B~-+V)qry z1v?ZR73nFsHLEhPEz-Mt*M~Q6d2*o11Vy4mK{EnRwx2~zYH2goG~K?OuK%_rFSMOe(`Ac{#7sBI&aak znZE2=Qp6^FQG{UF@6X`W12kdE$jIWV8byy(`CjvsRpGb#K+1#z=qgPl;jo8*SS2bj zBLekKs`|+*Tjw{8M;wc{kp{$xh-xLZnHWHI^Pjv1T;wpYJ|bBTTt($>hEoPV!_#Q zy2Js^98G}OKx32444@GkWM+e7g+P~0I&xT_X*Z9&@~%Y1up;fQ-Sq09TW?*sIxFXR z>Gyy3Lsr$Q+~fv1!C=q@?C>Mv0gTx5I z1?M(-`l03HyH+HI2m5Ur5GNw4mDFau0CD%8BR+N93^7P5FQ~)fv_k=6tOCU&S=kXU z#8I^X4-m($JS9FsScV0PEQ8D}P^2L3->>uB={NP9T1mr{zD$B6kOssF4saQppD}Os zo$EKeGJ%pT*>a1}kUxxET<=IJKx~^3$kZVi%m-bPAj_}7#>bbR)U|WpJqF9*L<%g* z#E&IXEO=2J2gE|wE2(p!M8LKj@M}J>j1XwD4VgX*9^bk)=alLsuZ%-is?%LSyuf0C z;%KW>zfYBu@cU`YLX#NBHK6;z42M8s7G&yRUw3V{>ElOrN~uioD?7hzH}<9(&)76G zBVtLQ2mD}|CK!eRK3{;-Bs9$jpAhNzEGaAL2;mr z+eg%*plcc^V1s4+%{sI{`}tM(+|((VJx^adei29m;`qff9xYuvcJ>=PUfq4Zq~-`I zM=o<01;iXcGR*mSddtbmS_#=k$|z3&$Pxn;EY|q6`foh_$h7v&FS_oJfAXbjTz$uL z(BcwNQ9zu0l@bKyGACm*%K}}YKu2;uV_Zj>hzv36pwa?xXde6MjV;xyR3ZPA`2kG-Amt*E2E?f|B)>2gxVUw%T*K5= z3Vv`yMZxFuLBuKmMWSea!mjP#WB#-oyG$B#{lX`=zy4Vl z%h4rOmw?(fsFDiQX5c6i*r*N7OYD+)Aivpl3E}-gC65B=dd2x`7Tz&@a3Xqk^Z;T3 zyo8>#(3eIP6wDU$-2i5QtQOeayR~07d&;2e6A{bOw)xgOzqY-0*tnM*HAe~C63D&) z7<}gw`yOrO;DD}VqnYTpy|g`v?|B}E@pg}K8{eLY*3y7D5mBwAHsb+^(W$O&yB>cKs3PI^CbHrvYO|uV7sF4P&}|h5mRZ~G zCm@wF#0LUm?}bui4Q!i&OeC;zOHs4Ir`p!-GsgGm-to+*DruA77T+^Z?!-;};LZh_$Dp(b*dRfeIZmEAf8O*V-7jzQXsH4e=abMT z`m)aB-~alDKO5U}fHB<%LBk}zfDT|{p=uNnABliiNH7*pW(h#dhz#I301icNH&h9j z?1MKR^Cc={p9aKnet0Xhxp)BLy^Q%UYH@W?B2|fD3qVZJ*aj?e`)#}Lfu|?lxAd{Owwwi&1e{zW3|fXyLcI_D2dU_(H)Sfd6tUf!~9!KI1naT*XODzcT(Zae@ncC*pBJ*g4#Ndgcn zplB-CPWTXj7(W5xK}PqcWFFBMI|_)sl|Ob3v)#4@kdcuI4z+>W5g-tPoJ`qTzj1lJ zCdUW%CbR$PYgar1X+T`@7{;rG%X>|E`^&F>I|p-XMAG;!laOuXjA5?UAfU0EIZgpU z95KS+^P>t)2(r{Le6njZW}uA!e*0&Gj#rKS3bYzL3ri#h3TCa4r*Gr29_g%tSVsI0uXb(;UXDgmv`l6h?8AZ;$^Fm`-KN?AE6u) zr*;qkRr5hOZ162w{BU3q0x%P^D0EQYuJ_EI)MtDp3|0CP35>wM3J^D_v+LOnbIwg* zILqDiSHI-dxaz9w{|p*3m<|I)(}AZhivVK71;l98Dt4WcmtjS2GtP0?2Lluc!RaSg zfBU)3OWJVI&Y0floI#O%LkEcKy-!=1~QR3llmBh+}l@(dL~w%%|vV|3A6XF;#Pb*+I*;{*)eCv$$337N>ns z?iZyTKm3ES%y9!}JoWx3U$&Rj0EA2v^guQkCQ^A&7El1+!zrE=H^MpG`Q_+p8GmwU zK#Un;pbqFN0XzIVUA|;;_l|8_CXDKs2E=6?zEnCrUVwP;_4A&5^Ucq$qTmBGEtM23 ztc!?Zje`PWksL@pK#a2jb*1AN5P~vE2=EyYz`{BQ6qx~IVaV}01$WPx)TRA}jdrBc zxTgD3wg{vFaoOUPsI%8T`PPV8x2;%4NhU#kS5?=5QLz;o%@BKlxL9pMqB?cRc5zc2 zKvfm6tO8I;&>7h6;^niZ4k$87FOGGKy2|B z%d%`xwE!@paJ^1G0ie5+&cMw79qJwD`}y_lkDW%25dZoVdGu1M8)-nC8pF|V*o^0Q zy|?EwDrIr^H(4PrAjWT=EOu|?u$WgEN}0tJ>n7zEB%lrhS;kt42uMzzy=>vMK3B9q zW3$(tS&OzVc;KNYZ;~~gP*mR$T5+7)$U$h*0Ws#S8CbT%cf%Zzfm#vJ+Kmi;BYS+m8VewtJ^=Z@mm|gLXWqI0Tj42D2 zJUjD&wVQ7-9G_%M$^n^Sj|$>Fq0!7R)(1t8R0qV2_;`j`VHPxRdcw{v58rxTd16-D z-=qO?X(N?_=fw*UuUNNz+}wGq7fEW4Y*2?!uqbUQELMes4BuLDw>P;9oEwj1bBIMZ zybM%v$^_#X6NhV_VlfPU{7|RS1WhHNk_h;mf7qbD-KX4qQ@@mSB}&1^F6FwE2E@r9 z65P@~zr|JgCaVE9_<%~d3xnz|lye*|7pMRQ|7H<#HTpi5l-f+6u7jGa!!*Ne>5!6G%#%gKv8)?zE4xY3gy8` z$7lSo^ZEP!6Yt)o79d770-XQFci_Oo`%)E$fu3}z2Z3DZ=z?KPnn+;S_3Iw<#lm^h zuW42<`+xC{V@2Cry5hyjcdvMKjs-fA7y$?AKg`Xr#w^r|(ZU)2X62 zz#&Dff|ciQ5cLxu{OZdU(T@<)P)EZuwpB9I2e2?%N#o8129w-=8XH~l3OvWZPpkTnK| z83audHqDZQ8DU&yqwcFvs}Ud8l0ZxuFJ8{m3+FIGKs6oENIv}c<45&aNvBVL*mqjj ztA~DSvuv3tS;&~+DieW#!qq7x*;UIZXCEs1Gt|t*%%&sR;NTV+pZp|Hr~)eFv)5mL zxMrPf@>fN#6Z?A?5YMw%Ah|cswQBKsicQ>zol60bF>5YCIFiqIJh6rZ7c;0$50WhY ziBF}h@c)j$%P~!mBnvdzw6E!Q>Ecn7d(W&*NGP81i)UM_*1kS^>HUw)4Mofh(2KQ1|`LfJP(j&$%*aIyE2|RzXpH+z~7s z{2Tm!9dX7%GL!M^=b>7X9T^;?h{+b8kNG0QkwKw4s4QZwxOYmYi_bgx<#_fcbpWw2 zao_;0a3|A~0~H#>xErWwD8?y@A+b0Tv*7{SPDmu_GZE=KIrvV&y2HfeNw{0p|Q+Z+-ru#to0p{wh&% zM`>WWAY_kZ}|MX zy#=RQ%ny`c*3tx7LcnVmW{6V}5HqB9SSDmE8tdQv(j`+TUv+?_Q})uI_Tq^7%7|j*4dwQwb1bjistYl$#DNFe0cZL(FpUDxH3xh?J8#IqUURM=+IexJj344T4zX?h@dwM? z`0TS|);_xB#^3h^Yh~utg1>UZd;zEGelQFJbX5kM8W0HuAuBTgHVX9f9bb=f5^b?i zeZu8c7w00o$@K~)#EJl7cVXl4xG_7-|86@F&>g6IV$O%#9-n^}As*2?F_BCI;>5(Y zQd*5CARa&M!H1sS_U1qXi_dUE)nzau7ATVD0%C;02#7@~NpTVLO1a^;J6ynk8i#Fz)A7!V@d&HSEWFtXFTUQ555u5 zR3GH!6>wna_X}W%W+s}B7TggaRv0wJa?WV-pEvGUFs0wAH3C1!Ggg(|)^ESDS_8+9 zf9Z?Qe`=}+s)0#SfkFkFQixa)@aqcbJ_4o{ntO7? zOd^U8EU@{?+OY`84!$`2^C9F=yrLM?CoTsmKY<}BW79%*iCed#@`Q@JY+-b)vKK9w zbefl9HkOsubeLU`2@x-l5mTkJtk+Q*{8Yn(Lm^1_u7SwS-j9c0+ zhd9LmF*?IC8Uc-l*z=nouHT@6@4MpBeC(NBL#EGMzKlv)YA9krMn(oV!63;OaRm<$ zGsyyqfo5tUm{6I4${B3O)<;h`;e_}By;K6kLVwG@&OTPwTe^22JHB7Paohgb7d*qXRft#;IFbxG zRkI;v1R*cD4>Gef&V`q$U+5UShX)9wGHBut(Zamq5`z_^OcttFd4L!T`CZ=wtntxR z69Sr*xBclyPN-g;|RDh>w4KEjtXdf?5oeOCl0S16~Qw=~kG@Ls>+mR3taU zil7!3!5NwfpTF~%N{H(%9TSiL`|S6o-FuDuNcYzwp-2Q|6|-tc!6aNsBbkQ)gcJ}E z^9&mTVs21`0&E6oPS{yAe_HQOmo(WFuYS6Kc&^0)A`nSDJV3=kFyBqb@jx1d(9pLn z27y2(go7b&y`7V#!T$Y!;N&Y~?bNL_jz=7hKE82%#eMP&aciuK| zT)du=lmf&aRl?;G^G_3(9~0CO3C)W z;JB%LzL2?OV-PZYVY=qw#Z6i?sQurHU8i)vP6Oi7#VIAviYFk(8@zeueGhDU;`Qq^ ze>KPthrs6#aP3~sG2%L+B>`gm<&g`DxjQu$SXdTlnhzoo6LekY)2m}gK$R$~Q7vO{ zuWLHpJE-Sn4^*i_{z=J);a}XTG$2mi;J>x|m-Bn}8u5mzRs~thg0RVeND64W1Qv2M zz3TN60dd7-o8ocTwq-!oOo?^B>f9x_O&okcL7jJv&b?>8{po-AoMSow{y;Vq0Cw5!()9OnQI!|5~2a?9_J?(SCW_{PA~I zZ|c-}_rCG=hnHq%*CKgA8x$=77PWy8%6EJZ1_Ub`5F^gu;x8N!7qE_(w_LMi&h^)o z=f2DHn=~LUPt;Q6H}M9Zgi zrF;~vD-eYS1V1Xo0f|LucDAx_&df;zFK>6+iz)I5q`LtCX+WI3$Kaj^w%vU1@{RK> zTOp2v{NVtEB4JQflvuN4ELn?FBM?a9QPB)j`R`p+xucL|fxT?$)Gi&)JAK>1TAML< z!_r6AKR1S`0S@|ARR_zaAWQfOO$9(~3*S8E(K$>GDm0=3HFD{5TUVUYux^z?!;$hw zEtLQ<=Z5fPMn)h9g24#*eHr}L!l4l88qVPnkRS}TkIngR`YksN>u^E6S1NMvhx+Xw zf3Rb3zV+7CAH4r=$LC(yQoC-=j9<%ot?z#R^VFqxFQ3-1$(bLwXnE$VwNI=4Wjv%n z(cNz5o$Kds+Wg{Z!&Ft<(ZQdQ1wm^+NDATf36v8w42$o4_3YxbzP;wvsznMa+K2S-D;|L~Ag*`}%iF@ZTOU~e?6#e~aDj|GMOo3g z3WK7_Tmu$)o6#dyhTj8`75t!n7AN}@uE9I3+TMLN%$ zD^szm*T~#Ea%jI<{koj@=+VwYOZCxB1LEY3Q2VPVz5n$Of3=V#6{sVDmqxdMLA`f;um!(QF4UylD8&ecK#^=vBm-m; zvAcA>;E}o0M~@_g81Wt_G;LXb-`49lY_x!WdYz%{eWfTeEb0*Ro#o z>z`Piu2=WmW0;C$+Y+@Yk@Y};%EWO@BPeMqNcHO0+1a|yS-V>{Z~VeJO&h*hts2>1 zmh0^PGVjz0lcsF=cF(WPD9Hr$=m_XOkTo5G!65(kp{WPHznC>HdU%{;@y`l#h$SLa zp0Eg10#JzrW;hqBSJC%xd;FnOjysP0S(baN=(%Y?T+s+7@%M=U#IL>e&E>$Yq z*b7nyV-T>JtJT7=fRjsuqGpT9s2!0Qm_$`5oK*Mt_nMv2?8BDL&-~zw(@%T7;mP{9 z1j)gNI1tR=IAq$^o$q|rHjq^VOw$G%i$#4tV3N#h?Ywt6k$@QEh2w|s5y~_&%YZ7G zGCQ|bqm3)?nb5l|v5UvKM;x3MfC~e@i289HR}qRv-!SaM1wXeCx|lv4j{X+WHuG1~F=SMB?cxbkJYM^P5!EAe^Uw&J9a=jtpETZ07*naR5oO1 z1Rz+jpBuqs_z7#*uJzgp6Gz{4LJs-6qW4<-_uv1)j=krem3M7<>ZJi0nN>+RVuM8i z0Wm0=#?TE=iDW`Y?BgYHwo zuS-x6%mqfNbwcf0p~j6*-FErK7d+njvc@k|gzFWDTl?2Ekp{%c8S0xRFI@fjiyscA zN*0%I;+#X<{cy`-t2IigN>xB?L*Jg4-!pS^_k$`-c+nj@W#PkHw|+i=DcN9?Fn8R; z3~VwB1I0qaD|!~xFA;bli;0N~T(rxOPZ!Lc((md^n{KG+(~>HH7{QsQFbL=8g03^W zRm&!?jT?L2q;r}c|6xV%G4}V2F?H)JA71_F`lkkb@#UU&;RyH)QvylWcp(_dyfH}y z)3zAb_9Zq6_#9|<+R4vvTzyN&vh?NCpF<~f?bQEAN&?`JfbBSnBFSiKBjm}5#DH=O zYM~>Hlm@==WXS&&UI8{WK_(8}fW2Yck9}6HdSK@FKkhvlGu@_530GV)@L6(q9ufqIEoyS9Q^zJim;tIBf;O!h zZ+>{$lpbY?TfELq1LAl^G70S*3=r@9U{h8_3JA8n^3~-xOF)3ORFS2pOtmVG$5|5NJp=O1-R$8@B8ad`C2uD`anTU zhDBVML*kh%nbQh{(L3g?gtacR3%EFPv+=8m03oJDGEqvJ#Lz&+3M`G zx7R3jh|q6*-F43{|wI6g8reVr7JFZirR? zmk@$B6#YLc>1O%C_WmiF&yKwR2LrQmsq0>q3lf74dOehgb$4V+$)O5jKa|9HuE zM%1-VeCm?=QLEUncCB%yt!w8?PdO~tbmvFk zo;7&LoOi>P4pg!@KUx^oC6hMcWr$rsj5Q7%5v#5`kj<$CKtpi+ae?o5y|C)!iasqx z0deuI^O9mwbax;YV zPhPfa?VOjk|KBxXQ2BYnSLk;6@aSA+?HI?bgtV^WC?W52M#rXI0pEL z0n=_CK4wtw^GmHZ@$E0+6EEr5V~?y?fuM;_syhB3K#Ys;5=xRG_+<`q^<|*8%nRQo z#K!nAB8>;7(m0jJbC?y>RrDDx@9)!qxV(`| zf!`$x5aX@ge%Dir9$NqGjgG8>$t;k34g^CX$keky20vI4%mg8K3PELTVadU&t`GL# zlld|6KGd-vwZl*7MTg#-p2dF^94j$-qiwB>iwQey)~;Rcmmb}_+<*18mo7blkZ=k- zK1WR#(tx<~hw|>_TcN(QE-`Q^dRi58K0AK9q18_tioIb%Cw z>leW~f(4#Ha~P!JQ01;jp$Np9^HUf=773&!{Y zs8GsM%!^1b;Nq4969_gC%jCNYD4ixL3Q(JXru(^TC?32xGaQ8K)w1EQKYxROCWEfY zP$eg0&$KBwkL%R-KhMT<2kxJLSe3a;ADsR8mgh$T_z7b=P=ao)5;(lT+&MazN)nGMnHUNr+$0T1|1z^@e)W|^p3)!_QJiF;@_)- zFHlN0*@*ovi~SqUh%Ch-PrQ5HJquG5&x+m4V%xR>sz!kFq!MzIgS==@*D}DdO;8;h zWCX=dg!S&(W!3Ddy@!`JR*5(-4TuvF)k&x9X6&#j-P$+Vn$8%B-fko{d&=q>9;-b(=UJ3)BIH+9HsygQWg;8;_3?VqWHe?#0M|RMxc!UYI3lQ zsSt@N+}Rbav$HfCUU+I{M(x@pRGQ}m0r6#5^xtE%s;DW!FN@z;yapZ~XFWBF+P#8% zeEv!X#EQzmG{an%9BCVh>H|sf0U-)l;UEN%6K&)|!-gk*wsysWbIYpAQJR>R<(xDi zE=#mh?A$~GV!YM+AAWVr{JU2yjW`PU{234mo5G>VqM$2&G2vmlC1#>Hc!*LpLtN28 zExIC)f&;M;h!eU`m%%oJpsEafngqH3?28;zv)Uh*UE1OK%PwlarTRI?z1m1v0H%*} zL?8`_%Mr8+{N&3YgSESK8~(FJ{b2JA?9>IsTnR#UK?`F*Tx5YjR$*Z{y>6Ayp4+mh zNom7z&4Agjeel^27g8bv|T-}Vi!T=&GL zXNGYQ z++&aBR5=0waZJ&y>q~&5aQtvF0i_lwD%RoH;P(gk4nRRL44UQ#8EjCTJZN&-iJ#pz zbJCSf8^*^;u{3c$*g0uHT#@J{`L~G%#OTX@Wxrc?e)-L>t%G3#vXTKdb$Df~>{@1W z&Y)WXd+2Z+jet0|C{M(pI3PxS%upx~fZ3p{Nc6Hml_ih~fMuGLSdPB#PVyslL|#4(h%0y4R;+*V#(8reUc{tK7Y3ycAQn=J(F`%?Q(_hh7%x6TK#a-& z0uYB-mk!MzSUhj+u+m0w{IrK2+_LS>YjGPrl>xD!Cx{F&76GF)7phIvuA%+*){CoZ zSA=Fz2#B354U4)sRRY)ZxKqdhG0y>uj5P;JI4?#sth`@%F481G2U*gfpdb&bRH*`% zX>chqUB!a1Ae?x7jbBF$yKa2Hu4inFcfs6eU;W;6!j##MeYfYghLWsFhUtK;`XDdg zfXwWw5JFvHMM$0%9xhG5%Mg1M0nFkGurIR4UWQmDAvWaNE_Y5GclFfLJY(p3cljkf z{xN9|afqJc8DeoqMLFT#UAl#R+z#3RT^FVws8yaB$O0Q}&%uC9E&TVECs&?XueSf7 zE|H~)TfELm1LAl^G70S@8W7_x?b!8Yn_*+7z3Px^DnKTfSXGO=V#ELkxy9~;clg^s zIsvg)=-~ljzP-k03Gq)&QK$byOB`}TsMypnhUmrPq zz#SL0IPuNH$1{C~7lAY&uH0v#?}*!;djI|JyF_d(+(K*j%DsN<)rusfyu=hg0Skh} zoD(}wB6F2-grP`f3iy@N%|pP#m5#fDiR`y|UjK$pauFO;>5QYIu+ zK5&Z|IY8t0i&S0#KonX4Z@lnCt%}eMTtIxM#WHo`$bufhV@(B*meW;=&G&`bVlg(} zz}Obfg$fYlA~V$RwYamMqS)-b^IASR(^Nw3tv!DRgQR8EwIU#;6L)1mPKS%zVcHVh1_(sIx+mw+-jEYWUKl zE2kY+=NjAp^G}x5=CU5ShMg^e?B`73)TK_|oy(dGS9Kz@YdpGEg8$A6a?V`E6R&*;U%^uYcx~K~tvBUB#44#df9RO8eVH zoOd8)0s*m@UmVHdd}#!nj%|Sg1`wLZ9$j-^+jE;A_j-Bz69vQpUFJ#w9$(nQxn2RC zH$QsWVj;H&$h&p{GWHGUKUKytGC-9Kt7+3yUK=xJ@XQO(towF(`*^6|ZF}**ou^Ej zv(|F-DhR&~ir^O@keLbj!4Ow%z*0fXYH}B~LJbTdYsLX_p?sj=Orz7Ocos!bod<{& z5`n5&F!7~BJ(sLPQ)8mNo`gZAVzndZrw-zFBDd?_7_;7_;di-?)a`BQJ~KBF`fX(iuwN?k4uh%0Y6-umFT)_n$!+@PgU?1Zqbfi#aWvr$%C+nr zAaVq#6T*Z5J^AF?Uym6zcw*P~jSnk9Ua3ry4 zz^#4cn+siGh41dkvY5xY{sLF@5Lb?J$2~xd1?Ewe2?UDBoR(M!h?7g7*u1<&X%ZYR zApR#}WywSdq5Of({b{MlTP>3oPpuj+p9B`}<8kaz|Z2#U38&~Y+ zp0P~SZ_92&lP0dSq6QifK zT6FtZOr~5vlG|?*uuT+EXP_t=mxMBD2sFP2R>a`kMn#sv3Wq>b2xu}hYgW(t?c%oQ zuIt>n-NxpP(;4HEo`N(WuDo|+${lO(-}J=GBP=xNQGHz2tGF$5<@F{?hbRtIJU~oP ztCb4Ss$g*)H8_1BD>DOXR8c>E{ker_mZiU6?F}7&d6xk{*-kc~wLK;Ul6f2s5F=+3 zImD{00HG$RBn&;SYQJ*M^ugtpw~7|k`7~0fdyGIB=`$ijiV|favnoI_2fs|HPlzlr z^0*BEl1rO5ssDeMU4F?US6$q0T_RKl7-RC<$6pw-Z26V|^dvHML%F1~eVg!LmQ;|uKU3KL}tLM)gKJ;+U%Abs7 zo!jD?e+)bOhycX0LtFqX76gJvjX_lSSYsjxo#<>M1S+B6(<#(D`Pf}|FS@f=z1k!t zc*C({k_N&!dRS!J;{0oW$`4D&MJxp*v|JUUzLnE~60YKL_l5pEcv)r$u(nkt09SQxyK>&lzGVW2j4{&q{J#17^OOwTSA}a4C-W!@h(#td zmNLQB&~3(z59~+~blHF=4ePwQW&NEOl(*keKpfC;{znx7%&M9e>d6Ags?Lk2uy6|d zgFsW32#;mT5yLG&$jzPs-bu!~Kpiri_|!&m*tA`t~&r_+-mb zxy`b}WNvJM*~oXSmSW? z0L&1dd+9ZQQ>doc+*~Dr((A+C@kG0T}ae)#pn`=57jS>w@t=&dil`|b~y5IHM`ELGN4 z;&Xmfhgq1T6ar#5Q-{FRqL`_aK$TF(HXmwK(f)a7$Eq6TRc(j`#CSzqB$&1ViX!nO ziLkeKz^4a5LZBQ8gKdT&D@zC4%(qWCq2`yj&z>^+!ZT{W5uYfO+{)KKh3ecoZP6ni zfBMY@h9yg~9sm>F+6aJ2!~FZCIBE%Hk+E~PyU=oZ(w@HZp#d@eRU|-Ahu$`FA)q^S z(Y%>gbZXo1g+tx*kp_s7GKo}^%*+7T4uxg_2{QmJdQ1}~YgA5TkwSJvQ$=bYxx z+&1;*n=0x$bu^4n8W2~`D6V|))tl!od2qhPd^|ghAHZbl@OoxAv4A)li6|iE-~>%H zkkd*mkO&3G46$`!Wy1q(E+FQ7UcqG@TeWIre|fH5+TU#1_DR=y3+`X}>mT8o4)FnM3x|yeP~re4 zFHI)`0bK{ja9mT9n3fN)CypjC4iAV0j~EwZIIr7w1Ty^!P;)=)bou!!m(CeI;&6cY zoDSXpc1U%_LbD6BKTla>4&XFD9CvQf&KO^0@I)A;V44x|tC)#5A;ZUVA6#{Jo92zG ze^J^oOvZU>K%9)I$LX5M0L0k!ag**@xApm5y+QI5TT-}af~Tf{t3v#DEFMFd6$Hpf z?@vl$`VXD^?9TuD>IzHJKtlQf6%J_00>uIlzSBg2g2K3kGo3s8mSNqmX!c-P?;X!yw&wYp7Tmi5W!F?mR-8!0B)YCj z2#yN!^FUQ)$jm$eif*h2glUR z_+{4%_n$~e5o^~XmqiY7>odFk#iSbQkpPHsXShms4&I&Bv>kwv_HI)F7P>F&6o4iL&67^7_1WSD3$8h%f$zJD-_w!T zLK+Y!e$23jpyl~P{`x1MWLiW6iZW9Y3M$Dd1BeUtVL4?&aizV4+!_L6+`9Ft4mfrg z>eR0G-#4DS_w@2aZs$keo;6_5ly{j_RTz^b=_^_qKuiD)M9{ff2Wo^slPu5`lXdEF z-pWODh8;3nd9c_-0dYV@aA(^#k!6*rvLq372Bf%%52IB*oYlPHo6}}Z9@w;Q;$6so z`is@+)qC`|Uw+SPBFh;Nu?T-g4a)>g*Fn)y?T7O0rJ(XTJi}RJ_=*AFlE>CnlPIL- zcr_qGY>X?LxO()+r41J3LUx7*mif26>Csg!TQ#nFP&rKx5QAJ(HK_pdshlD9D3J=+ zZ$=dn3ZY;gWcXyTtUTwWI>&swbkVGCXPkEIr{#IqD*HD{dX>w6n`uCtd_asn_$iN7 zzjgZj)z82DerHv$ibOKrF`h=;j2*pC8azNO}BSr%_Y6lsWa zu~>o2+Yth~=I7ZAj4l2dv&9k-V)oUmW&YmfiVk=89ng8@31yIxD*v09I=@T<;>3@| z2fP1j-Lv1wU7%D0ThbszF~cTv=eJU2*b>l1!4t+Rcab433W!}=5*DYTt}NC#fXM+d zvxDr?4s9P^Hh1K;<>}U5#{3=5?)SH4XZTFQ#kI=QOoe~r0b))W!R>Vfz6_}nt`0G; z-POQ|plxmjP|M(U)tY2No#V2<-?4RR{qpdLV>rYLrIwSK;g<}#Va1vyfPI-gU@=H{N^yt2U@G5ekJ0 zDH2%7;(_C$VJiOdIFd8O2R;CY1_z#IYc#`vTfUrU%s*m6!pTAMFdtlD11b>(R9WRB z@ha+NhC+Nbj$AF=w#KXswZo8|rCL7S`Fq^xL6ZkvbJ4>Uv1d*4qg|%UrvY)9!d0%5 zSFU+^?1H=3+)W`zVww&inhy%fE?PnnB^gH)5OXbs5&dJB_G;8Xl zo5l?4(YoAPyjS&^wf&PXerj)F0w9F}F(WEiSeUEmz^DZpX7*_w1T>4Se`MKdO&iwy zs;pxd3y39jH~}h!f`5_YkFAzJpkKFngRZ`8X`(s8UY|ezCQ^Uu^f?4Yktu|5r%x(q(V$5)(E^;boh!s_bU??9l zeF3nHAow)`x=w#zv+|xUEgR+hUs<26WS^e~#K|6k3S7Uk0dYxPedo)9GkW(K^&t>d z=GEM?2Bu+yqNzgei0e_t06_QS;jO3-z1?^y@azHU{|y^uTJtR@Q57|KTQMT#1GR=lUF{x?WOm&gxYQTbU!wi+GUfbl4jNBMoF)Uz zKx)YTg>!Ge>f-b2yjs@hDizL81L9N|g>v>G6#y}IebY1V^`Aa-{%VK$RnwLM9d;-# z#vKb}nec6YR7*gf5pMURW1GTVUnQVCLmCZ0(YdMke?KulCP`BF|z!9@s03qi9HE`Th*LQgs6_}5lHI;(3fLJAUl zkI8L44TuvT|Bl_J@A~rVKU(u5G6le7hR_&CgQ_HDh{audpul^N+;<36zOckDMnVOU znc)X!A}D4cIeD<_la1Lm3CS;SWE9)`gJ znyd?22iJ0DlAy)#@1+B_jQZE&dWB!f!uK$0r(Ou?J!%mX6eCYy%yV(Xr-(y;bajkf zA5e$$u<@^&PlNnm9>|)^K`^r{P?!yxgg%8PJHB?!&lk!RXZa1!X-WTX+T`o z*&v0^PZdCnAzA;#JN<9FW8s4~^D7Z5Lw41g@ONG=e{no>4k3b$t8|I4n$fX@n4PxK%B@2#sLZz2gKAwds-EA%?Cy#%(v)ra&%TDTmA37i*Fy$;1VmaKxtRof>Bg90oiZ<1hYhM#52;k(wi6_?h<+W$- zKj~n~K=oVpGD1|<99hSjI*=R!Dpf#2wG1Q&NeGAyPOU?yxFQQu50J-vI!kf_@JvO- z4lY-dMl|f+L-dJIRUxN}1@ovH<~!gJ`I^ahjJ)AUPrjr9 zaam`B6goeZ05OK;-A{hGVDhv(SADnV&jyqQ03;unmMx0wkmpK8##oV5o-yWIR*vOv z816tXCw5l6B<#;NikI3m+dQHjCdHOCOw(JmO;TC#01PUs&ND8~+vNo$1%^7%D8{I?Q7aAzE>(nDJ-_8OA z#3D0%uuNm@JQbTAj>r5}{F-9kjAr@7mOla?+^IuAjD9Ly6-YJMvzwQldV0N_ugfxq zxw))rP7dT&W=0s5jh@~9_O)x)ZkVv=$6xEHx{sja9A(J{#KIZSbFV8>D2MvxBy8IQ#Fz;e8Das55iB3LLsR;1 zB0)+A2gBa;E9f@f;h@W*F95;(0`4`S;`xrv`(<1E?bc^Cczg87L6gpFQRkhqJVU8^ zZW<7$>d2I$U#SL&vCDt|&2p}}?)rDX`DR}OO|J?-d_Ylkg4sZD+ei`)Ht1x;HHsy# z7^c__m$cpJ6*}-!kFH|8QVe&Ar$mbvalwJHM9!on#PM;lL2X|38!q?(l+bhs%4tRQz2U5GQt2M%=V;-K%eY)hBEq9SWfz zNspZG}<`<_vrueb)%8wl7A<1{vhngBEe0UdzSeAf1Y zRvT9>p3u9b{+!&bn?aRq&2lr}NS9Ek!n45$h%rO#NQVN%ZmY$tr(@$J91R8K5bwd0 zq2tc8E-J)t3ok@;7%xioDKa>Q#dlk(prq_?V?ajObDGR^{rXzvPY_wei8Og&aRm45+2{_CID6Ugpm=P{P zn#}#1>mXmONUaispAwgnz(Gzn$}M4G17X5bp6iZEfQ~7+=rAH7@M$s^$+xZj#*AAg z4C&Xi&7&!C3vuW~8W6`JhzDr`WuVT!=(=ADBHFP9VFzT~?QsDyW{ezLEW(m?910L) zpHxkPNF)RqJ`JcD0?D@MhV?7YI;&B}M-}b!q*)KF-1PKYgKh91B2Dgrwc-o-c|kDjJJK{eHu?U43tv zJntduWGaf9#jTeWRRhBouBZssl6iQP6>oG7&*ii=o(7@MM7V` zx48--1j)cfj=D{{n2uIe1<4OK!|XExV$TE$0Wk$fGTjWZpivYS-W5p{Mft$|iHO;0 z6~%Q3geeEWJlBNu4v7GD&qF}0$qGcm`H-FA17?K5HVSB)R?Xj@F=hPl1`YK8CNuVl zxON&4CnBnq)MlyzV!ZuVc7Aukt% zZG*eCJMGCzdQ=m7nKU3yTzGeXli#>!uaTby4FzN^gWEN8YgW`bv2DH`oXq2JfS6Mx z8QL{FAkzrQjtM(=Z^(*A!eG_f7st)Hd)-1CGD;w^9!enxBNi_}e5kq4rIBD}u@D%G zf0qGVUm<5)=i*(d%*@VoBlei6W!H5(R36xmK?#*=);W51iTf)XW1+IvTdFv_PJs0@*G$1Zbl*)I`-78+4 zaR16p^MWX)=nH^Nap5Jnk=}>Cd@aZ4SH%^xJWbg`jbev_A~RsN0h(;X$#rV&e)*Y& z&Ej$Ox8MEY-2Nk`?zAAYP{zu0C=)5S*z9FIsS*e4eT;RrdkSWSDcTbgS=4Rte-d7E zpgWWV{)!}r%eyGixE@rX%0+W7jXP@P+*%zyNQ-Cv()Sdy&zGCB3Y=lAmhFGbhE zh+sVm`XnAYp%Rb&9K4OFQz_rEBtj9QkaB>TTQsadK&&Fb6we_p(6TfA_6?&4j2zPE zya$T6f8Hg-e%bqH=uXnjB)j$=;47po?MDiqVRsh z3+vDkkBK@IJaB_i;jFu`L#P3rF1v8!ZIefgtSo)$#E#p+TTcVx|7Y(yprk0e?yHUy zc9$q33JQn;Oc+oE6$KMuKt&J`#Q+MTf;nOY1j$*+IV&KTK?D>NM%3>&Vn8LcyAwK9 z{pVG6&&)0?Y?$4hf$4J;mhDjes=E62tNZS)tjH(fx~UF`@fLUPWI3Z>o%z(#WvhGT zg=jXD{J>-lBw6NKk;tInTVd&@*jH|0ZkAUxB8Kka4v2Bd8aZk>p?S91JT9(F64p8M zjF3#gGNRz~D?n`n6s!=Y5#y5PXTI}b-=6oMa6;9zwS7LU0PzXOe7s`*!1I$ZeH7~y zH{LRE{imCLZlMMI5Q;`X!pe6^0mHQTM;7XkR^|%L!2mJ7>^ZH#2}4i=dc~#9Cy#is zSCNue#R`hM6V^+d)27QF4u}!_#3Z-&rz2TjfVe0*H_^zLiU7}4x?slzX@1oKi2i2} zc@^bDX9&m5=GkOb-kmsvvzR0Qi_0mTnUiGoj+Y)xf* zTD5Gk{D$k=&AhPLQEN-`Y^3YH89hj@P>{pzRPO>gV@ zz=~aatfOTu8}dU2w-ZGWCnh;jd|+5M{}Z{ej8VQUCMG<=&GK{}y@&en2E;ChkON?k zOC~1i_?+jt;Ki5IJP;u>2UG`bMV;JPGhc0a+R0gIsUMjE#N{)I{qWoFcR*KH=eo20w_xPoa$-HVtoM? z*I}_Oen6vho35)oCIKlAF1g_B*CvjA=DLzzJDL0c^dD<@=WX{c+qT_koFB4@=Ff&G z7R||CwMhJG1!Gy6oSlOMVnK0;f0!VeN6@7!G6Zz!K zRwS^@5NN8!jh(7wYx!L}UpwTMj@ON-RqN2!urEA@Gk`dmPjv;KD;+Y#i6Pmzd27oa zxA$8W4olhoU`>dc6etRhEBGQIU|N{%^nr~JEpq<&Wav7$#j1F{3~^j$se;3vLYKoA zpP))`K#bV}E`#L>v*Qw~x1{K0+C46|C|L9p1`3Hn{RTBRu2}d|D?*5oLN{2frepwd zvBFg1o#rmz*!$_HCysL<2##dB`o4vAhbxo6?*bBTHX-N&abpHIV@r`|k55Mgz}f9A zoHf4b*{9V`+J|4C$0ki(@#cmes_F;o5HM|2dBKbz7PQ#{t9UMY2|bVuK#cRhX-0WH zh9+yA8i7-%EU8?7nCrfyBp7jc=Fg$1M=X~1@n@fE+ov2~=abuS>-a*uHs`-p;sKJR z1EwzepvTL@UL9iFzM4@3m#!2*oQLy2(n}jT)|v%IyVD|ixZ_3-6!1uF@|yDw|}1Y?DJ#h{P4qHjV()-G`|j#jLUiG zY)8PS2f(x)4vKZ33N~`CJX>SWssr753RqaCXa|*hv+#w71$9_uuDXC2CpvEl4PAy1 z5Tn9}3l$JB^Vqrim8K0om4d8@D}EC-DLqK%B&2CY%qOfu>NPXzNa*kR4PY63sP^Z&Y_vpFXz@ysG6XD=Sh@ zIPq@(%4Id4d}_oi8#aD@wM+s^ZeA25#RvXC5c2YKLDBHzz940e=R@7GCqSU5=urAN zmgPuJO-pzl5;aA<_cM-4PTfJSuA9L}DQ|^D>HWPsK6`J^_Rl4@;kuh1`uv+8wsXpa z<5sN-Kr8?^M#KZY3QvScg8%EPMQ}juo)FcYva_?f?sPammrEt$N`YmXAW5i76lOlv zVQpHseC@Vdx(saI_=rtqiATC0n*qdW+=J-|h%wy1>|#}h4V*M~-P+G?3R{Lu`SOj< zGXv3x1O8w(uXYVbL!heoLUFUiJQF0UVPh7V2_oWY+?AzldSV8+V1`(r76({D>_mzW zL4*g074g!vB4C=hr0l@yryjR@!IVL5(`n4Jbk0#)&WDr;zt#$^|=ydWCh1A%}9`FT5N zjUxiP?(ci&1Gjd(WM(qsP||a)djFd%2R#4sq&;D+?v7nis9wD~M2#>9a!8rO;zY63 zFV2iKiMU!qe9R$4EGzA#q-{^!-@7)aG$3Qa{iOh{;)g^)9J>bx$7C29pLFCWZ_FQj zUg9}Bbb9dfFMs&&EUKdE3j%)ZV${=4$ZNRgMk{juK1AAK0wCt+laM}R^Hl`Q1p9Pc zH8A+r ztPk!UGwGF~yY_~IvJwDE4gzHgL`~G1)Hw&w!I^zOfH;-`sl;MRQKuT{4;Lq zdee{j0=*m_Km@@C9J}-|LJ=~_cW?ESwX?_TWcR`Js zRUjG-L2hn7`1GKleejnYrbqCj!pnOi@)OjZL|3)q^jEU?*#{82ng5u!FXxfRr9m-s zkKk1RSrarVMBiRA_n703Bma19yS7um&%XKJjIl9# zDu^WF0TDAa!osodfP;n9vdtK^2vTS+Z+-FH-o1JZXmWg&pOYPvbUt4O5T|kPr8^+T z(69aU=kte-oH+8UuYWvUk^)+GPHot}V=rXoR0G2_c~Qmw0kJ3jS(zNhR2V$_t1{oW zU5VBBUOf~aKZ?pZW&us*70^BfAd5wQD|o*t56Y zp6qBfzq0q=fBwCrj;3WXMm1vL5;g@;Gz7+IloO{cC3}Sni;|HW%3bKF#T5ehpTwcT zfEv26MYBbnJ9b#u;LM}eCzC2tni#&jaZAhj^OrsN!H1u;4Ml8K({cdKHln5lit51b zJ=>vr^(x$c-iV?-u*&7(aPw9q;i^mIzw9|XY|20tm!bqV$XH|^lTM2pYj}W|w}v7| z84LF)rwSqXb*wPdJ-X&UEt{YHdaDbXzjt2KlU7%&M)s7Z4-fTYGJrUZd-zZQ#QZCl zF=_g18+(o#`N~T>c1Lp*1$8GSkQ8*qN+=3LROc@HdrP;KC%Kaf0|&WdqBw$QP`m=V zm}O_29wB&lJlecU8Rdb{0+gxfPNaYpwjrRRdzB47oUNUFIHIQim$}m>G^<;e>`H~Z zEvgL}K%D&Ex#)_1zy1AR&`x9W-{#@>Od(OKJ{5_fkf5E-4m?=7Zm_ z3rlHK$#8@Pz0kPUTs?Ihe=bxZ2r%PPe{ticioZ**9dSVHQTbxFQM|2O@dK41Q2hh5 zyc`hY7_mT;DAYYV=lA!Pk7(d=xv%cr|I^Js?>xtFkh_obyU38^v|Jbv^YSwjv{t0mNxMI1Uv+>~+Dne?%KTJK*J4 zzTN!G1%@f9$SICj>n1u+#s$XX5WHETO%J z8X(47V~mjrGv4n#W%9g1d-Ba}N>yBY9lWm`D;%;(7*4IN0R@NeSf7r-&^apw0ZRLr{@_4sTs9#ZdZX3%y`QDUO1SG z$wD41p;6R4cd+A1+xp@jS9q@Vj`Q>&iaw7hl0$$Tp}p?7_W8&9ba)2$?$vMTlGSU! zzRqTTuyKWh=YR0|bEyy%x%|5OUh_b?8wUj13EI~Kn61b6?ZUg`8}Iy}opQtrP2z9m$Orz>Fnp?s)!% zX=AAq&_QKj6UINt71a-n8zX~IF1FXs&d{jfAVab{~OOP zG6!TX*@gPSC?SVB!?NvIdzEHq9Q)q=_uuy1xu>7FF4^~0+VgE?EHHiaYtK%fwWuE< ze%Z7oa5w;#c@~&kOt^*+U%?o-XAe;K!;TP(8>VfrRo6Tlq-u0j-$IZ(uT3wR+J zMi`4+Igp_Ss3_{DI-tmodE9YzHeP!9CCjg9bPZ_exunHAr(AOKTXhMEB=IiO=2Vq7m6bL^U;VVR$@QIkedo|> z;1IDKez-nVhdLnk#t0VOOP?a+9DIgvnT*ynV3~UjYZ5v zNMiXhHo_A)hP>!Z0OHD(jVkR^kj&!_42WeJz3nZqjNSIN?OV?p^}>C(CG+aZI9CP` zCnJjSb6nK+t}R>siqymG6qVe9AQwl| zEgLVGI`V-o#XoQH_x$z0{3F|5ao4|=699)ujL8x)9SVw~b80{g5WC=y7g~WR4#Rnh z*GX8I6~+$?)CSi;#I=R>ODURJkm_5bU6N7q3&UVY&lLK3V3Q!|K3ZB+&kCpDZEd$Pj?5PMPG{ClYB zJ-r{EzIE%KlY!`JB+7tj0Wci#V!@>$M8K9M9)7|z$Ku7!UrMgh0x#3xp75UaXT|ng zYF@1%b;K*y;PO3^1I&(q!XoB`Q7?74?4lD_rP4iQ0CDnqjNA9roXUcXv)kl2#O z*HO6Sn){{@@>0U~yYijtL>t7mFCa!;3|y1eWXtJ!$Mr8gc=y#$Brj6&Gcm@L)6ea0 zMNJS4O?znH{(hok|)WN1ca3rl*fHl|kifjS3^Q?vq>im5Btv5Z_>FNs>mdDCU z5(AmEQ>EQ#%w&iYCSteuaH3IgBBBvcrCjGw;1Cxz!Wm=w)LHB9o;YF3V}`9%k2sn_ z2@1F~FddTvVo4EV{b*?_mgPLVPXUS(mz6YqWmH^E*X-a9gF|o&?(Po3A-KD{ySrPE z;DO-o?(QMD1}AuMhkKs)uJ70UJZtrI@2;+0yNb@So!ffWDMeAO&T4p%2Qh#PCVDOD zAfv!zy6@q#m-QZ5tc_Dk)((K$T@IP;Ui$e*aPb6tb)+Y8LxA6^7&yWBbvEjuJ-t4X~*aE7ZsA$z6-jnw@DwOVYS(Fp`U0l&m zaF*l-W}{Fv0jD>|;Fx_^ZN|+~z@C+trCghFlCQzC25bb;Ud`?c zPF@wRK1$bytyLQZm3+F5UoKs8)EfPezM9o*5X|@TI9ZUK+&XnomV{iCmKS<}A7=^4 zI?=O0GL8D}?wpk(PN64`chDDY$Jbz&1UtI?)S!E0JL1;ev3RDY4&mka_M!j$+Lv7W zUhjTc-(#e{(oBup(9qCs?oNXhY@~r&T1&=`;)p8@@3fe(-syx01Ih6^I&keu73=GB z8J|T)V;ZH_E3hBM&nzIko&KOvd)(k~eq>+tg@oG5G(HfqoEJ6fq5hreRRu2*aq0JV zC_Pptv_6cmRNEqZh#4d}T7s0GKJsRXBALdpT4Y(AFqKZUxdf~>d-cZuZESnJ}AuyieLFd~dydr;tgBY{(6*2Sm=KWvs%hB0|4V+3i6zVEPh zM?l;?yCy9zi zq@y6`!XGKzJ*GnHevBp`_$CPEaP??PRS?XSbQLjtt*#bd!`Cz@-mm# z^Vr|_rrPG)quJ-vZ60!4I~ROlG=T)MSDFlbE6VW=jZHnd32-2ozHY#rq&e}-2&5e2`R82>a9flwgYe@SnCS~B9!83 zmIf2`r%v|ZEf%0HbPG=O?RkxS0>)YoJ z*|Iz@pAkP;k*r2j=WxVVW{io*0>j7%6dQjaCw32)#E{=t*LhU2;xYqbsC-Kt&I%wf zafx!2dS8xmf(fmr}T`i70u0~OoQ+iKbh@7Q)_U9HD(VWE3Z2E zzOLXh+sfjS8)8K$9{4>3KH1SVWm>sJ=hyu%Sdj$-whN zQ1GJnZ;q58q(_*J|K?S$L@ZC*`@}U)kaU;IuYB!_1$%?M5c+VSQnbNxTBw zgrzkH4H8ej@a`d%i)E;t9v3@@U&~~O{vcW`?dhz)Og53MI8CVUB$f|*AtZ&o0mftq zY6!;|pI6dti3iZ^jvmmD=p&!D;Rgg){lFOHZiR9 z{2o)^MteW59@xzpbv3^+z)RzQ(W(MLBV$@)h~dD~yRhoUX&b+GT4raxCwk9$lG1&X zgz?)!$q=U1ptt$NQ{u#zLiMddjEU7e{)FV|xB@10rt<6&K&7j`+Zl!{2= zp@o*gFjnz1&_~$VLlSFI>pXjz#`0EuzB-8Jj-unUedlXWlw&cVA@pBk#P=8LatY<0 z(5pJv^xw{+UWoD8-B)8~J5PMn#mrvSqAIvH>sin2^Zf}QVo^N1Du>M zycXiPUlKnxd(}<9(up4#PO*(N3~b?d4fF%lVdk0nwg1-`S0vhoL>jY0I+cp;Tc3-t z*VR3epM@-qEHw99Z#+b!{dT+dY0zNbQL2EPHhLyCt!US7yPW4u597iwQiFM89&L{y zjT(yhH;;FbkTf%(T`X@7+4(qRQYM21Jk$N@yXKJY)vx0!u;d z$|uK|nLVycc#4$d?t_V3%< zTCw1uP*5gI!N!0#WH@9QIQWx#)p>r^ckNDcD+J6EMgkVMUsIN^+R{7`_%3*12QBux zGv`ZB&vQq4+RRkN^Rk#PD(o8fB%C(ZfcNfp9gh1*2&mdfRLfe&xr~s4Z3rVvX8iB) zE-1@t+cyfA=(-fmT8=!xnG;)cA@MXMme=p2ugxe2(Q*&T^55RIeO?H1&_Skv=#cki z!t{D1!Pj6&HYhO^tGU8s0;PEG#|SCwJX&BOIRa|ff`C?0t1WJ2gVV6@<{xiI{iDmk z$7XGw6PnLf1vU^f_#=gUSKF0-(eNMfa!^FD1SbW%pVK*8?25iUltn?vSt7+n3wk;9qQz8GWB|{g`+$#klEF)q5DWH-j zeE&K06C^2`+iIN6K)^VvBBfjw8pN2>}J&tsA7Aw>x`}H{{VvoTH>zA}OK$*gv`YT*a`~gE=EUh?$!{KRp*Cb^WndfDtcE3ItrUaQ92SB##$tH$ zG|W~1zzznY9ztuI3RI7bI1wN^*3s)Z8ti{*_aHCX1g6yye$VoJ9Y=9}uO+X^n6jP9 z{SZyG%nvj^DXR}<>fYUT-Qxe%E^WbjCoE;$uWI%cQpGz?;Cvayi;G@RiC0;X#lSrn?_1A1)jzdkOY|R3+N)sqT7W2eDRt?wizOq z&TyTI9uBSt4PDje{C(DH(I7ng+lHj?r?l|EI7PM;riWEjAlk!ee4Cn~=hGj3iso@Y zc=xd0QeQQPS%T{4znU#bg>ZYy-%P-_{eu{dgoYRr%uHZ6&yeP76kel){0YfV&#i?g z4diTWii>*7bI2f2ixkNn486zZ`m*;x?8Pu#E~Pg-da#dJZIq0yp{DXTo<1$F`R<(t z^XlxXXIAPMR1X>?rWwgMySN)`tKn!#4E4x?OH!md?jywKPyhtvki}2istRqdzYlLl zkUM(i_=Hpe*p$$H*wPL!;`c?DJ44#j{)u^QyTZH(rw*3RtWnIckU$^TfY{!~*$*)jD zPIyKwvNuoR^LUUmnbGlH#-Ckdd)qc|eB@fU2yp`o5h0myLxwr*sRq`oY3O)b$gnr{At)uL&(1?*e&mul=YHQD4oGu-PW%*( zzgsZzf`)X8Vb_SZ^q%Q=*YCk_^v5*~-OzatkI|i+P&`1*qZ^ z^q`YSnmVdYI0V9{qL`|RK|2UyZvj3nZB@yHF=P0kDseeLVUZ*Nh+n)@TyZ#S8D z!hJm1o(4+ORiMt5#RF2B4x;bz&aPP@%zwQ`D$Ys>iAC19*{LsVNwOMVj3XHLKV&cp z^x7!tMdmDGv%qRZW$EJYZ)SH3MY1Hh;x}Iwc*4A?Xb0;WJ{y4QKBSMLJ894P}$@CXt${g%Hwbi z`B8Twl!Od%SfqoD9dlfq&I;)WXJZ%^wETKNb{~##k8cnT$!E?^m=Ml>KYeG_ATRkM z77&3MJ3IGbX_9G@E8;M|)Vc%IzZgQkx_}4BR+qr}@5wy}_MkR_LLJegDS$eMdo~;i znLMoSw7&16N_>BMxQ_sWJ1DV#O)Rl6z(YfJ{X?ae()-=O_>Bmo_ROmVFwgglhuW~X z4xvN?cYch>;nCHzlrx|Yc~qvrE^JNf=zF~q%#R58yKB#Au9*U#YD$J$`KRD;Goyc@ zS9=11Ky{Djf`P5xwZZZNlleAS{R*mYm8S>ZNg!Xt_oCLnGwuZqw{w|t){pt`pCT#ZY5xK*=_87>$y|Qu83iTyP}AKeWg=oXOKyN zs8y8MJS?pCMgu0Iy0ibfjcHzZ&1j81U2(!$$c`>n-v!S7LtVe5kVwH2i-MN=7E<%H z^T624l|l(wQGq@YWuK|`xq*&82DK#IV~We_9i&wP6)b|Ye{>Xjp;WLt{QH3E7bDBQ zfJm3H&Q?!BJDU`Jg%QoC&rt&cPzlZ4LgB&YXCasbOKSoaw?UIiRk}Bq6IQy`HGmGY z7>Jc4Oa=6q%jkgz4WG~iZ(pZox$S#6FsLe+wTK4LG0h~~HjQ_PLQHObm7oU$6Xbv0ee}NR2Q4BvLCI|DjClO6Wa?<0dm#c*CYuvs8nE9CE{k9LL=!ns~k(q){ z0vXdU*p3AyTX)1okz&}S;~Hw{#U%+7xWHqR)Q;K`W*?o&681TrM%Zt@9`)4{@%MoCwUzwQ{0+qhfp#3=T-jsN+K(R^{LE~ zHJ33zojX`48N`?(RqiqQD5oa5i<)YDOcG8f6q;M`b6nep82WsqB7!Ow9#|N!N zrgzfxKYChZkL|3|^W?F26AxP{&K|WBhAGHSXVv#1+NR7rm$%OZsm>QEIeX_1z3taE zkr6d6`wVr2Bj=J-1ib!j1x!$BER)9-R&5P>dO+0Pox7Y%x7o$1wq>l1vm@Vq+o2a4 z&7|24Zj)@GlWdClvQBgN!@7NEoND1`n87BI#n26+Sn3+R@$Qfytyi_SvC<}18MPQN zwW448z4R!}nEAe>j08=gQBKk*JOkvyitS7;>-%pU%cXL)__N<5RNAAgBTYM)nnG;O z*JlvvRFhfEaAuO0Kce~>A~CeT{=y287$i%_R*N>>Zycdse6l(SA!9^Cjxr>%E1Vc2 z14Rky?(@Ve{H@=MOdA^b*Ixn?+yR$dNKaU47-%lt)B8S1fYW;~m1r37$0ymw)c0i~{hb7w6c1DE;w296 zSFPzK)#WAOE_OmfKfdEEB_sH2K*ULo^f%HReB~k}jUAU~7$+meSzKl6Y%_77Jk}IV z^#$oWi8 zCQ)P73ZW;$9%;3Mv`V&Mc84V)GYLV+xXK`rXps?i)e?MI{nX%9vLx-yo`;!~qSIya zk8~!!!PAM}|ljR$&F z8+pl(gZ~I#?D`%zy#Bv)B(z3fQ7LeG(eMDKD``WG>*7(4VcQlR386%!WK<2uVGs|_L&1Vlksz3EMl8Y7!P#DkN_R@EQaYET1K!e^w5O_ z;hx;LZkF<0@?Nx$h);ieP!**?IIcqi>2 z9Zs?is-_K#eCqo6*9>vJ%=K&_dkLnLb^9DL6>?+e&3u9-bVRgkTED5xG$gJPLJ`kq z`S$X8zk8fh7WezDu+8+5uCCDY3X*HwZ1ai3;G_1wZ_F)7a+!xJ<9bB9yg!heN zFlkA`Fa&>qvT46J%joRK&_F*!AgIiG#|EXz#`}7=9Fyc+D;-Z`s2fi5tH2XUA$zgh&bDpyO^3Lu2WsYrNz+=55C-%klYm(qFTZR<+B)D^_Rq~WT z^R+weFb4ih6ei5~u+?_U+&Yh~eM`EHW+td8xp`L*re)X7Sb_08>~m=I&#o@;7@Y+Q z_Pf}i7$@|Q)uz6(hk_oxb`VdpI76TM>z=ZJbchMovXlZeGzM5^Cu_Vxj0f*C)-ZbE z*+S~6f0N0~HhIRI9B%!B5Mu1%lHc=bTI%Q7&WBh9VFNq%eA%C%S#hYk(Erl{Y<(|5 z;pOGsh{z~pJ3yhVl>U2Pv z{3wcpTHE=?%^Xd}&M{I4XlMS-Yt~v~eg(1shp(p5TAT9N{O@n_9iHz6WUkQ>wc26? zcA+H^-h;enMf=U7y$mq&f@NpG>^7ZyaNfT&AsW10zNGqrQL+mrK0*JI-dwdvB;hP@ zKaKrV$`KBjwW#_g@Ee^141x>aHoM+azggF*$)Y;)9IS)qoX*34ZQ z5|JI{F(pxz!ikN(>PDCMAvvzHP#^;sZ1NyhLrB>)tj*U>O@b=Brrs+Ip8-l)G15t{ zzoC!m-ShN0gWA_<#>p5ofgkQ!NzI#)14(*^AlMtAfFde7Mx<82kB0MfeR{=&+vJAhY%OG=Ii) zs&-6=3r`CzTC%pjwQEqbN`Oe$04%BALk{Mg`+*7J@=diML6GioGmCp9Uk8hnnAKvH zbP~bpg$@WSJlpL{$&LjZ8!~I$;gwB6M~4{?>c&pwkSWF?2DAxWzs5Ps8R#xfM%a;$ zkFA$(J3VpjBve?jX{95?QQU@LbpeTQCIZoEDy%p_tf3xuQk_BQ1SwQPxgO8aRK(hVSkYxqN2QJ3Mju%~c#|+NAz=je5W(f*vMv^!B^6G<0bHGFKUb?(S8e zTLVKTObDs2*@l2Mw);l5L?Y<_BC!}fQM?XBV!klQC4Bi{K?y1+4F!zrMXB1iRc{9A zHRNrzdNnjAuAk=}I0EnHXFe}`Ufku1R|boR{dMnP=Fjlp`>zm7G4YP>{Jej3Wgn^W zJKE!Sy(vUwYJjO+2(w@Jyb9s>i>9cpCnd#Urb`Z&`%oxDX93c@)J!sqB7_!u^s_Oy zs>k?&e=4Jr`W2DTldo zIa)Dox^=0fSPOVmo)(mjieQGKG_TA_5|_HZe}C{ZEtp)Qs*m!$_h%fq^*AUH6y#S` z?EtBh_w6ZE$*hiBuf%JXIXb)~Av|cS3& zM_86oq(=jOYNWwjhh(THBAn4~74}^im)z_i+%O z>GLqR?#zkDXi+}DGPc;03OsbBNErW$bLeAwLv}HbR;m*yEqJ1INBUr_KWmm_1eMEn zUB5}HP=C-s31&h`EgXg%EVMj^;mm@4S9fmVhQ!8*4Xd%t;OH9%J^mQz!`@$RdWi5w zcK00vud4kygQnfni$nolvk1nQ`Y;-erc{v?1uq0@r%y;&t!b|v;fXY$C{vQ?D@!O& zU3c|El8mmpMBa-dO3VfytK?XGWeZ-wukg8?+TYo|b4k_V*zL+q3_c*9IAwh;URa-N zJN(C9z`LoEzsz_tRpHH9yKvHU?7^#O{`T-!h_c7m!8>f!YSt>=Yxp!i%m)Dm{NItCyKsS?JtuMbWnes^@9DWe$%tw4b)rWB!X(Qhp zNCMxE+8+e}-KKQ6JKb*iAz^V6P`X|2U`mLJ#KmB3rOzn3KSH7hWd@CKC|hAE3iKRi zRN|lsHIlL^)s6Zz*^xSI}H67ayRC74tcd=R`u%4A^uY z_<5}K{x&-k5g~~!b1%L?T2S_BHhn#TYX8W~IsH+&KajZ%JI9xYKs}|e&yFTzQydcy zQ9A~jZhy^IbEZZ^%f)Ut4*Lx*QP1g%S(Ko9fyA1*s0d*QisP)3jf(zG^271Rxlqx% zLTm5ojb`Qd&Ww;@Gk6P4z{KAPXb}2Ypo1xfp}kKAMBuq=$7Y&n0e1l{V^so5YGn6> zUmsbGRs+_f8dROC=d=Jvqjs8%(L@a(IdB!?%H7^&YrePKgRd|bkpcyx2I^je3OT7F z4XI0TxaK!yh-tZJDlnLT+lf&NdMJe`_$&y*(4RxKcI@B;*vQ(;OuBCX=|w_#FEykQ zR7UfH#r!)OYA*(2$eEY3wtzXW9#q2bnw3zI0>v8x!e6*mO&E!!> zb(-t{V9!-6s2mi5^7ijii8Uc!_xbU7WKuLA~0 z7>Lb&gM^OEySrrtx8~z<4`uVtvcOtbF(+JI&2@SZtguGELlz%;9tXzIWAr4y-Vv^J z^CR;vR=VDy&9YF|)2!2nRBt>)LdPMPqKhH-0Qx{YEu_9bKF}g_*im7O1vtSuA~;%e z0>6IN-H3eDC~f&qriIcs-#oZpH4#kXPe}Z)h%6FQ2W5mVFs-fqWl6?xlcTM|ec>t1W>WfYR4ckgOgcermmojT2<5h^w3Qx6aM~AMf zitp7~hAfo<{tcyOp5M2813&2b?}Md@4PWPH13AnKCI@J!L>pff4xxmbVKg}OzExxp_Z~f$VifUuKd-+T;IaEA4ZreL2$en@ zes#yN5_MkXgm(IY2r+~=sCmeA$?r8*wUeG&{KW<*0QLIU*Kx?`f*s^THMa+C2AVx> zZ+~z;H)4xu)t7C;AUf8zn6Y&;sntl^D|en$=Qa`#vKok3%ORC-v^qwhC-h#^QN@ozAIHG}8{|kv<`tF z9@MzuN^z68-dj9bKi2(MKE3Lo$p8o^ek+a{kvm9rQG8lIGPWeDXack^h*0aSeWjBL zbiDF~=`K2{m_lt&C8v@4{!itOSRXT}@q%;Y0l%l39};}c4^!u8)SAoX+fwnxw@)@r z3$qPZFLVL5zAjD(ArQAmcO_pgPkt5>tEesHZ}tIcftXs-vw2yJ;0lLdaGH|(9)x$v z&jojbjj_W)7YczmZc5Ojm8pu($-Ca_INS3Y5&1Ed_*k(YPCG`|LjeY_Z;*z$y3=O; z9Roq@YkDQ7*@GzG{)U|I%n3P z;J3lI;P2^!zt=|LvSv+Zo)u@5f?6J#lrjUTejn0Agdu>Tdf@ zkQnd~DnzU#2U>-@!f^Ar)&53(u0;_nlaWc!b>O~|6#&;s3PriqT4OxxpRUM`?8^xX%E4hZt4cLof2RN%FlZc~KGhIE=mKSma zFwEk1lP2w*AW~Q;8 z{Ws}pZ`CrQ{YL4vyHX$6XRI{C;#y1TA=fJ73n%ktW@>BTlt5nL8c`PhBeO^ifJSk*(}8E z>)CmbI-7$r&JhOE_9RkrCTIvFdANZ_bwi%D=S`v{p7%>+9VvfVXa&nkr)6ZSDwUjr zkJKLbWn1@pl*SRE?hh%Z;Y5w$vv$9`LtA3M?YU#FG{_1ZHO30?JmkNkymn)38Xtzf za~yDse7pddbVQ6+eY%wXPmZTu(WiapOEFc;nu~|CvGP#)lX<|TN4@ycLs>-cM}-3Y z)`wx_)`Os+aFYACbP`co0aOZ@$V}G=mCa%LB>CYoT*5>>`VDo#{xnJ;ltv|1HT=6Y zt~{~J_|x=BjY1m#f9UNv`fC#ffGvR79D)4`CZ&Ma^F-a*!D4H;e2%FebU3pZ3=XRd zdXCTYyy9_E2n~f-$gGMUbkTf7wcTb@Nu`|+m1WBRts(iFCR63yb4mig-5BKL6_hy! zjQ~ZQi;Qz0eNep@r_(Of+S;`+jAOD(8f0>=8l`aQq|xWhuN;=5imcqid$4G1IuMgq zImRGU^iG3KieBsGi|b)ceeb8Uy+qVk?XGl^EZ-ln=eMl2f~@9i0|1ph&lnkOtx|F# z8dC1I-d~0!-M)ge*U`~n0~13eM@)^c4)NH~^+-DK42z)Y%c3et$w9Zj(Ew|=NDNvoD%fK4ISgWe+%BhC;`6J?F; zg6zW_vHqG#HNp!Sc*qGG7Nk^P_2TQ{_j8s=GvP}bDjLb*DzYMFE0&)B-bQ@A;-pb7S)Cq5)dSS6$Q zobY`5NBOOcihctUf8OFT`A0=kHpy5`>&%6|F`Qy*WeUpefI^Et&KTKwq z65@lecD(b%sVJ879oqnWl*0Ue`so<$Nbd_)tp4Kj8B9^cZFhN>j>_*FKr}2vkuLTE zY$-(dk$^0=qr1co;kS)UYt%<7xXPjAnq!@^3ALaxH@G1$;cvJL?U3h+Lbid!Pq8Dt zZl0wvC%FL5HTX&5cer>(zoq3Vy`qLy2#qjtT!au>px~ALpehDS7hxz_g2=96!u<2A zRgj%ALyf6Xfj4Zb+30;`A4mNA++O-jqi%DL(S7+{#rxMT4dON5w!vDn8{z5V4Pr><@9hMiBrI4{ zV?Wk&Gyi>M{@;Y{oL|vmn5)t|MR1>7CcHrQ_#t z!#si6$G36VSO<~G11iT}*U7Wh+K2V)qnZvOLu^3QB(m7Z!#Ut$_lpC@E{B9gn?YtH z0-xO$&vFVmUE1KSFK7jJawal|p@7~nU%#|Jd0)5-cM9Aq;5@gTL}kl%MTjKFN3LrA zu`mh#Xo+9!d5y^qY_!`vqIo=y4zHp!WK61y!nQ=tQno#6;W4{5h=(4R`>_5>}mwCr_8tM{<4f@ZtQo>co;~)7Mi(wvu)VT zL#qFN{GA-%Q60V1hP}{YrXQg~;ARLK*rCbar~Fh{%`D)5wV(X_CMXGhdINu?{~8`CmjZo^_ddL1P5ix zx-0BDU-X_mgq2Mu_jc1U^xwL&8D2KXY9@;}+a|)~emi9xF@6GwRF6Eb?F56?Ew4GO zjmT4QVwT_vnfBl31Ui=qoP zVb-HJbf?o!2h|Z)e4n!1FGhvlw2b`?VIO?jfKbXQWO07ln3u>{Pkcsb{`O`p`JKi* z!fUR=u|w$fZ=d$x5SWJiwS{DKdF`MGd>pvmtU|<6J_eti!4zi)mRa&Ou17cQr+yA* zX50jUhWi>IImur8aw|8In~&?|rQv?(hu3R5;~cE#pO=5P!YvopEv`xuns2KGe??i! zQMih8D9$n^p>}xS72PN?L5e2OW!Y>@f;2cxVFUlfcaFX#LCv5yu$=X|%7F`WYdXEI zlc*gp!+W!M%*{WHQ`3zd{IY~ydQp`n_8eYMANyh&ft+I zI8}sce#>17%3Lk@MWg3CO~q~yP%~Ox&H@K?g8nx=p$ttLfnvxoRRd3U^_AC2!|2J!>e&GvaPPuJ!INi?3CH-gKUBn3mC0XcF1ZN| zlaUDgo<%Wy-fhB{BWWQbiYLZnQU=SA!#0!QjU7rdC71`7Jh$2Am}Y|i9gAe5q?kbz z0q(BjI~LQ5y6&cNM_#sm*f8ZGcUjj9I{_WPuc$4`wLB&W!qhjUzo&*_Z z6I$&`!&eA6DOmPUogl>qMt>;2PQ`8xIi^4Yba%`flu3Xn&?L!m^SfjIqt6!ODmbdB zJr}s}a~W2WL1E8TOUJSNJK6j5OP8v{U%&O`mK;X1%>;~n@ZMCK|iPNb~zEqcZiRp)APxwqAPTbzW~hFv^Cswm}RGD4XKvVtLawl>)GlgM`{ zAsD1XJK1UQLZ#;E(G0hT*Fi)jlYg@mN=kNB06*63%~Af@-=l~Gyu1Dmg>!7GGHH1| zQBfPLy;mcK^i*{>54WH-__Xi}aX)$3_dfn5ABkq`y~MefIIY%sW)Hybv*d)olwEH42!fVkzY!`w`P6_j4_0 z@%m8TcTgt*CZK>P1AXcs8wTWjg3pgl0yY(lpFwgH|95esy_i@n>!E2D_uyHLOj>hB zOfz`*|6e%;;)b7Y)?5Kwj)0tTb@Rx=pV$+cyr2d2pcRj1Df%+O@g8K&>FsdCU6{(r z&-VT*^OCj5r|Z0{%XBAx_#%G)zHs-Rk$4XLOhm<>~Y`-(tFGUqM~;tUQR zr!-NWoSX#K2&x7MO?6LHziwwL?PjGWK;ZA_g~D8KkFJqs9jUVEE4O838Ay*#&v z2kSzHz^u@C($HX%i|6nKJsOcnZMAuPNMsSExYI0AhE-kd<=MM>$HJ0m+$+=FP^iyw zCyj$gDe?gMgW$7lKsT%EmXFQCV>=XKI#m%ieQhNLD!8weYEP%m+&!DlyE4TSy60C> z#4s%;O)=&It-be!Ol)bqcilkD30u%(-`msiVXi{Qmdi)$Hw&^au4XX(+Fw%O)7*ZQ znd*G?NEfaZ9W)gZyg5@9>S-JHcFgtk$c+!%&d{~sSB6&Z-b;hAb;uU--!ffqIa)%H z&MdL!1;wC7Scg{qQ<5@>iXyv=8A#+MRi&Yc(;*L zVAJ7-=n$W-{J0wuRoYnfz3%dSK_TYz^jf&`b|0YXw39v0?FjOks9Jo3L&@eJiwLri zOOX2>1!Yn%8|0sf2*HR#I->al3S!eD*U^UEMdU;Ajs8XPEBQAn1VEesAVrxGIrB?? zliz?EJkWiPJw2C7TORhd&Z%si(XKvIhTH@}Sf6_zOmPlnzN|L^-PyFbibRcanmP`~ zEmEZqVY}Kb^M)E#(s@p*&`6E?$tqJa;{nC4$0!;}`gu&|s-#7cjm;VRq|LMYQ^aECPP zyFsVRHEXIxukXhs#bLaNNX`W(c$l`L5_tj|wbAiC!}qs)?z3ZycDmUlj`H{+9qGyu z+r4kqzk0L17QcHY=&0_*HoPPMKztKcKexrOJpv1RE#5${@Wos#>`(yF|H zc+C=PRLf$+TN*?h%$q|+%n-5KUR1mgeZ{t;yNOFS2E10NL(TC?(RZ{mY6vXCp@JD$ zP~bS!A^AJjFP5IJfxPCe>Vc~4$rLiF9<#aUnwME0N(;0511}RLoawMY2($mw0u<3d z>s*=8DtSZK4m!y|xJN-CDa-R5gz*t*PLb%56YVOt-WtA4dj{%Tt!9auX&~|e+BXIUUHjFxX-4{jSmqLQ*etp5M{v3eV*U)I zq)?)&Fb<0eVS3PmAjCBt*K^cJ+sTofF$~8tFlmBibU1HJYZ^YdlW)c9wePO(`@vy} z^P4Q}IvE(A#z^vgu-M+~<9yk+R_AUD$l065BP-{v>2@=}lVGdK?!Y%0$@KV*-zuRn zM%FR~Qs8Ujr^~9;Z~G3YjpHmUQf88o zMP3&V1GA6`Sa%Op#0^gLy7^XhWm;Xv4DOSUN)-(1Zr|1!v!EIvP?&j&_#9k=_H2aapwpMqI|_IzejnWGy=cv#+!Q zs)O7Pd89w9?$P|voxBM7!X&KhWm#p$%um6$q`g>s6OFE!qLgf4ClM2^6|+H^yGlnt z)17}NP`kn(8@k;57n#Oy0jL^do4tVJmfJ<04RsLFAZ-AW|XNRniH7X%YuuM zH{OpTTYkG=Pk$~NmB%~W-k|zHspT_cNM2Ho6jkrey?Ol_c`Eeu2d04;$t<7bn%tM{ z?@cIny+~U9XDWQX>j~cmp739yf+m1#yS3FM(ro#Y^+B^#UBkT1r1Iz8P4#c6SJIBm zRbTbeq8$TP-A_1|J)RGL0`Bz!0k3VRCxBL~WHIQ=)rd!@@2_h#?f_5hP#cq{IS&zX zoZ1bGZICNFJ8b~Li#;(U4|JrS&p7GdVK~I`=F4OE`NoI)o|EvHj#4)Bs0WB4NGz-s zJ);~NSW*#IzNsC!__5dMj~`j#aCC?|n#;J4 zgm7vI5(w%JBt_w;6{Ym)z~ipnk^9SD&!xBHQWC|EzlAuqY~jws@oPOV=O$GXa-o*U zT3xs2om8BYt=!9?d|`NoY3-#g{-6Kgavs=cRQ`%YchO7`t~JXYA#mDieE6TO)Qex4 zP8-Vt+-`st(e0QtaW04XsxE8^34bYirMqOZo#~^ z&e5k(v`^n$HURWK$=Y_{e_{sOofbae>}k1~Hbj@UXilhldeHaWe0OU_owmsETt|z% zVITR4qq)(1UTgp3lSBB=PxwW=?ed8!Bb7kbX#VRdl=^FI=6)CID-ykq}laKiS;0lr$bOcHZPJ zp7LKzH&(E&Qe$dE%{PD+d4HvI<#H#+sAN84LXBxP4HGImS!eSqU#@fr>u>hFeY?UO zL6LIcIAF2?I?CSh!T7Gr_dec3RrTI2Rhf@u)w0{lNF06{ZKx^bDr%b7@LoZ9cra-) zPVd^(jM?l@!M1V%CHq8x_-8!UJUpKkKgetTFgM<@=qH-yZ^8#M?!D8qMMY3S?AK&v z1cxih%uP0nyKRZ|75u44QIdx6B0-c}AsgIEAK2w+T07GaoFA%v2O%*a81`uxL%oZy zjDh6{(`G;Oy;e=23EIXbAhZjSr&z{@C`nw+`Yh;4Yad^GyAHx@G zUzwQ{!V>zF-N;vEXfp*Ua^LT7;sjt!8LW?rN8<>-Hn!jzeaBC{o);T0D3cJh;@@eO zlOLa!*Jsbxx<91k?kiP(S{dg?*oUHKei5a2Pba6tq(Xz5N%NE6p({d2+GAf`CMbP^ z@6V^R{7(=R?fbPR3t6PgTh1W$Ui0BmC&i_2m#a`-18d&r=IbY)%)I^3 zcwMIMX3LLOs%k`5nv>)c5t<4%t)Lz_KQTE~7KXlj`WI7vu-aQ+6?{}vX80u!GHeDeLrbhE~+a~ zF}adM5nzbvXy{^Q<9JJ{zp$8$#Qi@2NqLYV#)%sCSIVLpZEgts^Phd+ z|9sZ016__LLoBcRu$ImtUb9A&?6LpAm0T}o4%NXGuADq;p1+!u=YSadJ6&TE5PSA2 zZ`!Mm@3zzS9p*OIn-c=!=8Aj{&YKHB{LRAho=2Z>>USk2+jz;8=Mi8!=arHzUJ5JGtR{#R&%;Y8`g(a$# zX;dX$pz#4p)?xe%3YZB-cQ_E9g@U!9GXPzqUS(n}Y`aaT<$M2gmzRz@^ni)`?bUNu zF5(s*qiO{HTq(A=``$wVc{-?NskOh5;& z$G~zeY59#DVtg)G^q9XJ2bViw8U|300P)J*+ip1L($h}v_e68uQwWHgEAlxwZ!Q4w zw?CKn>Oc6rc}a_TE@v(flNH7bNZH!uw7A&tdhfK|yHEZ5#zC!Gk+nIvfMs3rRCzth&B&#i{Fh0=Qrr1FF%KXjP#7e$O4(oOj56UEj&UWp5UTSh`fiPZ&Jxm*s1$4xDJ< z$!rqH3{x~32dmOk18W`wVl|K`>9Cka!Lv&F{`>4Wb?g&29oLi(xxRo{0$+Kd>&jax ze=)UXc)^PAo4sWc$Qb|}Xv0>o+{b*50^3=K{=%I#qfmFb4jlhcLuUL@XWNV*t;GY^ zv%u6fs7zKs#4x~d(1{K$bn~+YU_&B{fLPHb)P`UT-*@c0Y}*E^;RG7-1AG*MWlW`?l2O5Z98Q4OR^kNfASDYJ=IZMaSqLA5MFGyXNZm@)Z!z z^LQ)b5$ueD0j(uJ_{O=mTmj+}2c1991?F+Cd4iclaE4T3z_OvJMp-JcS`Nw-{Qv2`U_kVr+_I|(L{(HQ>U5A2YO&Pb% z^<1d_^1_svgC2YA*%2#Oq_*TlmlaAVd50`nY|{cT`<7ksiXa5lL{RSvt=F;c2S29+ zpceHezSV3%Q@w~ZAA`{H0rBYP-?{R(d!N2bi?=p#VM0nYx-v&!gROTyJ%bD&)@cN& zR|!N^z?7Gt?%uOo@z2e1Cm|qij;QD8oH+r+^UHgkc>4MCT%qBDm06_TBB}o30slVf*&Y$EnIu_!{jne+m&j<(SLn|Gl`Ziw8P*LC2K_ z#2OHsbYNyFuK_Uv0(9i^fN?bCsI+dmVc4+K2K0Nj(SlpUf$I&3Q60i_WuXuPTnUH~ z>F^uYHI+Hc?STW(2KHD#`2wsBUchA-5oqWu0qno2$g@Cv@qMoC3<_Zv>blR}Ft}uiP6w_9e z;{rcsK?IlF9^w*+>2Yu!OX$?`w%W4w{JZYG@ytDXw)#3px3Wnc=IQ4@x%{4gKX#wP zb)BI4LX~BAzu?LrXqD=0zGjFOO#lI(&Mb7Pv&WBnWY^t#cADRm540hGSh$vyltREO zbyfYzV5S(3`o$}%_>JH{r2rv|s*qQSls?SJ+(?jyL?+Tt&%Ll~s|19l(%yH*0;H;QgXzWBO7+O@W zK1tQiJl?2A)G8V?Va41=$7*S zFc)1v>ZNIKzCSSKP!cOF0o!)hE1aI+Y;2?hP@u#GO;m_2w=9_V(Hl?nZt92F5I`&o z+jbXmcbHLO`4^y?YJUnL9vy z?mW&T;0gl-GbC>km9jbYB)`(OJSZ+~3)~}6QBfh6iggpyX*Mvo((b+U4qu&h`k)7n zIk?Abo3m!|y^l`0bM!Nlu1?rs78JFCwdEC3rb!{LY6A(HIrv5o`P&2)AZFA9%1hk? z59s~IGY?;LVpHEweE~5i685GoP_alwRneoHAR-`7W-UNCU@*)KBLKFD!6@z0WvhAJ z|FPYdyY9UGoGx2!F@M`$UBB6;gsf@mdk@dIZUp8pN_2Yp)&E^F?)k~*JDwSLU7b=b zCbRx%k8RtQbXbg`;fZZ!y@$SBo-*Q=K$n6mW%dF+5(R{@Rj9RU$tey2aUM6r`~bv< zoOIRa3m28{35akJ(yXxUb$KLHifzGuU$l?c06gXG|RO;zp}nWHul!vo0Do__nLgKl6uKA41-4|7T*RQjok~|@9&g>MX!%Y%c7K2WegFBvp1u3L z)xCS{ucp4w@OAqfl<7bF{K6UkoS2dr>((BIK z#+e_0`1DIgPWj-|?~g-3%sIumI%t&n#vFBJ^;_=4!S@LPvET%_%fVy@2)@F*=k7Dl z8g$g5{0qTiLZhYQL!;LH*B{6F~g)>Rtl|o;%MIG4Qwvf<{q-SatZ= z@e9<;#h*R-JuWAsYZF7xj{wwAkXaH#1F)=8&^6Dw`MRsmKW)H2n^b9_{!wiBo*#ev z+n(p0J^Z7jts6{l1)La=KoS2)1Vwt)32Ftz%`e%cj3tzU*v3&fR8bu+8*8G}y6>Lr zPVaxjE)yFb(TzL8n;*_S>cT7TnaXJqchPH+Xp{ti7+1OFKUdxx@g=gF#1i?6=*HACpw<1QlbplF9SZPBeH9~4j`0s4+ov&6c zC$jiCq(Lc2oK}me@t$g<7X%YwrE1Z<+j=Myc&|8N558ur3}#VFn)mt}diMMP#KUhH zJ?@qNeR!HnbYL3NC6pGln#|`fAjS-_wEyNrx_x5io4{J{l8XZ4V!uO3qk+1(R9V%>fyjQ9jv~0D^$7T9-Sox*kgCzj6(H`9 zI>bB@&`%&o30h96of!hx6tx*ptx+xHx`rMa2d}Y!A^hw%d3?gznnA*DFUIbl^)yt0P#tK&Y$Ob#gaozBp}A+BzvsU7Q5O_1u(ljQUsAozMqa2z{%Kuu{1PX&HXE5NIFQ^Af_{8XSTA z0K`v@ef#2v9vL+<i)SQ_zgue2VwvaWD-B{?V;)_Ourt=-c4O zyO9S70dW9`)5xJVKwQ1!Tz_V+_71q}Us^(jxFLWT?K>lph+JyKrAS>zeOBZHVFkAh zhQ_Vp!pPF&jy`<+Nhcis16e&5|A5iJ%g033|* zrIs^ZSG`&YlB;gH0>Ifv&CcZ17Ot8G{wxb&Kbuvx_)lfLG5{Ej3915QAp|ER<(+WE zUeEpKu8YoYj)(Q$=YJk`&e_9Xr>v02Vy(s6wQHFfW0XVE6<~qq*`iJBl2tu=bo*}G zZMONTOP9{`diUDl%f7uj%_E!OM6EfVK~tUcn}ut39Y21`X&-&`>42px$~q*yh)$Uy zD5V^;!Md(fP1A_970$98ZVW)Ij){gInU$67{yYG~@{O0PFlrA;-SICd!^v%`2!`jW z8iD)(#IH`BbMj5M-T!=fQqw^%NCRTUe{YO2r77Bpx^8Jj%_8c1$Ax%IKtx+(P5F3y zNmDCLgn)P*ANmjwZ%l?53+xaGVm40t+H((F&z1%TOcTI_;ujO*IB`>}IAzG7`_CG5 z>|?E4lhUSm$q_fZt|$f9MA|eV~|RvWR)z+IUye^$P7zO+bUbGJFg8r zUhRMwpH*gv4k$!5e107YEfokIrGxbJyLAA1QnqGt9n2~<&-=I#Q4riZoeLr^~(<*&wYiB=Xl5L7kb92nDm39rU`{;H(}S>9^xrWzNxrsAC- zQxy!-{?M+ztdC1fxbN=ea-BM)q)7k$%XgpZ-W+rZyws`Fzc}LN8}E8^kG}i8@z1^X zes{OtJH4~>&IJp@?C*y6B`x)n=rH&4^tmTL`q=1OeqFSrhhY{|%O=8%7I5TIR;DUI zGc|nI2&I(ZyT>^v_%7l*8F0vJyT6U)%-0^L?4cCXcG-y)l|@c3w`2q8jpXdN)aR7H z*OecD_>UE$^ZxygSrmzP)-7&=!;ycks5kizh%u3*8(71H`7|3ek^-Gn!j+eubN#S0 z4sBA^qI?C!-+H_i%dN^p^;bFs#EKiYehx8e7E1u^ON`+lgd6hrBw^n3RKXp?DpC%P zl>(#+MRev;>Qr8Q!JvCiI`Y^@S~_=gX}M^B>m83g_}+Un2e=|)xUK0xm!Y~*(Zc+}WjH#6weEoFYq^VS;oS3TjB;CTZe$G}^sp;>v?HByszn^u8 z!ddpt5*VX8Mdq_y7V;?|#_B3D*tn2|pWf&Q^lP2@aBO7zHYw zP&agyaHE6M$UCU(#&?!!QAsr<-~i{9P!iK%&pmp)^vuK83~A(xsB-ua5X*4X)Szn1 z1aEAHSj9VV#7als&mc5}LzasSF{*a-AAG@g^)0HCUgVA=0U?55qG^&kfd6nHKw}Cg zWy!CCqeUayKMSa=tbme&7`Rr2-L@pY?1&=|dv3ts6QAw575TX-Ux2#Kg_2G$P5I)? z2OfI#*43q{PMTiG5-Bd1cyN$Kst9Jo)qu==+C)Ttl`psya?akWx3&7UCv`;sSXr`2 znKK0){rc}P;5=ecP*wT0w11ahRHp{@v@WYu_;ny|B<)8>jyU|ly|(?Ju2_bD4?$(9$ZE;m-&&sA=whME%O4JkUR5dZ)n07*naR7>Lyc?B|;hx!tz zl#Oo>ZY=MOJvQWtw&c&`2O!1>?swR^i~nAh?BqfeTr}pu+F?1N%3nY%I0u5o=t8dY z0HNrBYe7UK(7sLdk5AuxY@4QRJs}{jwK0W&c!M&;2yzWw0%DaNR@vg9phddRm?qfC z6htB>xQ+w1or2=xVkj?L3(~3)tHHr>T&I$6*RAvSd+*ujlRfv?`K`VO_WH0rAr(#e zLImgf_J^__Gp4_H`n0#+Iq{FbmUg9j#E=kBP@vMy&(}`$hdTtn2#A%|sRqep5@NBK zKQU-5KwMjAm}$Fm!c`CXTnUh?sY_(;LUq85Bt?&H+RmOn`GLI&@pbx|<6(v8+$19K z-H&T}PkMFw$#1>&(W%QanNm6Ba+l2?#-FJ0h>n1m2%*cDH2BEQxG07%>dWIu_O6-zf-Int_)+$+m`=l= zrL$s{Ei0=hbEx&t5VnL2aaLJL`Yvl-1*`_l2+F&Gz{PpFFU5qaa*A>Z=Pn_hw(s71 zOx>f;E+6#k*LUiUT_cUEaVvx{W_<9=LE|S)IcwJJZ;p3dLP1asrI|c*G?UU}GRx!N zYhd-dKENCNt+rWw{hxpBFH066#?uBS0@yD7jI}aa!T(Vh9Xa2=W~$WdRmB>D5)iHf zRM(^&j>lb@>9?$;h{xl^O00Ar8gb*${>SX{e4Q_D_<=A2wM1afud8<+dEcY=e)`#0 zhni+FNm-cqGC|3+O*t zXtw%QRzG&NpM5JzsaB*`StQVvP6M0}&cSs(5;0>?X$y}Tah9|R6QENgV#*?-{LS!f z3QanH0P*!BM*U~f+ex^F!O3=Aww$+T z-<{vyYwz7Y>e_RMZ@aaI#SL{2Ll8V|*1`j(yfSU@%+J3(GEru=(eyZVJ;rPst6xoZ zB{;|NZ%hq(s+}nP(fR`7Mg+tD$egBZ_?ST&RHXHU(I?2KLim6fBOd@{D!6R#x}nLe zw`C>4b8T$%+_qD+bGxF&Q=faXdrRkkH&tgEo@e7CfCY08{&(t)PmCUSvu%MEjTe#1 zqzAERAtWtNaL$EcXd+cvM&fbiTyn`dS6zDA-j8nFSz6YouetN(rzXEPeW(Xf&Gm4( zxTb!wWnJ^8eKq+5h#wvO#tjcYI{p?%M0Agu5)f0_Z|5szA{!7hIhmAzSa8tLr~{I4 z!ZCY~dEm|qhBj3j3;}UQIH$&#BfwR1S_YJsmO^1+A#mY>m2w~!kARg-Nl=V{0dt*> z?fJ!2n#?8#ndEg{jvD@mbC@B{0U%!Yew1*1P^_Y~II}mL8FIj)JzulePqyH!kpNZ; zC?_5vTwu}}gbUBb%@L+)(pZ$O-nm!zuRFGD{ZrSj+b!y{O_v`#bZGZ?VPVXTX~t40 z$eayL%MxqWbohJm(ybOQT(sM7ixzcSwrXYf55JhzPc!433SDzKPGxYWs^eHp2w{Z# zs!i*vG}H!WYXkj_0e&;UJbkC>3-!+@R0cSJ^Ju><{p0;?F_*f@nH3L}2UpsV_y}UL z2$YqtmDZbeDmBNe&4+! z$#v6=0#J>kyCbSaV4tgLR8Wd_2Oi~4xw!Y9+fP3E@SZQ{bF3a2{mu;!jC|@YY8Hd- zsRT;6HD?6s1jPK)ITK5oi@KK`nHe9L3d;lPaCDD$g^Nr3R4SCBK(0>Yi-i`Kxa98&z&~Me4luz4N3Y1Jp`|Pv zTt^)rjWtq9)G-BVIFjjbstsK07`g?n2%vjU_$F+cS)Ys4nW{RWHs6AoAGdt|O4f%B=`kU~hn|TE0 zELhuT3*MTo-8b`w(qy-vKY;k>KU3X~IQH}ff|Y0v zXA*BHnr1`CkR}WEIwuMMu}pW#zfvhBhgo6<7DQ+Q-hO|4+bxU8s;0Qg5D>2u<*EP! zC-6vzKzc+ZYCvUWB@`DIiPF+iucWw;c(x^xui%6VLM4L$fiPjZuR5R}b2^(_ok!aM z*_|9_i0iE~kzw!E@={g@#u$t&RRn3B8qf}^Xm=_)g3QhvrUa|_y=_ZH3qh$SbVfjM zM|KDd!5uyUJUSl7^8f*|EV!Wr?K9+81jP7=2q(fN0xZv_x@pL4u)H)-oeTm;%!J}| z&sei&4PLc69M%SmGrZ$;gQ#K^Ucc8p!&waW52zgKXSDWInR(QQR&-1GRd~RKlBq%v z!l)+cJ(BvvrENE6gRww~r;-&s9*+v7bz8{<>CvOd_lF#O@WiVwI=o3WBI_5SaIcmS z0aT8-bL7O^$38dt8powtG*SePOF0mOSdLK6@DwG}P|qCOr45ug!q7aCO01$Lb;YM2 zPi^11h^%Z0_fy|%c<-Yh55Dlqn`R^(gK-i8K(&Ad)RENpI>P;`_LpikGq9^y2^j{K z&`5cU$q=Kwh>>c^6@OU12dX%gVUapmK%8=S%;=E^AJDh+ zM@`XYLqJ>yAa-38cPBCgqy4?M=AxC8G8hT(`eK8Zwl3~)ZN-`amBH6AlgF)phqf*t_U}?oGW;5PzuH~qgmK1( z9AY8>rvRp*d5&v?W82j8JYwn^v}xPwkIo%C{n4&XtCiby+3LG4TXg=teaE(oI<;=Q zsLhT=OF9ygXo}7$JV*XVV9wmdeWrgfbHFRFOdV2IVRbO0CB~YvN+~$Ts4m~(f`UTO z4FguKSt}=@M$~}v@-irhX%I1pNR%xj+i%E)RhshwD7jAr#4eydw-CBagvr7>)cEHq zIPc7VJ$%jZ6EAOy>kI*L9kX);!w8BoI~k3cVA~caL^x**J#*~ZRV(#5vu5sBzP7Ae zS)#%rgmFWUQ9>DWT`aUi&ID!vKxRO)lfjBBQ$v09Mm+Uu8Dc?rlIXMyni>#i8~@gM z`Ps-=zRZ}7R4^4O6lw`23pC2#Bj8n;Wdw5g55X&@dNmeFXLN~7eR7|!;#Fze!NeqO zrR-;=r4FL63L>$yP|q8`kH#WWB5oZwxO5?10FJXkZCz>-m=RBxqWj@$2q0GbREg5Q6mH_l%XR%DmQQycit20ZWAW9*h=o z{dEFj@#&n2#T%MnYV2DYdhtV(Kl*g;zc?!ZEXv#z0I^J7(Et#eJ|K1!AQlev?B3~% zDU zU2^{wr|)|2PfMWqhlPvxo;`b3zb`(Yb;vKj{IZkdcwRJC#Ib`%8wc$0mBf!CkEaXF z(uxWhyWGrDNKIi|w=m6@$>M}3sZJ{3)33&FRED_!zzgQNynu5aLAx~~ao3?IMQnuBWoxkX^ZI|D>b?x$JkFMQ5 z_{R=g{?w%%S(39CGdxfj0RTWpt*7pL>CSP_O}to-l;|F3#1j-8tQyx1+4rHcNw9*W z`zsbm-@!f-q%)>pd%*=D!O7Ge_w1p^-*fFn$K0|h1bNW8cfIxXyx$KkPYB7I4!7ov zKz;$@>qm@xc+xBHUgAKU$al&g_nI?;4LLXC=!}{Th%*^ttP#@D*JGEJG|ATj((YJ>&J2={J%a?cj>-VL-KKty; zgBJa|q{p1E796m0b*hza#y!`=-kuR>0_9j# ziq-xS_(8w{)gc;*K%!zTFN!lNoVD=jj28>rx8E>Bi*J7}?{#ATbLI&z;-UMRWdozk zl=`$vGfvGy14;yPa;5nOUaK7393TuU!x2;>?Epb2QWfxilrD3yDbT6zC8K@oXE=k> zFRqjcgU=wR5aWRV5S%JoWYnPWz;ik1EFv>X>UfwnRvF)HFdQg_ARPiT_XvPp#{*X1$m%>UhDOum05AKc;JUHGFOVnoBy9st zh0@og?gb4#bnrX`0_vFA`>TvEPBc8p@x{L(Z3Le?&RG~R&b^e7vuNfqBm}o>*XsA~ zUAOzbO}pYhw%vN0#k=&`>AkMqxA~<*0a>=OEj|2v7=ew60CI%KzB+Tr=ut1;_WPep zw~iIGVU?9G05#N#5B6iY!kbm#Dc|v+covsU)ihW2b$+F}K_cKJS9vcyclV+D?!M*w z8*@!9^|ROC_0%JiCVx82;ZaTMn&;gp+)^W3pXXym=~v!2@|pij@)Ab0C=jFt zHaIC*pSa~_A9UJ71c0;&54#C}l~|^lIQ|n5(Jb$oCr0eQci$~O%gtG9KT6)ciZVki z0dbL^Azpumw=n~VfH=ZXb)o_W4?OPvi-(?mN4s{Uy!ttDu=srmbpQPGZ+823?t-0{ ztzNO?f&~lutXfmr34x>IqPQ3J5EctT7)s7#j?Zz?2qBU-O$dM?f=ao}&k%&_*q(?+ zT%nN^6}$pId2>=h$BrAu^ZaIEdC!vvU+|p}y619@gD`cXnG!g9sM>&qE==)FC8Yps zuCSpB1&D#E&jmm<+qfk7T>x$~ami$m0~L>Ki{s#X{E8|E2w?HJGINVuV$M||82(OP zPX+`BcF6%C4gfTQ+Q3>_X-A{gG6CDQ(q=1iAE{`e+7$AW@%-_4T;6+Sd8IrTF6ZL0 zq~Zty_KZStT0c49F$X%4YC@5@Z#6kk69%PSO@$C1=kgDpU`VaPA~)`6R3IlEp94Uv zR>iBf*=p;rx7m8@KU%deT((1(t><^?vi1B9UD__%s+g>9%=R80JB&b05g0%9>*Jpt z`{LaTepuKoR?ymTT?*w18_Y;SHIA&(HA$<;_|R7ZLSp-}OX}UjRS%qeGh2tK?uaR` zkKDTZma)G!g(om}^84rCK4SDEK#L6*lOB0D3U3NeA-IS90>m>u{QjUzufA=XMcSK| zs{<3xCIW~RlTa4K%lBXT5@;O2V77bt1t;G;?A${ey@)&SUd0R`ZjKCb)s6t2)=c7o zV<*7SnTQvdD=$9p>|4${WuK=v#LD)szeJl~moDCBO?l}*R;^gxYU$GD9hWRwy8Yiv zmvvsXVs*P!Yf5`0lNOqM2tss@S!1k9Mnwc62t^jM#|8JeEh0J)?jl?hh zfPnb;foIO8G|D;X5)h{xSEjJBxWxlk8j)~MQ3y1oCt&thXew(=aoCfym>0hh509O4V(lsct6 zuvHFkY1&b(fEZj=Y3|n#WB@UPZMSN@@Vz%j{G)m9H1}tn``gOxk3as>1we}dD;+{W zockDW_z~9&h`C0}u_mX*aEO2VZB3Vc$DO_q%q=zB(|{p;F0V7hN?k(MSk(fEHIm|c z^xkIbi(_s%Zo{8z{XQ82;`+r+fjlIGJGf+xt|}A^TS&l4fdrsExIQAYvj$*(UeY9dO=&}CzVjf5R1!6J74Y>u7h(}r#D{>` z(3k*@91}#sgmdl*DO)ByjSxZ!5gaqg+ibbz7hSg9YI&qmBWIu9 zRQK4}=fQq`*Zs~dElrRD&({HO>~n_4uPp-k1&FcjY~S}JtCF|TTpr1LKpcR1rH8Lp zQL)x4J3~xGB^1Ui@%3jfLKAQ2E2mGVz&VBqBL5t`I%NfRANS6APmOxvnq-o6N+h{f5HEs?L>a_lG3C%HIGE8m*e)E}#A5qGX?xhwAz&F_*8~`T;RAGAS^T0t#!q>94%7 zUDvMBKN|C1LqOc1=&E87qy-py3?ilpiL!DqbOEX4YA7fKr*o(1Z};AP{mFaw+V0y1 zovM*`p0_a7^}@@qeE0W7e|9#ELeTXHwQQH@W>o4f8-^hq$MVoF8OJTgG@=n{Q;k5A z3gO7&G^qfrGQ$$cA`(`>R{~;^p)X*DIg>%o&hBOk?Nmlts%Q9FTl7-KgZgv?$XxL$DI&lTpHHy4pq(k6!VPRg17ZyZGhYlU) z#0p|=o7TlkO;hvQw{E+{j7G{#Q%h~L)fV&GcWhT4jhM?iv@2Y#wT-Ra&G++g6T3W$|*wk)Varz$j$u^ji=Q4bz+(BADnY_c0}f)m|x_k{mGKYr?Y zoSDS)SJ9f_wBae%i9r4V;&ZRO|D_op%4WBX2M$k`fu-=#vt-M=AHnksAM+FoS&+GShVmaDHWUDI*Z@)aEu$wb8S zcp-N{othz@wV@pzoJYSrqyf`Wo14z#Fd5ivCpk4OJPzOQa-(5kRx6*Dzk z*EER5qbm^jM&i*_`_^rKh!@46P1|$)N0(MV~GM3b5ZsSQ=+Xzcih#}6aWk|OZK z(&V-e-#_ZM4?q5Dz}kvb#4rko?Qx*GA?pevkr*T^EHHJSMkH5@kUD|yrcy*vTPA}Q zjNfwLkrImmAPH8Au$TtHFuG4V5YZV-ojR)XrX~?MVait*TzkWPkAhLiLO|S{tv>$% z@f{;yeBkLZZ(c040$obX=k*r!4T1b%1{5n}RSFvMK%)ug(hJYL?BcTyeWEdMH}8U( zdmZA2gjW`|sbVb5hG))hd? zb%I!mW8Ckbi*qnMofE9dX~7#~jZz1Eu`t ziCsg_noae{0OGU}mhUi&!lu9z;?%*%j2dy>knrOYEvBm!#LrgrZw>wfY}b`4`U^UJ??J9XG~pE)9G3hDOM zeA2TGdzM*%Sg1)MK~;ZMqwfD~f@4=gM0cT2@9v+x{Ory9HSC=0-#hOB@n_#G>3iDQ zm(Fy&LW+RcueEB-7_Il%>CA?7c2gCSaudpRNn=rPEhV1qrYfOBhhj)ntOV{Qyo)b5 z?e;5&op@)nU3_@rFalu&HtPr=Q)$9mUmZQ+r71Ul^YxFr07Olu6%gAJfW|>+SC5l? z;rDN{Ym-t>K`~hNV7x96PGjY?-MIqL=w&ZmF6D-bF-lt;b=r^@Njw*HlC&=zHt4qD z=N)^`rudLfJmrRWzWrgz!Ip;w%ODGv13q?;SDU95M8LHzi0B-O3;6P{K76J_W44*R1H{um`swIPue$Aj zDJx1jHGMa<#tczi$5ykMbl0A?XU2j%rP*sGZ742`gKZ~4a2rgMKr&GZC5499Z|~mI zZoJ{j3%6`THVM)Bx}p{SJ&ZsYftC@0S@Ra}e(Q(_A6~d<>29t=Ow))%MY#n)O;T7; z436W0>)L+CMj2`Zd|>G(DN%6%C={^u(Qf(%5%|ij8X#7-byyTj!SR%m5*E-(4Mf)i zgAx$D)P3slI}bj1pMQMRG9s4StGMB|(NB(l{gbmi64Rthrh(jSl_^ilRyKFWC%3oU z0*_WFAVwYHqQ+8+s&7Dc{O2i7nWbxln0XC|<>VUs2H{&a69;$}Am&^LwPKV2LrcPp zcV616dn00{yaU89zWT+fx86N+wC%(VL8BnDI_dg0u7>TW1_9OYcJO!yN;1zlo0HC%<&Xa}!=Y&k}`&wnr%{6XF^@Lt$@J&T*AgAzI6416`>S z;p>HF`n@1qysrFHP&}uuD2q1X17g&T3g`hSVHs$HKMU&}w7KE6}Oj%4|!_)JGV z_x8mj9vt@o(Mt>j#DQ))#yxQ6+!XJ-W!+PL0^*~F-1Ncs3;sMn5JMW_t7cfyNB*9Hda${E?A29e2$B|CriX_nUWs_&-liyLsdjV{Y6a>2;?UqzTmniUY!2+%t2h3WYYk| zrYy9j5)flOmLvNX0lL&UFNjCMPOaqUo^itcw+tU}ZQakcexJxYKz!qf(NB$k^{t^? zw9;&kN)6oR2gLYNDNW+^COI%%N`s+=FD?hVo+q;}R5RpP;d1HprX224VB2M|WvAB5 z2lhYm-{%ZI_L<^hvbuhcHQXzVKp25A0&?k{eKO~--6y;<<*W}rm^E;1sTDUOag7oK z9G3voVvtBy%GE1o5J)D=foT-I4E}q!9rajDc|0La*&R z%zksi{e2s&?c^OG9(d-BGiJ|ScnG0wDFR}p-_v{<;s67u^)&-BvA?VsSQ#giNiZU& zH1McMBxSAzIb-;5ZRsj7bxo>JIH__dh-wb;l54NJ@{-$6J2|9LG*;sej~hl{Q;h(s z7`*t(Cxf3F{oFN+m#yt;JH&{_OPJ>|k+RX`hEnXixa)u!HNZmOcFv)os1Pj6f|?T>tMswD_DAwO3qn-fp|KnP1nngnths5Jn)3z}p`$=y%WmJ@TKwm#*$+ImFP6 zICVWFWpP5836wCoLd7%y&$Cp&Lzr~jlrm_{073=W9%hKE#!~@eExj71{#<`REceFM zG7ps7o#z607Q{5-KK|t0{SMlr!>60_6TRZr7oL7~+DGTOt^kg}fKdsEUEA^Ffs=;} zXv=eBvKII#^Aiw%_p9CexRXx*(j^5N(hBl(;~=O4#MFz*NjCu(1ZIb2h8X*$DAw4b z?JekFgT`0$aii}$aG%|_Ym`FUyaL33tVnb|{D`4{TV512qcv2f93WcrW{7KVh=Got z8ZOk9&7})CciGwPj6NsYm!fqkV=hph61U!Z!>NN$*!ji$Z1~|-hY<)P(AW|9_J^__ z&pbc=>gjKPcuGaWjYOhF!tqeZOu|~szgD}1Y?-umdA_Rdt@`R)ww`csIA4>v)*GyS z1rM#;5r{L*1kZ7$%O_g33U{^m^t0F6HC865v7g0;9{;g1Z(Vc$L(kr=M_RG+lnaC* zxZyxCF@i;nU;rmXf&-4K9DWfw^#_#5#-u{XXs{jFnl zvq)zw%1X;q5RDaq>s8I(1{`2ibHJ^+0aXBqDT~PLu*Lv%mV}Z*zI67xV>)eGPioz} z`Dpg<`<#9LRUahXsOHfK=w?((-C>s8&~yM-6*an4nxg<9=NbWXkY$nf*PD8j8uR}0 z6A)uWcHO6c>Dpwh$OT+|u4}6Xh<%lp=EY7*Wdc{7kVC98#F#L4fU~4*@0=naHh_T% z+_pd$<#5pcJHIyiKUbYt*B#gA?|JnqU47e=PfmXAy|aN9Fw50J(<4|No!5X^5zBGQ zZM|h!oXgTSiUfCen878u``{tCyF&uO-QC@TyL)iA;7))9cbDK2{F|)3cUI21-uXS< zRb5@y)z$X{+keE(F1k07VK-n#}%#XchXcO^|@bgx4F)O=|hDA+`GLHE`%AA*l|! zG;pyh(-x}L>F_1kO(%w`UbnZi)(AlLPWkritV>vQlg8^)xUAa3hN$KWC%S%P>pZqJ zD9H>RvwUDI<@6?45DC-!WUBA<jAU z7y`DUIAILUI`M{#b8w8#@wIsxz)5yF9xW_5{t$$jL`&YblR=)0jJJ%0h}cudYJ_f8 zF053c@X7K8xz^ZmYgBOWi?7h@c_*H=!{-Uk#s=?L;@iH2WE(U%#@2Ba`RUW-+yS68firUBlZsy!3?) z@T*?3aqyEyh(ZgjOU!Ux+*uCTrsSkx<|w-_Rd4z!ijySkl+AAG#A1AZ)mh4S){_8t z84oAFS|a>*u&&^YC7Ra#whYh4?LL`%N^X(-6hW?}&MyFAmZR+0?wvMWn$g?@d`k@6 zXA=f~Q?iG0{US3+K81>1gt(m}p^PG$)pMR@NqZ0i_zBnC<`-i>tNu6`%48)Yh0SF|W^PhC$8_^j1f& zL)xtxr&tu0$v`|B1nZ9n!X6mtDe9TdnOt0+5uB&Cipe(nh3SH`31^*&41m7<@_|xK z=f!DSQweLiM6V0vv|2d40$t7S&(HCItwnixAJkC8l3`l6mds&zaaof0GV^|Ahdrrq z7_(PPP4t>heQMw)v>g$>l3i>3uSmbcj$syjuGdnkbPkHoN%%*}O8tz3QUdz|@?DTf z2R=Bb1AG|lvDYort4QNBa z=q*~4f4BqBFF!qMq5J9Y(2nk$^hR-T%ghxL7bDM8_wKt#syg!IfYJ~%7!dsO8wmS7 zNK;oUNS@D_0@X+`-|#6h5e$3dip$dih1S1nUCY}y@vnPo)|j|#X| zZc_cWAw`)txXie<+`^fhPERt4q0g6(2{r*1A;lT_0`Zip^9Ua>^kfnJ=ond*`sR1D zcXB?3poZi@FF_VG*%{^o`JW(&;OJo{1fUFaLcNJct1UL9L9#&bDc>FZ)Xin}C~zXr zKg#PeIzvk6;Yn`pEthWfeT;WDab`S2l!?D`S`VUE=A7Mh2RizGvGp86*yisjq@6zc zX6;dBN)8N47|*orELRbUC!DXzBfohMTB0lrPP>b)5?H!%5qV5i~*4{ zs^(Bx6mh`hWN!I#|1CpdXJw!+t-TKgX`S&-@NVOZxyv5m+t%AdsBh7!JKCFr(?{&F z?EQ=Lq~H?84LcVG-QYg|DiEHU=a-V*TRbOd8klUm6UuOl;hM4?II@monb_yY5EbsX zb(>ka187;e6Mw$IdZZqJ#v-8ydPGrN}B2rS6?$8Sp-c$Z;2n5nB?RjFej+R>*Cm^F zFmQsenw;+-f~}YRQFOD=WrNHX#`1tr7DQhF`4n_?>5c+?7}0SnSj)1X9>)DORv&)h z;~`#RqZj0hfB95Yw8{bvdP{RInYZr#iFD!ilhAV`p6f!Meg6l(3L-giq>c1SuYf2kB9 znIV$>`;M0NV){1Qta{alG9atfa96LhnYzH-ww6@WOV)5J}6 z$H_QDNS4nu1q!d{jkk^fpzEdjTWk#YF$_%lT7(u;V)9&2{saxokfTV1>`obKEmZ%z zN5#ObjzmxhO3F~VAY&z9$}}n7UaCiIh>kpnn%GeBDBJ!h9&O!Wmq25`Ee&afw-5uns12lXr5(1z|W@Xl3{PxwL*!CuvQBX z-%B_iJ6&V)z~#`41`s^rFXnN?#_;QR|12kGYp^OlNT;E{2gj#WuG2%EmlLMLz0s)K`vM7o|xUE~Wy%QK1*ALJ!pzE{QriAE0=nb3z&u7n;sa zj9#053}fFH2g&wgrBmixYG$Dn-JZ)Rv~DNV$Fx`E&EuYufe#y?ZE+C1h)_nSDHzo8 zZ1d4qx1rK?CJz=>Uz0NG2I?!>__=3gVksSTDr7%BFz#L!wnuAuOM=`qVlLmMOgQqdI$kZ)wcq`E)a|+Vg>|mG^t4PVu|{}r$5(Jw6GqqfbHtB8aGSxQ zfp67XHi7+yC|s<`cMj;u;PGr&$WPU%oq1^a)T2R_b(OGT7emgl5{1eTmt#raOMq{u z-=zs|#mLB$IE}9*5_(u~z8Jmv3ctez^)5Q~_T}rgl;F*i+Pe2$A5*%PDYag-c|5+V zy1H>Fti(WYof}s?ZRn3Goj^0S@7Ys|WOI!$*bz%DJ(#F)OsNiNcj+dlr)91J4fz&;1|f@H>jRjACh%KoYswG6R~LFcFj4(K7`^#lM}hAzjn0_(A7nc zeCpxN9F}da3jTi_vmk7{-LJE{bno>rPx2U!ZkWjbk;K1LN}JY>W7@{E0S z`s>c>WY=}RHrXe3ZQZjdUlNkhXE~>XVdfaO6RBUC_a_CHUZ&57_opzbI~`9{unfFk zt%lgkFv0_}-jg$ZPE2!#V8zvH5Az3q!=Nw6?gh%Y5GBU0u)qS}%2aHUqT%uQ3v?_dyCLm%)M(xba zNrH)!?BHN4Dc8CpP3!Ui1qLnv;IfuO8b7f@n;(~8#%~gGJ;@*YzB%b8hRkJ0>~{u? z64ORRsMQO5xI_+qF{^q_=6cD-($Dcc1w&!prHbWyP-?@6U$U{tqP+PH95i>n&kg80 z82mWcadAsi;#mz)4#7<{C4Enj?`0r&Ud=~qbBbK+(Q*vk4=D$aG^i*IS5c9g7r3X^ z^4fL(l=mFFPV=!s`UbYYB-{B|gUn0dqlTb<)C|6UdEK1lY$30D<{4?aR=$0n$moqMz zMSq})SP!B@*=JR=iXV#4z1zO_E~qp)zi>pEQfJ2qU=VCZ_v7gwG z0*Z-d47D8k*#-%F4{?I?PemBnH)!>?dg@yFU<&BSD&LlGL&@qvZ)qC_OxzvLUfr-N z7&wZm=u64)%&)AgEN9t0wF>i5mRq!qqFeHzK-w1wXFkF9zuxUcEt9%m24^UGAX#84 z+e<2*3!Jb#ogDEIH1Fx)l)vx<;#?RO$R2?#L@Z%AVO`m{Y3rQ zedf)r=Xe|4`iUAWYpG1Pft1J>?Zyn5d~ypd0o-q;A8FtVs%65UJ3XATyn7%$JMD-4 zpI@3yntveG(c!@R;k_ue4cuM%u3SYje>}UI3}uhiYpu(t_>76J4SJKy$PTCbzCjNu zOtQC8C4mqlasZGf8zAWn6E#~$-ijzaOIjii%A^`opH0rIqG1b9D-9~ONuJEPQI?)v z6LD+$eJK-1_H+~lu6OP&UNrj%`+kdQQ!;n3@uN}1kqW&O$IQQguj>NDmj`LSg?yKBk)oA@82z`9`9x=6xg_imH>c!=_@M76 z^M3NIqq;dM?aPVA1Isad&EcSOX6p!v3gjKW-l9E!L)neUG6}shFWN3B@Rl{rpT1ba$edUg_^09z>t1hMazVb9SrFnfe+c&8D z=-(00YoJ`#x~|6QnAh4}S3N^=;D6^(co-nOiTM(5htZ0fE*CHg^y>p$UWf>Yf(Jb> z*Gq9agmVLNw=`e_Bq4c|2)Q=_TO5I@*0^55Sg(SYYt2iLcal0Llzp_pOUGi4xz%>O z;?O4{21n9;hSciDb?*{|HPr&{W$k+OwoQ?Or-|C2_m}p-Bi`YcS< zaZtv_dQml>IiLq7It3c1XziF;xZ8WmCgUSYe{!?H!+26zPSz&`6=*`L>cXMC@*q`m z*ewQG+9GsL7aL8bUFrol2PYX>ZIcSQYE8dOm|;9H){FADm$*JSCSXI@*88OBHDto! zuk6w^H^>mWMF|WO=BEiTVHlP6&fWJdMysk7=JcHVi762XKo_RdygWa*SV9Q<08&Agm#5M%q4s=&W_uRoZPt_TqgmCVY6Uf)Dy#%c4bpZ;DHD`SP!RQ`aOYxDF z#Va)L{ngl*)SCf~q3WtH+8Rqt1s>Q=t4UbCJ5L@=qtJ9$xl8w*M(PR|sR$3}kXNI* z&a7Ij`_J}S2*A|5{y_Myy#W^zWG!4vdYt|iZslUM8dva8 zUr_mGydORt?K_GDBwmZrH(p#O#!50Ad+=N9`#p|620D|?xL@ClIh#g{8eSK%^&dlR z8Lp!g=r)eiL?_|yRqk!)cpBFTx*T3hFjceR`SIxGD$T+G4+dmeP*EWvP!TuLDfc~< zbeTv+#bW$d#GGuxS(gdym(NvTiR&#(MONbcLcmqDQe1yBT&ia8hcZ@fxr~cmi@FAh^>GE;I9sT_}_ z*RBh1V0R11agCqUl4@j66HT^SGIa~%NaWFB_xjs4L*O#vEDOCpC0$W>U3OoMj%8u8 z>&uRfS?8uBM5Wb%*{!s;Do-1Y$YX&<2RbR^me&(Ny?j2pv=zljT)gj+N#D@NxSVc{#5fqr1o+s znHlze?lsQS@D%DU&N(c5$(z&2k%pq7)QC)0Th0X-D`KJr+-2L{T0N^s!r@_ z_Q(#abX>pTR~dN8d{%^(aD?GLklzgqir$B^whPJ+UkRv+*G&i z`opPfP3w+HNzQeQ(KEt)K&+SZKzes0X_W*t8f7h>p#!s>(}kHT+teE0*w2AZ&%RAB z=}%558{TX_P55EF0!yUESa;}=II+(i7J!dpMALW-w!lKPS*Tk=yLsS7DweR2|toQ zB(~;i-QgsJlfnKO451@4h<$e6C%`6dp&Z=GSd^@M}6Z%n$FgG5zJf3OGex zRdcvh8(=ocG8zb`CjH#zKKW)>>T-VF$6j-Lhu1~!&yyw__?k+& z9mZ;!-yIsGU@6B(t7xKqV6rdgd;Xd1t^V9=qcI9PJ}J~-YRJ0a%}i!8_-4MaL_^5) zx}&`hakE zpP1)VXOzc&)I}jK9rwaq-6d&uo{gryV#>kW&d0k*+h5(T48glB68!O5=vV#9V^ zqP)OIIrNxmn-5W=mfM65nMz@8(Q-FeMW(H`*7ei&C!l8 z2uAWH5ttz^?T@UJ%%{kke=Xgy*5#xqbGP~E&#wQpq~5%*pc=nSn{_K{f70Q)<~xSg zbzS@Ni30sj<4eTY6~d|VyM(%4l4h^{)cg7p0hNJ0!&&rF3xDpWj6j?2tKKV8k6+)e z>VDqW-h*1Qxg#uN>9Y}{nBO+fBH7Q2ao0pOL67)|r#yXWuBgAmRrSzmDyDFO)K6AIoLw)(Y$btjj~qij`e?D)k3ey*_RXn%g9>;A`bjpoJpkxJA%3O-<+YOrx3E{6*{ zvxe!A(6uEzXv88h-jDZZKAdfzkI~s@VDMhf<4e>9e3eC{x815Y?9M!taRWd+Aya9_ z;k=K75iOeb0yYbiNZnJ-y*xP&OEE1v{FLjvq){%1iWyG>1;QC#2Zgn-%~PJrb)ZH5 zMrOS4Hzod>O&=jq`z>g4FHBSz8A#im2`d2*{`nBTNB869`+HTIFDIePe28D=K1OY6 z$#r7GL?A2VZ$9{NBygVEvkREn?DHUW9Z;7Oq$M$Kk+#x~N>a_8oJR;oluJx4UfJtJ z=7$co3$45CT{~sTT$fZT9MkQ)zsE;~`JC5%7lXlNbFzl2!y^JK&L@>!aYKWf_571g zg^+veiR$6blZ^lM`#hH{wmI4)uWJ6$#r9_jhxwqb)Ir)!^n6CX&*$Y1reZm+y7L z%nyAzKgNNZkpZJfa_%NkY}x1c;^FIZ2qG(3Hd3eU0hj3mpDJG$ zP{V%}vHE;RrK3G5bPAk)b@(CmnbfPt$MVr63baDjNzcqco0~MA5loiqc!x6YwYNgg z4VMuL@df|^2@isRa;8&s0qDE!?M^jSF7mW9o6R377o!qR;1#BRm3Mx2HhBCcg-h&i zOTs}Q7xZToCygIS*Dr^UW?{_>-Ce^@Xl{~6=YhXVpsANkks*3l6z zlMc>04vH+a+(7 zXhGnA!bLCDfqb(?Pu6C-msh%^uX{F!ixfME#$PQJESil?_x_Q|0%sw9z$gzi)M-2D zyXrW*rBdF3^!Ego|4h(j42U7byg_%|w{xo1D@DHVQqZLY(AAH+#fOESO3-n!AmNCP0w3nK2kO#&rk_N<~o)1;bc;T?YQZ50fGcDeaQ0 zg<^N9S$TZIdS|?BO&4c8Jf-$HiA7NZQ@2NaqSFDDcRfmFnYQo zf(o-U=JNbKQt0kpA=`U=g7cdb2h<;;bFC0i_TSMAE%0OL<P z3*pq+p1AE@NKtcd8@H8{@&2Lcp9lP}QC8^uu*xhODKKqn%o9-_>DI57WeXdjgI0vKfM z0H|B2Cenqo;)7IlZ!D4v8WK7247^_OguQ<}`lx=V{(H;95Pol&-+RoamoL=YPUsj4 z!@cXgl+N^s{Q@dk;0#gBXx27m-F`zHSf^&q_BYK`FijjZ+Nt+LW?_O;MKQS(>iX=; zaa;+?HWY_mAnXv1;t|fFsSKZew3_F+do?R2E|h;cF8pUS!&Eo05l{r>z)l)WT{stp z(cpZn&X!lW7caLH;(laqiQ?n1kAk!}m3AqPlMyK=_D5JiIR-r4S=x#Fm;W%f-;d_~yHTmCCZuv(}EGe2Qx}W5bE=`v{YbF*B=eZE_Yc~kl zz0TZqSbJ@U&~ssAg#2;)V)_vNEfJwS<-Bi4ob{Aj{R)31Nz=V|50-0wJ|H6VIjbCD zC|?k;BK%_j$Vg!SaWV2yzv*azv#OrM-SizQQl*27vZdUiQ#xWWRIt&z>>(_Bac+}0 z1Y32M5i{9R)K)YKI}Xk3UaKQR#Dbe64o#u|A1TQ}_`9uljC!~T<&+E#N@9vGD2~7W zvSezOq_h|>jc@QCBT8}*({3@G6y(-_Tyz{=LdOmGvj+5qkH1;^%Fb-CTK8dF_8R?c zHPbVwe(|jt8^O`R0f4Rmi0P6Vq%3X(GK!;6faTa^j9&KfSdKmuI>;TjeDtEM{dY1y zkQUgrnbqES15rDPBY5E*S!~SB0jI1@+y$k*DO|{jYu|k)zNh$H_aUucX|B)5{2d;z zHNf)h4(NP4WfI1Vd?g5Ha!Rn)Xqobpm0AUmwJaKKQGZoFmZIx62=|I`69RYdW_a_j zS9AsMyND2t8{vmj40(@;M5JRL{N^*S#9~r5o7LnL@6$|^SRt!>05?p9sx#a1wo> z-(0A({EBX`xBAe2Q)HUCX40Jh98I?GnOG^M4cEJ#QCc39b2(fZmxM~YdvP8P6;1lR z;qbO-o`m~2Y|h|l3YqaQZIa48f%iN*)Tr^XXM{7BCPv~#JtZKD1h!K5)uGg`V%cr% z>RiwM$|%j5f0^>E3Z@>y!VYp*P9JvmRtCOKmn3Br$5?@?ordp-kIdKQDcFb;maicb z(+#>_9&9r&s>Ozykh4?}JfZ%0ha;6-1OHz|-A$9K3GaS3eJ%~?0c*k2&Ug4}fQ6T`E5CX6) zE|z)+U0X@0IWe7(xGEs47h!1J=U|!J>%M+M^rUo31-9z170cwFfV>Fr&}$Z1*jHo# z#iq0(htH=zSz;({FMdQn9MNN->rkqRQzON=67q;T*OAz`c0){;E%*au`rI#$DK}i_ z;h6NMP$M_8jZT4k&UVXsDYVG-lyWgM`U|Wk56dYAzsekIvba4jx5bXJzpnk8S3Te! zNCCQLP}6ANg*wGrh6h-t71dsiG%1VVli}FP?lD_Deh`Unff^7 z6RzJmI81ygY5uXX|HnEYpuS_!3Zv)PUzC65v>hKE!w&x1i1*#uHPXW?vU#$$b!5Ow z5IOB2A;TTnp4eOFtYE)%ZP(+-=oGniK+SF-YOBgL(>`VY62@74<~$B%UY{pr?6eRg zTF7jfD>RYj>~)k%hUw|Hj7Ijc41LwA@D6vI;4kVpn7^s}d^<|{VUs!HuNgm2B`&$% z-&^N6E>in8?YWlZeebp_@AU0lACaJb$Ge*20Y`7HBN+e_UB-{a7p85h_kj*`Oub@E zPBCm2WnXjU+~sMRIyN$G-*#;@oFVq|hZ6nCulzt&NJ%7N!VTsZORPKMWvQ!cZozAT6TSbUan5-=@j2W27e z(juI;-`KmZRx;gNG{|Evy+izJzfHK7%6k=7vNxI4Xmz@>7)!$P-m2;*Fy{8J(1#5( zirR0<-4t!GJj3@ovdbX<%W-VX(Lk%+=2Na{qCEGz>X9)uyrAR7bIY(H0wm1-L^mEK z%_c~#Wu)n-P2a(ndIC-O$JkJ+g>XhMCNo?)hhFwhX}S@6H^GF4t$lu%UjbVSRndBr zKoLnow)YqpSMKg4FgiXfn@#2-+DHjsY3TBQA{9u#^U0HmF?f}Igk2rI*#>`0K1UZS?|JsCO zzbQdw1?d0=s)U0TfA0hs5li8Biwjz{alN zI_n^Q{M3HqkEM6gWpym$TC^PAPOgOk`g?9!kkRZznw;IwObTe<~5U zh5M6wIN_9P0@jG0Lb5)rWMsJfe0^A-C%cSAA&RlGwqCWp`fOd`aIZT%h*E{cWxMRs z|ATRvC=jr*xDn(;;;EI(KO*_(u|ulWh-uVA152)id`16>AujR zmdkALc?!ZfE+*kRRM@^Fx_aov%HYmtd*dVcC$H-{$0`j6t!Uid44Nv7$1KR^XPE~r zrCpsQ*{!ayiO zbB5 zR{w4VD3=-rJ?wZrIfARAE_fg_K;j;g~X;-N< zcxmYZZ_Tm)6&9%I4SE;@RrJq4tAGTT+`vndBgN$a*IWN5g#TN78?TV<(k%h#MzSjq P;GeXFym+;!VZi?bX2u0% literal 0 HcmV?d00001 diff --git a/cfg/gui/resources/nos3.png b/cfg/gui/resources/nos3.png new file mode 100644 index 0000000000000000000000000000000000000000..87e246377d20d5daab582688ec5b17f601248624 GIT binary patch literal 53018 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 n{!n}F4t4 Date: Fri, 26 Apr 2024 10:51:38 -0400 Subject: [PATCH 137/153] [nasa/nos3#234] Fixed paths to logos --- cfg/gui/cfg_gui_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index cc52e5ea..9dddb4dc 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -32,9 +32,9 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) - pixmap = QPixmap('resources/JSTAR-transparent.png') + pixmap = QPixmap('./cfg/gui/resources/JSTAR-transparent.png') self.ui.label_jstarLogo.setPixmap(pixmap) - pixmap = QPixmap('resources/nos3.png') + pixmap = QPixmap('./cfg/gui/resources/nos3.png') self.ui.label_nos3Logo.setPixmap(pixmap) # Build Tab From 448c4e80dcbdf593926f35ccf94010ab90635696 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Fri, 26 Apr 2024 10:55:11 -0400 Subject: [PATCH 138/153] [nasa/nos3#234] Fixed logo paths again --- cfg/gui/cfg_gui_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 9dddb4dc..fc0a8254 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -32,9 +32,9 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) - pixmap = QPixmap('./cfg/gui/resources/JSTAR-transparent.png') + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/JSTAR-transparent.png') self.ui.label_jstarLogo.setPixmap(pixmap) - pixmap = QPixmap('./cfg/gui/resources/nos3.png') + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3.png') self.ui.label_nos3Logo.setPixmap(pixmap) # Build Tab From 992c100a81b6526a7fe7c4d21e4c84046bec4c52 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Fri, 26 Apr 2024 11:08:47 -0400 Subject: [PATCH 139/153] [nasa/nos3#234] Added terminal message to press enter when it is done running --- cfg/gui/cfg_gui_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index fc0a8254..c6757185 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -317,7 +317,7 @@ def gnome_terminal(self, textbox:QTextEdit, command:str): process = QProcess() # `read line` is to hold the terminal open after execution, allows errors to be seen - process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; echo Done; read line" ') + process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; echo Done. Press ENTER to close.; read line" ') process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) From c006ff6d648aee280b20c30ede0cec4d2e7e6f6e Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 26 Apr 2024 15:45:45 +0000 Subject: [PATCH 140/153] [nasa/nos3#234] Added +x to scripts; --- cfg/gui/resources/JSTAR-transparent.png | Bin cfg/gui/resources/nos3.png | Bin scripts/gsw_cosmos_build.sh | 0 scripts/gsw_cosmos_launch.sh | 0 scripts/gsw_openc3_build.sh | 0 scripts/gsw_openc3_launch.sh | 0 scripts/igniter_launch.sh | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 cfg/gui/resources/JSTAR-transparent.png mode change 100644 => 100755 cfg/gui/resources/nos3.png mode change 100644 => 100755 scripts/gsw_cosmos_build.sh mode change 100644 => 100755 scripts/gsw_cosmos_launch.sh mode change 100644 => 100755 scripts/gsw_openc3_build.sh mode change 100644 => 100755 scripts/gsw_openc3_launch.sh mode change 100644 => 100755 scripts/igniter_launch.sh diff --git a/cfg/gui/resources/JSTAR-transparent.png b/cfg/gui/resources/JSTAR-transparent.png old mode 100644 new mode 100755 diff --git a/cfg/gui/resources/nos3.png b/cfg/gui/resources/nos3.png old mode 100644 new mode 100755 diff --git a/scripts/gsw_cosmos_build.sh b/scripts/gsw_cosmos_build.sh old mode 100644 new mode 100755 diff --git a/scripts/gsw_cosmos_launch.sh b/scripts/gsw_cosmos_launch.sh old mode 100644 new mode 100755 diff --git a/scripts/gsw_openc3_build.sh b/scripts/gsw_openc3_build.sh old mode 100644 new mode 100755 diff --git a/scripts/gsw_openc3_launch.sh b/scripts/gsw_openc3_launch.sh old mode 100644 new mode 100755 diff --git a/scripts/igniter_launch.sh b/scripts/igniter_launch.sh old mode 100644 new mode 100755 From 3b316f6c24a45a98105851e06ac00301e31de481 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Fri, 26 Apr 2024 11:56:32 -0400 Subject: [PATCH 141/153] [nasa/nos3#234] Fixed logo sizes --- cfg/gui/cfg_gui.ui | 8 ++++---- cfg/gui/cfg_gui_ui.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cfg/gui/cfg_gui.ui b/cfg/gui/cfg_gui.ui index 51c2dea8..02234ade 100644 --- a/cfg/gui/cfg_gui.ui +++ b/cfg/gui/cfg_gui.ui @@ -688,9 +688,9 @@ - 30 + 50 585 - 161 + 111 41 @@ -704,9 +704,9 @@ - 450 + 480 585 - 171 + 131 41 diff --git a/cfg/gui/cfg_gui_ui.py b/cfg/gui/cfg_gui_ui.py index 5d31b05f..32b50d49 100644 --- a/cfg/gui/cfg_gui_ui.py +++ b/cfg/gui/cfg_gui_ui.py @@ -178,11 +178,11 @@ def setupUi(self, Form): self.pushButton_saveAs.setGeometry(QRect(330, 590, 94, 26)) self.label_nos3Logo = QLabel(self.tab) self.label_nos3Logo.setObjectName(u"label_nos3Logo") - self.label_nos3Logo.setGeometry(QRect(30, 585, 161, 41)) + self.label_nos3Logo.setGeometry(QRect(50, 585, 111, 41)) self.label_nos3Logo.setScaledContents(True) self.label_jstarLogo = QLabel(self.tab) self.label_jstarLogo.setObjectName(u"label_jstarLogo") - self.label_jstarLogo.setGeometry(QRect(450, 585, 171, 41)) + self.label_jstarLogo.setGeometry(QRect(480, 585, 131, 41)) self.label_jstarLogo.setScaledContents(True) self.label_jstarLogo.setAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter) self.tabWidget.addTab(self.tab, "") From ca033447c6799483829826eb324e5a1e17eeee9c Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 26 Apr 2024 15:55:25 -0400 Subject: [PATCH 142/153] [nasa/nos3#202] Swapped to a hybrid setup with CI udp_tf (TC) and TO udp (SPP); --- cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake | 2 +- cfg/sims/nos3-simulator.xml | 8 +++++++- fsw/apps/to | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake index b0656fc0..80f34130 100644 --- a/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake +++ b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake @@ -31,4 +31,4 @@ add_definitions(-D_LINUX_OS_) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CI_TRANSPORT udp_tf) -set(TO_TRANSPORT udp_tf) +set(TO_TRANSPORT udp) # Note udp_tf used for Transfer Frames required for CryptoLib diff --git a/cfg/sims/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml index 2cd2e2f1..d15d315b 100644 --- a/cfg/sims/nos3-simulator.xml +++ b/cfg/sims/nos3-simulator.xml @@ -501,10 +501,16 @@ 6010 6011 --> - + + cosmos + 8010 + 6011 + + prox diff --git a/fsw/apps/to b/fsw/apps/to index a3b534de..d30dca15 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit a3b534dedd2e212d0eb2a500b2eac67cd30c497a +Subproject commit d30dca1539175f3555ffad6289a5ef5008a49b20 From ac7f0299b4f73728bee36c73de20fc0da7981c90 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Mon, 29 Apr 2024 10:22:07 -0400 Subject: [PATCH 143/153] [nasa/nos3#290] Set PNGs to upload as binaries --- .gitattributes | 3 +++ cfg/gui/cfg_gui_main.py | 5 +++-- ...ent.png => JSTAR-transparent_original.png} | Bin 96293 -> 96294 bytes .../resources/{nos3.png => nos3_original.png} | Bin 53018 -> 53019 bytes 4 files changed, 6 insertions(+), 2 deletions(-) rename cfg/gui/resources/{JSTAR-transparent.png => JSTAR-transparent_original.png} (99%) mode change 100755 => 100644 rename cfg/gui/resources/{nos3.png => nos3_original.png} (99%) mode change 100755 => 100644 diff --git a/.gitattributes b/.gitattributes index 4e8a4875..b0c5febf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,6 @@ # Declare files that will always have LF line endings on checkout. *.sh text eol=lf + +# Handle PNGs as binary +*.png binary diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index c6757185..3fc9825e 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -18,6 +18,7 @@ def __init__(self, *args, **kwargs): self.ui.setupUi(self) self.setFixedSize(655, 655) self.setWindowTitle("NOS3 Igniter - Version 0.0.1") + self.setWindowIcon(QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3_original.png')) # globals self.dateTimeEdit = QDateTimeEdit() @@ -32,9 +33,9 @@ def __init__(self, *args, **kwargs): self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) - pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/JSTAR-transparent.png') + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/JSTAR-transparent_original.png') self.ui.label_jstarLogo.setPixmap(pixmap) - pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3.png') + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3_original.png') self.ui.label_nos3Logo.setPixmap(pixmap) # Build Tab diff --git a/cfg/gui/resources/JSTAR-transparent.png b/cfg/gui/resources/JSTAR-transparent_original.png old mode 100755 new mode 100644 similarity index 99% rename from cfg/gui/resources/JSTAR-transparent.png rename to cfg/gui/resources/JSTAR-transparent_original.png index 35568dba98b5e141573b36e17dd2be40dbbfdd60..5a988078b02f277dfab5bc1538b95a448c12d5e9 GIT binary patch delta 19 acmZ4bfpysjR@Tk{KX=|nmaQy|iWLA(LI#ci delta 18 ZcmZ4XfpzHzR+i2HKlet~t*nfS6#z*x27&+p diff --git a/cfg/gui/resources/nos3.png b/cfg/gui/resources/nos3_original.png old mode 100755 new mode 100644 similarity index 99% rename from cfg/gui/resources/nos3.png rename to cfg/gui/resources/nos3_original.png index 87e246377d20d5daab582688ec5b17f601248624..a4a9a98d6814440184a418b76973cf9825c8e8c2 GIT binary patch delta 16 XcmbO=k9qbyX4cLCKX=}ZEMn&YG2aD} delta 15 WcmbO|k9pQSW|qzXKlhESV&?%Zumyzx From 0333916fbb855c0e8b4c3d035365c4c868fd8f58 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 30 Apr 2024 19:50:43 -0400 Subject: [PATCH 144/153] [nasa/nos3#202] Updates after submodule pull requests; --- components/cryptolib | 2 +- fsw/apps/ci | 2 +- fsw/apps/io_lib | 2 +- fsw/apps/to | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/cryptolib b/components/cryptolib index 393b6214..fb72ee2e 160000 --- a/components/cryptolib +++ b/components/cryptolib @@ -1 +1 @@ -Subproject commit 393b621486a5dcd9474065bfb39e88c77099f21f +Subproject commit fb72ee2e836f39737e0df20d838bae56076d277b diff --git a/fsw/apps/ci b/fsw/apps/ci index 153db705..57189901 160000 --- a/fsw/apps/ci +++ b/fsw/apps/ci @@ -1 +1 @@ -Subproject commit 153db705202edec3391c7b0dab11be0cd9cb128d +Subproject commit 57189901d7eae241a90e4fc346748bf56a686856 diff --git a/fsw/apps/io_lib b/fsw/apps/io_lib index f9c841b4..523edf70 160000 --- a/fsw/apps/io_lib +++ b/fsw/apps/io_lib @@ -1 +1 @@ -Subproject commit f9c841b42dec4b485cb02dbf5a682e974461606c +Subproject commit 523edf70f8a620f4a7988eef3beb23713289d1a4 diff --git a/fsw/apps/to b/fsw/apps/to index d30dca15..db65b438 160000 --- a/fsw/apps/to +++ b/fsw/apps/to @@ -1 +1 @@ -Subproject commit d30dca1539175f3555ffad6289a5ef5008a49b20 +Subproject commit db65b4381160adbbd35b8b140b2e5a19cfab1c5a From e9ae3a3c763574c0dc3f3a7aba3ea98da8ea3050 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 30 Apr 2024 20:08:27 -0400 Subject: [PATCH 145/153] [nasa/nos3#202] Updated docker container to ivvitc/nos3-64:20240430; --- scripts/env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/env.sh b/scripts/env.sh index 6bf3791a..426d55f9 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -40,7 +40,7 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -DBOX="ivvitc/nos3-64:dev" +DBOX="ivvitc/nos3-64:20240430" # Debugging #echo "Script directory = " $SCRIPT_DIR From c70fbe8274b9348cf9c007b5e17c0c4ce242a277 Mon Sep 17 00:00:00 2001 From: Donnie-Ice Date: Thu, 2 May 2024 12:46:52 -0400 Subject: [PATCH 146/153] [nasa/nos3#294] Fixed config_path in Igniter --- cfg/gui/cfg_gui_main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py index 3fc9825e..232bfacb 100644 --- a/cfg/gui/cfg_gui_main.py +++ b/cfg/gui/cfg_gui_main.py @@ -27,6 +27,8 @@ def __init__(self, *args, **kwargs): self.defaultStyleSheet = self.ui.pushButton_buildAll.styleSheet() # Saves default stylesheet to return button color to normal, buttonColor() self.setup = 0 # Allows for switchConfig() to initially be called without calling saveText() self.configNumTrack = 0 # Tracks the index of the previous SC config when switching to another index + self.defaultConfig = f'{os.path.dirname(os.path.abspath(__file__))}/../nos3-mission.xml' + self.config_path = self.defaultConfig # Config Tab self.ui.pushButton_browse.clicked.connect(self.browseConfig) @@ -61,7 +63,7 @@ def __init__(self, *args, **kwargs): self.ui.lineEdit_secondsEntry.setDisabled(1) # Load Default Config - self.reloadConfig(f'{os.path.dirname(os.path.abspath(__file__))}/../nos3-mission.xml') + self.reloadConfig(self.defaultConfig) # Replaces the textbox on launch tab with a date/time box and vice versa def run_ForUntil(self): From b59559254f69b405845d36258f5a46067031115a Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Sun, 5 May 2024 14:21:30 -0400 Subject: [PATCH 147/153] [nasa/nos3#275] Updated sample checkout app to not force 32bit, swapped to USART 16, and renamed checkout script; --- Makefile | 2 +- cfg/sims/nos3-simulator.xml | 3 +++ components/sample | 2 +- scripts/{checkout.sh => docker_checkout.sh} | 9 ++++----- 4 files changed, 9 insertions(+), 7 deletions(-) rename scripts/{checkout.sh => docker_checkout.sh} (75%) mode change 100755 => 100644 diff --git a/Makefile b/Makefile index 5b93ca4c..95ea8b5b 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ build-sim: $(MAKE) --no-print-directory -C $(SIMBUILDDIR) install checkout: - ./scripts/checkout.sh + ./scripts/docker_checkout.sh clean: $(MAKE) clean-fsw diff --git a/cfg/sims/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml index d15d315b..69461bce 100644 --- a/cfg/sims/nos3-simulator.xml +++ b/cfg/sims/nos3-simulator.xml @@ -131,12 +131,15 @@ + SAMPLE_PROVIDER + diff --git a/components/sample b/components/sample index 5382e509..3a9923e0 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 5382e5097253ed661f715caf6d9f046087454c3c +Subproject commit 3a9923e0505130465ced4b37ee43b9d5eb4cdfef diff --git a/scripts/checkout.sh b/scripts/docker_checkout.sh old mode 100755 new mode 100644 similarity index 75% rename from scripts/checkout.sh rename to scripts/docker_checkout.sh index 8cc3d7fb..54d39142 --- a/scripts/checkout.sh +++ b/scripts/docker_checkout.sh @@ -20,11 +20,10 @@ echo "" # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually #echo "42..." -#cd /opt/nos3/42/ -#rm -rf NOS3InOut -#cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut +#rm -rf $USER_NOS3_DIR/42/NOS3InOut +#cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut #xhost +local:* -#gnome-terminal --window-with-profile=KeepOpen --title="42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t $DBOX /opt/nos3/42/42 NOS3InOut +#gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR:$USER_NOS3_DIR -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w $USER_NOS3_DIR/42 -t $DBOX $USER_NOS3_DIR/42/42 NOS3InOut #echo "" echo "NOS Core..." @@ -44,6 +43,6 @@ gnome-terminal --tab --title="Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --na # make # Rename for your checkout under test to allow checkout -gnome-terminal --title="Sample Sim" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR $DBOX ./components/sample/support/build/sample_checkout +gnome-terminal --title="Sample Checkout" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR $DBOX ./components/sample/support/build/sample_checkout echo "" From e527d51d73e1f3f907a1edf4ada308632cc18a89 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Sun, 5 May 2024 23:37:24 +0000 Subject: [PATCH 148/153] [nasa/nos3#275] Removed sample from 42 Inp_IPC.txt and updated to default to TGTNAME=cpu1 --- cfg/InOut/Inp_IPC.txt | 12 +----------- components/sample | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt index e7f7a534..1e2bc0d8 100644 --- a/cfg/InOut/Inp_IPC.txt +++ b/cfg/InOut/Inp_IPC.txt @@ -1,15 +1,5 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> -17 ! Number of Sockets -********************************** Sample IPC ***************************** -TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) -0 ! AC.ID for ACS mode -"State00.42" ! File name for WRITE or READ -SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -fortytwo 4242 ! Server Host Name, Port -FALSE ! Allow Blocking (i.e. wait on RX) -FALSE ! Echo to stdout -1 ! Number of TX prefixes -"SC" ! Prefix 0 +16 ! Number of Sockets ********************************** RW 0 to 42 ***************************** RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode diff --git a/components/sample b/components/sample index 3a9923e0..6b519d95 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 3a9923e0505130465ced4b37ee43b9d5eb4cdfef +Subproject commit 6b519d95486ca84d91b2dcf470a5055451e062c8 From 6b3fe3e1797a05021aab7dacf4189886d3165338 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Tue, 7 May 2024 19:01:38 +0000 Subject: [PATCH 149/153] [nasa/nos3#269] Updated the cosmos build script to copy targets into a COMPONENTS folder for use; --- gsw/cosmos | 2 +- scripts/docker-compose.yml | 112 ------------------------------ scripts/docker_build_cryptolib.sh | 0 scripts/docker_checkout.sh | 0 scripts/gsw_cosmos_build.sh | 17 ++--- 5 files changed, 8 insertions(+), 123 deletions(-) delete mode 100755 scripts/docker-compose.yml mode change 100644 => 100755 scripts/docker_build_cryptolib.sh mode change 100644 => 100755 scripts/docker_checkout.sh diff --git a/gsw/cosmos b/gsw/cosmos index fd47c51d..d72c4030 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit fd47c51da784167318bee3a2bc8533ab11628a03 +Subproject commit d72c403091a35bea6d1b5acb4f3e7e67573a49cd diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml deleted file mode 100755 index 953c6e72..00000000 --- a/scripts/docker-compose.yml +++ /dev/null @@ -1,112 +0,0 @@ -version: '3.3' -services: - nos_engine_server_standalone: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json - working_dir: $SIM_BIN - tty: true - nos-time-driver: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos-time-driver - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-simulator-terminal: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-simulator-terminal - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-cam-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-cam-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-generic-reactionwheel-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-generic-reactionwheel-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-gps-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-gps-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-sample-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-sample-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - truth42sim: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-single-simulator truth42sim - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - fsw: - volumes: - - '$FSW_BIN:$FSW_BIN' - network_mode: host - image: nos3 - command: $FSW_BIN/core-cpu1 -R PO - working_dir: $FSW_BIN - stdin_open: true - tty: true - sysctls: - - fs.mqueue.msg_max=500 - depends_on: - - nos_engine_server_standalone - fortytwo: - volumes: - - '/opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut' - - '/tmp/.X11-unix:/tmp/.X11-unix:ro' - network_mode: host - image: nos3 - command: /opt/nos3/42/42 NOS3InOut - working_dir: /opt/nos3/42 - tty: true - environment: - - DISPLAY=$DISPLAY - depends_on: - - nos_engine_server_standalone - cosmos: - volumes: - - '/home/nos3/Desktop/github-nos3/gsw/cosmos:/cosmos/cosmos' - - '/home/nos3/Desktop/github-nos3/components/:/COMPONENTS' - - '/tmp/.X11-unix:/tmp/.X11-unix:ro' - network_mode: host - image: ballaerospace/cosmos - command: /bin/bash -c 'ruby Launcher -c nos3_launcher.txt --system nos3_system.txt && true' # true is necessary to avoid setpgrp error - working_dir: /cosmos/cosmos - tty: true - environment: - - DISPLAY=$DISPLAY - - QT_X11_NO_MITSHM=1 diff --git a/scripts/docker_build_cryptolib.sh b/scripts/docker_build_cryptolib.sh old mode 100644 new mode 100755 diff --git a/scripts/docker_checkout.sh b/scripts/docker_checkout.sh old mode 100644 new mode 100755 diff --git a/scripts/gsw_cosmos_build.sh b/scripts/gsw_cosmos_build.sh index 53085664..84d591ac 100755 --- a/scripts/gsw_cosmos_build.sh +++ b/scripts/gsw_cosmos_build.sh @@ -7,14 +7,11 @@ CFG_BUILD_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd SCRIPT_DIR=$CFG_BUILD_DIR/../../scripts source $SCRIPT_DIR/env.sh -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#exit - -#echo "Make /tmp folders..." -#mkdir /tmp/data 2> /dev/null -#mkdir /tmp/data/hk 2> /dev/null -#mkdir /tmp/uplink 2> /dev/null - echo "COSMOS build..." +mkdir $GSW_DIR/COMPONENTS 2> /dev/null +rm -r $GSW_DIR/COMPONENTS/* 2> /dev/null +for i in $(find $BASE_DIR/components/ -name "gsw" -type d) +do + #echo "$i" + cp -r $i/* $GSW_DIR/COMPONENTS/ +done From e7abfa8e9b58809dc1cda2262b4fea0cd5ba49a1 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 8 May 2024 11:52:32 -0400 Subject: [PATCH 150/153] [nasa/nos3#269] Minor update to readme; --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f376f763..61a19ae8 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,17 @@ The best source of documentation can be found at [the wiki](https://github.com/n ### Prerequisites Each of the applications listed below are required prior to performing the installation procedure: -* Option A +* Option A, you already use Linux * [Git 2.36+](https://git-scm.com/) * Linux with docker and docker compose installed -* Option B +* Option B, deployment of a virtual machine (VM) * [Git 2.36+](https://git-scm.com/) * [Vagrant 2.3.4+](https://www.vagrantup.com/) * [VirtualBox 7.0+](https://www.virtualbox.org/) ### Installing +Option B only. +Will provision a VM with all required packages installed to be used immediately. 1. Clone the repository `git clone https://github.com/nasa/nos3.git` 2. `cd nos3` 3. Clone the submodules `git submodule update --init --recursive` From 4704a5b32e384b918d1e8b0134842e6d74e326dd Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 8 May 2024 12:40:56 -0400 Subject: [PATCH 151/153] [nasa/nos3#269] Removed invalid git reset command in prepare script; --- scripts/prepare.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/prepare.sh b/scripts/prepare.sh index d73ae7b3..03371dc6 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -18,7 +18,6 @@ echo "" echo "Clone openc3-cosmos into local user directory..." cd $USER_NOS3_DIR git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main $USER_NOS3_DIR/cosmos -git reset --hard echo "" echo "" From 037bc8cb2bf8070767499c4aff265e8db0b369ed Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Wed, 8 May 2024 14:28:35 -0400 Subject: [PATCH 152/153] [nasa/nos3#269] Updated cosmos submodule after merge; --- gsw/cosmos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsw/cosmos b/gsw/cosmos index d72c4030..50c889a4 160000 --- a/gsw/cosmos +++ b/gsw/cosmos @@ -1 +1 @@ -Subproject commit d72c403091a35bea6d1b5acb4f3e7e67573a49cd +Subproject commit 50c889a4f6ad21bd0dbc6e32254252a435e57770 From fc2674c29df6bc4e257a03ca2330cc6adad736af Mon Sep 17 00:00:00 2001 From: Mark Suder Date: Mon, 13 May 2024 16:07:06 -0400 Subject: [PATCH 153/153] [nasa/nos3#303] - Fix compiler warnings and errors. --- cfg/nos3_defs/arch_build_custom.cmake | 12 ++++++++---- components/arducam | 2 +- components/generic_adcs | 2 +- components/generic_css | 2 +- components/generic_eps | 2 +- components/generic_fss | 2 +- components/generic_imu | 2 +- components/generic_mag | 2 +- components/generic_star_tracker | 2 +- components/generic_torquer | 2 +- components/novatel_oem615 | 2 +- components/sample | 2 +- components/syn | 2 +- fsw/apps/hwlib | 2 +- 14 files changed, 21 insertions(+), 17 deletions(-) diff --git a/cfg/nos3_defs/arch_build_custom.cmake b/cfg/nos3_defs/arch_build_custom.cmake index e2af60d2..a2919a52 100644 --- a/cfg/nos3_defs/arch_build_custom.cmake +++ b/cfg/nos3_defs/arch_build_custom.cmake @@ -28,18 +28,22 @@ add_compile_options( #-std=c99 # Target the C99 standard (without gcc extensions) #-pedantic # Issue all the warnings demanded by strict ISO C - -Wall # Warn about most questionable operations + #-Wall # Warn about most questionable operations #-Wstrict-prototypes # Warn about missing prototypes - -Wwrite-strings # Warn if not treating string literals as "const" - -Wpointer-arith # Warn about suspicious pointer operations + #-Wwrite-strings # Warn if not treating string literals as "const" + #-Wpointer-arith # Warn about suspicious pointer operations #-Werror # Treat warnings as errors (code should be clean) - -Wno-address-of-packed-member + #-Wno-address-of-packed-member # Build Specific -DBYTE_ORDER_LE -D_LINUX_OS_ -D_DEFAULT_SOURCE ) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wstrict-prototypes -pedantic -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wwrite-strings -Wpointer-arith -Wno-address-of-packed-member") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + if (CFE_SYSTEM_PSPNAME STREQUAL "nos-linux") # find itc cmake module path find_path(_ITC_CMAKE_MODULES_ diff --git a/components/arducam b/components/arducam index 88e946d5..b05c9746 160000 --- a/components/arducam +++ b/components/arducam @@ -1 +1 @@ -Subproject commit 88e946d54da6e0ed5e2084fd46e8476ff473b3c2 +Subproject commit b05c9746b7f49f852a79e05ccc7f01e043fca72f diff --git a/components/generic_adcs b/components/generic_adcs index 2755e61e..4911e51d 160000 --- a/components/generic_adcs +++ b/components/generic_adcs @@ -1 +1 @@ -Subproject commit 2755e61e66d847aada2bce545e537ea5606d9e27 +Subproject commit 4911e51d589623ab1c1899d1eac6ccde57fa40e1 diff --git a/components/generic_css b/components/generic_css index 1bbba058..448e0251 160000 --- a/components/generic_css +++ b/components/generic_css @@ -1 +1 @@ -Subproject commit 1bbba058117e2c8a3bf17229a1102eab7a67bee4 +Subproject commit 448e0251a2e5ff756c9c86142f17db6be45a7662 diff --git a/components/generic_eps b/components/generic_eps index 2c6d147e..c460ba5a 160000 --- a/components/generic_eps +++ b/components/generic_eps @@ -1 +1 @@ -Subproject commit 2c6d147eb6b7c4b6e43298ff8c4d743da9002d38 +Subproject commit c460ba5a6e9ab9eb9f0f04bd009517b7a0ad24c6 diff --git a/components/generic_fss b/components/generic_fss index a20aaa5f..29426d8d 160000 --- a/components/generic_fss +++ b/components/generic_fss @@ -1 +1 @@ -Subproject commit a20aaa5f0a4bd3c6ed9b76e088a172ac17f05847 +Subproject commit 29426d8d7d6d253272bda468076a1b6453327a47 diff --git a/components/generic_imu b/components/generic_imu index 6d1058e3..5e317f3b 160000 --- a/components/generic_imu +++ b/components/generic_imu @@ -1 +1 @@ -Subproject commit 6d1058e370f09ead713f03a8cee10d308549059c +Subproject commit 5e317f3b3734c6944843fb0afc06fc14099bac5a diff --git a/components/generic_mag b/components/generic_mag index a67fdade..c995ff79 160000 --- a/components/generic_mag +++ b/components/generic_mag @@ -1 +1 @@ -Subproject commit a67fdadea4663bebc308d88c974438c677aab8ba +Subproject commit c995ff79d2b49351761b255ab48de3121f52b634 diff --git a/components/generic_star_tracker b/components/generic_star_tracker index 6fb52ab3..bc075ea8 160000 --- a/components/generic_star_tracker +++ b/components/generic_star_tracker @@ -1 +1 @@ -Subproject commit 6fb52ab329c5ca783dcff2b904da1a3b3e19c876 +Subproject commit bc075ea8c1eaec71c613c8bb9e20582ae02c6430 diff --git a/components/generic_torquer b/components/generic_torquer index fda1fb7c..bd9242dc 160000 --- a/components/generic_torquer +++ b/components/generic_torquer @@ -1 +1 @@ -Subproject commit fda1fb7c323b5e66707e4c7acd8cc45d6213654f +Subproject commit bd9242dceba6c982191efdb9cb8a0aaedf4aad65 diff --git a/components/novatel_oem615 b/components/novatel_oem615 index 8d526247..ba08c053 160000 --- a/components/novatel_oem615 +++ b/components/novatel_oem615 @@ -1 +1 @@ -Subproject commit 8d526247d049ba1ec45f0eb108daff7f9e8e8003 +Subproject commit ba08c053c734ebdf94f4f3e3dc787a52b2a73a3f diff --git a/components/sample b/components/sample index 6b519d95..34260dd8 160000 --- a/components/sample +++ b/components/sample @@ -1 +1 @@ -Subproject commit 6b519d95486ca84d91b2dcf470a5055451e062c8 +Subproject commit 34260dd8a8d929b6d36c8805f08754aa847d6e97 diff --git a/components/syn b/components/syn index dcf625c3..b7d5cc8b 160000 --- a/components/syn +++ b/components/syn @@ -1 +1 @@ -Subproject commit dcf625c30879d129aaa25a36789cf676cce59973 +Subproject commit b7d5cc8bde0d88ba20700a02acb17cf95644de1a diff --git a/fsw/apps/hwlib b/fsw/apps/hwlib index 7f4fc717..cf82b544 160000 --- a/fsw/apps/hwlib +++ b/fsw/apps/hwlib @@ -1 +1 @@ -Subproject commit 7f4fc7177f7819d034d237c2a8a26a3cca319a98 +Subproject commit cf82b54413a007e79f534234733f113359660eb3