using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Threading;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.IO.Ports;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Input=Microsoft.Xna.Framework.Input; // to provide shorthand to clear up ambiguities
namespace Coachoid
{
public partial class MainForm : Form
{
//To keep track of the current and previous state of the gamepad
///
/// The current state of the controller
///
GamePadState gamePadState;
///
/// The previous state of the controller
///
GamePadState previousState;
///
/// Keeps track of the current controller
///
PlayerIndex playerIndex = PlayerIndex.One;
///
/// Counter for limiting the time for which the vibration motors are on.
///
int vibrationCountdown = 0;
///
/// Contains the current status of the Swath Boat
///
Hashtable status = new Hashtable();
///
/// Contains parameters to send to the Swath Boat
///
Hashtable parameters = new Hashtable();
///
/// Contains the controls that display the table of properties in the "status" window
///
Hashtable statusControls = new Hashtable();
///
/// Contains the dataset log of all incoming data and some properties sent
///
DataSet LogDS = new DataSet();
///
/// Contains the datatable of all incoming data and some properties sent
///
DataTable logTable = new DataTable();
///
/// logInitTime - initial time of the log started used for timestamps of seconds into recording
///
DateTime logInitTime;
///
/// SerialOccupied means we are already recieving string
///
bool serialOccupied = false;
///
/// controlsChanged means a gain or desired value was changed, it is sent twice to ensure reception
///
int controlsChanged = 0;
///
/// waypoints contains arrays of all the lats and longitudes of the destinations
///
public string[] waypointLats;
public string[] waypointLons;
///
/// Flag that is raised when waypoints are updated
///
int waypointsUpdated = 0;
///
/// Waypoint index for when we're sending waypoints, we only send 3 at a time, this keeps track
///
Byte waypointsIndex = 1;
public MainForm()
{
InitializeComponent();
}
///
/// When a new controller is selected from the drop down
/// update the player index and turn off all the vibration motors.
///
///
///
private void ddlController_SelectedIndexChanged(object sender, EventArgs e)
{
switch (this.ddlController.SelectedIndex)
{
case 0: playerIndex = PlayerIndex.One; break;
case 1: playerIndex = PlayerIndex.Two; break;
case 2: playerIndex = PlayerIndex.Three; break;
case 3: playerIndex = PlayerIndex.Four; break;
default: playerIndex = PlayerIndex.One; break;
}
this.StopAllVibration();
}
private void StopAllVibration()
{
GamePad.SetVibration(PlayerIndex.One, 0.0f, 0.0f);
GamePad.SetVibration(PlayerIndex.Two, 0.0f, 0.0f);
GamePad.SetVibration(PlayerIndex.Three, 0.0f, 0.0f);
GamePad.SetVibration(PlayerIndex.Four, 0.0f, 0.0f);
}
private void CheckVibrationTimeout()
{
if (vibrationCountdown > 0)
{
--vibrationCountdown;
if (vibrationCountdown == 0.0f)
{
GamePad.SetVibration(playerIndex, 0.0f, 0.0f);
}
}
}
private void UpdateControllerState()
{
//Get the new gamepad state and save the old state.
this.previousState = this.gamePadState;
this.gamePadState = GamePad.GetState(this.playerIndex);
//If the controller is not connected, let the user know
if (this.gamePadState.IsConnected)
{
ControllerStatus.Text = "Controller Connected";
ControllerStatus.ForeColor = System.Drawing.Color.Green;
}
else
{
ControllerStatus.Text = "No Controller";
ControllerStatus.ForeColor = System.Drawing.Color.Maroon;
}
//I personally prefer to only update the buttons if their state has been changed.
if (!this.gamePadState.Buttons.Equals(this.previousState.Buttons))
{
this.buttonA.Checked = (this.gamePadState.Buttons.A == Input.ButtonState.Pressed);
this.buttonB.Checked = (this.gamePadState.Buttons.B == Input.ButtonState.Pressed);
this.buttonX.Checked = (this.gamePadState.Buttons.X == Input.ButtonState.Pressed);
this.buttonY.Checked = (this.gamePadState.Buttons.Y == Input.ButtonState.Pressed);
this.buttonLeftShoulder.Checked = (this.gamePadState.Buttons.LeftShoulder == Input.ButtonState.Pressed);
this.buttonRightShoulder.Checked = (this.gamePadState.Buttons.RightShoulder == Input.ButtonState.Pressed);
this.buttonStart.Checked = (this.gamePadState.Buttons.Start == Input.ButtonState.Pressed);
this.buttonBack.Checked = (this.gamePadState.Buttons.Back == Input.ButtonState.Pressed);
this.buttonLeftStick.Checked = (this.gamePadState.Buttons.LeftStick == Input.ButtonState.Pressed);
this.buttonRightStick.Checked = (this.gamePadState.Buttons.RightStick == Input.ButtonState.Pressed);
}
//KILL USING BUTTON B
if (this.buttonB.Checked)
{
//Set Mode Parameter to "K" denoting kill or do nothing
this.parameters["MD"] = "K";
//play with buttons
ManEnable.Enabled = true;
ManDisable.Enabled = false;
HeadEnBtn.Enabled = false;
HeadDisBtn.Enabled = false;
}
//ENTER MANUAL MODE USING BUTTON A
if (this.buttonA.Checked)
{
//Set Mode Parameter to "M" denoting Manual..
ManEnable.Enabled = false;
ManDisable.Enabled = true;
HeadGrpBox.Enabled = true;
HeadEnBtn.Enabled = true;
HeadDisBtn.Enabled = false;
//Start Sending Manual Control Strings
ManControlTimer.Start();
this.parameters["MD"] = "M";
}
if (!this.gamePadState.DPad.Equals(this.previousState.DPad))
{
this.buttonUp.Checked = (this.gamePadState.DPad.Up == Input.ButtonState.Pressed);
this.buttonDown.Checked = (this.gamePadState.DPad.Down == Input.ButtonState.Pressed);
this.buttonLeft.Checked = (this.gamePadState.DPad.Left == Input.ButtonState.Pressed);
this.buttonRight.Checked = (this.gamePadState.DPad.Right == Input.ButtonState.Pressed);
}
//Update the position of the thumb sticks
//since the thumbsticks can return a number between -1.0 and +1.0 I had to shift (add 1.0)
//and scale (mutiplication by 100/2, or 50) to get the numbers to be in the range of 0-100
//for the progress bar
this.x1Position.Value = (int)((this.gamePadState.ThumbSticks.Left.X + 1.0f) * 100.0f / 2.0f);
this.y1Position.Value = (int)((this.gamePadState.ThumbSticks.Left.Y + 1.0f) * 100.0f / 2.0f);
this.x2position.Value = (int)((this.gamePadState.ThumbSticks.Right.X + 1.0f) * 100.0f / 2.0f);
this.y2position.Value = (int)((this.gamePadState.ThumbSticks.Right.Y + 1.0f) * 100.0f / 2.0f);
//The triggers return a value between 0.0 and 1.0. I only needed to scale these values for
//the progress bar
this.leftTriggerPosition.Value = (int)((this.gamePadState.Triggers.Left * 100));
this.rightTriggerPosition.Value = (int)(this.gamePadState.Triggers.Right*100);
//machine guns!!!
m1Player = new System.Media.SoundPlayer();
//M1
if (this.gamePadState.Triggers.Right > .05)
{
//m1Player.SoundLocation = @"C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\Coachoid\mg.wav";
//m1Player.Play();
//vibrate!!
GamePad.SetVibration(playerIndex, (float)this.gamePadState.Triggers.Right, (float)0.0);
}
else
{
m1Player.Stop();
GamePad.SetVibration(playerIndex, (float)0.0, (float)0.0);
}
}
//this is for playing sounds
private System.Media.SoundPlayer m1Player;
//I'm updating the controller display on a timed interval.
private void controllerTimer_Tick(object sender, EventArgs e)
{
this.CheckVibrationTimeout();
this.UpdateControllerState();
}
private void XnaInputForm_Load(object sender, EventArgs e)
{
this.ddlController.SelectedIndex = 0;
//Start Timer that updates controller status
this.controllerTimer.Start();
//Refresh list of available ports
refresh_ports();
//Initialize Paramters Hashtable
this.parameters.Add("MD", "K"); //mode initially in kill mode - no action
this.parameters.Add("M1", "A00"); //manual mode motor command1
this.parameters.Add("M2", "B00"); //maunual mode motor command2
}
private void refresh_ports()
{
//Load Serial Port List
//get an array of ports
string[] portnames = System.IO.Ports.SerialPort.GetPortNames();
//clear current list of ports
this.PortList.Items.Clear();
//loop through array and enter available
foreach (string port in portnames)
{
this.PortList.Items.Add(port);
}
}
private void XnaInputForm_FormClosing(object sender, FormClosingEventArgs e)
{
//stop controller if its vibrating
this.StopAllVibration();
//Stop Sending Manual Control Strings
ManControlTimer.Stop();
ManEnable.Enabled = true;
ManDisable.Enabled = false;
//IF Serial Port is Open, Close it!
if (serialPort.IsOpen)
{
try
{
serialPort.Close();
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
}
}
}
private void btnConnect_Click(object sender, EventArgs e)
{
try
{ //set serial port name to selected
serialPort.PortName = PortList.SelectedItem.ToString();
//serial port properties
serialPort.NewLine = "\r\n";
//open serial port
serialPort.Open();
//enable disconnect / disable connect / disable portlist
btnConnect.Enabled = false;
btnDisconnect.Enabled = true;
PortList.Enabled = false;
PortRefBtn.Enabled = false;
//set connected message
SerialStat.Text = PortList.SelectedItem.ToString() + " Connected";
SerialStat.ForeColor = System.Drawing.Color.Green;
}
catch(Exception x)
{
//there was an error opening serial port
MessageBox.Show(x.ToString());
}
}
private void VibButton_Click(object sender, EventArgs e)
{
GamePad.SetVibration(playerIndex, (float)this.leftMotor.Value, (float)this.rightMotor.Value);
vibrationCountdown = 30;
}
private void btnDisconnect_Click(object sender, EventArgs e)
{
try
{
//Close serialPort
serialPort.Close();
//enable disconnect / disable connect / disable portlist
btnConnect.Enabled = true;
btnDisconnect.Enabled = false;
PortList.Enabled = true;
PortRefBtn.Enabled = true;
//set connected message
SerialStat.Text = PortList.SelectedItem.ToString() + " DisConnected";
SerialStat.ForeColor = System.Drawing.Color.Maroon;
}
catch (Exception x)
{
//display error
MessageBox.Show(x.ToString());
}
}
//ControlsChanged is called when a gain or desired value is changed
private void controlsChangedCall(object sender, EventArgs e)
{
this.controlsChanged = 1;
}
//This function responds with all needed parameters to boat after it requests them
private void respond_to_request()
{
String output = "";
//construct string based on mode
switch (this.parameters["MD"].ToString())
{
//kill mode
case "K":
output += "$MDK";
output += "$M1a00";
output += "$M2b00";
break;
//manual mode
case "M":
output += "$MDM";
output += "$M1" + this.parameters["M1"];
output += "$M2" + this.parameters["M2"];
break;
//heading and Velocity mode
case "H":
//output mode
output += "$MDH";
//only output values if something has changed
if (this.controlsChanged > 0)
{
//output power scaling
output += "$PS" + PowerScale.Value.ToString();
//HEADING CONTROL
//output desired heading
output += "$DH" + DesiredSlider.Value.ToString().PadLeft(3, '0');
//output proportional heading
output += "$HP" + headPval.Value.ToString().PadLeft(2, '0');
//output integral heading
output += "$HI" + headIval.Value.ToString().PadLeft(2, '0');
//output derivative heading
output += "$HD" + headDval.Value.ToString().PadLeft(2, '0');
//VELOCITY CONTROL
//output desired velocity
output += "$DV" + DesiredVel.Value.ToString();
//output proportional velocity
output += "$VP" + velPval.Value.ToString().PadLeft(2, '0');
//output integral velocity
output += "$VI" + velIval.Value.ToString().PadLeft(2, '0');
//output derivative velocity
output += "$VD" + velDval.Value.ToString().PadLeft(2, '0');
//we send this out twice to ensure its been recieved, if controlsChanged is greate than 2, set to 0
this.controlsChanged++;
if (this.controlsChanged > 2)
{
this.controlsChanged = 0;
}
}
break;
//fully autonomous mode
case "A":
//output mode
output += "$MDA";
//only output values if something has changed
if (this.controlsChanged > 0)
{
//output power scaling
output += "$PS" + PowerScale.Value.ToString();
//HEADING CONTROL
//output proportional heading
output += "$HP" + headPval.Value.ToString().PadLeft(2, '0');
//output integral heading
output += "$HI" + headIval.Value.ToString().PadLeft(2, '0');
//output derivative heading
output += "$HD" + headDval.Value.ToString().PadLeft(2, '0');
//VELOCITY CONTROL
//output desired velocity
output += "$DV" + DesiredVel.Value.ToString();
//output proportional velocity
output += "$VP" + velPval.Value.ToString().PadLeft(2, '0');
//output integral velocity
output += "$VI" + velIval.Value.ToString().PadLeft(2, '0');
//output derivative velocity
output += "$VD" + velDval.Value.ToString().PadLeft(2, '0');
//we send this out twice to ensure its been recieved, if controlsChanged is greate than 2, set to 0
this.controlsChanged++;
if (this.controlsChanged > 2)
{
this.controlsChanged = 0;
}
}
//WAYPOINTS
if (this.waypointsUpdated > 0)
{
//output clear waypoints instruction if we're restarting
if (this.waypointsIndex == 1)
{
output += "$CW";
}
//Lattitude
//$LT(1 byte index)123.567890
byte index = this.waypointsIndex;
foreach(String lat in waypointLats)
{
output += "$LT" + System.Convert.ToChar(index).ToString() + lat.ToString().PadRight(10, '0').Substring(0, 10);
index++;
if (index >= this.waypointsIndex + 3)
{
break;
}
}
//LONGITUDE
//$LN(1 byte index)123.567890
index = this.waypointsIndex;
char[] neg = { '-' }; // negative sign to trim
foreach (String lon in waypointLons)
{
output += "$LN" + System.Convert.ToChar(index).ToString() + lon.ToString().TrimStart(neg).PadRight(10,'0').Substring(0, 10);
index++;
if (index >= this.waypointsIndex + 3)
{
break;
}
}
//increment waypoint counter
this.waypointsIndex += 3;
if (System.Convert.ToInt32(this.waypointsIndex) >= waypointLons.GetLength(0))
{
this.waypointsIndex = 1;
this.waypointsUpdated = 0;
}
}
break;
}
/*
* NOTE:
* System.BitConverter.GetBytes(); returns array of bytes from a c# variable - look at overloads
* System.BitConverter.ToSingle(); takes 4 bytes and retrun single precision float
* Lattitude Waypoint format: "LT" + byte representing waypoint number + 4bytes representing IEEE float value
* Longitude Waypoint format: "LN" + byte representing waypoint number + 4bytes representing IEEE float value
* desired heading format: "DH"+4bytes representing IEEE float
*/
//output
serialPort.WriteLine(output);
}
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//if occupied we are already recieving the string
if (serialOccupied)
{
return;
}
else
{
//we will recieve data
serialOccupied = true;
}
String newData = "";
//Read in new line
try
{
newData = serialPort.ReadLine() + serialPort.NewLine;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
}
//we're done recieving string, serial port is unoccupied
serialOccupied = false;
//check if data is request
if (newData == "$RQ\r\n")
{
//request for data, send parameters
this.respond_to_request();
return;
}
CommBox.Invoke(new addToCommBoxDelegate(this.addToCommBox), new object[] { newData.ToString() });
//check for correctness and parse if its properly formatted
//regular expressions
//^ denotes beginning of string
// $$ = literal $
// $ denotes end of string
if (Regex.IsMatch(newData, "^[$].*:.*(\r\n)$", RegexOptions.Singleline))
{
//This is a report to base of data, parse it!
this.Invoke(new parseDataDelegate(parseData), new Object[] { newData.ToString() });
//update the map using delegate
this.Invoke(new update_mapDelegate(update_map));
//update the avionics display using delegate
this.Invoke(new update_avionicsDelegate(update_avionics));
//add data to the log(
if (logDataStop.Enabled == true)
{
this.update_log();
}
}
else
{
//*data was bad, mention it?
}
}
//delegate for parseData function
delegate void parseDataDelegate(String buffer);
//This function is called when a full line is recieved in the serial buffer
//it parses the data and displays it on the forms
private void parseData(String buffer)
{
//check for spaces, if so, we likely had an error, so ignore string
if (buffer.Contains(" "))
{
return;
}
//remove line breaks
buffer = buffer.Trim();
buffer = buffer.Replace("\r", "");
buffer = buffer.Replace("\n", "");
buffer = buffer.Replace(Environment.NewLine," ");
//perform check to make sure string is valid
if (!buffer.StartsWith('$'.ToString()) || !buffer.Contains(':'.ToString()))
{
return;
}
//remove first '$' to eliminate troubles
buffer = buffer.Remove(0, 1);
//parse data into hasharray
//first clear hastable as its going to be rewritten
this.status.Clear();
//split string into key / value pairs
string[] parameters = buffer.Split('$');
//make sure we split the string
if (parameters.Length == 0)
{
//note bad data recieved
CommBox.AppendText("bad data");
return;
}
//split into key and values and put into hashtable
foreach(String param in parameters)
{
string[] keyvals = param.Split(':');
/* //DEBUGGING
CommBox.AppendText("\r\nDEBUG:");
foreach (String test in keyvals)
{
CommBox.AppendText(test + '#');
}
*///END DEBUGGING
if (keyvals.Length <= 1)
{
//note bad data recieved
CommBox.AppendText("bad data1");
continue;
}
//check if key already exists, if so, update, if not, add
if (this.status.ContainsKey(keyvals[0]))
{
this.status[keyvals[0]] = keyvals[1];
}
else
{
this.status.Add(keyvals[0], keyvals[1]);
}
}
/* //list all parameters in statusgrid
this.statusGrid.ColumnCount = this.status.Count;
//clear statusgrid
this.statusGrid.Controls.Clear();
//add new status info the the statusgrid
int i = 0;
foreach (string key in this.status.Keys)
{
//check if control already exists and modify, otherwise create new
if (this.statusControls.ContainsKey(key))
{
Label olabel = (Label)Controls.Find(key, true)[0];
olabel.Text = key + ": " + this.status[key].ToString();
this.statusGrid.Refresh();
//this.statusControls[key] = olabel;
}
else
{
//create new labels
Label nlabel = new Label();
nlabel.Name = key;
nlabel.Text = key + ": " + this.status[key].ToString();
this.statusGrid.Controls.Add(nlabel, 0, i);
//this.statusControls.Add(key, nlabel);
}
i++;
}
*/
}
public delegate void update_mapDelegate();
/**
* This function updates the google map!
**/
public void update_map()
{
//check if we got longitude / latitiude position
if(this.status.ContainsKey("LAT") && this.status.ContainsKey("LON"))
{
//Update position of Boat
//This line runs the javascript function to move the boat
Map.Document.InvokeScript("moveBoat", new object[] { Convert.ToDouble(this.status["LAT"]), -Convert.ToDouble(this.status["LON"]) });
}
}
/*
* Updates the status controls that display information
*/
public delegate void update_avionicsDelegate();
public void update_avionics()
{
//update Compass Heading
if(this.status.ContainsKey("HDG"))
{
//update compass
this.heading.Value = (int)(System.Convert.ToDouble(this.status["HDG"])/3.6);
//update oscilloscop
headingScope.MoveRays( DesiredSlider.Value , (int)System.Convert.ToDouble(this.status["HDG"]));
}
//update amps
if (this.status.ContainsKey("A1"))
{
this.starAmps.Value = (int) System.Convert.ToDouble(this.status["A1"]);
}
if (this.status.ContainsKey("A2"))
{
this.portAmps.Value = (int)System.Convert.ToDouble(this.status["A2"]);
}
//update SOG
if (this.status.ContainsKey("SOG"))
{
//update gauge - needs to be scaled by 10
this.velocity.Value = (int)(System.Convert.ToDouble(this.status["SOG"].ToString()) * 10);
//update oscilloscope - also scaled by 10
velocityScope.MoveRays((int)System.Convert.ToInt32(DesiredVel.Value * 10), System.Convert.ToInt32(System.Convert.ToDouble(this.status["SOG"].ToString()) * 10));
}
//update compass desired heading if in autonomous mode
if (this.status.ContainsKey("DH") && this.parameters.ContainsKey("MD") && this.parameters["MD"].ToString() == "A")
{
int desHead = System.Convert.ToInt32(System.Convert.ToDouble(this.status["DH"].ToString()));
DesiredSlider.Value = desHead;
DesiredLabel.Text = desHead.ToString();
DesiredCompass.Value = desHead;
}
}
/*
* Creates the log table
*/
public void create_log()
{
//clear log
this.logTable = new DataTable();
//name log
logTable.TableName = "SWATH_Log";
//add columns
// this will be the primary key
DataColumn timeCol = new DataColumn("Time", typeof(double));
logTable.Columns.Add(timeCol);
// make this the primary key
logTable.PrimaryKey = new DataColumn[] { timeCol };
// add some fields for all the data
logTable.Columns.Add(new DataColumn("TimeStamp", typeof(string)));
logTable.Columns.Add(new DataColumn("Latitude", typeof(string)));
logTable.Columns.Add(new DataColumn("Longitude", typeof(string)));
logTable.Columns.Add(new DataColumn("Heading", typeof(string)));
logTable.Columns.Add(new DataColumn("Desired_Heading", typeof(int)));
logTable.Columns.Add(new DataColumn("headPgain", typeof(int)));
logTable.Columns.Add(new DataColumn("headIgain", typeof(int)));
logTable.Columns.Add(new DataColumn("headDgain", typeof(int)));
logTable.Columns.Add(new DataColumn("Velocity", typeof(string)));
logTable.Columns.Add(new DataColumn("Desired_Velocity", typeof(string)));
logTable.Columns.Add(new DataColumn("velPgain", typeof(int)));
logTable.Columns.Add(new DataColumn("velIgain", typeof(int)));
logTable.Columns.Add(new DataColumn("velDgain", typeof(int)));
logTable.Columns.Add(new DataColumn("M1_Current", typeof(string)));
logTable.Columns.Add(new DataColumn("M2_Current", typeof(string)));
}
/*
* Adds new data to the log
*/
public void update_log()
{
// add record to the table
DataRow row;
row = logTable.NewRow();
//add timestamp
TimeSpan duration = DateTime.Now - logInitTime;
row["Time"] = duration.TotalSeconds;
//parameters recieved from swath
if (this.status.ContainsKey("TME"))
row["TimeStamp"] = this.status["TME"].ToString();
if (this.status.ContainsKey("LAT"))
row["Latitude"] = this.status["LAT"].ToString();
if (this.status.ContainsKey("LON"))
row["Longitude"] = this.status["LON"].ToString();
if (this.status.ContainsKey("HDG"))
row["Heading"] = this.status["HDG"].ToString();
if (this.status.ContainsKey("A1"))
row["M1_Current"] = this.status["A1"].ToString();
if (this.status.ContainsKey("A2"))
row["M2_Current"] = this.status["A2"].ToString();
if (this.status.ContainsKey("SOG"))
row["Velocity"] = this.status["SOG"].ToString();
//no conditions are required for control values
row["Desired_Heading"] = DesiredSlider.Value;
row["headPgain"] = headPval.Value;
row["headIgain"] = headIval.Value;
row["headDgain"] = headDval.Value;
row["Desired_Velocity"] = DesiredVel.Value.ToString();
row["velPgain"] = velPval.Value;
row["velIgain"] = velIval.Value;
row["velDgain"] = velDval.Value;
logTable.Rows.Add(row);
}
/*
* This function is a delegate that adds string to the CommBox
*/
public delegate void addToCommBoxDelegate(string text);
public void addToCommBox(string text)
{
CommBox.AppendText(text);
}
private void SendBtn_Click(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.WriteLine(txtToSend.Text.ToString());
CommBox.AppendText(Environment.NewLine + txtToSend.Text.ToString());
txtToSend.Clear();
}
}
//Enables Manual Control
private void ManEnable_Click(object sender, EventArgs e)
{
ManEnable.Enabled = false;
ManDisable.Enabled = true;
HeadGrpBox.Enabled = true;
//Start Sending Manual Control Strings
ManControlTimer.Start();
//Set Mode Parameter to "M" denoting Manual
this.parameters["MD"] = "M";
}
private void ManDisable_Click(object sender, EventArgs e)
{
//Stop Sending Manual Control Strings
ManControlTimer.Stop();
ManEnable.Enabled = true;
ManDisable.Enabled = false;
HeadGrpBox.Enabled = false;
//Set Mode Parameter to "K" denoting kill or do nothing
this.parameters["MD"] = "K";
}
private void ManControlTimer_Tick(object sender, EventArgs e)
{
this.ManualControl();
}
private void ManualControl()
{
//ManualTest.Text = this.gamePadState.ThumbSticks.Left.Y.ToString("X");
//Get Joystick Value -1.0 to 1.0 & Multiply by 127 & Scale by powerscale
float y1 = (this.gamePadState.ThumbSticks.Left.Y * 127)*((float)PowerScale.Value / 100);
float y2 = (this.gamePadState.ThumbSticks.Left.X * 127)*((float)PowerScale.Value / 100);
//round to nearest whole number
int y1rnd = Math.Abs( (int) Math.Round(y1));
int y2rnd = Math.Abs((int)Math.Round(y2));
//Convert to string
string y1str = y1rnd.ToString("X");
string y2str = y2rnd.ToString("X");
//String must be 2 characters in length
if (y1str.Length == 1)
{
y1str = "0" + y1str;
}
if (y2str.Length == 1)
{
y2str = "0" + y2str;
}
//B is forward / reverse
if (y1 > -3)
{
y1str = "b" + y1str;
//A is left / right turn
if (y2 > 0)
{
y2str = "a" + y2str;
}
else
{
y2str = "A" + y2str;
}
}
else
{
y1str = "B" + y1str;
//A is left / right turn
if (y2 > 0)
{
y2str = "A" + y2str;
}
else
{
y2str = "a" + y2str;
}
}
//put out test box!
ManualTest.Text = y2str;
//assign values to paramters of boat
this.parameters["M1"] = y1str;
this.parameters["M2"] = y2str;
//OUTPUT SERIAL STRING - not used anymore
if (serialPort.IsOpen)
{
//serialPort.WriteLine(y1str);
//serialPort.WriteLine(y2str);
}
else
{
this.ManControlTimer.Stop();
ManEnable.Enabled = true;
ManDisable.Enabled = false;
MessageBox.Show("No Connection To Serial Port");
}
}
private void tabPage1_Click(object sender, EventArgs e)
{
}
private void Map_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
}
private void add_point_Click(object sender, EventArgs e)
{
//This line runs the javascript function "addMarker()" with parameters in object
Map.Document.InvokeScript("addMarker", new object[] {pointDescription.Text.ToString()});
pointDescription.Clear();
}
private void groupBox6_Enter(object sender, EventArgs e)
{
}
private void PortRefBtn_Click(object sender, EventArgs e)
{
//refresh list of ports
refresh_ports();
}
private void ClearMonitor_Click(object sender, EventArgs e)
{
CommBox.Clear();
}
private void txtToSend_Enter(object sender, EventArgs e)
{
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
//IF Serial Port is Open, Close it!
if (serialPort.IsOpen)
{
try
{
serialPort.Close();
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
}
}
}
private void tabPage2_Click(object sender, EventArgs e)
{
}
private void DesiredSlider_ValueChanged(object sender, EventArgs e)
{
DesiredCompass.Value = DesiredSlider.Value;
DesiredLabel.Text = DesiredSlider.Value.ToString();
this.controlsChanged = 1;
}
private void HeadEnBtn_Click(object sender, EventArgs e)
{
HeadEnBtn.Enabled = false;
HeadDisBtn.Enabled = true;
//Set Mode Parameter to "H" denoting Heading & Velocity Control
this.parameters["MD"] = "H";
}
private void HeadDisBtn_Click(object sender, EventArgs e)
{
HeadEnBtn.Enabled = true;
HeadDisBtn.Enabled = false;
//Set Mode Parameter to "M" denoting Manual Control
this.parameters["MD"] = "M";
}
private void NumericUpDown2_ValueChanged(object sender, EventArgs e)
{
}
private void logDataStop_Click(object sender, EventArgs e)
{
//create new dataset
DataSet ds = new DataSet();
//name dataset
ds.DataSetName = "SWATH";
// add the table to the DataSet
ds.Tables.Add(this.logTable);
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
// dump to XML
ds.WriteXml(saveFileDialog.FileName);
}
logDataStop.Enabled = false;
logDataStart.Enabled = true;
}
private void logDataStart_Click(object sender, EventArgs e)
{
logDataStart.Enabled = false;
logDataStop.Enabled = true;
//reset timestamp
this.logInitTime = DateTime.Now;
//create log
create_log();
}
//this function runs the javasctipt function clear_traces and clears the history trace of the boat
private void clear_trace_Click(object sender, EventArgs e)
{
Map.Document.InvokeScript("clear_traces", new object[] {});
}
private void update_waypoints_Click(object sender, EventArgs e)
{
Object lats = new Object();
Object lons = new Object();
lats = Map.Document.InvokeScript("query_lats", new object[] { });
lons = Map.Document.InvokeScript("query_lons", new object[] {});
//careful about longitude sign's!
//explode into arrays
waypointLats = lats.ToString().Split(',');
waypointLons = lons.ToString().Split(',');
//set waypoints updated flag
waypointsUpdated = 1;
}
private void autoEnable_Click(object sender, EventArgs e)
{
HeadEnBtn.Enabled = false;
HeadDisBtn.Enabled = false;
autoDisable.Enabled = true;
autoEnable.Enabled = false;
//Set Mode Parameter to "A" denoting Autonomous Control
this.parameters["MD"] = "A";
}
private void autoDisable_Click(object sender, EventArgs e)
{
HeadEnBtn.Enabled = true;
HeadDisBtn.Enabled = false;
autoEnable.Enabled = true;
autoDisable.Enabled = false;
//Set Mode Parameter to "M" denoting Manual Control
this.parameters["MD"] = "M";
}
}
}