mirror of
https://github.com/nasa/trick.git
synced 2024-12-18 20:57:55 +00:00
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
This commit is contained in:
parent
8f76605f3b
commit
aa36c31231
7
trick_sims/SIM_msd/Modified_data/realtime.py
Normal file
7
trick_sims/SIM_msd/Modified_data/realtime.py
Normal file
@ -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)
|
84
trick_sims/SIM_msd/README.md
Normal file
84
trick_sims/SIM_msd/README.md
Normal file
@ -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)
|
23
trick_sims/SIM_msd/RUN_critdamp/input.py
Normal file
23
trick_sims/SIM_msd/RUN_critdamp/input.py
Normal file
@ -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)
|
23
trick_sims/SIM_msd/RUN_nodamp/input.py
Normal file
23
trick_sims/SIM_msd/RUN_nodamp/input.py
Normal file
@ -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)
|
23
trick_sims/SIM_msd/RUN_overdamp/input.py
Normal file
23
trick_sims/SIM_msd/RUN_overdamp/input.py
Normal file
@ -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)
|
21
trick_sims/SIM_msd/RUN_test/input.py
Normal file
21
trick_sims/SIM_msd/RUN_test/input.py
Normal file
@ -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)
|
23
trick_sims/SIM_msd/RUN_underdamp/input.py
Normal file
23
trick_sims/SIM_msd/RUN_underdamp/input.py
Normal file
@ -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)
|
33
trick_sims/SIM_msd/S_define
Normal file
33
trick_sims/SIM_msd/S_define
Normal file
@ -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 ;
|
2
trick_sims/SIM_msd/S_overrides.mk
Normal file
2
trick_sims/SIM_msd/S_overrides.mk
Normal file
@ -0,0 +1,2 @@
|
||||
TRICK_CFLAGS += -Imodels
|
||||
TRICK_CXXFLAGS += -Imodels
|
BIN
trick_sims/SIM_msd/images/MSD0.png
Normal file
BIN
trick_sims/SIM_msd/images/MSD0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
trick_sims/SIM_msd/images/MSD1.png
Normal file
BIN
trick_sims/SIM_msd/images/MSD1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
trick_sims/SIM_msd/images/MSD2.png
Normal file
BIN
trick_sims/SIM_msd/images/MSD2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
trick_sims/SIM_msd/images/MSD3.png
Normal file
BIN
trick_sims/SIM_msd/images/MSD3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
200
trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java
Normal file
200
trick_sims/SIM_msd/models/graphics/MSD/src/MsdController.java
Normal file
@ -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
|
||||
|
||||
|
||||
}
|
50
trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java
Normal file
50
trick_sims/SIM_msd/models/graphics/MSD/src/MsdDisplay.java
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
218
trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java
Normal file
218
trick_sims/SIM_msd/models/graphics/MSD/src/MsdGui.java
Normal file
@ -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
|
||||
|
||||
}
|
||||
}
|
24
trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java
Normal file
24
trick_sims/SIM_msd/models/graphics/MSD/src/MsdUtils.java
Normal file
@ -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 <port-number>\n"
|
||||
+ "----------------------------------------------------------------------\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TrickSimMode {
|
||||
public static final int INIT = 0;
|
||||
public static final int FREEZE = 1;
|
||||
public static final int RUN = 5;
|
||||
}
|
183
trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java
Normal file
183
trick_sims/SIM_msd/models/graphics/MSD/src/MsdView.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
36
trick_sims/SIM_msd/models/graphics/Makefile
Normal file
36
trick_sims/SIM_msd/models/graphics/Makefile
Normal file
@ -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 "-------------------------------------------------------------------------------"
|
48
trick_sims/SIM_msd/models/msd/include/msd.hh
Normal file
48
trick_sims/SIM_msd/models/msd/include/msd.hh
Normal file
@ -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 */
|
17
trick_sims/SIM_msd/models/msd/include/msd_numeric.hh
Normal file
17
trick_sims/SIM_msd/models/msd/include/msd_numeric.hh
Normal file
@ -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
|
19
trick_sims/SIM_msd/models/msd/src/msd.cpp
Normal file
19
trick_sims/SIM_msd/models/msd/src/msd.cpp
Normal file
@ -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 <math.h>
|
||||
#include "../include/msd_numeric.hh"
|
||||
#include <float.h>
|
||||
|
||||
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 */}
|
15
trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp
Normal file
15
trick_sims/SIM_msd/models/msd/src/msd_deriv.cpp
Normal file
@ -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 <math.h>
|
||||
|
||||
int MSD::state_deriv(void) {
|
||||
/* system equation for second derivitive */
|
||||
a = (F - b*v - k*x)/m;
|
||||
|
||||
return(0);
|
||||
}
|
28
trick_sims/SIM_msd/models/msd/src/msd_init.cpp
Normal file
28
trick_sims/SIM_msd/models/msd/src/msd_init.cpp
Normal file
@ -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;
|
||||
}
|
31
trick_sims/SIM_msd/models/msd/src/msd_integ.cpp
Normal file
31
trick_sims/SIM_msd/models/msd/src/msd_integ.cpp
Normal file
@ -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 <math.h>
|
||||
|
||||
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);
|
||||
}
|
17
trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp
Normal file
17
trick_sims/SIM_msd/models/msd/src/msd_shutdown.cpp
Normal file
@ -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 <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user