Java tutorial
/** * Copyright (C) 2014 Bnome SPRL (info@bnome.be) * * This file is part of VectionVR Stabilizer. * * VectionVR Stabilizer is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VectionVR Stabilizer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VectionVR Stabilizer. If not, see <http://www.gnu.org/licenses/>. */ package com.vectionvr.jort.gui; import static com.vectionvr.jort.gui.SettingsManager.getSettingsManager; import static com.vectionvr.jort.jogl.CameraViews.FirstPerson; import static java.awt.BorderLayout.CENTER; import static java.awt.Desktop.getDesktop; import static java.awt.Desktop.isDesktopSupported; import static java.lang.Integer.parseInt; import static java.lang.Math.abs; import static java.lang.Math.toDegrees; import static java.lang.System.nanoTime; import static javax.swing.SwingUtilities.invokeLater; import static jssc.SerialPortList.getPortNames; import static org.apache.commons.lang3.ArrayUtils.isEmpty; import java.awt.Color; import java.awt.Component; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.text.DecimalFormat; import java.text.NumberFormat; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLJPanel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import com.jogamp.opengl.util.FPSAnimator; import com.vectionvr.jort.data.SensorData; import com.vectionvr.jort.jogl.WorldScene; import com.vectionvr.jort.net.UDPSender; import com.vectionvr.jort.serial.ImuOrientationDataStreamer; import com.vectionvr.jort.serial.SensorException; import com.vectionvr.jort.serial.StreamingSensorEventListener; /** * @author (Nicolas Chalon) n.chalon@bnome.be */ public class MainFrame extends javax.swing.JFrame implements Runnable, StreamingSensorEventListener { private FPSAnimator animator; final WorldScene scene = new WorldScene(); private static final NumberFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); private static final NumberFormat SHORT_DECIMAL_FORMAT = new DecimalFormat("##0.0 "); private static final NumberFormat INT_FORMAT = new DecimalFormat("###0"); private final SettingsManager settingsManager; private boolean running; private final UDPSender udpSender = new UDPSender(); private ImuOrientationDataStreamer streamer; private long counterStartTime; private SensorData lastSensorData; private int counter; private SettingsDialog settingsDialog = new SettingsDialog(this, true); private float absMaxX = 0f; private float absMaxY = 0f; private float absMaxZ = 0f; public MainFrame() { initComponents(); setPortItems(); init3DView(); settingsManager = getSettingsManager(this); } private void init3DView() { final GLProfile glp = GLProfile.getDefault(); final GLCapabilities caps = new GLCapabilities(glp); caps.setDoubleBuffered(true); caps.setHardwareAccelerated(true); caps.setSampleBuffers(true); final GLJPanel canvas = new GLJPanel(caps); animator = new FPSAnimator(canvas, 100); animator.setIgnoreExceptions(true); animator.setPrintExceptions(false); orientationPanel.add(canvas, CENTER); canvas.addGLEventListener(scene); scene.setBackgroundColor(new float[] { 0f, 0f, 0f, .3f }); scene.setCamera(FirstPerson); scene.setLineWidth(2f); scene.setCubeEnabled(true); scene.setGridEnabled(false); scene.setCubeSize(10f); } /** * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jButton1 = new javax.swing.JButton(); jPanel1 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); hostName = new javax.swing.JFormattedTextField(); port = new javax.swing.JTextField(); jLabel2 = new javax.swing.JLabel(); jPanel3 = new javax.swing.JPanel(); jLabel7 = new javax.swing.JLabel(); rate = new javax.swing.JLabel(); jLabel9 = new javax.swing.JLabel(); jLabel11 = new javax.swing.JLabel(); delay = new javax.swing.JLabel(); temperature = new javax.swing.JLabel(); jLabel8 = new javax.swing.JLabel(); jLabel10 = new javax.swing.JLabel(); jLabel12 = new javax.swing.JLabel(); orientationPanel = new javax.swing.JPanel(); tareButton = new javax.swing.JButton(); jPanel2 = new javax.swing.JPanel(); jLabel3 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); direction = new javax.swing.JComboBox(); jLabel5 = new javax.swing.JLabel(); reverseX = new javax.swing.JCheckBox(); reverseY = new javax.swing.JCheckBox(); reverseZ = new javax.swing.JCheckBox(); refreshPortsButton = new javax.swing.JButton(); jLabel22 = new javax.swing.JLabel(); lockX1 = new javax.swing.JCheckBox(); lockY1 = new javax.swing.JCheckBox(); lockZ1 = new javax.swing.JCheckBox(); deviceChooser = new javax.swing.JComboBox(); settingsButton = new javax.swing.JButton(); jPanel5 = new javax.swing.JPanel(); jLabel14 = new javax.swing.JLabel(); zAxisAngle = new javax.swing.JLabel(); jLabel13 = new javax.swing.JLabel(); xAxisAngle = new javax.swing.JLabel(); yAxisAngle = new javax.swing.JLabel(); jLabel15 = new javax.swing.JLabel(); jPanel6 = new javax.swing.JPanel(); jLabel16 = new javax.swing.JLabel(); maxZAxisAngle = new javax.swing.JLabel(); jLabel17 = new javax.swing.JLabel(); maxXAxisAngle = new javax.swing.JLabel(); maxYAxisAngle = new javax.swing.JLabel(); jLabel18 = new javax.swing.JLabel(); jLabelLink = new javax.swing.JLabel(); jLabel6 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Vection-VR Stabilizer"); setIconImage(new ImageIcon(getClass().getClassLoader().getResource("imgs/logo.png")).getImage()); setMinimumSize(new java.awt.Dimension(478, 340)); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowOpened(java.awt.event.WindowEvent evt) { formWindowOpened(evt); } public void windowClosing(java.awt.event.WindowEvent evt) { formWindowClosing(evt); } }); jButton1.setBackground(new java.awt.Color(51, 204, 0)); jButton1.setFont(jButton1.getFont().deriveFont(jButton1.getFont().getSize() + 2f)); jButton1.setText("Start"); jButton1.setEnabled(false); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Destination")); jLabel1.setText("Host"); hostName.setText("::1"); port.setText("27015"); jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); jLabel2.setText("Port"); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup(jPanel1Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap() .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(hostName) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(port, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap())); jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup().addGroup(jPanel1Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(hostName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(port, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel1).addComponent(jLabel2)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Status")); jLabel7.setText("Rate"); rate.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); rate.setText("N/A"); jLabel9.setText("Delay"); jLabel11.setText("Temp"); delay.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); delay.setText("N/A"); temperature.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); temperature.setText("N/A"); jLabel8.setText("p/s"); jLabel10.setText("ms"); jLabel12.setText("C"); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup(jPanel3Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap().addGroup(jPanel3Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(jLabel9, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel11, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(delay, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE) .addComponent(rate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(temperature, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jLabel12, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel10, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel8, javax.swing.GroupLayout.Alignment.TRAILING)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel7) .addComponent(rate, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel8)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel9).addComponent(delay).addComponent(jLabel10)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel11).addComponent(temperature).addComponent(jLabel12)) .addContainerGap())); orientationPanel.setIgnoreRepaint(true); orientationPanel.setMinimumSize(new java.awt.Dimension(100, 83)); orientationPanel.setPreferredSize(new java.awt.Dimension(100, 83)); orientationPanel.setLayout(new java.awt.BorderLayout()); tareButton.setText("Tare"); tareButton.setEnabled(false); tareButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { tareButtonActionPerformed(evt); } }); jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Device")); jLabel3.setText("USB port"); jLabel4.setText("Direction"); direction.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "X: Right, Y: Up, Z: Forward", "X: Right, Y: Forward, Z: Up", "X: Up, Y: Right, Z: Forward", "X: Forward, Y: Right, Z: Up", "X: Up, Y: Forward, Z: Right", "X: Forward, Y: Up, Z: Right" })); direction.setSelectedIndex(1); jLabel5.setText("Reverse axis"); reverseX.setText("X"); reverseY.setSelected(true); reverseY.setText("Y"); reverseZ.setText("Z"); refreshPortsButton.setText("Refresh"); refreshPortsButton.setToolTipText("Refresh list"); refreshPortsButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { refreshPortsButtonActionPerformed(evt); } }); jLabel22.setText("Lock axis"); lockX1.setText("X"); lockY1.setText("Y"); lockZ1.setText("Z"); deviceChooser.setModel(new javax.swing.DefaultComboBoxModel(new String[] { " -- No device --" })); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel2Layout .createSequentialGroup().addContainerGap().addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE) .addComponent(jLabel22, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(direction, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel2Layout.createSequentialGroup().addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(jPanel2Layout.createSequentialGroup().addComponent(lockX1) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lockY1) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lockZ1)) .addGroup(jPanel2Layout.createSequentialGroup() .addComponent(reverseX) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(reverseY) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(reverseZ))) .addGroup(jPanel2Layout.createSequentialGroup() .addComponent(deviceChooser, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(refreshPortsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap())); jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(refreshPortsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel3).addComponent(deviceChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4).addComponent(direction, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel5) .addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(reverseX).addComponent(reverseY).addComponent(reverseZ))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lockX1).addComponent(lockY1).addComponent(lockZ1)) .addComponent(jLabel22)) .addContainerGap())); settingsButton.setText("Settings"); settingsButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { settingsButtonActionPerformed(evt); } }); jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("Angles")); jLabel14.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); jLabel14.setText("Y"); zAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); zAxisAngle.setText("N/A"); jLabel13.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); jLabel13.setText("X"); xAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); xAxisAngle.setText("N/A"); yAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); yAxisAngle.setText("N/A"); jLabel15.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); jLabel15.setText("Z"); javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); jPanel5.setLayout(jPanel5Layout); jPanel5Layout.setHorizontalGroup(jPanel5Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup().addContainerGap() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel14, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE) .addComponent(jLabel15, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel13, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(xAxisAngle, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(yAxisAngle, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(zAxisAngle, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap())); jPanel5Layout.setVerticalGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup() .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(xAxisAngle).addComponent(jLabel13)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel14, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(yAxisAngle)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(zAxisAngle).addComponent(jLabel15)) .addContainerGap())); jPanel6.setBorder(javax.swing.BorderFactory.createTitledBorder("Max")); jLabel16.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); jLabel16.setText("Y"); maxZAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); maxZAxisAngle.setText("N/A"); jLabel17.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); jLabel17.setText("X"); maxXAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); maxXAxisAngle.setText("N/A"); maxYAxisAngle.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); maxYAxisAngle.setText("N/A"); jLabel18.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); jLabel18.setText("Z"); javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); jPanel6.setLayout(jPanel6Layout); jPanel6Layout .setHorizontalGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup().addContainerGap() .addGroup(jPanel6Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jLabel16, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel17, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel18, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(maxXAxisAngle, javax.swing.GroupLayout.DEFAULT_SIZE, 73, Short.MAX_VALUE) .addComponent(maxYAxisAngle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(maxZAxisAngle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap())); jPanel6Layout.setVerticalGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup() .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(maxXAxisAngle).addComponent(jLabel17)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel16, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(maxYAxisAngle)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(maxZAxisAngle).addComponent(jLabel18)) .addContainerGap())); jLabelLink.setForeground(new java.awt.Color(51, 51, 255)); jLabelLink.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabelLink.setText("www.vectionvr.com"); jLabelLink.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { jLabelLinkMouseClicked(evt); } }); jLabel6.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N jLabel6.setText("Provided by Bnome under GPLv3 license"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tareButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(settingsButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(orientationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE) .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGroup(layout.createSequentialGroup() .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabelLink, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap())); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addComponent(tareButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(settingsButton)) .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(orientationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabelLink).addComponent(jLabel6)) .addContainerGap())); pack(); }// </editor-fold>//GEN-END:initComponents private void refreshPortsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshPortsButtonActionPerformed setPortItems(); }//GEN-LAST:event_refreshPortsButtonActionPerformed private void settingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_settingsButtonActionPerformed settingsDialog.setLocationRelativeTo(null); settingsDialog.setVisible(true); }//GEN-LAST:event_settingsButtonActionPerformed private void jLabelLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelLinkMouseClicked if (evt.getClickCount() > 0) { if (isDesktopSupported()) { try { URI uri = new URI("http://www.vectionvr.com"); getDesktop().browse(uri); } catch (IOException ex) { } catch (URISyntaxException ex) { } } else { } } }//GEN-LAST:event_jLabelLinkMouseClicked private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened }//GEN-LAST:event_formWindowOpened private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing stopSending(); }//GEN-LAST:event_formWindowClosing private void jButton1ActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton1ActionPerformed if (running) { stopSending(); jButton1.setText("Start"); jButton1.setBackground(Color.GREEN); temperature.setText("N/A"); delay.setText("N/A"); rate.setText("N/A"); xAxisAngle.setText("N/A"); yAxisAngle.setText("N/A"); zAxisAngle.setText("N/A"); running = false; } else { temperature.setText(" - "); delay.setText(" - "); rate.setText(" - "); xAxisAngle.setText(" - "); yAxisAngle.setText(" - "); zAxisAngle.setText(" - "); jButton1.setText("Stop"); jButton1.setBackground(Color.RED); startSending(); running = true; } tareButton.setEnabled(running); refreshPortsButton.setEnabled(!running); settingsButton.setEnabled(!running); setComponentsEnabled(!running); }// GEN-LAST:event_jButton1ActionPerformed private void tareButtonActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tareButtonActionPerformed streamer.tare(); absMaxX = 0; absMaxY = 0; absMaxZ = 0; }// GEN-LAST:event_tareButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel delay; private javax.swing.JComboBox deviceChooser; private javax.swing.JComboBox direction; private javax.swing.JFormattedTextField hostName; private javax.swing.JButton jButton1; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel10; private javax.swing.JLabel jLabel11; private javax.swing.JLabel jLabel12; private javax.swing.JLabel jLabel13; private javax.swing.JLabel jLabel14; private javax.swing.JLabel jLabel15; private javax.swing.JLabel jLabel16; private javax.swing.JLabel jLabel17; private javax.swing.JLabel jLabel18; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel22; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel8; private javax.swing.JLabel jLabel9; private javax.swing.JLabel jLabelLink; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel5; private javax.swing.JPanel jPanel6; private javax.swing.JCheckBox lockX1; private javax.swing.JCheckBox lockY1; private javax.swing.JCheckBox lockZ1; private javax.swing.JLabel maxXAxisAngle; private javax.swing.JLabel maxYAxisAngle; private javax.swing.JLabel maxZAxisAngle; private javax.swing.JPanel orientationPanel; private javax.swing.JTextField port; private javax.swing.JLabel rate; private javax.swing.JButton refreshPortsButton; private javax.swing.JCheckBox reverseX; private javax.swing.JCheckBox reverseY; private javax.swing.JCheckBox reverseZ; private javax.swing.JButton settingsButton; private javax.swing.JButton tareButton; private javax.swing.JLabel temperature; private javax.swing.JLabel xAxisAngle; private javax.swing.JLabel yAxisAngle; private javax.swing.JLabel zAxisAngle; // End of variables declaration//GEN-END:variables private void setPortItems() { new Thread(new Runnable() { @Override public void run() { refreshPortsButton.setEnabled(false); deviceChooser.removeAllItems(); deviceChooser.setEnabled(false); boolean validPorts = false; final String[] portList = getPortNames(); if (isEmpty(portList)) { deviceChooser.addItem(" -- No device --"); jButton1.setBackground(null); } else { validPorts = true; for (String portName : portList) { deviceChooser.addItem(portName); } jButton1.setBackground(Color.GREEN); deviceChooser.setEnabled(true); } jButton1.setEnabled(validPorts); refreshPortsButton.setEnabled(true); } }).start(); } private void setComponentsEnabled(final boolean enabled) { for (final Component component : getContentPane().getComponents()) { setChildsEnabled(component, enabled); } } private void setChildsEnabled(final Component component, final boolean enabled) { if (component instanceof JPanel) { for (final Component subComponent : ((JPanel) component).getComponents()) { setChildsEnabled(subComponent, enabled); } } else if (!(component instanceof JLabel) && !(component instanceof JButton)) { component.setEnabled(enabled); } } private void startSending() { absMaxX = 0; absMaxY = 0; absMaxZ = 0; new Thread(this).start(); } private void stopSending() { running = false; if (streamer != null) { streamer.stop(); } if (udpSender != null) { udpSender.stop(); } } @Override public void run() { try { startUdpSender(); setupStreamer(); while (running) { updateMax(); outputStatistics(); suspend(1f); } } catch (final UnknownHostException ex) { showError("The provided destination address is not valid."); jButton1ActionPerformed(null); } catch (final NumberFormatException ex) { showError("The provided destination port is not valid."); jButton1ActionPerformed(null); } } private void showError(final String message) { invokeLater(new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(MainFrame.this, message, "Error", JOptionPane.ERROR_MESSAGE); } }); } private void startUdpSender() throws UnknownHostException, NumberFormatException { udpSender.setDestinationAddress(hostName.getText()); udpSender.setDestinationPort(parseInt(port.getText())); new Thread(udpSender).start(); } private void setupStreamer() throws NumberFormatException { streamer = new ImuOrientationDataStreamer((String) deviceChooser.getSelectedItem()); streamer.setDirectionAxis(direction.getSelectedIndex()); streamer.setReverseAxis(reverseX.isSelected(), reverseY.isSelected(), reverseZ.isSelected()); streamer.setAccelerometerRange((byte) settingsDialog.getAccelerometerRange().getSelectedIndex()); streamer.setCompassRange((byte) settingsDialog.getCompassRange().getSelectedIndex()); streamer.setGyroscopeRange((byte) settingsDialog.getGyroscopeRange().getSelectedIndex()); streamer.setInterval(getInterval()); streamer.setLockX(lockX1.isSelected()); streamer.setLockY(lockY1.isSelected()); streamer.setLockZ(lockZ1.isSelected()); streamer.registerListener(this); new Thread(streamer).start(); } @Override public void sensorStarted(final ImuOrientationDataStreamer sensor) { counterStartTime = nanoTime(); tareButton.setEnabled(true); animator.start(); } @Override public void onSensorData(final SensorData data) { udpSender.onSensorData(data); scene.update(data); lastSensorData = data; ++counter; } @Override public void sensorStopped() { scene.reset(); try { animator.stop(); } catch (final Exception e) { } } private void outputStatistics() { if (streamer.getStatistics() != null && streamer.getStatistics().get() > 0) { final double timeDiff = nanoTime() - counterStartTime; rate.setText((short) (counter / (timeDiff / 1e9)) + ""); delay.setText(DECIMAL_FORMAT.format(udpSender.getRunningAverage())); temperature.setText(INT_FORMAT.format(lastSensorData.getTemperature())); xAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(lastSensorData.getEulerAngle().getxAxis()))); yAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(lastSensorData.getEulerAngle().getyAxis()))); zAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(lastSensorData.getEulerAngle().getzAxis()))); maxXAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(absMaxX))); maxYAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(absMaxY))); maxZAxisAngle.setText(SHORT_DECIMAL_FORMAT.format(toDegrees(absMaxZ))); } counter = 0; counterStartTime = nanoTime(); } private static void suspend(final float durationInSeconds) { try { Thread.sleep((long) (durationInSeconds * 1000f)); } catch (final Exception e) { } } @Override public void handleException(final SensorException e) { showError("There was an error using the sensor. Please check your cable."); jButton1ActionPerformed(null); } private int getInterval() { return parseInt(settingsDialog.getIntervalInput().getText()); } private void updateMax() { if (lastSensorData != null) { if (abs(lastSensorData.getEulerAngle().getxAxis()) > absMaxX) { absMaxX = abs(lastSensorData.getEulerAngle().getxAxis()); } if (abs(lastSensorData.getEulerAngle().getyAxis()) > absMaxY) { absMaxY = abs(lastSensorData.getEulerAngle().getyAxis()); } if (abs(lastSensorData.getEulerAngle().getzAxis()) > absMaxZ) { absMaxZ = abs(lastSensorData.getEulerAngle().getzAxis()); } } } }