From aa36c312315ce3198ba967cb02728ded751261c0 Mon Sep 17 00:00:00 2001 From: Scott Fennell Date: Wed, 31 Jan 2018 13:37:14 -0600 Subject: [PATCH] added new mass-spring-damper sim and graphics client (#555) * added new mass-spring-damper sim and graphics client * changed math model image for README.md * updated math model image for README.md --- trick_sims/SIM_msd/Modified_data/realtime.py | 7 + trick_sims/SIM_msd/README.md | 84 +++++++ trick_sims/SIM_msd/RUN_critdamp/input.py | 23 ++ trick_sims/SIM_msd/RUN_nodamp/input.py | 23 ++ trick_sims/SIM_msd/RUN_overdamp/input.py | 23 ++ trick_sims/SIM_msd/RUN_test/input.py | 21 ++ trick_sims/SIM_msd/RUN_underdamp/input.py | 23 ++ trick_sims/SIM_msd/S_define | 33 +++ trick_sims/SIM_msd/S_overrides.mk | 2 + trick_sims/SIM_msd/images/MSD0.png | Bin 0 -> 14682 bytes trick_sims/SIM_msd/images/MSD1.png | Bin 0 -> 27755 bytes trick_sims/SIM_msd/images/MSD2.png | Bin 0 -> 10223 bytes trick_sims/SIM_msd/images/MSD3.png | Bin 0 -> 18795 bytes .../graphics/MSD/src/MsdController.java | 200 ++++++++++++++++ .../models/graphics/MSD/src/MsdDisplay.java | 50 ++++ .../models/graphics/MSD/src/MsdGui.java | 218 ++++++++++++++++++ .../models/graphics/MSD/src/MsdUtils.java | 24 ++ .../models/graphics/MSD/src/MsdView.java | 183 +++++++++++++++ trick_sims/SIM_msd/models/graphics/Makefile | 36 +++ trick_sims/SIM_msd/models/msd/include/msd.hh | 48 ++++ .../SIM_msd/models/msd/include/msd_numeric.hh | 17 ++ trick_sims/SIM_msd/models/msd/src/msd.cpp | 19 ++ .../SIM_msd/models/msd/src/msd_deriv.cpp | 15 ++ .../SIM_msd/models/msd/src/msd_init.cpp | 28 +++ .../SIM_msd/models/msd/src/msd_integ.cpp | 31 +++ .../SIM_msd/models/msd/src/msd_shutdown.cpp | 17 ++ 26 files changed, 1125 insertions(+) create mode 100644 trick_sims/SIM_msd/Modified_data/realtime.py create mode 100644 trick_sims/SIM_msd/README.md create mode 100644 trick_sims/SIM_msd/RUN_critdamp/input.py create mode 100644 trick_sims/SIM_msd/RUN_nodamp/input.py create mode 100644 trick_sims/SIM_msd/RUN_overdamp/input.py create mode 100644 trick_sims/SIM_msd/RUN_test/input.py create mode 100644 trick_sims/SIM_msd/RUN_underdamp/input.py create mode 100644 trick_sims/SIM_msd/S_define create mode 100644 trick_sims/SIM_msd/S_overrides.mk create mode 100644 trick_sims/SIM_msd/images/MSD0.png create mode 100644 trick_sims/SIM_msd/images/MSD1.png create mode 100644 trick_sims/SIM_msd/images/MSD2.png create mode 100644 trick_sims/SIM_msd/images/MSD3.png create mode 100644 trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java create mode 100644 trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java create mode 100644 trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java create mode 100644 trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java create mode 100644 trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java create mode 100644 trick_sims/SIM_msd/models/graphics/Makefile create mode 100644 trick_sims/SIM_msd/models/msd/include/msd.hh create mode 100644 trick_sims/SIM_msd/models/msd/include/msd_numeric.hh create mode 100644 trick_sims/SIM_msd/models/msd/src/msd.cpp create mode 100644 trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp create mode 100644 trick_sims/SIM_msd/models/msd/src/msd_init.cpp create mode 100644 trick_sims/SIM_msd/models/msd/src/msd_integ.cpp create mode 100644 trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp diff --git a/trick_sims/SIM_msd/Modified_data/realtime.py b/trick_sims/SIM_msd/Modified_data/realtime.py new file mode 100644 index 00000000..76de2adf --- /dev/null +++ b/trick_sims/SIM_msd/Modified_data/realtime.py @@ -0,0 +1,7 @@ +trick.frame_log_on() +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) +trick.sim_control_panel_set_enabled(True) \ No newline at end of file diff --git a/trick_sims/SIM_msd/README.md b/trick_sims/SIM_msd/README.md new file mode 100644 index 00000000..b546ab88 --- /dev/null +++ b/trick_sims/SIM_msd/README.md @@ -0,0 +1,84 @@ +# SIM_MSD + +SIM\_MSD is a simulator for a mass-spring-damper system. + +![Picture of MSD](./images/MSD0.png) + + The system is described by the equation _mẍ_ + _bẋ_ + _kx_ = _F_, where: + + _m_ is the mass of an object. + + _x_ is the position of the mass. + + _b_ is the damping coefficient. + + _k_ is the spring coefficient. + + _F_ is an external force applied to the mass. + +--- +### Building the Simulation + +In the SIM_MSD directory, execute **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 display client for the simulation. + +### Running the Simulation +In the SIM_MSD directory: + +``` +% ./S_main_*.exe RUN_test/input.py +``` + +The following windows should appear: + +![Picture of MSD](./images/MSD2.png) + +![Picture of Control](./images/MSD3.png) + +### Controlling the Simulation +Click **Start** to begin the simulation. + +Click **Reset** to freeze the simulation and reset the position and velocity to +their initial conditions. + +Change **Position** and **Velocity** to adjust the initial conditions for those +attributes. + +Change **Mass**, **Spring Coefficient**, **Damping Coefficient**, and **Applied +Force** to adjust initial conditions _**and**_ also update the sim in real-time. + + + + + + +--- +The following inputs can be set in any of the RUN_*/input.py files to change +the inputs on startup +### Inputs + +Variable | Type | Units | Default Value +---------- |-----------|-------|-------------- +dyn.msd.x_0 | double | m | 5.0 +dyn.msd.v_0 | double | m/s | 0.0 +dyn.msd.b | double | N.s/m | 0.5 +dyn.msd.k | double | N/m | 2.0 +dyn.msd.F | double | N | 5.0 +dyn.msd.m | double | kg | 1.0 + +--- +Some sample input.py files have been created to demonstrate different +mass-spring-damper conditions +### Samples + +Path |Type +------------------------|---------------------------------------------- +RUN_underdamp/input.py |Underdamped Harmonic Oscillator +RUN_critdamp/input.py |Critically Damped Harmonic Oscillator +RUN_overdamp/input.py |Overdamped Harmonic Oscillator +RUN_nodamp/input.py | Simple Harmonic Oscillator (No Damping Force) diff --git a/trick_sims/SIM_msd/RUN_critdamp/input.py b/trick_sims/SIM_msd/RUN_critdamp/input.py new file mode 100644 index 00000000..dbad25fe --- /dev/null +++ b/trick_sims/SIM_msd/RUN_critdamp/input.py @@ -0,0 +1,23 @@ +dyn_integloop.getIntegrator(trick.Runge_Kutta_4, 4) +execfile("Modified_data/realtime.py") + +dyn.msd.b = 2*(2**(0.5)) + +#========================================== +# Start the display VarServer Client +#========================================== +varServerPort = trick.var_server_get_port(); +MsdGui_path = "models/graphics/dist/MsdGui.jar" + +if (os.path.isfile(MsdGui_path)) : + MsdGui_cmd = "java -jar " \ + + MsdGui_path \ + + " " + str(varServerPort) + " &" ; + print(MsdGui_cmd) + os.system( MsdGui_cmd); +else : + print('==================================================================================') + print('MsdGui needs to be built. Please \"cd\" into models/Graphics and type \"make\".') + print('==================================================================================') + +trick.stop(300.0) diff --git a/trick_sims/SIM_msd/RUN_nodamp/input.py b/trick_sims/SIM_msd/RUN_nodamp/input.py new file mode 100644 index 00000000..bbb30c2d --- /dev/null +++ b/trick_sims/SIM_msd/RUN_nodamp/input.py @@ -0,0 +1,23 @@ +dyn_integloop.getIntegrator(trick.Runge_Kutta_4, 4) +execfile("Modified_data/realtime.py") + +dyn.msd.b = 0 + +#========================================== +# Start the display VarServer Client +#========================================== +varServerPort = trick.var_server_get_port(); +MsdGui_path = "models/graphics/dist/MsdGui.jar" + +if (os.path.isfile(MsdGui_path)) : + MsdGui_cmd = "java -jar " \ + + MsdGui_path \ + + " " + str(varServerPort) + " &" ; + print(MsdGui_cmd) + os.system( MsdGui_cmd); +else : + print('==================================================================================') + print('MsdGui needs to be built. Please \"cd\" into models/Graphics and type \"make\".') + print('==================================================================================') + +trick.stop(300.0) diff --git a/trick_sims/SIM_msd/RUN_overdamp/input.py b/trick_sims/SIM_msd/RUN_overdamp/input.py new file mode 100644 index 00000000..9d62bbe3 --- /dev/null +++ b/trick_sims/SIM_msd/RUN_overdamp/input.py @@ -0,0 +1,23 @@ +dyn_integloop.getIntegrator(trick.Runge_Kutta_4, 4) +execfile("Modified_data/realtime.py") + +dyn.msd.b = 4*(2**(0.5)) - 1/2 + +#========================================== +# Start the display VarServer Client +#========================================== +varServerPort = trick.var_server_get_port(); +MsdGui_path = "models/graphics/dist/MsdGui.jar" + +if (os.path.isfile(MsdGui_path)) : + MsdGui_cmd = "java -jar " \ + + MsdGui_path \ + + " " + str(varServerPort) + " &" ; + print(MsdGui_cmd) + os.system( MsdGui_cmd); +else : + print('==================================================================================') + print('MsdGui needs to be built. Please \"cd\" into models/Graphics and type \"make\".') + print('==================================================================================') + +trick.stop(300.0) diff --git a/trick_sims/SIM_msd/RUN_test/input.py b/trick_sims/SIM_msd/RUN_test/input.py new file mode 100644 index 00000000..fb5c80ab --- /dev/null +++ b/trick_sims/SIM_msd/RUN_test/input.py @@ -0,0 +1,21 @@ +dyn_integloop.getIntegrator(trick.Runge_Kutta_4, 4) +execfile("Modified_data/realtime.py") + +#========================================== +# Start the display VarServer Client +#========================================== +varServerPort = trick.var_server_get_port(); +MsdGui_path = "models/graphics/dist/MsdGui.jar" + +if (os.path.isfile(MsdGui_path)) : + MsdGui_cmd = "java -jar " \ + + MsdGui_path \ + + " " + str(varServerPort) + " &" ; + print(MsdGui_cmd) + os.system( MsdGui_cmd); +else : + print('==================================================================================') + print('MsdGui needs to be built. Please \"cd\" into models/Graphics and type \"make\".') + print('==================================================================================') + +trick.stop(300.0) diff --git a/trick_sims/SIM_msd/RUN_underdamp/input.py b/trick_sims/SIM_msd/RUN_underdamp/input.py new file mode 100644 index 00000000..1ced0935 --- /dev/null +++ b/trick_sims/SIM_msd/RUN_underdamp/input.py @@ -0,0 +1,23 @@ +dyn_integloop.getIntegrator(trick.Runge_Kutta_4, 4) +execfile("Modified_data/realtime.py") + +dyn.msd.b = 0.5 + +#========================================== +# Start the display VarServer Client +#========================================== +varServerPort = trick.var_server_get_port(); +MsdGui_path = "models/graphics/dist/MsdGui.jar" + +if (os.path.isfile(MsdGui_path)) : + MsdGui_cmd = "java -jar " \ + + MsdGui_path \ + + " " + str(varServerPort) + " &" ; + print(MsdGui_cmd) + os.system( MsdGui_cmd); +else : + print('==================================================================================') + print('MsdGui needs to be built. Please \"cd\" into models/Graphics and type \"make\".') + print('==================================================================================') + +trick.stop(300.0) diff --git a/trick_sims/SIM_msd/S_define b/trick_sims/SIM_msd/S_define new file mode 100644 index 00000000..3b74619c --- /dev/null +++ b/trick_sims/SIM_msd/S_define @@ -0,0 +1,33 @@ +/************************TRICK HEADER************************* +PURPOSE: + (This S_define works with the RUN_numeric input file) +LIBRARY DEPENDENCIES: + ( + (msd/src/msd_init.cpp) + (msd/src/msd_numeric.cpp) + (msd/src/msd_shutdown.cpp) + (msd/src/msd.cpp) + (msd/src/msd_deriv.cpp) + (msd/src/msd_integ.cpp) + ) +*************************************************************/ + +#include "sim_objects/default_trick_sys.sm" +##include "msd/include/msd_numeric.hh" + + +class MSDSimObject : public Trick::SimObject { + + public: + MSD msd; + + MSDSimObject() { + ("default_data") msd_default_data( msd ) ; + ("initialization") msd_init( msd ) ; + ("derivative") msd.state_deriv(); + ("integration") trick_ret= msd.state_integ(); + } +} ; + +MSDSimObject dyn ; +IntegLoop dyn_integloop (0.01) dyn ; \ No newline at end of file diff --git a/trick_sims/SIM_msd/S_overrides.mk b/trick_sims/SIM_msd/S_overrides.mk new file mode 100644 index 00000000..1b84a37b --- /dev/null +++ b/trick_sims/SIM_msd/S_overrides.mk @@ -0,0 +1,2 @@ +TRICK_CFLAGS += -Imodels +TRICK_CXXFLAGS += -Imodels \ No newline at end of file diff --git a/trick_sims/SIM_msd/images/MSD0.png b/trick_sims/SIM_msd/images/MSD0.png new file mode 100644 index 0000000000000000000000000000000000000000..11f07ac60e09d0cf38636f7fde007a43235ca5a3 GIT binary patch literal 14682 zcmeHucR-U@+jjtQA)=xnAcShsT0m3~P)2A~umz;n!6pjG5HO-Ffe^H<$_#Zd1VqKn zDl-@$aj;|~GDCjm# zu0$XZ@;@Cq@GAl#qlrLBJ1k!c{^xec<#PyxCgP_9KO76oU{Z1CsKJ?BL2*}&x|e3n zAC4!!+kW%3?8@!*hO-BMU4N+oA9O2D?L@EA0gLjxvJbc1-^w5T{?*d8?|7Cg-qT;X zl$O+p)m}C9jCST^69`6trW{MED4VimIRa696|vn%dI=(We95676an#` z+bmYzMo1wvO{9KpgI4seNV>e$0)ePM9KGH^N*ZAiBK_d*iZuvCk)o!oZ8QRrl=;sQ z|M21;z4*sQ{=o|vJAa;@YSgRKZ#7lKn{gam0&6y~?B8{lMvFqq>pDSsGv^rYTK-+u?m94~*&8wzv;eUM!p- z@oL{}%knqW<_fuF)BvZ9P_x!*)7m=qP!|K$1cwrzBb7sD6ET#t6}oO=AO0YUR_=FR z10!{C7`sN9F`845_}l7z-wm)6L#rLVGdB>ZAJ zRLM}ExW;0!%4fTr$Ao_J2gQ)DKXMhtKb3LuQ(9pdo9r&~C_=AVd;|u=&HZRSXx@TpFF7<9ubk9o$aAx(UtG& z%zfCtl}IGgSrrrc0-={zXJ*jbpV(=wk&jr;OWyqmxz|@+xh~Jo>sVa5dUcGnsqY1a zCgg;@zqITOnUL0-9NMt`akUw@|0p+4+A9P8P~HfOm1vp0R$W~^7`-y!edTmZoL@mz z8HaZ}Eda}7643l^oWPz+Se1GN_SAtEUZ(ztE#HpqFZj>iJW?4 z{NZ=SGvt&s$LR`@kjDTE^LU2R`eJT)LZ5E$=ujlkq9T~w-TD-gU=S@lZMra=9ZdWA z?x0vYUNhd&Hjz>b@86%ybt?USVPU~ke|Mvx4#&5u9CMv`CNTH%qL54dx@-3iWgO)) zmpH+(%&X*83JMsG^vs`s{^?NYesJ({c59}I5xDVamBX3oOA3*i`Q`N3z6lSnG7kzc zSGqTf=SU^2_t_4|M$Sbc%)Y|$@nVez7`bekcpsjmBXmj@T`f9p18KOFNYcB&hDu8WInFurVjH+b4DEb!LXM@wI;7Rj-<$o zrgQIqE2X_|@(a7jia;cP)S*6&g>Y?M3O=alansU{4Mj`qjQ|uPXFI~D+SSP<~Ra4LG zkt-3b=i3gO&wuQjKzkWtBj_>P++SXn4W_x>Jq;^oypgeSxh<{t48L{7Db89=ulcPO z;!yfk7-cFmuhuFyE85&-#hT(sMNM(=eX5d8yBunbR0fLSEcozy(`xBz9omxR;z)cW z#>dA;$0AwB@z?oMNbk!0dv6vfe1np5PsT|9E{@}E41_}wI?iP}U3t#RM*ZjZ>o}Fv z>mv{Rj@Z>`EcK%}gx{*FqVklllf*{dZ1Xd}wno!SW!oZco`8kfWHJiimfGvruY=L6 zWhH5sHn5IP9ZW}jBhC`qbR<7+QM}}uBWcB&&p~nXI*CjF@7q{EK0Wzb!3vE=TZg`u zH>w68Ma3O+Iv~Nn`f+_@KtKUxm$21*yD;0>Ξ=d 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 SDIo&!)4{_B@_#&e`M&_)nZ!N- literal 0 HcmV?d00001 diff --git a/trick_sims/SIM_msd/images/MSD1.png b/trick_sims/SIM_msd/images/MSD1.png new file mode 100644 index 0000000000000000000000000000000000000000..9472a7fe5c5bc234c9d530b9452562921974b3e8 GIT binary patch literal 27755 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 literal 0 HcmV?d00001 diff --git a/trick_sims/SIM_msd/images/MSD3.png b/trick_sims/SIM_msd/images/MSD3.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb1a9d3b73180ab934e3b9abca60125cda1ee3b GIT binary patch literal 18795 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 M52R2T_a8t1FG}8%od5s; literal 0 HcmV?d00001 diff --git a/trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java new file mode 100644 index 00000000..ebeebe4f --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java @@ -0,0 +1,200 @@ +/* + * Trick + * 2018 (c) National Aeronautics and Space Administration (NASA) + * Programmers: Scott P. Fennell + */ + + + +import javax.swing.*; +import javax.swing.JTextField; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MsdController extends JFrame { + JTextField positionTextField; + JTextField velocityTextField; + JTextField springTextField; + JTextField dampingTextField; + JTextField forceTextField; + JTextField massTextField; + + ButtonPanel buttonPanel; + JPanel positionPanel; + JPanel labelPanel; + + public void armResetCommand() { + buttonPanel.armResetCommand(); + } + + public void armStartCommand() { + buttonPanel.armStartCommand(); + } + + public boolean getResetCommand() { + return buttonPanel.getResetCommand(); + } + + public boolean getStartCommand() { + return buttonPanel.getStartCommand(); + } + + public MsdController(MsdDisplay display){ + setTitle("Mass-Spring-Damper Control"); + setLayout(new GridLayout(1, 2)); + + buttonPanel = new ButtonPanel(display); + positionPanel = new JPanel(); + labelPanel = new JPanel(); + labelPanel.setAlignmentX(Component.RIGHT_ALIGNMENT); + + positionPanel.setLayout(new GridLayout(13, 1)); + labelPanel.setLayout(new GridLayout(13, 1)); + JPanel framePanel = new JPanel(); + GridLayout layout = new GridLayout(1, 3); + framePanel.setLayout(layout); + + positionTextField = new JTextField(2); + velocityTextField = new JTextField(2); + massTextField = new JTextField(2); + forceTextField = new JTextField(2); + springTextField = new JTextField(2); + dampingTextField = new JTextField(2); + + + + + + + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Position: ")); + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Velocity: ")); + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Mass: ")); + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Spring Coefficient: ")); + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Damping Coefficient: ")); + labelPanel.add(new JLabel()); + labelPanel.add(new JLabel("Applied Force: ")); + labelPanel.add(new JLabel()); + + positionPanel.add(new JLabel()); + positionPanel.add(positionTextField); + positionPanel.add(new JLabel()); + positionPanel.add(velocityTextField); + positionPanel.add(new JLabel()); + positionPanel.add(massTextField); + positionPanel.add(new JLabel()); + positionPanel.add(springTextField); + positionPanel.add(new JLabel()); + positionPanel.add(dampingTextField); + positionPanel.add(new JLabel()); + positionPanel.add(forceTextField); + positionPanel.add(new JLabel()); + + + for(Component L : labelPanel.getComponents()){ + if(L instanceof JLabel){ + ((JLabel)L).setHorizontalAlignment(JLabel.RIGHT); + } + } + framePanel.add(buttonPanel); + framePanel.add(labelPanel); + framePanel.add(positionPanel); + + add(framePanel); + positionPanel.setSize(positionPanel.getLayout().preferredLayoutSize(positionPanel)); + buttonPanel.setSize(buttonPanel.getPreferredSize()); + setSize(getPreferredSize()); + setLocationByPlatform(true); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + } + + class ButtonPanel extends JPanel implements ActionListener { + + private MsdDisplay msdDisplay; + private boolean startCommand; + private boolean resetCommand; + private JButton startButton, resetButton, zoomOutButton, zoomInButton; + + + public ButtonPanel(MsdDisplay cd) { + msdDisplay = cd; + startCommand = false; + resetCommand = false; + setLayout(new GridLayout(4,1 )); + + startButton = new JButton("Start"); + startButton.addActionListener(this); + startButton.setActionCommand("start"); + startButton.setToolTipText("Start MSD"); + add(startButton); + + resetButton = new JButton("Reset"); + resetButton.addActionListener(this); + resetButton.setActionCommand("reset"); + resetButton.setToolTipText("Reset MSD"); + add(resetButton); + + zoomOutButton = new JButton("\u25b2"); + zoomOutButton.addActionListener(this); + zoomOutButton.setActionCommand("zoomout"); + zoomOutButton.setToolTipText("Zoom in"); + add(zoomOutButton); + + zoomInButton = new JButton("\u25bc"); + zoomInButton.addActionListener(this); + zoomInButton.setActionCommand("zoomin"); + zoomInButton.setToolTipText("Zoom Out"); + add(zoomInButton); + + } + + public void actionPerformed(ActionEvent e) { + String s = e.getActionCommand(); + switch (s) { + case "start": + startCommand = true; + break; + case "reset": + resetCommand = true; + + break; + case "zoomin": + msdDisplay.setScale(msdDisplay.getScale() / 2); + break; + case "zoomout": + msdDisplay.setScale(msdDisplay.getScale() * 2); + break; + default: + System.out.println("Unknown Action Command:" + s); + break; + } + } + + public void armResetCommand() { + resetCommand = false; + startButton.setForeground(Color.red); + } + + public void armStartCommand() { + startCommand = false; + startButton.setForeground(Color.gray); + } + + public boolean getResetCommand() { + return resetCommand; + } + + public boolean getStartCommand() { + return startCommand; + } + + } // class ButtonPanel + + +} diff --git a/trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java new file mode 100644 index 00000000..46aec4d1 --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java @@ -0,0 +1,50 @@ +/* + * Trick + * 2018 (c) National Aeronautics and Space Administration (NASA) + * Programmers: Scott P. Fennell + */ + + +import javax.swing.*; + + +public class MsdDisplay extends JFrame { + MsdView msdView; + + + + public void setPosition(double value) { + msdView.setPosition(value); + } + + public void setVelocity(double value) { + msdView.setVelocity(value); + } + + public void setScale(int value) { + msdView.setScale(value); + } + + public int getScale() { + return msdView.getScale(); + } + + public void drawMsdView() { + msdView.repaint(); + } + + + + public MsdDisplay(MsdView arena) { + setTitle("Mass-Spring-Damper"); + msdView = arena; + add(msdView); + + + setSize(800, 500); + setLocationByPlatform(true); + + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + +} diff --git a/trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java new file mode 100644 index 00000000..bdbff287 --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java @@ -0,0 +1,218 @@ +/* + * Trick + * 2018 (c) National Aeronautics and Space Administration (NASA) + * Programmers: Scott P. Fennell + */ + + +import java.awt.*; +import java.io.*; +import java.net.Socket; + +public class MsdGui { + + static BufferedReader in; + static DataOutputStream out; + + public static 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 static void main(String[] args) throws IOException { + + String host = "localHost"; + int port = 0; + + // ========================================================== + // Handle program arguments. + // ========================================================== + int ii = 0; + while (ii < args.length) { + switch (args[ii]) { + case "-help": + case "--help": { + MsdUtils.printHelpText(); + System.exit(0); + } + break; + default: { + port = (Integer.parseInt(args[ii])); + } + break; + } + ++ii; + } + + if (port == 0) { + System.out.println("No variable server port specified."); + MsdUtils.printHelpText(); + System.exit(0); + } + + boolean go = true; + double dt = 0.01; // Time between updates (seconds). + double pos = 0.0; + double vel = 0.0; + boolean resetCommand; + boolean startCommand; + + + int simMode = 0; + + + int mapScale = 32; // pixels per meter. + + MsdView msdView = new MsdView(mapScale); + MsdDisplay display = new MsdDisplay(msdView); + MsdController controller = new MsdController(display); + display.setVisible(true); + display.drawMsdView(); + controller.setVisible(true); + controller.setLocation(new Point((int)display.getLocationOnScreen().getX() + display.getWidth(), (int)display.getLocationOnScreen().getY())); + controller.setSize(controller.getWidth() + 10, display.getHeight()); + + // Connect to the Trick simulation's variable server + System.out.println("Connecting to: " + host + ":" + port); + connectToServer(host, port); + + out.writeBytes("trick.var_set_client_tag(\"MsdGui\") \n"); + out.flush(); + + // Have the Variable Server send us the simulation mode ONCE. + out.writeBytes("trick.var_add(\"trick_sys.sched.mode\")\n" + + "trick.var_add(\"dyn.msd.x_0\")\n" + + "trick.var_add(\"dyn.msd.v_0\")\n" + + "trick.var_add(\"dyn.msd.m\")\n" + + "trick.var_add(\"dyn.msd.b\")\n" + + "trick.var_add(\"dyn.msd.k\")\n" + + "trick.var_add(\"dyn.msd.F\")\n" + + "trick.var_send() \n" + + "trick.var_clear() \n"); + out.flush(); + + // Read the response and extract the simulation mode. Initialize text fields with initial values. + try { + String line; + String field[]; + line = in.readLine(); + field = line.split("\t"); + simMode = Integer.parseInt(field[1]); + controller.positionTextField.setText(String.format("%.2f", new Double(field[2]))); + controller.velocityTextField.setText(String.format("%.2f", new Double(field[3]))); + controller.massTextField.setText(String.format("%.2f", new Double(field[4]))); + controller.dampingTextField.setText(String.format("%.2f", new Double(field[5]))); + controller.springTextField.setText(String.format("%.2f", new Double(field[6]))); + controller.forceTextField.setText(String.format("%.2f", new Double(field[7]))); + } catch (IOException | NullPointerException e) { + go = false; + } + + // If we're in FREEZE, make ready to start. + if (simMode == TrickSimMode.FREEZE) { + controller.armResetCommand(); + } + + // Configure the Variable Server to cyclically send us the following variables. + // Tell the variable server: + // 1) We want the values of the following variables: + out.writeBytes("trick.var_pause() \n" + + "trick.var_add(\"dyn.msd.x\")\n" + + "trick.var_add(\"dyn.msd.v\")\n" + + "trick.var_add(\"trick_sys.sched.mode\")\n" + + // 2) We want the responses in ASCII: + "trick.var_ascii() \n" + + /* 3) We want debug information: + "trick.var_debug(1) \n" + + */ + // 4) We want values to be updated at the specified rate: + String.format("trick.var_cycle(%.3f)\n", dt) + + // 5) Start sending values as specified. + "trick.var_unpause() \n"); + out.flush(); + + while (go) { + + // Receive and parse periodic data response from the variable server. + try { + String line; + String field[]; + line = in.readLine(); + field = line.split("\t"); + pos = Double.parseDouble(field[1]); + vel = Double.parseDouble(field[2]); + simMode = Integer.parseInt(field[3]); + } catch (IOException | NullPointerException e) { + go = false; + } + // Get inputs from the GUI. + resetCommand = controller.getResetCommand(); + startCommand = controller.getStartCommand(); + + if (simMode == TrickSimMode.FREEZE) { + + controller.armResetCommand(); + resetCommand = false; + if (!controller.positionTextField.getText().isEmpty() && new Double(controller.positionTextField.getText()) >= 0.0) { + display.msdView.hideWall = false; + } + if (!(controller.positionTextField.getText().isEmpty() || + controller.velocityTextField.getText().isEmpty() || + controller.springTextField.getText().isEmpty() || + controller.dampingTextField.getText().isEmpty() || + controller.massTextField.getText().isEmpty() || + controller.forceTextField.getText().isEmpty())) { + + out.writeBytes( + "dyn.msd.x_0 = " + controller.positionTextField.getText() + ";\n" + + "dyn.msd.v_0 = " + controller.velocityTextField.getText() + ";\n" + + "dyn.msd.k = " + controller.springTextField.getText() + ";\n" + + "dyn.msd.b = " + controller.dampingTextField.getText() + ";\n" + + "dyn.msd.m = " + controller.massTextField.getText() + ";\n" + + "dyn.msd.F = " + controller.forceTextField.getText() + ";\n"); + out.writeBytes("dyn.msd.x = dyn.msd.x_0 ;\n"); + out.writeBytes("dyn.msd.v = dyn.msd.v_0 ;\n"); + } + + if (startCommand) { + out.writeBytes(String.format("trick.exec_run();\n")); + + out.flush(); + } + if (resetCommand) { + out.writeBytes(String.format("trick.exec_freeze() ;\n")); + continue; + } + out.flush(); + + } else if (simMode == TrickSimMode.RUN) { + controller.armStartCommand(); + startCommand = false; + if (resetCommand) { + out.writeBytes(String.format("trick.exec_freeze() ;\n")); + out.flush(); + } + if (!(controller.springTextField.getText().isEmpty() || + controller.dampingTextField.getText().isEmpty() || + controller.massTextField.getText().isEmpty() || + controller.forceTextField.getText().isEmpty())) { + out.writeBytes( + "dyn.msd.k = " + controller.springTextField.getText() + ";\n" + + "dyn.msd.b = " + controller.dampingTextField.getText() + ";\n" + + "dyn.msd.m = " + controller.massTextField.getText() + ";\n" + + "dyn.msd.F = " + controller.forceTextField.getText() + ";\n"); + } + } + + // Update the display data. + display.setPosition(pos); + display.setVelocity(vel); + + // Update the scene. + display.drawMsdView(); + + } // while + + } +} diff --git a/trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java new file mode 100644 index 00000000..7c8f52ca --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java @@ -0,0 +1,24 @@ +/* + * Trick + * 2018 (c) National Aeronautics and Space Administration (NASA) + * Programmers: Scott P. Fennell + */ + + + +public class MsdUtils { + + public static void printHelpText() { + System.out.println( + "----------------------------------------------------------------------\n" + + "usage: java jar CannonDisplay.jar \n" + + "----------------------------------------------------------------------\n" + ); + } +} + +class TrickSimMode { + public static final int INIT = 0; + public static final int FREEZE = 1; + public static final int RUN = 5; +} \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java new file mode 100644 index 00000000..8dbdbf80 --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java @@ -0,0 +1,183 @@ +/* + * Trick + * 2018 (c) National Aeronautics and Space Administration (NASA) + * Programmers: Scott P. Fennell + */ + + + +import javax.swing.*; +import java.awt.*; + +class MsdView extends JPanel { + + private int scale; + private Color massColor; + private Color backgroundColor; + private Color wallColor; + private Color springColor; + private Double position; + private Double velocity; + private Double massRadius; + boolean hideWall = false; + + // Origin of world coordinates in jpanel coordinates. + private int worldOriginX; + private int worldOriginY; + + + /** + * Class constructor. + */ + public MsdView(int mapScale) { + + setScale(mapScale); + + backgroundColor = new Color(200, 200, 255); + springColor = new Color(150, 150, 100); + massColor = new Color(10, 10, 10); + wallColor = new Color(120, 118, 118); + springColor = Color.BLUE; + massRadius = 0.75; + position = 0.0; + velocity = 0.0; + } + + /** + * @param value angle in degrees + */ + public void setPosition(double value) { + position = value; + } + + public void setVelocity(double value) { + velocity = value; + } + + public void setScale(int mapScale) { + if (mapScale < 4) { + scale = 4; + } else if (mapScale > 128) { + scale = 128; + } else { + scale = mapScale; + } + repaint(); + } + + public int getScale() { + return scale; + } + + public void drawCenteredCircle(Graphics2D g, int x, int y, int r) { + x = x - (r / 2); + y = y - (r / 2); + g.fillOval(x, y, r, r); + } + + 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(); + + + worldOriginX = (width / 3); + worldOriginY = (height / 2); + + while (worldOriginX + scale * position > width) { + scale = scale / 2; + } + + // Draw Sky + g2d.setPaint(backgroundColor); + g2d.fillRect(0, 0, width, worldOriginY); + + // Draw mass + g2d.setPaint(massColor); + int bx = (int) (worldOriginX + scale * position); + int by = (int) (worldOriginY); + drawCenteredCircle(g2d, bx, by, (int) (scale * massRadius)); + + // Draw spring + double springPosition; + // reflect spring visual over origin correctly + if(position < massRadius/2 && position > -massRadius/2){ + springPosition = 0.0; + } else if(position < 0){ + springPosition = position + massRadius/2; + } else{ + springPosition = position - massRadius/2; + } + int SCALEFACTOR = 200; + int cycles = 5; + int points = SCALEFACTOR * cycles * 2; + double[] sines = new double[points]; + for (int i = 0; i < points; i++) { + double radians = (Math.PI / SCALEFACTOR) * i; + sines[i] = Math.sin(radians); + } + int maxWidth = (int) (scale * (springPosition /*- massRadius / 2*/)); + double hstep = (double) maxWidth / (double) points; + int maxHeight = (int) (scale); + int[] pts = new int[points]; + for (int i = 0; i < points; i++) { + pts[i] = (int) (sines[i] * maxHeight / 2 * .95 + maxHeight / 2); + } + g2d.setColor(springColor); + for (int i = 1; i < points; i++) { + int x1 = (int) ((i - 1) * hstep); + int x2 = (int) (i * hstep); + int y1 = pts[i - 1]; + int y2 = pts[i]; + g2d.drawLine(x1 + worldOriginX, y1 + height / 2 - scale / 2, x2 + worldOriginX, y2 + height / 2 - scale / 2); + + } + + //Draw wall + if (!hideWall && position >= 0) { + g2d.setPaint(wallColor); + g2d.fillRect(0, 0, worldOriginX, height); + } else { + hideWall = true; + } + + + // 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.BLACK); + + 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); + } + + g2d.drawString(String.format("SCALE: %d pixels/meter", scale), 20, 20); + g2d.drawString(String.format(" Position (m): %.2f", position), 20, 80); + g2d.drawString(String.format("Velocity (m/s): %.2f", velocity), 20, 120); + + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + doDrawing(g); + } +} \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/graphics/Makefile b/trick_sims/SIM_msd/models/graphics/Makefile new file mode 100644 index 00000000..fe61dffd --- /dev/null +++ b/trick_sims/SIM_msd/models/graphics/Makefile @@ -0,0 +1,36 @@ +SHELL = /bin/sh + +PROJECT_NAME = MsdGui +SRC_DIR = MSD/src +BUILD_DIR = build +CLASSES_DIR = $(BUILD_DIR)/classes +JAR_DIR = dist +MAIN_CLASS = MsdGui + +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)/MsdGui.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 "-------------------------------------------------------------------------------" diff --git a/trick_sims/SIM_msd/models/msd/include/msd.hh b/trick_sims/SIM_msd/models/msd/include/msd.hh new file mode 100644 index 00000000..832ecf1c --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/include/msd.hh @@ -0,0 +1,48 @@ +/************************TRICK HEADER************************* +PURPOSE: Mass-Spring-Damper class header file . +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ + +#ifndef MSD_H +#define MSD_H + +class MSD { +public: + + double a; /* m/s2 acceleration */ + double v; /* m/s velocity */ + double x; /* m position */ + double m; /* kg mass */; + + double v_0; /* *i m/s initial velocity of the mass (at t = 0) */ + double x_0; /* *i m initial position of the mass (at t = 0) */ + + double b; /* N.s/m damping constant */ + double k; /* N/m spring constant */ + double F; /* N force constant */ + + + + MSD(void); /* not used */ + + MSD(double _m, double _k, double _b, double _F, + double _v_0, double _x_0); + + int state_deriv(void); + int state_integ(void); + + }; + + +#ifdef __cplusplus +extern "C" { +#endif +int msd_default_data(MSD &); +int msd_init(MSD &); +int msd_shutdown(const MSD &); +#ifdef __cplusplus +} +#endif + +#endif /* MSD_H */ \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/msd/include/msd_numeric.hh b/trick_sims/SIM_msd/models/msd/include/msd_numeric.hh new file mode 100644 index 00000000..29093004 --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/include/msd_numeric.hh @@ -0,0 +1,17 @@ +/************************TRICK HEADER************************* +PURPOSE: Msd Numeric model +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ +#ifndef MSD_NUMERIC_H +#define MSD_NUMERIC_H + +#include "msd.hh" + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/msd/src/msd.cpp b/trick_sims/SIM_msd/models/msd/src/msd.cpp new file mode 100644 index 00000000..4c2a3f60 --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/src/msd.cpp @@ -0,0 +1,19 @@ +/************************TRICK HEADER************************* +PURPOSE: MSD is a mass-spring-damper class for a trick sim. +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ +#include +#include "../include/msd_numeric.hh" +#include + +MSD::MSD(double _m, double _k, double _b, double _F, double _v_0, double _x_0) { + m = _m; + k = _k; + b = _b; + F = _F; + v_0 = _v_0; + x_0 = _x_0; +} + +MSD::MSD(void) {/* not used */} \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp b/trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp new file mode 100644 index 00000000..815256ca --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp @@ -0,0 +1,15 @@ +/************************TRICK HEADER************************* + PURPOSE: ( Trick integration ) +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ +#include "../include/msd_numeric.hh" +#include "../include/msd.hh" +#include + +int MSD::state_deriv(void) { + /* system equation for second derivitive */ + a = (F - b*v - k*x)/m; + + return(0); +} \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/msd/src/msd_init.cpp b/trick_sims/SIM_msd/models/msd/src/msd_init.cpp new file mode 100644 index 00000000..627c41ee --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/src/msd_init.cpp @@ -0,0 +1,28 @@ +/************************TRICK HEADER************************* +PURPOSE: Set the initial data values of the MSD +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ + +/* Model Include files */ +#include "../include/msd.hh" + +/* default data job */ +int msd_default_data(MSD &M) { + M = MSD( + 1.0, /* m */ + 2.0, /* k */ + 0.5, /* b */ + 5.0, /* F */ + 0.0, /* v_0 */ + 5.0 /* x_0 */ + + ); + + return 0; +} + +/* initialization job */ +int msd_init(MSD &M) { + return 0; +} diff --git a/trick_sims/SIM_msd/models/msd/src/msd_integ.cpp b/trick_sims/SIM_msd/models/msd/src/msd_integ.cpp new file mode 100644 index 00000000..30566922 --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/src/msd_integ.cpp @@ -0,0 +1,31 @@ +/************************TRICK HEADER************************* + PURPOSE: ( Trick integration ) + PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ +#include "../include/msd_numeric.hh" +#include "msd.hh" +#include "trick/Integrator.hh" +#include "trick/integrator_c_intf.h" +#include + +int MSD::state_integ(void) { + int ipass; + load_state( + &x, + &v, + NULL); + + load_deriv( + &v, + &a, + NULL); + + ipass = integrate(); + + unload_state( + &x, + &v, + NULL); + return(ipass); +} \ No newline at end of file diff --git a/trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp b/trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp new file mode 100644 index 00000000..48fa22e4 --- /dev/null +++ b/trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp @@ -0,0 +1,17 @@ +/************************TRICK HEADER************************* +PURPOSE: (Print the final msd state.) +PROGRAMMERS: + (((Scott P. Fennell) (CACI International Inc.) (January 2018) (Trick Learning Project))) +*************************************************************/ +#include "../include/msd.hh" +#include "trick/exec_proto.h" +#include + +int msd_shutdown(const MSD &M) { + printf("========================================\n"); + printf(" MSD State at Shutdown \n"); + printf("pos = [%g], vel = [%g], acc = [%g]\n", + M.x, M.v, M.a); + printf("========================================\n"); + return 0; +} \ No newline at end of file