add SIM_webpanel (#1291)
BIN
trick_sims/SIM_webpanel/Images/BalloonGraphicsClient.png
Normal file
After Width: | Height: | Size: 264 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation1.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation10.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation11.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation12.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation13.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation2.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation3.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation4.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation5.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation6.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation7.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation8.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
trick_sims/SIM_webpanel/Images/Equation9.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
trick_sims/SIM_webpanel/Images/Picture1.png
Normal file
After Width: | Height: | Size: 245 KiB |
BIN
trick_sims/SIM_webpanel/Images/Picture2.png
Normal file
After Width: | Height: | Size: 205 KiB |
BIN
trick_sims/SIM_webpanel/Images/Picture3.png
Normal file
After Width: | Height: | Size: 245 KiB |
BIN
trick_sims/SIM_webpanel/Images/Tree1.png
Normal file
After Width: | Height: | Size: 485 KiB |
BIN
trick_sims/SIM_webpanel/Images/Tree2.png
Normal file
After Width: | Height: | Size: 547 KiB |
9
trick_sims/SIM_webpanel/Modified_data/realtime.py
Executable file
@ -0,0 +1,9 @@
|
||||
trick.real_time_enable()
|
||||
trick.exec_set_software_frame(0.1)
|
||||
trick.itimer_enable()
|
||||
|
||||
trick.exec_set_enable_freeze(True)
|
||||
trick.exec_set_freeze_command(True)
|
||||
|
||||
simControlPanel = trick.SimControlPanel()
|
||||
trick.add_external_application(simControlPanel)
|
202
trick_sims/SIM_webpanel/README.md
Normal file
@ -0,0 +1,202 @@
|
||||
# Hot-Air Balloon Simulation
|
||||
A hot-air balloon is a lighter than air aircraft consisting of
|
||||
|
||||
1. an envelope (the big air-bag),
|
||||
2. a burner system to heat the air in the envelope, and
|
||||
3. a basket to carry fuel and passengers.
|
||||
|
||||
The motion of the balloon is controlled by changing the temperature of the air within the envelope. As the temperature of the air within the envelope increases, its density, and therefore its mass decreases. When the total mass of the balloon becomes less the mass of the cooler outside air that it displaces, the balloon ascends.
|
||||
|
||||
![Balloon Parts](Images/Picture1.png)
|
||||
|
||||
## Building the Simulation
|
||||
In the ```SIM_balloon``` directory, type **```trick-CP```** to build the simulation executable. When it's complete, you should see:
|
||||
|
||||
```
|
||||
=== Simulation make complete ===
|
||||
```
|
||||
Now **cd** into ```models/graphics/``` and type **make**. This builds the graphics client for the simulation.
|
||||
|
||||
## Running the Simulation
|
||||
In the SIM_balloon directory:
|
||||
|
||||
```
|
||||
% S_main_*.exe RUN_test/input.py
|
||||
```
|
||||
The Sim Control Panel, and a graphics client called "Balloon Range" should appear.
|
||||
|
||||
Click the Start on the Trick Sim Control Panel.
|
||||
|
||||
## U.S. Standard Atmosphere Model
|
||||
|
||||
The US Standard Atmosphere is a static model of pressure, temperature, density, gravitational acceleration, and viscosity as functions of altitude.
|
||||
|
||||
In the ```models/atmosphere``` directory of SIM_balloon we've implemented the following four C-language functions using data found at [www.engineeringtoolbox.com](https://www.engineeringtoolbox.com/standard-atmosphere-d_604.html). The functions are valid for altitudes between -1000 meters and 80,000 meters.
|
||||
|
||||
```double US_STD_density( double alt_m);```
|
||||
|
||||
Returns atmospheric density (kg/m3) at the given altitude (m).
|
||||
|
||||
```double US_STD_gravity( double alt_m);```
|
||||
|
||||
Returns acceleration of gravity (m/s2) at the given altitude (m).
|
||||
|
||||
```double US_STD_temperature( double alt_m);```
|
||||
|
||||
Returns atmospheric temperature (℃) at the given altitude (m).
|
||||
|
||||
```double US_STD_pressure( double alt_m);```
|
||||
|
||||
Returns atmospheric pressure (pascals) at the given altitude (m).
|
||||
|
||||
|
||||
## Dynamics Model
|
||||
|
||||
The forces acting on our balloon will be those of gravity, buoyancy and aerodynamic drag.
|
||||
|
||||
![Balloon Forces](Images/Picture2.png)
|
||||
|
||||
To determine the balloon’s motion, we first need to know it’s acceleration. We can determine this by calculating and summing the forces acting on the balloon, and then dividing that sum by the balloons total mass.
|
||||
|
||||
<a id=Equation-1></a>
|
||||
![Equation 1](Images/Equation1.png)
|
||||
|
||||
To help us calculate these forces we use the US Standard Atmosphere model described above.
|
||||
|
||||
To find the state of the balloon, we integrate acceleration and velocity, over time, to get velocity and position.
|
||||
|
||||
---
|
||||
|
||||
### Force of Gravity
|
||||
|
||||
Applying the acceleration of gravity to Newton’s 2nd Law:
|
||||
|
||||
<a id=Equation-2></a>
|
||||
![Equation 2](Images/Equation2.png)
|
||||
|
||||
At sea-level, **g** is around 9.81 m/s2. But as altitude increases **g** decreases. To determine **g** for a given altitude we use the ```US_STD_gravity(altitude)``` function from the atmosphere model library.
|
||||
|
||||
#### Balloon Mass
|
||||
|
||||
The total balloon mass is the sum of the fixed mass and the mass of the heated air inside the balloon envelope.
|
||||
|
||||
<a id=Equation-3></a>
|
||||
![Equation 3](Images/Equation3.png)
|
||||
|
||||
##### Balloon Fixed Mass
|
||||
|
||||
The fixed mass is simply the sum of the balloon component masses:
|
||||
|
||||
| Balloon Component | mass (m) |
|
||||
|----------------------|-----------:|
|
||||
| Envelope | 113.4 kg |
|
||||
| Basket | 63.5 kg |
|
||||
| Burner System | 206.4 kg |
|
||||
| Payload (passengers) | 300.0 kg |
|
||||
| -------------------- | -------------|
|
||||
| **m<sub>fixed</sub>**| **683.3 kg** |
|
||||
|
||||
#### Mass of Air in the Balloon
|
||||
|
||||
The mass of the air in the balloon envelope is the product of the volume of the balloon envelope and the density of the heated air within the envelope.
|
||||
|
||||
<a id=Equation-4></a>
|
||||
![Equation 4](Images/Equation4.png)
|
||||
|
||||
#### Balloon Volume
|
||||
|
||||
To calculate the volume the the balloon, we separate the balloon into two parts:
|
||||
|
||||
1. a spherical dome and
|
||||
2. a cone.
|
||||
|
||||
![Balloon Volume](Images/Picture3.png)
|
||||
**R** represents the radius of the spherical dome. **θ** represents angle at which the spherical dome transitions to the cone. The height (h) for each of the spherical and conical parts is given shown in the diagram. They are each used in their respective volume calculations below.
|
||||
|
||||
The volume of the spherical dome is:
|
||||
|
||||
<a id=Equation-5**></a>
|
||||
![Equation 5](Images/Equation5.png)
|
||||
|
||||
The volume of the cone is:
|
||||
|
||||
<a id=Equation-6></a>
|
||||
![Equation 6](Images/Equation6.png)
|
||||
|
||||
The total volume of the envelope is the sum of the two component volumes.
|
||||
|
||||
<a id=Equation-7></a>
|
||||
![Equation 7](Images/Equation7.png)
|
||||
|
||||
#### Air Density
|
||||
To calculate air density (𝝆) we use the following form of the Ideal Gas Law.
|
||||
|
||||
<a id=Equation-8></a>
|
||||
![Equation 8](Images/Equation8.png)
|
||||
|
||||
* p is just the standard pressure (in pascals) at the balloon's current altitude. Use ```US_STD_pressure(altitude)```.
|
||||
* R<sub>air</sub> is the specific gas constant for dry air. R<sub>air</sub> = 287.055 J/kg K.
|
||||
* T is the temperature of the gas in kelvin. The conversion from celsius to kelvin is T<sub>kelvin</sub> = T<sub>celsius</sub> + 273.15.
|
||||
|
||||
---
|
||||
|
||||
### Force of Buoyancy
|
||||
|
||||
Buoyancy is a force on an object, that opposes gravity, by a fluid within which it’s immersed. This force is equal to the mass of the displaced fluid times the acceleration of gravity.
|
||||
|
||||
<a id=Equation-9></a>
|
||||
![Equation 9](Images/Equation9.png)
|
||||
|
||||
Here, we can do that same calculation for air mass as before, using
|
||||
[Equation #4](#Equation-4), but this time with 𝝆 = ```US_STD_density(altitude)```, which assumes U.S Standard temperature at the given altitude.
|
||||
|
||||
---
|
||||
|
||||
### Force of Drag Due to Motion and Wind
|
||||
|
||||
As a balloon moves through the air, it encounters an atmospheric drag force. This force is a function of:
|
||||
|
||||
* the density of the surrounding air (𝝆),
|
||||
* the balloons velocity with respect to the surrounding air (v<sub>TAS</sub>),
|
||||
* the balloons coefficient of drag (C<sub>d</sub>) perpendicular to v<sub>TAS</sub>, and
|
||||
* the cross-sectional area (A) perpendicular to v<sub>TAS</sub>,
|
||||
|
||||
|
||||
<a id=Equation-10></a>
|
||||
![Equation 10](Images/Equation10.png)
|
||||
|
||||
Since the balloon will be moving through our “standard atmosphere” 𝝆 = ```US_STD_density(altitude)```.
|
||||
|
||||
The velocity of the balloon through the surrounding air (v<sub>TAS</sub>) is equal to its velocity with respect to the ground (v<sub>balloon</sub>) minus the wind velocity (v<sub>wind</sub>). **TAS** stands for True air speed.
|
||||
|
||||
<a id=Equation-11></a>
|
||||
![Equation 10](Images/Equation11.png)
|
||||
|
||||
The default value of C<sub>d</sub> = 0.5 (the coefficient of drag for a sphere) for both the horizontal and vertical axes of motion.
|
||||
|
||||
We can calculate the cross-sectional area (A) from the radius of the spherical portion of our balloon.
|
||||
|
||||
For vertical motion:
|
||||
![Equation 12](Images/Equation12.png)
|
||||
For horizontal motion:
|
||||
![Equation 13](Images/Equation13.png)
|
||||
|
||||
## Graphics
|
||||
|
||||
Before running the simulation, the graphics client needs to be compiled. ```cd``` into ```models/graphics```, and run ```make```.
|
||||
|
||||
![](Images/BalloonGraphicsClient.png)
|
||||
|
||||
When the simulation is run, the client will automatically be launched.
|
||||
|
||||
## References
|
||||
|
||||
* [https://www.engineeringtoolbox.com/molecular-mass-air-d_679.html](https://www.engineeringtoolbox.com/molecular-mass-air-d_679.html)
|
||||
* [https://www.engineeringtoolbox.com/standard-atmosphere-d_604.html]
|
||||
(https://www.engineeringtoolbox.com/standard-atmosphere-d_604.html)
|
||||
* [https://en.wikipedia.org/wiki/Ideal_gas_law]
|
||||
(https://en.wikipedia.org/wiki/Ideal_gas_law)
|
||||
* [https://en.wikipedia.org/wiki/Hot-air_balloon]
|
||||
(https://en.wikipedia.org/wiki/Hot-air_balloon)
|
||||
* [https://www.balloon-rides.com/atics-facts.htm]
|
||||
(https://www.balloon-rides.com/atics-facts.htm)
|
32
trick_sims/SIM_webpanel/RUN_test/input.py
Normal file
@ -0,0 +1,32 @@
|
||||
exec(open("Modified_data/realtime.py").read())
|
||||
web.server.enable = True
|
||||
web.server.port = 8888
|
||||
web.server.document_root = "www"
|
||||
web.server.debug = False
|
||||
web.server.ssl_enable = False
|
||||
web.server.error_log_file = "civet_server_error.log"
|
||||
|
||||
|
||||
dyn.balloon.pos[0] = 0
|
||||
dyn.balloon.pos[1] = 0
|
||||
dyn.balloon.vel[0] = 0.0
|
||||
dyn.balloon.vel[1] = 0.0
|
||||
dyn.balloon.envelope_air_temperature = 92.0
|
||||
dyn.balloon.wind_speed = 0.0
|
||||
|
||||
# ==========================================
|
||||
# Start the Satellite Graphics Client
|
||||
# ==========================================
|
||||
varServerPort = trick.var_server_get_port();
|
||||
BalloonDisplay_path = "models/graphics/dist/BalloonDisplay.jar"
|
||||
|
||||
if (os.path.isfile(BalloonDisplay_path)) :
|
||||
BalloonDisplay_cmd = "java -jar " \
|
||||
+ BalloonDisplay_path \
|
||||
+ " " + str(varServerPort) + " &" ;
|
||||
print(BalloonDisplay_cmd)
|
||||
os.system( BalloonDisplay_cmd);
|
||||
else :
|
||||
print('==================================================================================')
|
||||
print('BalloonDisplay needs to be built. Please \"cd\" into ../models/graphics and type \"make\".')
|
||||
print('==================================================================================')
|
31
trick_sims/SIM_webpanel/S_define
Normal file
@ -0,0 +1,31 @@
|
||||
/************************************************************
|
||||
PURPOSE:
|
||||
( Simulate a hot-air balloon. )
|
||||
LIBRARY DEPENDENCIES:
|
||||
((balloon/src/Balloon.cpp)
|
||||
(atmosphere/src/atmosphere.c))
|
||||
*************************************************************/
|
||||
#include "sim_objects/default_trick_sys.sm"
|
||||
##include "balloon/include/Balloon.hh"
|
||||
#include "sim_objects/CivetServer.sm"
|
||||
|
||||
class BalloonSimObject : public Trick::SimObject {
|
||||
public:
|
||||
Balloon balloon;
|
||||
|
||||
BalloonSimObject() {
|
||||
("default_data") balloon.default_data() ;
|
||||
("initialization") balloon.state_init() ;
|
||||
("derivative") balloon.state_deriv() ;
|
||||
(0.1, "scheduled") balloon.control() ;
|
||||
("integration") trick_ret = balloon.state_integ() ;
|
||||
("post_integration") balloon.check_ground_contact() ;
|
||||
}
|
||||
};
|
||||
|
||||
BalloonSimObject dyn;
|
||||
IntegLoop dyn_integloop(0.1) dyn;
|
||||
|
||||
void create_connections() {
|
||||
dyn_integloop.getIntegrator(Runge_Kutta_4, 4);
|
||||
}
|
2
trick_sims/SIM_webpanel/S_overrides.mk
Normal file
@ -0,0 +1,2 @@
|
||||
TRICK_CFLAGS += -Imodels
|
||||
TRICK_CXXFLAGS += -Imodels
|
@ -0,0 +1,24 @@
|
||||
#ifndef ATMOSPHERE_H
|
||||
#define ATMOSPHERE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Returns atmospheric density (kg/m^3) at the given altitude (m).*/
|
||||
double US_STD_density ( double alt_m );
|
||||
|
||||
/* Returns acceleration of gravity (m/s^2) at the given altitude (m).*/
|
||||
double US_STD_gravity( double alt_m);
|
||||
|
||||
/* Returns atmospheric temperature (℃) at the given altitude (m).*/
|
||||
double US_STD_temperature( double alt_m );
|
||||
|
||||
/* Returns atmospheric pressure (pascals) at the given altitude (m).*/
|
||||
double US_STD_pressure( double alt_m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
71
trick_sims/SIM_webpanel/models/atmosphere/src/atmosphere.c
Executable file
@ -0,0 +1,71 @@
|
||||
#include <stdio.h>
|
||||
|
||||
static double interpolate( double x, const double xa[], const double fa[], int N_elems ) {
|
||||
int ii;
|
||||
for (ii=0 ; ((ii+2 < N_elems ) && (x > xa[ii+1])) ; ii++ ) ;
|
||||
double x_lower = xa[ii];
|
||||
double x_upper = xa[ii+1];
|
||||
double f_lower = fa[ii];
|
||||
double f_upper = fa[ii+1];
|
||||
if (x < x_lower) {
|
||||
fprintf(stderr, "Interpolation x is out of range low.\n");
|
||||
return(f_lower);
|
||||
}
|
||||
if (x > x_upper) {
|
||||
fprintf(stderr, "Interpolation x is out of range high.\n");
|
||||
return(f_upper);
|
||||
}
|
||||
double f = (x_upper - x)/(x_upper - x_lower) * f_lower +
|
||||
(x - x_lower)/(x_upper - x_lower) * f_upper ;
|
||||
return(f);
|
||||
}
|
||||
|
||||
#define NUM_ELEMENTS 21
|
||||
// Units = meters (above sea level).
|
||||
const double altitude_array[NUM_ELEMENTS] = {
|
||||
-1000.0, 0.0, 1000.0, 2000.0, 3000.0, 4000.0, 5000.0, 6000.0,
|
||||
7000.0, 8000.0, 9000.0, 10000.0, 15000.0, 20000.0, 25000.0, 30000.0,
|
||||
40000.0, 50000.0, 60000.0, 70000.0, 80000.0 };
|
||||
|
||||
// Units = kilograms per cubic meter.
|
||||
const double US_STD_density_array[NUM_ELEMENTS] = {
|
||||
1.347, 1.225, 1.112, 1.007, 0.9093, 0.8194, 0.7364, 0.6601,
|
||||
0.5900, 0.5258, 0.4671, 0.4135, 0.1948, 0.08891, 0.04008, 0.01841,
|
||||
0.003996, 0.001027, 0.0003097, 0.00008283, 0.00001846 };
|
||||
|
||||
// Units = meters per second squared.
|
||||
const double US_STD_gravity_array[NUM_ELEMENTS] = {
|
||||
9.810, 9.807, 9.804, 9.801, 9.797, 9.794, 9.791, 9.788,
|
||||
9.785, 9.782, 9.779, 9.776, 9.761, 9.745, 9.730, 9.715,
|
||||
9.684, 9.654, 9.624, 9.594, 9.564
|
||||
};
|
||||
|
||||
// Units = celsius
|
||||
const double US_STD_temperature_array[NUM_ELEMENTS] = {
|
||||
21.50, 15.00, 8.50, 2.00, -4.49, -10.98, -17.47, -23.96,
|
||||
-30.45, -36.94, -43.42, -49.90, -56.50, -56.50, -51.60, -46.64,
|
||||
-22.80, -2.5, -26.13, -53.57, -74.51
|
||||
};
|
||||
|
||||
// Units = pascals
|
||||
const double US_STD_pressure_array[NUM_ELEMENTS] = {
|
||||
113900.0, 101325.0, 89880.0, 79500.0, 70120.0, 61660.0, 54050.0, 47220.0,
|
||||
41110.0, 35650.0, 30800.0, 26500.0, 12110.0, 5529.0, 2549.0, 1197.0,
|
||||
287.00, 79.78, 21.96, 5.20, 1.10
|
||||
};
|
||||
|
||||
double US_STD_density ( double alt_m ) {
|
||||
return interpolate( alt_m, altitude_array, US_STD_density_array, NUM_ELEMENTS );
|
||||
}
|
||||
|
||||
double US_STD_gravity( double alt_m) {
|
||||
return interpolate( alt_m, altitude_array, US_STD_gravity_array, NUM_ELEMENTS );
|
||||
}
|
||||
|
||||
double US_STD_temperature( double alt_m ) {
|
||||
return interpolate( alt_m, altitude_array, US_STD_temperature_array, NUM_ELEMENTS );
|
||||
}
|
||||
|
||||
double US_STD_pressure( double alt_m) {
|
||||
return interpolate( alt_m, altitude_array, US_STD_pressure_array, NUM_ELEMENTS );
|
||||
}
|
51
trick_sims/SIM_webpanel/models/balloon/include/Balloon.hh
Executable file
@ -0,0 +1,51 @@
|
||||
/************************************************************************
|
||||
PURPOSE: (Simulate a hor-air balloon.)
|
||||
LIBRARY DEPENDENCIES:
|
||||
((balloon/src/Balloon.o))
|
||||
**************************************************************************/
|
||||
#ifndef BALLOON_HH
|
||||
#define BALLOON_HH
|
||||
|
||||
class Balloon {
|
||||
public:
|
||||
// State Variables (Uncalculated Variables)
|
||||
double pos[2];
|
||||
double vel[2];
|
||||
double envelope_mass;
|
||||
double basket_mass;
|
||||
double burner_system_mass;
|
||||
double payload_mass;
|
||||
double envelope_air_temperature;
|
||||
double envelope_radius;
|
||||
double envelope_theta;
|
||||
double wind_speed;
|
||||
double Cd[2];
|
||||
|
||||
// Calculated Variables
|
||||
double acc[2];
|
||||
double envelope_volume;
|
||||
double fixed_mass;
|
||||
|
||||
// Control Variable
|
||||
int temperature_change_command;
|
||||
int wind_change_command;
|
||||
|
||||
// Methods
|
||||
int default_data();
|
||||
int state_init();
|
||||
int state_deriv();
|
||||
int state_integ();
|
||||
int check_ground_contact();
|
||||
int control();
|
||||
double calc_fixed_mass();
|
||||
double calc_envelope_volume();
|
||||
double calc_total_mass();
|
||||
double calc_envelope_air_mass();
|
||||
double calc_heated_air_density();
|
||||
double calc_buoyancy_force();
|
||||
double calc_displaced_air_mass();
|
||||
void calc_drag_force(double * F);
|
||||
double volume_of_a_spherical_dome( double r, double h);
|
||||
double volume_of_a_cone( double r, double h);
|
||||
};
|
||||
#endif
|
163
trick_sims/SIM_webpanel/models/balloon/src/Balloon.cpp
Executable file
@ -0,0 +1,163 @@
|
||||
/********************************* TRICK HEADER *******************************
|
||||
PURPOSE: ( Simulate a hot-air balloon. )
|
||||
LIBRARY DEPENDENCY:
|
||||
((Balloon.o))
|
||||
*******************************************************************************/
|
||||
#include "balloon/include/Balloon.hh"
|
||||
#include "atmosphere/include/atmosphere.h"
|
||||
|
||||
#include "trick/integrator_c_intf.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
|
||||
int Balloon::default_data() {
|
||||
|
||||
pos[0] = 0.0;
|
||||
pos[1] = 2.0;
|
||||
vel[0] = 0.0;
|
||||
vel[1] = 0.0;
|
||||
|
||||
envelope_mass = 113.4;
|
||||
basket_mass = 63.5;
|
||||
burner_system_mass = 206.4;
|
||||
payload_mass = 300.0;
|
||||
|
||||
envelope_air_temperature = 80;
|
||||
envelope_radius = 8.5;
|
||||
envelope_theta = 45 * (M_PI/180.0);
|
||||
|
||||
Cd[0] = 0.5;
|
||||
Cd[1] = 0.5;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int Balloon::state_init() {
|
||||
envelope_volume = calc_envelope_volume();
|
||||
fixed_mass = calc_fixed_mass();
|
||||
return (0);
|
||||
}
|
||||
|
||||
int Balloon::state_deriv() {
|
||||
double total_mass = calc_total_mass();
|
||||
double F_gravity = total_mass * (-US_STD_gravity( pos[1])); /* Equation #2 */
|
||||
double F_buoyancy = calc_buoyancy_force();
|
||||
double F_drag[2];
|
||||
calc_drag_force(F_drag);
|
||||
acc[0] = 0.0;
|
||||
|
||||
acc[0] = (F_drag[0]) / total_mass; /* Equation #1 */
|
||||
acc[1] = (F_gravity + F_buoyancy + F_drag[1]) / total_mass; /* Equation #1 */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int Balloon::state_integ() {
|
||||
int integration_step;
|
||||
load_state ( &pos[0], &pos[1], &vel[0], &vel[1], (double*)0);
|
||||
load_deriv ( &vel[0], &vel[1], &acc[0], &acc[1], (double*)0);
|
||||
integration_step = integrate();
|
||||
unload_state( &pos[0], &pos[1], &vel[0], &vel[1], (double*)0);
|
||||
return(integration_step);
|
||||
}
|
||||
|
||||
double Balloon::calc_total_mass() {
|
||||
return (fixed_mass + calc_envelope_air_mass());
|
||||
}
|
||||
|
||||
double Balloon::calc_envelope_air_mass() {
|
||||
double heated_air_density = calc_heated_air_density();
|
||||
return ( heated_air_density * envelope_volume ); /* Equation #4 with density of heated air. */
|
||||
}
|
||||
|
||||
double Balloon::calc_envelope_volume() {
|
||||
double h;
|
||||
|
||||
h = envelope_radius * (1.0 + sin( envelope_theta));
|
||||
double v_dome = volume_of_a_spherical_dome(envelope_radius, h);
|
||||
|
||||
double r = envelope_radius * cos(envelope_theta);
|
||||
h = r / tan(envelope_theta);
|
||||
double v_cone = volume_of_a_cone(r, h);
|
||||
|
||||
return (v_dome + v_cone); /* Equation #7 */
|
||||
}
|
||||
|
||||
double Balloon::volume_of_a_spherical_dome( double r, double h) {
|
||||
return (M_PI*((r*h*h)-((h*h*h)/3.0))); /* Equation #5 */
|
||||
}
|
||||
|
||||
double Balloon::volume_of_a_cone( double r, double h) {
|
||||
return ((M_PI*r*r*h)/3.0); /* Equation #6 */
|
||||
}
|
||||
|
||||
double Balloon::calc_heated_air_density() {
|
||||
double t_k = envelope_air_temperature + 273.15;
|
||||
double rho = US_STD_pressure(pos[1]) / (287.055 * t_k); /* Equation #8 */
|
||||
return rho;
|
||||
}
|
||||
|
||||
double Balloon::calc_buoyancy_force() {
|
||||
return( calc_displaced_air_mass() * US_STD_gravity( pos[1])); /* Equation 9 */
|
||||
}
|
||||
|
||||
double Balloon::calc_displaced_air_mass() {
|
||||
return( US_STD_density(pos[1]) * envelope_volume); /* Equation #4 with standard air density. */
|
||||
}
|
||||
|
||||
double Balloon::calc_fixed_mass() {
|
||||
return (envelope_mass + basket_mass + burner_system_mass + payload_mass);
|
||||
}
|
||||
|
||||
void Balloon::calc_drag_force(double *F_drag) {
|
||||
double altitude = pos[1];
|
||||
|
||||
/* Equation 11 */
|
||||
double v_tas[2];
|
||||
v_tas[0] = vel[0] - wind_speed;
|
||||
v_tas[1] = vel[1];
|
||||
|
||||
double A[2];
|
||||
A[0] = (0.75 * M_PI + 1.0) * envelope_radius * envelope_radius; /* Equation 13 */
|
||||
A[1] = M_PI * envelope_radius * envelope_radius; /* Equation 12 */
|
||||
|
||||
/* Equation 10 */
|
||||
F_drag[0] = -( 0.5 * US_STD_density(altitude) * abs(v_tas[0]) * v_tas[0] * Cd[0] * A[0] );
|
||||
F_drag[1] = -( 0.5 * US_STD_density(altitude) * abs(v_tas[1]) * v_tas[1] * Cd[1] * A[1] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int Balloon::control() {
|
||||
if ( temperature_change_command != 0) {
|
||||
envelope_air_temperature += temperature_change_command;
|
||||
temperature_change_command = 0;
|
||||
}
|
||||
if (envelope_air_temperature > 120.0) {
|
||||
envelope_air_temperature = 120.0;
|
||||
}
|
||||
if (envelope_air_temperature < 80.0) {
|
||||
envelope_air_temperature = 80.0;
|
||||
}
|
||||
if ( wind_change_command != 0) {
|
||||
wind_speed += wind_change_command;
|
||||
wind_change_command = 0;
|
||||
}
|
||||
if (wind_speed > 10.0) {
|
||||
wind_speed = 10.0;
|
||||
}
|
||||
if (wind_speed < -10.0) {
|
||||
wind_speed = -10.0;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int Balloon::check_ground_contact() {
|
||||
if (pos[1] < 2.0) {
|
||||
pos[1] = 2.0;
|
||||
vel[0] = 0.0;
|
||||
vel[1] = 0.0;
|
||||
}
|
||||
return(0);
|
||||
}
|
37
trick_sims/SIM_webpanel/models/graphics/Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
SHELL = /bin/sh
|
||||
|
||||
PROJECT_NAME = BalloonDisplay
|
||||
SRC_DIR = src
|
||||
BUILD_DIR = build
|
||||
CLASSES_DIR = $(BUILD_DIR)/classes
|
||||
JAR_DIR = dist
|
||||
MAIN_CLASS = BalloonDisplay
|
||||
|
||||
all: jar
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
rm -f manifest
|
||||
|
||||
spotless: clean
|
||||
rm -rf dist
|
||||
|
||||
$(CLASSES_DIR):
|
||||
@ mkdir -p $(CLASSES_DIR)
|
||||
|
||||
compile: | $(CLASSES_DIR)
|
||||
javac -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) $(SRC_DIR)/BalloonDisplay.java
|
||||
|
||||
manifest:
|
||||
@ echo "Main-Class: $(MAIN_CLASS)" > $@
|
||||
|
||||
$(JAR_DIR):
|
||||
@ mkdir -p $(JAR_DIR)
|
||||
|
||||
jar: compile manifest | $(JAR_DIR)
|
||||
jar cvfm $(JAR_DIR)/$(PROJECT_NAME).jar manifest -C $(CLASSES_DIR) .
|
||||
@ echo "-------------------------------------------------------------------------------"
|
||||
@ echo " BUILD COMPLETE"
|
||||
@ echo "The Java jar file (the Java Executable) is located at: $(JAR_DIR)/$(PROJECT_NAME).jar"
|
||||
@ echo "-------------------------------------------------------------------------------"
|
||||
|
677
trick_sims/SIM_webpanel/models/graphics/src/BalloonDisplay.java
Executable file
@ -0,0 +1,677 @@
|
||||
/*
|
||||
* Trick
|
||||
* 2021 (c) National Aeronautics and Space Administration (NASA)
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.sound.sampled.*;
|
||||
import java.net.URL;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import javax.swing.text.NumberFormatter;
|
||||
import java.text.NumberFormat;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.border.EtchedBorder;
|
||||
import java.awt.Component;
|
||||
/**
|
||||
*
|
||||
* @author penn
|
||||
*/
|
||||
|
||||
class ScenePoly {
|
||||
public Color color;
|
||||
public int n;
|
||||
public double[] x;
|
||||
public double[] y;
|
||||
}
|
||||
|
||||
class RangeView extends JPanel {
|
||||
|
||||
private int scale;
|
||||
private Color skyColor;
|
||||
private Color groundColor;
|
||||
private Color envelope_color_1;
|
||||
private Color envelope_color_2;
|
||||
private Color basket_color;
|
||||
private Color envelope_phong;
|
||||
|
||||
// Origin of world coordinates in jpanel coordinates.
|
||||
private int worldOriginX;
|
||||
private int worldOriginY;
|
||||
|
||||
private double[] balloonPos;
|
||||
private double[] balloonVel;
|
||||
private int envelopeAirTemp; /* degrees C */
|
||||
private int windSpeed;
|
||||
private double envelope_radius;
|
||||
private double envelope_theta;
|
||||
|
||||
private ScenePoly cone;
|
||||
private ScenePoly upright; // The frame that connects the basket, burner, and balloon
|
||||
private ScenePoly basket;
|
||||
|
||||
private int[] workPolyX, workPolyY;
|
||||
|
||||
// Controls
|
||||
private int deltaTemp ;
|
||||
private int deltaWind ;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public RangeView( int mapScale) {
|
||||
|
||||
setScale(mapScale);
|
||||
|
||||
deltaTemp = 0;
|
||||
deltaWind = 0;
|
||||
|
||||
skyColor = new Color(184,202,231);
|
||||
groundColor = new Color(100,140, 60);
|
||||
|
||||
balloonPos = new double[]
|
||||
{0.0, 2.0};
|
||||
balloonVel = new double[]
|
||||
{0.0, 0.0};
|
||||
|
||||
envelope_color_1 = new Color(254,181, 36);
|
||||
envelope_color_2 = new Color(251, 0, 21);
|
||||
basket_color = new Color(220,180,120);
|
||||
envelope_phong = new Color(220,220,220,80);
|
||||
|
||||
envelope_radius = 8.5;
|
||||
envelope_theta = Math.toRadians(45.0);
|
||||
|
||||
envelopeAirTemp = 0;
|
||||
windSpeed = 0;
|
||||
|
||||
cone = new ScenePoly();
|
||||
cone.color = envelope_color_1;
|
||||
cone.x = new double[4];
|
||||
cone.y = new double[4];
|
||||
cone.n = 4;
|
||||
|
||||
upright = new ScenePoly();
|
||||
upright.color = Color.BLACK;
|
||||
upright.x = new double[] {-0.40, 0.40, 0.50, 0.40, 0.30,-0.30,-0.40,-0.50};
|
||||
upright.y = new double[] { 0.00, 0.00,-1.00,-1.00,-0.10,-0.10,-1.00,-1.00};
|
||||
upright.n = 8;
|
||||
|
||||
basket = new ScenePoly();
|
||||
basket.color = basket_color;
|
||||
basket.x = new double[] {-0.50, 0.50, 0.50,-0.50};
|
||||
basket.y = new double[] {-1.00,-1.00,-2.00,-2.00};
|
||||
basket.n = 4;
|
||||
|
||||
workPolyX = new int[30];
|
||||
workPolyY = new int[30];
|
||||
}
|
||||
|
||||
// |jpanel_x| = |origin_x| + |scale 0 | * |cos(angle) -sin(angle)| * |world_x|
|
||||
// |jpanel_y| |origin_y| | 0 -scale| |sin(angle) cos(angle)| |world_y|
|
||||
|
||||
public void drawScenePoly(Graphics2D g, ScenePoly p, double angle_r , double x, double y) {
|
||||
for (int ii = 0; ii < p.n; ii++) {
|
||||
workPolyX[ii] = (int)(worldOriginX + scale *
|
||||
( Math.cos(angle_r) * p.x[ii] - Math.sin(angle_r) * p.y[ii] + x));
|
||||
workPolyY[ii] = (int)(worldOriginY - scale *
|
||||
( Math.sin(angle_r) * p.x[ii] + Math.cos(angle_r) * p.y[ii] + y));
|
||||
}
|
||||
g.setPaint(p.color);
|
||||
g.fillPolygon(workPolyX, workPolyY, p.n);
|
||||
}
|
||||
|
||||
public void drawSceneOval(Graphics2D g2d, Color color, double x, double y, double w, double h) {
|
||||
g2d.setPaint(color);
|
||||
g2d.fillOval( (int)(worldOriginX+scale*(x-w/2)), (int)(worldOriginY-scale*(y+h/2)), (int)(scale*w), (int)(scale*h));
|
||||
}
|
||||
|
||||
public void incTemperature() { deltaTemp = 1; }
|
||||
public void decTemperature() { deltaTemp = -1; }
|
||||
public void resetDeltaTemp() { deltaTemp = 0; }
|
||||
public int getDeltaTemp() { return deltaTemp; }
|
||||
|
||||
public void incWind() { deltaWind = 1; }
|
||||
public void decWind() { deltaWind = -1; }
|
||||
public void resetDeltaWind() { deltaWind = 0; }
|
||||
public int getDeltaWind() { return deltaWind; }
|
||||
|
||||
public void setballoonPos(double x, double y) {
|
||||
balloonPos[0] = x;
|
||||
balloonPos[1] = y;
|
||||
}
|
||||
public void setBalloonVel(double vx, double vy) {
|
||||
balloonVel[0] = vx;
|
||||
balloonVel[1] = vy;
|
||||
}
|
||||
public void setAirTemp(int temperature) {
|
||||
envelopeAirTemp = temperature;
|
||||
}
|
||||
public void setWindSpeed(int speed) {
|
||||
windSpeed = speed;
|
||||
}
|
||||
|
||||
public void setScale (int mapScale) {
|
||||
if (mapScale < 2) {
|
||||
scale = 2;
|
||||
} else if (mapScale > 128) {
|
||||
scale = 128;
|
||||
} else {
|
||||
scale = mapScale;
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
public int getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
private void doDrawing(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
RenderingHints rh = new RenderingHints(
|
||||
RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
rh.put(RenderingHints.KEY_RENDERING,
|
||||
RenderingHints.VALUE_RENDER_QUALITY);
|
||||
|
||||
int ii, jj;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
// |jpanel_x| = |origin_x| + |scale 0 | * |cos(angle) -sin(angle)| * |world_x|
|
||||
// |jpanel_y| |origin_y| | 0 -scale| |sin(angle) cos(angle)| |world_y|
|
||||
|
||||
worldOriginX = (width/2) - (int)(scale * balloonPos[0]);
|
||||
worldOriginY = (height/2) + (int)(scale * balloonPos[1]);
|
||||
|
||||
// ===============================================================================
|
||||
// Draw Sky
|
||||
// ===============================================================================
|
||||
g2d.setPaint(skyColor);
|
||||
g2d.fillRect(0, 0, width, worldOriginY);
|
||||
|
||||
// ===============================================================================
|
||||
// Draw ground.
|
||||
// ===============================================================================
|
||||
g2d.setPaint(groundColor);
|
||||
g2d.fillRect(0, worldOriginY, width, height);
|
||||
|
||||
// ===============================================================================
|
||||
// Draw Balloon
|
||||
// ===============================================================================
|
||||
|
||||
double r_cone_top = envelope_radius * Math.cos(envelope_theta);
|
||||
double h_cone = r_cone_top / Math.tan(envelope_theta);
|
||||
double h = envelope_radius * Math.sin(envelope_theta) + h_cone;
|
||||
double balloon_diameter = 2.0 * envelope_radius;
|
||||
|
||||
// Draw Dome
|
||||
drawSceneOval(g2d, envelope_color_1, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians( 0.0)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_color_2, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians(22.5)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_color_1, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians(37.5)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_color_2, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians(52.5)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_color_1, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians(67.5)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_color_2, balloonPos[0], balloonPos[1]+h, balloon_diameter*Math.cos(Math.toRadians(82.5)), balloon_diameter);
|
||||
drawSceneOval(g2d, envelope_phong, balloonPos[0], balloonPos[1]+h+4.0, balloon_diameter*Math.cos(Math.toRadians( 40.0)), balloon_diameter*Math.cos(Math.toRadians( 60.0)));
|
||||
|
||||
// Draw Cone
|
||||
cone.color = envelope_color_1;
|
||||
double rt = r_cone_top * Math.cos( Math.toRadians( 0.0));
|
||||
cone.x[0] = -rt;
|
||||
cone.y[0] = h_cone;
|
||||
cone.x[1] = rt;
|
||||
cone.y[1] = h_cone;
|
||||
cone.x[2] = 0.0;
|
||||
cone.y[2] = 0.0;
|
||||
cone.x[3] = 0.0;
|
||||
cone.y[3] = 0.0;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
cone.color = envelope_color_2;
|
||||
rt = r_cone_top * Math.cos( Math.toRadians(22.5));
|
||||
cone.x[0] = -rt;
|
||||
cone.x[1] = rt;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
cone.color = envelope_color_1;
|
||||
rt = r_cone_top * Math.cos( Math.toRadians(37.5));
|
||||
cone.x[0] = -rt;
|
||||
cone.x[1] = rt;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
cone.color = envelope_color_2;
|
||||
rt = r_cone_top * Math.cos( Math.toRadians(52.5));
|
||||
cone.x[0] = -rt;
|
||||
cone.x[1] = rt;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
cone.color = envelope_color_1;
|
||||
rt = r_cone_top * Math.cos( Math.toRadians(67.5));
|
||||
cone.x[0] = -rt;
|
||||
cone.x[1] = rt;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
cone.color = envelope_color_2;
|
||||
rt = r_cone_top * Math.cos( Math.toRadians(82.5));
|
||||
cone.x[0] = -rt;
|
||||
cone.x[1] = rt;
|
||||
drawScenePoly(g2d, cone, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
// Draw Upright
|
||||
drawScenePoly(g2d, upright, 0.0, balloonPos[0], balloonPos[1]);
|
||||
|
||||
// Draw Basket
|
||||
drawScenePoly(g2d, basket, 0.0, balloonPos[0], balloonPos[1]);
|
||||
// ===============================================================================
|
||||
// Draw range markers.
|
||||
// ===============================================================================
|
||||
int tickRange = 50;
|
||||
if (scale >= 8) tickRange = 20;
|
||||
if (scale >= 16) tickRange = 10;
|
||||
if (scale >= 32) tickRange = 5;
|
||||
if (scale >= 64) tickRange = 1;
|
||||
|
||||
int lower = ((int)(( - worldOriginX)/(scale * tickRange)) + 1) * tickRange;
|
||||
int upper = ((int)((width - worldOriginX)/(scale * tickRange)) + 1) * tickRange;
|
||||
|
||||
g2d.setPaint(Color.WHITE);
|
||||
|
||||
for (ii = lower ; ii < upper ; ii += tickRange) {
|
||||
int mx = (int)(worldOriginX + scale * ii);
|
||||
g2d.drawLine( mx, worldOriginY, mx, worldOriginY + 20);
|
||||
g2d.drawString ( String.format("%d",ii), mx, worldOriginY + 15);
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
// Draw Information
|
||||
// ===============================================================================
|
||||
g2d.setPaint(Color.BLACK);
|
||||
g2d.drawString ( String.format("SCALE: %d pixels/meter",scale), 20,20);
|
||||
g2d.drawString ( String.format("Envelope Air-Temp (°C) : [%d]", envelopeAirTemp), 20,40);
|
||||
g2d.drawString ( String.format("Wind Speed (m/s) : [%d]", windSpeed), 20,60);
|
||||
g2d.drawString ( String.format("Balloon Pos: [%.2f, %.2f]", balloonPos[0], balloonPos[1]), 20,80);
|
||||
g2d.drawString ( String.format("Balloon Vel: [%.2f, %.2f]", balloonVel[0], balloonVel[1]), 20,100);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
doDrawing(g);
|
||||
}
|
||||
}
|
||||
|
||||
class TrickSimMode {
|
||||
public static final int INIT = 0;
|
||||
public static final int FREEZE = 1;
|
||||
public static final int RUN = 5;
|
||||
}
|
||||
|
||||
class TemperatureCtrlPanel extends JPanel implements ActionListener {
|
||||
private RangeView rangeView;
|
||||
private JButton increaseTempButton, decreaseTempButton;
|
||||
|
||||
public TemperatureCtrlPanel(RangeView view) {
|
||||
rangeView = view;
|
||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||
setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
|
||||
|
||||
increaseTempButton = new JButton("\u25b2");
|
||||
increaseTempButton.addActionListener(this);
|
||||
increaseTempButton.setActionCommand("increaseTemp");
|
||||
increaseTempButton.setToolTipText("Increase Temperature");
|
||||
|
||||
decreaseTempButton = new JButton("\u25bc");
|
||||
decreaseTempButton.addActionListener(this);
|
||||
decreaseTempButton.setActionCommand("decreaseTemp");
|
||||
decreaseTempButton.setToolTipText("Decrease Temperature");
|
||||
|
||||
add(increaseTempButton);
|
||||
add(decreaseTempButton);
|
||||
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String s = e.getActionCommand();
|
||||
switch (s) {
|
||||
case "increaseTemp":
|
||||
rangeView.incTemperature();
|
||||
break;
|
||||
case "decreaseTemp":
|
||||
rangeView.decTemperature();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown Action Command:" + s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WindCtrlPanel extends JPanel implements ActionListener {
|
||||
private RangeView rangeView;
|
||||
private JButton increaseWindButton, decreaseWindButton;
|
||||
|
||||
public WindCtrlPanel(RangeView view) {
|
||||
rangeView = view;
|
||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||
setBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
|
||||
|
||||
increaseWindButton = new JButton("\u25b6");
|
||||
increaseWindButton.addActionListener(this);
|
||||
increaseWindButton.setActionCommand("increaseWind");
|
||||
increaseWindButton.setToolTipText("Increase Wind");
|
||||
|
||||
decreaseWindButton = new JButton("\u25c0");
|
||||
decreaseWindButton.addActionListener(this);
|
||||
decreaseWindButton.setActionCommand("decreaseWind");
|
||||
decreaseWindButton.setToolTipText("Decrease Wind");
|
||||
|
||||
add(decreaseWindButton);
|
||||
add(increaseWindButton);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String s = e.getActionCommand();
|
||||
switch (s) {
|
||||
case "increaseWind":
|
||||
rangeView.incWind();
|
||||
break;
|
||||
case "decreaseWind":
|
||||
rangeView.decWind();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown Action Command:" + s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ControlPanel extends JPanel implements ActionListener {
|
||||
|
||||
private RangeView rangeView;
|
||||
private JButton zoomOutButton, zoomInButton;
|
||||
private JButton shutDownButton;
|
||||
private TemperatureCtrlPanel temperatureCtrlPanel;
|
||||
private WindCtrlPanel windCtrlPanel;
|
||||
|
||||
public ControlPanel(RangeView view) {
|
||||
|
||||
rangeView = view;
|
||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||
|
||||
JPanel labeledTemperatureCtrlPanel = new JPanel();
|
||||
labeledTemperatureCtrlPanel.setLayout(new BoxLayout(labeledTemperatureCtrlPanel, BoxLayout.Y_AXIS));
|
||||
JLabel temperatureControlLabel = new JLabel("Temperature Control");
|
||||
temperatureControlLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
labeledTemperatureCtrlPanel.add(temperatureControlLabel);
|
||||
temperatureCtrlPanel = new TemperatureCtrlPanel(rangeView);
|
||||
labeledTemperatureCtrlPanel.add( temperatureCtrlPanel );
|
||||
add(labeledTemperatureCtrlPanel);
|
||||
|
||||
JPanel labeledWindCtrlPanel = new JPanel();
|
||||
labeledWindCtrlPanel.setLayout(new BoxLayout(labeledWindCtrlPanel, BoxLayout.Y_AXIS));
|
||||
JLabel windControlLabel = new JLabel("Wind Control");
|
||||
windControlLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
labeledWindCtrlPanel.add(windControlLabel);
|
||||
windCtrlPanel = new WindCtrlPanel(rangeView);
|
||||
labeledWindCtrlPanel.add( windCtrlPanel );
|
||||
add(labeledWindCtrlPanel);
|
||||
|
||||
zoomOutButton = new JButton("Zoom Out");
|
||||
zoomOutButton.addActionListener(this);
|
||||
zoomOutButton.setActionCommand("zoomout");
|
||||
zoomOutButton.setToolTipText("Zoom Out");
|
||||
add(zoomOutButton);
|
||||
|
||||
zoomInButton = new JButton("Zoom In");
|
||||
zoomInButton.addActionListener(this);
|
||||
zoomInButton.setActionCommand("zoomin");
|
||||
zoomInButton.setToolTipText("Zoom In");
|
||||
add(zoomInButton);
|
||||
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String s = e.getActionCommand();
|
||||
switch (s) {
|
||||
case "zoomout":
|
||||
rangeView.setScale( rangeView.getScale() / 2 );
|
||||
break;
|
||||
case "zoomin":
|
||||
rangeView.setScale( rangeView.getScale() * 2 );
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown Action Command:" + s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // class ControlPanel
|
||||
|
||||
public class BalloonDisplay extends JFrame {
|
||||
|
||||
private RangeView rangeView;
|
||||
private BufferedReader in;
|
||||
private DataOutputStream out;
|
||||
private JPanel panelGroup0;
|
||||
private JPanel panelGroup1;
|
||||
private ControlPanel controlPanel;
|
||||
|
||||
public BalloonDisplay(RangeView arena) {
|
||||
setTitle("Balloon Range");
|
||||
|
||||
rangeView = arena;
|
||||
|
||||
panelGroup1 = new JPanel();
|
||||
panelGroup1.setLayout(new BoxLayout(panelGroup1, BoxLayout.X_AXIS));
|
||||
panelGroup1.add(rangeView);
|
||||
|
||||
controlPanel = new ControlPanel(rangeView);
|
||||
|
||||
panelGroup0 = new JPanel();
|
||||
panelGroup0.setLayout(new BoxLayout(panelGroup0, BoxLayout.Y_AXIS));
|
||||
panelGroup0.add(panelGroup1);
|
||||
panelGroup0.add(controlPanel);
|
||||
|
||||
add(panelGroup0);
|
||||
|
||||
rangeView.setScale(8);
|
||||
rangeView.setballoonPos (0.0, 2.0);
|
||||
|
||||
setSize(800, 500);
|
||||
setLocationRelativeTo(null);
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setFocusable(true);
|
||||
|
||||
}
|
||||
|
||||
public void connectToServer(String host, int port ) throws IOException {
|
||||
Socket socket = new Socket(host, port);
|
||||
in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
|
||||
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
||||
}
|
||||
|
||||
public void drawRangeView() {
|
||||
rangeView.repaint();
|
||||
}
|
||||
|
||||
private static void printHelpText() {
|
||||
System.out.println(
|
||||
"----------------------------------------------------------------------\n"
|
||||
+ "usage: java jar BalloonDisplay.jar <port-number>\n"
|
||||
+ "----------------------------------------------------------------------\n"
|
||||
);
|
||||
}
|
||||
|
||||
public enum ModelState { INACTIVE, READY, ACTIVE }
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
|
||||
String host = "localHost";
|
||||
int port = 0;
|
||||
boolean boom = false;
|
||||
|
||||
// ==========================================================
|
||||
// Handle program arguments.
|
||||
// ==========================================================
|
||||
int ii = 0;
|
||||
while (ii < args.length) {
|
||||
switch (args[ii]) {
|
||||
case "-help" :
|
||||
case "--help" : {
|
||||
printHelpText();
|
||||
System.exit(0);
|
||||
} break;
|
||||
default : {
|
||||
port = (Integer.parseInt(args[ii]));
|
||||
} break;
|
||||
}
|
||||
++ii;
|
||||
}
|
||||
|
||||
boolean go = true;
|
||||
double dt = 0.100; // Time between updates (seconds).
|
||||
double posx = 0.0;
|
||||
double posy = 0.0;
|
||||
double velx = 0.0;
|
||||
double vely = 0.0;
|
||||
int airtemp = 0;
|
||||
int windspeed = 0;
|
||||
|
||||
// Outbound command variables
|
||||
int temperature_change_command;
|
||||
int wind_change_command;
|
||||
|
||||
int simMode = 0;
|
||||
boolean standalone = false;
|
||||
|
||||
int mapScale = 32 ; // pixels per meter.
|
||||
|
||||
RangeView rangeView = new RangeView( mapScale);
|
||||
BalloonDisplay balloonDisplay = new BalloonDisplay( rangeView);
|
||||
balloonDisplay.setVisible(true);
|
||||
balloonDisplay.drawRangeView();
|
||||
|
||||
if (port == 0) {
|
||||
System.out.println("No variable server port specified.");
|
||||
printHelpText();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// Connect to the Trick simulation's variable server
|
||||
System.out.println("Connecting to: " + host + ":" + port);
|
||||
balloonDisplay.connectToServer(host, port);
|
||||
|
||||
balloonDisplay.out.writeBytes("trick.var_set_client_tag(\"BalloonDisplay\") \n");
|
||||
balloonDisplay.out.flush();
|
||||
|
||||
// Have the Variable Server send us the simulation mode ONCE.
|
||||
balloonDisplay.out.writeBytes( "trick.var_add(\"trick_sys.sched.mode\")\n" +
|
||||
"trick.var_send() \n" +
|
||||
"trick.var_clear() \n");
|
||||
balloonDisplay.out.flush();
|
||||
|
||||
// Read the response and extract the simulation mode.
|
||||
try {
|
||||
String line;
|
||||
String field[];
|
||||
line = balloonDisplay.in.readLine();
|
||||
field = line.split("\t");
|
||||
simMode = Integer.parseInt( field[1]);
|
||||
} catch (IOException | NullPointerException e ) {
|
||||
go = false;
|
||||
}
|
||||
|
||||
// Configure the Variable Server to cyclically send us the following varibales.
|
||||
// Tell the variable server:
|
||||
// 1) We want the values of the following variables:
|
||||
balloonDisplay.out.writeBytes( "trick.var_pause() \n" +
|
||||
"trick.var_add(\"dyn.balloon.pos[0]\")\n" +
|
||||
"trick.var_add(\"dyn.balloon.pos[1]\")\n" +
|
||||
"trick.var_add(\"dyn.balloon.vel[0]\")\n" +
|
||||
"trick.var_add(\"dyn.balloon.vel[1]\")\n" +
|
||||
"trick.var_add(\"dyn.balloon.envelope_air_temperature\")\n" +
|
||||
"trick.var_add(\"dyn.balloon.wind_speed\")\n" +
|
||||
"trick.var_add(\"trick_sys.sched.mode\")\n" +
|
||||
// 2) We want the responses in ASCII:
|
||||
"trick.var_ascii() \n" +
|
||||
// 3) We want values to be updated at the specified rate:
|
||||
String.format("trick.var_cycle(%.3f)\n", dt) +
|
||||
// 4) Start sending values as specified.
|
||||
"trick.var_unpause() \n" );
|
||||
balloonDisplay.out.flush();
|
||||
|
||||
while (go) {
|
||||
|
||||
// Recieve and parse periodic data response from the variable server.
|
||||
try {
|
||||
String line;
|
||||
String field[];
|
||||
line = balloonDisplay.in.readLine();
|
||||
field = line.split("\t");
|
||||
posx = Double.parseDouble( field[1]);
|
||||
posy = Double.parseDouble( field[2]);
|
||||
velx = Double.parseDouble( field[3]);
|
||||
vely = Double.parseDouble( field[4]);
|
||||
airtemp = Integer.parseInt( field[5]);
|
||||
windspeed = Integer.parseInt( field[6]);
|
||||
simMode = Integer.parseInt( field[7]);
|
||||
} catch (IOException | NullPointerException e ) {
|
||||
go = false;
|
||||
}
|
||||
|
||||
// Update the display data.
|
||||
rangeView.setballoonPos(posx, posy);
|
||||
rangeView.setBalloonVel(velx, vely);
|
||||
rangeView.setAirTemp(airtemp);
|
||||
rangeView.setWindSpeed(windspeed);
|
||||
|
||||
temperature_change_command = rangeView.getDeltaTemp();
|
||||
if (temperature_change_command != 0) {
|
||||
balloonDisplay.out.writeBytes(String.format("dyn.balloon.temperature_change_command = %d ;\n", temperature_change_command ));
|
||||
rangeView.resetDeltaTemp();
|
||||
}
|
||||
|
||||
wind_change_command = rangeView.getDeltaWind();
|
||||
if (wind_change_command != 0) {
|
||||
balloonDisplay.out.writeBytes( String.format("dyn.balloon.wind_change_command = %d ;\n", wind_change_command ));
|
||||
rangeView.resetDeltaWind();
|
||||
}
|
||||
|
||||
balloonDisplay.out.flush();
|
||||
|
||||
// Update the scene.
|
||||
balloonDisplay.drawRangeView();
|
||||
|
||||
} // while
|
||||
} // main
|
||||
} // class
|
1
trick_sims/SIM_webpanel/www/apps/alloc_info.html
Symbolic link
@ -0,0 +1 @@
|
||||
/home/cacistudent/trick/trick_source/web/apps/alloc_info.html
|
1
trick_sims/SIM_webpanel/www/apps/vs_connections.html
Symbolic link
@ -0,0 +1 @@
|
||||
/home/cacistudent/trick/trick_source/web/apps/vs_connections.html
|
1
trick_sims/SIM_webpanel/www/apps/wsexp.html
Symbolic link
@ -0,0 +1 @@
|
||||
/home/cacistudent/trick/trick_source/web/apps/wsexp.html
|
35
trick_sims/SIM_webpanel/www/example.css
Normal file
@ -0,0 +1,35 @@
|
||||
.parent{
|
||||
display:grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
/*background-color: black;
|
||||
padding: 10px; */
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
/* column-gap: 2px; */
|
||||
}
|
||||
.child{
|
||||
background-color: pink;
|
||||
border: 2px solid black;
|
||||
padding: 20px;
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
/* grid-row: 3;
|
||||
grid-column: 4/4; */
|
||||
|
||||
}
|
||||
.childheader{
|
||||
background-color: white;
|
||||
grid-row: 1;
|
||||
grid-column: 1/4;
|
||||
}
|
||||
|
||||
.childtable{
|
||||
background-color: purple;
|
||||
grid-row: 2;
|
||||
grid-column: 1/4;
|
||||
}
|
||||
.childbutton{
|
||||
background-color: blue;
|
||||
grid-row: 2;
|
||||
grid-column: 2/4;
|
||||
}
|
12
trick_sims/SIM_webpanel/www/example.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<link rel="stylesheet" type="text/CSS" href="example.css">
|
||||
<div class="parent">
|
||||
<div class="childheader">HEADER</div>
|
||||
<div class="childtable">TABLE</div>
|
||||
<div class="childbutton">BUTTONS</div>
|
||||
<div class="child">EXTRA SPACE</div>
|
||||
<div class="child">BOTTOM OF PANEL </div>
|
||||
<div class="child"> MORE SPACE</div>
|
||||
</div>
|
||||
</html>
|
68
trick_sims/SIM_webpanel/www/exampleCode/helloworld.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/CSS" href="mystyle.css">
|
||||
|
||||
<header>
|
||||
<h1> Working with HTML, JS, and CSS</h1>
|
||||
</header>
|
||||
<body>
|
||||
<script type="text/javascript" src="helloworld.js">
|
||||
function displayDate(){
|
||||
document.write(Date());
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--Changes content of own element using "this" keyword-->
|
||||
<button onclick="this.innerHTML = Date()"> What time is it? </button>
|
||||
<!-- SHOWS AN ALERT WINDOW-->
|
||||
<button onclick="alert('HI')">CLICK ON ME PLEASE</button>
|
||||
<table>
|
||||
<caption><b>Astrological Signs</b></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="background-color:white" class="empty"></th>
|
||||
<th class="fire">Aries</th>
|
||||
<th class="earth">Taurus</th>
|
||||
<th class="earth">Virgo</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="side">Element</th>
|
||||
<td>Fire</td>
|
||||
<td>Earth</td>
|
||||
<td>Earth</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="side">Symbol</th>
|
||||
<td>Ram</td>
|
||||
<td>Bull</td>
|
||||
<td>Maiden</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="side">Planet</th>
|
||||
<td>Mars</td>
|
||||
<td>Venus</td>
|
||||
<td>Mercury</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
zero.addEventListener('mouseenter', function onClick(){
|
||||
zero.style.backgroundColor = 'red';
|
||||
zero.style.color = "blue";
|
||||
});
|
||||
zero.addEventListener('mouseleave', function onClick(){
|
||||
zero.style.backgroundColor = 'black';
|
||||
zero.style.color = "white";
|
||||
});
|
||||
flower.addEventListener('mouseenter', function onClick(){
|
||||
flower.innerHTML="Click for a surprise"
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
60
trick_sims/SIM_webpanel/www/exampleCode/helloworld.js
Normal file
@ -0,0 +1,60 @@
|
||||
// Writing to the HTML tree
|
||||
document.write("I am learning JavaScript<br>");
|
||||
|
||||
// Declaring and defining variables then displaying on console
|
||||
let x,y;
|
||||
x=5; y=6;
|
||||
console.log(x + y);
|
||||
// Prompting for password until number is given and then displaying on screen
|
||||
let password = Number(prompt("Enter your password: "));
|
||||
|
||||
while (Number.isNaN(password)){
|
||||
password = Number(prompt("Enter your password: "));
|
||||
}
|
||||
document.write("The password entered: " + password);
|
||||
|
||||
// An array of integers
|
||||
const array = [1,2,3,4];
|
||||
console.log(array);
|
||||
|
||||
// Creating an object with 3 properties & 3 methods
|
||||
const person = {
|
||||
firstName:"Zero", lastName:"Nelson", age:20,
|
||||
fullName: function(){
|
||||
return this.firstName + " " + this.lastName;
|
||||
}
|
||||
};
|
||||
console.log(person.fullName());
|
||||
|
||||
//Gets the type of the variable --- variables are dynamic;
|
||||
console.log(typeof(x));
|
||||
x = "Harry Potter";
|
||||
console.log(typeof(x));
|
||||
|
||||
// Using JS functions
|
||||
function add(x,y){
|
||||
return x + y;
|
||||
}
|
||||
// X = "Harry Potter" + Y = 6 = Harry Potter6
|
||||
let z = add(x,y);
|
||||
document.write("<br>" + z);
|
||||
|
||||
function displayDate(){
|
||||
innerHTML = Date();
|
||||
}
|
||||
|
||||
let text="Jacayla Nelson";
|
||||
text = text.replace("Jacayla", "Zero");
|
||||
console.log(text);
|
||||
text = text.toLowerCase();
|
||||
console.log(text);
|
||||
|
||||
// To set precision
|
||||
x = 10.245356;
|
||||
x.toFixed(2);
|
||||
console.log(x.toFixed(2));
|
||||
console.log(x.toPrecision(4));
|
||||
|
||||
// Parsing strings for integer or float
|
||||
x = " 0 Nelson";
|
||||
console.log(parseInt(x));
|
24
trick_sims/SIM_webpanel/www/exampleCode/helloworld.json
Normal file
@ -0,0 +1,24 @@
|
||||
[{
|
||||
"firstName": "Zero",
|
||||
"lastName": "Nelson",
|
||||
"favs": ["ice cream", "flowers", "peace"],
|
||||
"car": {
|
||||
"make&model": "Mazda 6",
|
||||
"year": 2011,
|
||||
"color": "gray",
|
||||
"type": "sedan"
|
||||
}
|
||||
}
|
||||
,{
|
||||
"firstName": "Litzy",
|
||||
"lastName": "Membrano",
|
||||
"favs": ["food", "flowers", "Zero"],
|
||||
"car": {
|
||||
"make&model": "Toyota Yaris",
|
||||
"year": 2010,
|
||||
"color": "blue",
|
||||
"type": "sedan"
|
||||
|
||||
}
|
||||
}
|
||||
]
|
1
trick_sims/SIM_webpanel/www/images/trick_icon.png
Symbolic link
@ -0,0 +1 @@
|
||||
/home/cacistudent/trick/trick_source/web/images/trick_icon.png
|
32
trick_sims/SIM_webpanel/www/index.html
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<title>Trick Simulation</title>
|
||||
<div class="header">
|
||||
<table>
|
||||
<th class="header"><img src="images/trick_icon.png" height="64" width="64"></th>
|
||||
<th class="header"><h1>Trick Simulation</h1></th>
|
||||
</table>
|
||||
</div>
|
||||
</head>
|
||||
<body>
|
||||
<div style="background:#efefef">
|
||||
<ul>
|
||||
<li><a href="http://github.com/nasa/trick">Trick on GitHub</a></li>
|
||||
<li><a href="http://github.com/nasa/trick/wiki/Tutorial">Trick Tutorial</a></li>
|
||||
<li><a href="http://github.com/nasa/trick/wiki/Documentation-Home">Trick Documentation</a></li>
|
||||
<li><a href="wsexp_balloon.html">Variable Server Client</a></li>
|
||||
<li><a href="wsexp.html">Experiments</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div style="background:#efefef">
|
||||
<ul>
|
||||
<li><a href="/apps">Applications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
5
trick_sims/SIM_webpanel/www/style.css
Normal file
@ -0,0 +1,5 @@
|
||||
h1 {font-family: sans-serif, cursive, serif;font-size: 32px;margin-left: 1em;}
|
||||
h2 {font-family: sans-serif;font-size: 18px;margin-left: 1em;}
|
||||
a {font-family: sans-serif;font-size: 16px;}
|
||||
div.header { background-image: linear-gradient(#afafff, white);}
|
||||
.button{width: 20%}
|
55
trick_sims/SIM_webpanel/www/trick.css
Normal file
@ -0,0 +1,55 @@
|
||||
html{background-color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
|
||||
div {
|
||||
background-image: linear-gradient(#afafff, white);
|
||||
}
|
||||
th {border: 2px solid black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tr:nth-child(even){background-color: pink;
|
||||
}
|
||||
|
||||
th, td{width: 50%; text-align: center;}
|
||||
table{border-collapse: collapse;
|
||||
width: 50%;
|
||||
}
|
||||
h1{ text-align: center}
|
||||
h2{width: 50%; text-align: center}
|
||||
p{width: 50%;}
|
||||
|
||||
/* button{float:left;border:1px solid black; width: 10px;} */
|
||||
/*button{height: 50%; width: 50%;display:inline-block;}*/
|
||||
|
||||
|
||||
/* .parent{display: flex; flex-flow: row nowrap; justify-content: space-around; }
|
||||
|
||||
/* Splitting screen in half
|
||||
.side{
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
position: fixed;
|
||||
}
|
||||
.left {
|
||||
left: 0;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.right {
|
||||
right: 0;
|
||||
background-color: pink;
|
||||
}
|
||||
*/
|
||||
button{
|
||||
border: double black;
|
||||
width: 50%;
|
||||
font-size:larger;
|
||||
justify-content: center;
|
||||
background-color: lightskyblue;
|
||||
/* display:flex; flex-direction: row; padding: 10%; */
|
||||
}
|
||||
|
||||
|
122
trick_sims/SIM_webpanel/www/wsexp.css
Normal file
@ -0,0 +1,122 @@
|
||||
html{
|
||||
font-family: sans-serif;
|
||||
background-color: rgb(235, 232, 232);
|
||||
}
|
||||
*{
|
||||
/* outline: 2px solid orange; */
|
||||
}
|
||||
body{
|
||||
/* overflow-x: hidden; */
|
||||
}
|
||||
div.header{
|
||||
background-image: linear-gradient(#afafff, white)
|
||||
}
|
||||
|
||||
table.variables {
|
||||
border-collapse: collapse;
|
||||
width: 50%
|
||||
}
|
||||
th.table, td{
|
||||
border: 2px solid black;
|
||||
text-align: center;
|
||||
font-size: smaller;
|
||||
/* width: 50%; */
|
||||
}
|
||||
tr:nth-child(even){
|
||||
background-color: #afafff,;
|
||||
}
|
||||
h2,h1{
|
||||
text-align: center;
|
||||
width: 50%;
|
||||
}
|
||||
button{
|
||||
border: none;
|
||||
/* background-color: rgb(199, 199, 199); */
|
||||
font-size: larger;
|
||||
}
|
||||
table{
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#command{
|
||||
border: 1px solid black;
|
||||
background-color: rgb(103, 161, 243); /* 133,172, 228 */
|
||||
text-align: left;
|
||||
}
|
||||
.commands{
|
||||
/* background-color: rgb(56, 55, 100); */
|
||||
width: 10vw;
|
||||
|
||||
}
|
||||
#variableDisplay {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
hr{
|
||||
size: 1px;
|
||||
}
|
||||
#parent{
|
||||
display: grid;
|
||||
/* grid-template-columns: auto auto auto auto;
|
||||
grid-template-rows: auto auto auto auto; */
|
||||
grid-template-columns: 1fr 300px 1fr;
|
||||
grid-gap: 1rem;
|
||||
|
||||
|
||||
|
||||
}
|
||||
#navchild{
|
||||
/* background-color: orange; */
|
||||
grid-row: 2;
|
||||
grid-column: 1/span 4;
|
||||
border-bottom: 1px solid black;
|
||||
|
||||
}
|
||||
#modechild{
|
||||
/* background-color:rgb(14, 236, 25); */
|
||||
grid-row: 3;
|
||||
grid-column: 1;
|
||||
border: 1px solid black;
|
||||
|
||||
}
|
||||
#headerchild{
|
||||
/* background-color: rgb(207, 207, 207); */
|
||||
grid-row: 1;
|
||||
grid-column: 1/ span 4;
|
||||
font-size: smaller;
|
||||
|
||||
|
||||
}
|
||||
#tablechild{
|
||||
/* background-color: blue; */
|
||||
grid-row: 4;
|
||||
grid-column: 4;
|
||||
}
|
||||
#buttonchild{
|
||||
grid-row: 4;
|
||||
grid-column: 1;
|
||||
/* background-color: red; */
|
||||
border: 1px solid black;
|
||||
|
||||
|
||||
}
|
||||
#barchild{
|
||||
grid-row: 3;
|
||||
grid-column: 2/span 3;
|
||||
/* background-color: rgb(255, 1, 149) */
|
||||
}
|
||||
#bottomchild{
|
||||
grid-row: 5;
|
||||
grid-column: 1/span 2;
|
||||
/* background-color: rgb(251, 255, 13); */
|
||||
}
|
||||
#extrabottomchild{
|
||||
grid-row: 6;
|
||||
grid-column: 1/span 2;
|
||||
/*background-color: rgb(0, 225, 255); */
|
||||
}
|
||||
|
||||
#timechild{
|
||||
grid-row: 4;
|
||||
grid-column: 2;
|
||||
}
|
258
trick_sims/SIM_webpanel/www/wsexp.html
Normal file
@ -0,0 +1,258 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/CSS" href="wsexp.css">
|
||||
<title>WS Experiments</title>
|
||||
<!--START OF GRID LAYOUT -->
|
||||
<body>
|
||||
<div id="parent">
|
||||
<nav id="navchild" style="font-size: small">
|
||||
<button onclick="file()" style="float: right; border: 1px solid black;"><u>F</u>ile</button>
|
||||
<button onclick="actions()" style="float: right; border: 1px solid black;"><u>A</u>ctions</button>
|
||||
</nav>
|
||||
<header id="headerchild">
|
||||
<img src="images/trick_icon.png" height="60" width="60" style="float: left;">
|
||||
<h1>Sim Control</h1>
|
||||
<hr>
|
||||
</header>
|
||||
<div id="tablechild">
|
||||
|
||||
<table class="variables" style="width: 100%;">
|
||||
<div>
|
||||
<h2 style="width: 100%; text-align: center;">Simulation Variable Table</h2>
|
||||
<tr>
|
||||
<th class="table">Variable</th>
|
||||
<th class="table">Value</th>
|
||||
</tr>
|
||||
</div>
|
||||
</table>
|
||||
</div>
|
||||
<div id="modechild">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">MODE</th>
|
||||
<tr>
|
||||
<td>PERCENTAGE</td>
|
||||
</tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="buttonchild" >
|
||||
<table class="commands"style="width: 100%; height: 100%;" >
|
||||
|
||||
<th id="command" colspan="2" >Commands</th>
|
||||
|
||||
<tr>
|
||||
<td><button onclick="stepSIM(value)">Step</button> </td>
|
||||
<td><button onclick="">Data Rec On</button></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><button onclick="startSIM()">Start</button></td>
|
||||
<td><button onclick="stopSIM()">RealTime On</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button onclick="freezeSIM(value)" id="freeze">Freeze</button></td>
|
||||
<td><button onclick="">Dump Chkpnt</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button onclick="shutdownSIM()">Shutdown</button></td>
|
||||
<td><button onclick="">Load Chkpnt</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- Instead of resizing the window, I would like to
|
||||
create a second window that contains the buttons and what not -->
|
||||
<td><button onclick="liteSIM()">Lite</button></td>
|
||||
<td><button onclick="">E<u>x</u>it</button></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<div id="barchild">
|
||||
Here is a place for the buttons that start Trick TV, MTV, and Throttle.
|
||||
<hr>
|
||||
</div>
|
||||
<div id="bottomchild">
|
||||
<table style="width: 100vw;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">Simulations/Overruns</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>This is where the path goes</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="extrabottomchild">
|
||||
<table style="width: 100vw;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">Status Messages</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Space for the status messages</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="timechild">
|
||||
<table style="height: 85%">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)" >Time</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RET (sec)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="RET" script="displayTime()">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sim / Real Time</th>
|
||||
</tr>
|
||||
<td>1</td>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div id="output">
|
||||
<script type="text/javascript">
|
||||
|
||||
function log(s) {
|
||||
var p = document.createElement("p");
|
||||
p.style.wordWrap = "break-word";
|
||||
p.textContent = s;
|
||||
output.appendChild(p);
|
||||
}
|
||||
function sendMessage(msg) {
|
||||
ws.send(msg);
|
||||
log("Sent : " + msg);
|
||||
}
|
||||
|
||||
// Interface to Trick WebSocket Variable Server
|
||||
function setPeriod(period) {
|
||||
sendMessage(`{"cmd":"var_cycle","period":${period}}`);
|
||||
}
|
||||
function addVarTableRow(name, value) {
|
||||
// create a row in the table that contains two <td>s, one for the var_name and one for its value.
|
||||
let tr = document.createElement('tr');
|
||||
let td1 = document.createElement('td');
|
||||
td1.textContent = `${name}`;
|
||||
let td2 = document.createElement('td');
|
||||
td2.textContent = `${value}`;
|
||||
td2.className = "values";
|
||||
tr.appendChild(td1);
|
||||
tr.appendChild(td2);
|
||||
varTable.appendChild(tr);
|
||||
}
|
||||
function addVariable(name, value) {
|
||||
sendMessage(`{"cmd":"var_add","var_name": "${name}"}`);
|
||||
addVarTableRow(name, value);
|
||||
}
|
||||
function shutdownSIM(){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.stop()"}`);
|
||||
}
|
||||
function startSIM(){
|
||||
/* send message through wire from variable server client (website) to
|
||||
the variable server (which controls the mode via the Java file ???) */
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
}
|
||||
function freezeSIM(value){
|
||||
//log("The value is " + value);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_freeze()"}`);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_off()"}`);
|
||||
|
||||
|
||||
// Need to fetch an updated value from the server
|
||||
|
||||
// this function only works when value is false
|
||||
// because the debug_variable isn't updated????
|
||||
/* if (value == false){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_off()"}`);
|
||||
} */
|
||||
}
|
||||
function liteSIM(){
|
||||
window.resizeBy(10,50);
|
||||
window.resizeTo(100,50);
|
||||
}
|
||||
function stepSIM(value){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_on()"}`);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_signal()"}`);
|
||||
|
||||
/* log("The value is " + value);
|
||||
if (value == false){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_on()"}`);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
|
||||
} else {
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_signal()"}`);
|
||||
|
||||
}
|
||||
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`); */
|
||||
}
|
||||
function displayTime(value){
|
||||
document.getElementById("RET").textContent = value;
|
||||
}
|
||||
|
||||
var varTable = document.querySelector('table.variables');
|
||||
var ws = new WebSocket('ws://localhost:8888/api/ws/VariableServer');
|
||||
|
||||
// WebSocket Event Handlers
|
||||
ws.onopen = function(e) {
|
||||
log("Connection established");
|
||||
setPeriod(100);
|
||||
addVarTableRow("Time", 0.0);
|
||||
addVariable("trick_sys.sched.mode", 1);
|
||||
addVariable("trick_sys.name", 'trick_sys');
|
||||
addVariable("dyn.balloon.pos[0]", 0.0);
|
||||
addVariable("dyn.balloon.pos[1]", 0.0);
|
||||
addVariable("dyn.balloon.vel[0]", 0.0);
|
||||
addVariable("dyn.balloon.vel[1]", 0.0);
|
||||
addVariable("dyn.balloon.envelope_air_temperature", 92.0);
|
||||
addVariable("dyn.balloon.wind_speed", 0.0);
|
||||
addVariable("trick_instruments.debug_pause.debug_pause_flag", 0);
|
||||
|
||||
|
||||
// Requesting the sim mode but it returns an error
|
||||
|
||||
sendMessage('{\"cmd\":\"var_unpause\"}');
|
||||
};
|
||||
ws.onmessage = function(e) {
|
||||
log("Recieved : " + e.data);
|
||||
let msg = JSON.parse(e.data);
|
||||
if (msg.msg_type == "values") {
|
||||
let valueNodes = varTable.getElementsByClassName("values");
|
||||
valueNodes[0].textContent = msg.time;
|
||||
displayTime(msg.time);
|
||||
for (let i = 0; i < msg.values.length; i++ ) {
|
||||
valueNodes[i+1].textContent = msg.values[i];
|
||||
}
|
||||
valueNodes[9].textContent = msg.trick_instruments.debug_pause.debug_pause_flag;
|
||||
freezeSIM(msg.trick_instruments.debug_pause.debug_pause_flag);
|
||||
|
||||
/*
|
||||
log("The time is " + msg.time);
|
||||
displayTime(msg.time); // going to constantly reupdate the time as the value comes in
|
||||
// getting the value of the debug variable and assigning it to debug_flag
|
||||
valueNodes[8].textContent = msg.trick_instruments.debug_pause.debug_pause_flag;
|
||||
debug_flag = msg.trick_instruments.debug_pause.debug_pause_flag;
|
||||
log("The debug variable is " + msg.trick_instruments.debug_pause.debug_pause_flag);
|
||||
|
||||
stepSim(msg.trick_instruments.debug_pause.debug_pause_flag);
|
||||
// freezeSIM(debug_flag); */
|
||||
|
||||
}
|
||||
};
|
||||
ws.onerror = function(e) {
|
||||
console.log("WebSocket Error: " , e);
|
||||
handleErrors(e);
|
||||
};
|
||||
ws.onclose = function(e) {
|
||||
console.log("Connection closed", e);
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
231
trick_sims/SIM_webpanel/www/wsexp2.html
Normal file
@ -0,0 +1,231 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/CSS" href="wsexp.css">
|
||||
<title>WS Experiments</title>
|
||||
<!--START OF GRID LAYOUT -->
|
||||
<body>
|
||||
<div id="parent">
|
||||
<nav id="navchild" style="font-size: small">
|
||||
<button onclick="file()" style="float: right; border: 1px solid black;"><u>F</u>ile</button>
|
||||
<button onclick="actions()" style="float: right; border: 1px solid black;"><u>A</u>ctions</button>
|
||||
</nav>
|
||||
<header id="headerchild">
|
||||
<img src="images/trick_icon.png" height="60" width="60" style="float: left;">
|
||||
<h1>Sim Control</h1>
|
||||
<hr>
|
||||
</header>
|
||||
<div id="tablechild">
|
||||
|
||||
<table class="variables" style="width: 100%;">
|
||||
<div>
|
||||
<h2 style="width: 100%; text-align: center;">Simulation Variable Table</h2>
|
||||
<tr>
|
||||
<th class="table">Variable</th>
|
||||
<th class="table">Value</th>
|
||||
</tr>
|
||||
</div>
|
||||
</table>
|
||||
</div>
|
||||
<div id="modechild">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">MODE</th>
|
||||
<tr>
|
||||
<td>PERCENTAGE</td>
|
||||
</tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="buttonchild" >
|
||||
<table class="commands"style="width: 100%; height: 100%;" >
|
||||
|
||||
<th id="command" colspan="2" >Commands</th>
|
||||
|
||||
<tr>
|
||||
<td><button onclick="stepSIM(value)">Step</button> </td>
|
||||
<td><button onclick="">Data Rec On</button></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><button onclick="startSIM()">Start</button></td>
|
||||
<td><button onclick="stopSIM()">RealTime On</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button onclick="freezeSIM()">Freeze</button></td>
|
||||
<td><button onclick="">Dump Chkpnt</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button onclick="shutdownSIM()">Shutdown</button></td>
|
||||
<td><button onclick="">Load Chkpnt</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- Instead of resizing the window, I would like to
|
||||
create a second window that contains the buttons and what not -->
|
||||
<td><button onclick="liteSIM()">Lite</button></td>
|
||||
<td><button onclick="">E<u>x</u>it</button></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<div id="barchild">
|
||||
Here is a place for the buttons that start Trick TV, MTV, and Throttle.
|
||||
<hr>
|
||||
</div>
|
||||
<div id="bottomchild">
|
||||
<table style="width: 100vw;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">Simulations/Overruns</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>This is where the path goes</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="extrabottomchild">
|
||||
<table style="width: 100vw;">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)">Status Messages</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Space for the status messages</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="timechild">
|
||||
<table style="height: 85%">
|
||||
<tr>
|
||||
<th style="background-color: rgb(103, 161, 243)" >Time</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RET (sec)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="RET" script="displayTime()">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sim / Real Time</th>
|
||||
</tr>
|
||||
<td>1</td>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div id="output">
|
||||
<script type="text/javascript">
|
||||
|
||||
function log(s) {
|
||||
var p = document.createElement("p");
|
||||
p.style.wordWrap = "break-word";
|
||||
p.textContent = s;
|
||||
output.appendChild(p);
|
||||
}
|
||||
function sendMessage(msg) {
|
||||
ws.send(msg);
|
||||
log("Sent : " + msg);
|
||||
}
|
||||
// Interface to Trick WebSocket Variable Server
|
||||
function setPeriod(period) {
|
||||
sendMessage(`{"cmd":"var_cycle","period":${period}}`);
|
||||
}
|
||||
function addVarTableRow(name, value) {
|
||||
// create a row in the table that contains two <td>s, one for the var_name and one for its value.
|
||||
let tr = document.createElement('tr');
|
||||
let td1 = document.createElement('td');
|
||||
td1.textContent = `${name}`;
|
||||
let td2 = document.createElement('td');
|
||||
td2.textContent = `${value}`;
|
||||
td2.className = "values";
|
||||
tr.appendChild(td1);
|
||||
tr.appendChild(td2);
|
||||
varTable.appendChild(tr);
|
||||
}
|
||||
function addVariable(name, value) {
|
||||
sendMessage(`{"cmd":"var_add","var_name": "${name}"}`);
|
||||
addVarTableRow(name, value);
|
||||
}
|
||||
function shutdownSIM(){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.stop()"}`);
|
||||
}
|
||||
function startSIM(){
|
||||
/* send message through wire from variable server client (website) to
|
||||
the variable server (which controls the mode via the Java file ???) */
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
}
|
||||
function freezeSIM(){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_freeze()"}`);
|
||||
}
|
||||
function liteSIM(){
|
||||
window.resizeBy(10,50);
|
||||
window.resizeTo(100,50);
|
||||
}
|
||||
function stepSIM(value){
|
||||
// Now the button is not functioning at all
|
||||
log("The value is " + trick_instruments.debug_pause.debug_pause_flag);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_on()"}`);
|
||||
|
||||
let debug_flag = 0;
|
||||
if (debug_flag == 0){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_pause_on()"}`);
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
} else {
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.debug_signal()"}`);
|
||||
|
||||
}
|
||||
|
||||
//sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
}
|
||||
function displayTime(value){
|
||||
document.getElementById("RET").textContent = `${value}`;
|
||||
}
|
||||
var varTable = document.querySelector('table.variables');
|
||||
var ws = new WebSocket('ws://localhost:8888/api/ws/VariableServer');
|
||||
|
||||
// WebSocket Event Handlers
|
||||
ws.onopen = function(e) {
|
||||
log("Connection established");
|
||||
setPeriod(100);
|
||||
addVarTableRow("Time", 0.0);
|
||||
addVariable("trick_sys.sched.mode", 1);
|
||||
addVariable("trick_sys.name", 'trick_sys');
|
||||
addVariable("dyn.balloon.pos[0]", 0.0);
|
||||
addVariable("dyn.balloon.pos[1]", 0.0);
|
||||
addVariable("dyn.balloon.vel[0]", 0.0);
|
||||
addVariable("dyn.balloon.vel[1]", 0.0);
|
||||
addVariable("dyn.balloon.envelope_air_temperature", 92.0);
|
||||
addVariable("dyn.balloon.wind_speed", 0.0);
|
||||
addVariable("trick_instruments.debug_pause.debug_pause_flag", false);
|
||||
sendMessage('{\"cmd\":\"var_unpause\"}');
|
||||
|
||||
};
|
||||
ws.onmessage = function(e) {
|
||||
log("Recieved : " + e.data);
|
||||
let msg = JSON.parse(e.data);
|
||||
if (msg.msg_type == "values") {
|
||||
let valueNodes = varTable.getElementsByClassName("values");
|
||||
valueNodes[0].textContent = msg.time;
|
||||
displayTime(msg.time);
|
||||
valueNodes[9].textContent = msg.trick_instruments.debug_pause.debug_pause_flag;
|
||||
//stepSim(msg.trick_instruments.debug_pause.debug_pause_flag);
|
||||
for (let i = 0; i < msg.values.length; i++ ) {
|
||||
valueNodes[i+1].textContent = msg.values[i];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
ws.onerror = function(e) {
|
||||
console.log("WebSocket Error: " , e);
|
||||
handleErrors(e);
|
||||
};
|
||||
ws.onclose = function(e) {
|
||||
console.log("Connection closed", e);
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
162
trick_sims/SIM_webpanel/www/wsexp_balloon.html
Normal file
@ -0,0 +1,162 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WS Experiments</title>
|
||||
<div class="parent"></div>
|
||||
<div>
|
||||
<h1>TRICK SIMULATION VARIABLE SERVER CLIENT</h1>
|
||||
</div>
|
||||
</head>
|
||||
<hr>
|
||||
<body>
|
||||
<link rel="stylesheet" type="text/CSS" href="trick.css">
|
||||
|
||||
|
||||
<!--<link rel="stylesheet" type="text/CSS" href="example.css"> -->
|
||||
|
||||
<!--HOW TO MAKE BUTTONS SIDE BY SIDE -->
|
||||
<div class="parent">
|
||||
|
||||
|
||||
<div class="variableDisplay"></div>
|
||||
<table class="variables">
|
||||
<th><h2>Simulation Variable Table</h2></th>
|
||||
<tr>
|
||||
<th>Variable</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<button onclick="startSIM()">Start</button>
|
||||
<button onclick="stopSIM()">Stop</button>
|
||||
<button onclick="shutdownSIM()">Shut down</button>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="variableDisplay"></div>
|
||||
|
||||
<table class="variables">
|
||||
<h2>Simulation Variable Table</h2>
|
||||
<tr>
|
||||
|
||||
<th>Variable</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--<div class="child"><button onclick="startSIM()"><button onclick="stopSIM()"></button>Start</button> </div>-->
|
||||
<!--<div class="child"><button onclick="stopSIM()">Stop</button></div> -->
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<button onclick="startSIM()">Start</button>
|
||||
<button onclick="stopSIM()">Stop</button>
|
||||
<div class="variableDisplay"></div>
|
||||
<h1>Simulation Variable Table</h1>
|
||||
<table class="variables">
|
||||
<tr>
|
||||
<th>Variable</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</table>
|
||||
-->
|
||||
</div>
|
||||
<div id="output"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
function log(s) {
|
||||
var p = document.createElement("p");
|
||||
p.style.wordWrap = "break-word";
|
||||
p.textContent = s;
|
||||
output.appendChild(p);
|
||||
}
|
||||
function sendMessage(msg) {
|
||||
ws.send(msg);
|
||||
log("Sent : " + msg);
|
||||
}
|
||||
|
||||
// Interface to Trick WebSocket Variable Server
|
||||
function setPeriod(period) {
|
||||
sendMessage(`{"cmd":"var_cycle","period":${period}}`);
|
||||
}
|
||||
function addVarTableRow(name, value) {
|
||||
// create a row in the table that contains two <td>s, one for the var_name and one for its value.
|
||||
let tr = document.createElement('tr');
|
||||
let td1 = document.createElement('td');
|
||||
td1.textContent = `${name}`;
|
||||
let td2 = document.createElement('td');
|
||||
td2.textContent = `${value}`;
|
||||
td2.className = "values";
|
||||
tr.appendChild(td1);
|
||||
tr.appendChild(td2);
|
||||
varTable.appendChild(tr);
|
||||
}
|
||||
function addVariable(name, value) {
|
||||
sendMessage(`{"cmd":"var_add","var_name": "${name}"}`);
|
||||
addVarTableRow(name, value);
|
||||
}
|
||||
function shutdownSIM(){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_stop()\n"}`);
|
||||
}
|
||||
function startSIM(name, value){
|
||||
/* send message through wire from variable server client (website) to
|
||||
the variable server (which controls the mode via the Java file ???) */
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_run()"}`);
|
||||
}
|
||||
function stopSIM(name,value){
|
||||
sendMessage(`{"cmd": "python", "pycode": "trick.exec_freeze()"}`);
|
||||
}
|
||||
var varTable = document.querySelector('table.variables');
|
||||
var ws = new WebSocket('ws://localhost:8888/api/ws/VariableServer');
|
||||
|
||||
// WebSocket Event Handlers
|
||||
ws.onopen = function(e) {
|
||||
log("Connection established");
|
||||
setPeriod(100);
|
||||
addVarTableRow("Time", 0.0);
|
||||
addVariable("trick_sys.sched.mode", 1);
|
||||
addVariable("trick_sys.name", 'trick_sys');
|
||||
addVariable("dyn.balloon.pos[0]", 0.0);
|
||||
addVariable("dyn.balloon.pos[1]", 0.0);
|
||||
addVariable("dyn.balloon.vel[0]", 0.0);
|
||||
addVariable("dyn.balloon.vel[1]", 0.0);
|
||||
addVariable("dyn.balloon.envelope_air_temperature", 92.0);
|
||||
addVariable("dyn.balloon.wind_speed", 0.0);
|
||||
|
||||
// Requesting the sim mode but it returns an error
|
||||
|
||||
sendMessage("{\"cmd\":\"var_unpause\"}");
|
||||
};
|
||||
ws.onmessage = function(e) {
|
||||
log("Recieved : " + e.data);
|
||||
let msg = JSON.parse(e.data);
|
||||
if (msg.msg_type == "values") {
|
||||
let valueNodes = varTable.getElementsByClassName("values");
|
||||
valueNodes[0].textContent = msg.time;
|
||||
for (let i = 0; i < msg.values.length; i++ ) {
|
||||
valueNodes[i+1].textContent = msg.values[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
ws.onerror = function(e) {
|
||||
console.log("WebSocket Error: " , e);
|
||||
handleErrors(e);
|
||||
};
|
||||
ws.onclose = function(e) {
|
||||
console.log("Connection closed", e);
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|