Updates from upstream (firstforge): NetworkTable handles deleted values, CAN has a new minimum version, ...

git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4155 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/CANJaguar.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/CANJaguar.cpp
index abbad78..75d6195 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/CANJaguar.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/CANJaguar.cpp
@@ -43,16 +43,16 @@
 	if (StatusIsFatal())

 		return;

 	// 3330 was the first shipping RDK firmware version for the Jaguar

-	if (fwVer >= 3330 || fwVer < 92)

+	if (fwVer >= 3330 || fwVer < 101)

 	{

 		char buf[256];

 		if (fwVer < 3330)

 		{

-			snprintf(buf, 256, "Jag #%d firmware (%d) is too old (must be at least version 92 of the FIRST approved firmware)", m_deviceNumber, fwVer);

+			snprintf(buf, 256, "Jag #%d firmware (%d) is too old (must be at least version 101 of the FIRST approved firmware)", m_deviceNumber, fwVer);

 		}

 		else

 		{

-			snprintf(buf, 256, "Jag #%d firmware (%d) is not FIRST approved (must be at least version 92 of the FIRST approved firmware)", m_deviceNumber, fwVer);

+			snprintf(buf, 256, "Jag #%d firmware (%d) is not FIRST approved (must be at least version 101 of the FIRST approved firmware)", m_deviceNumber, fwVer);

 		}

 		wpi_setWPIErrorWithContext(JaguarVersionError, buf);

 		return;

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.cpp
index aea6fdf..957dda4 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.cpp
@@ -15,8 +15,11 @@
 static const char *kRunning = "running";

 static const char *kIsParented = "isParented";

 

+int Command::m_commandCounter = 0;

+

 void Command::InitCommand(const char *name, double timeout)

 {

+	m_commandID = m_commandCounter++;

 	m_timeout = timeout;

 	m_locked = false;

 	m_startTime = -1;

@@ -95,6 +98,15 @@
 }

 

 /**

+ * Get the ID (sequence number) for this command

+ * The ID is a unique sequence number that is incremented for each command.

+ * @return the ID of this command

+ */

+int Command::GetID() {

+	return m_commandID;

+}

+

+/**

  * Sets the timeout of this command.

  * @param timeout the timeout (in seconds)

  * @see Command#isTimedOut() isTimedOut()

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.h
index 760c8f5..2704624 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.h
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Command.h
@@ -65,6 +65,7 @@
 	CommandGroup *GetGroup();

 	void SetRunWhenDisabled(bool run);

 	bool WillRunWhenDisabled();

+	int GetID();

 

 

 protected:

@@ -147,7 +148,8 @@
 	bool m_runWhenDisabled;

 	/** The {@link CommandGroup} this is in */

 	CommandGroup *m_parent;

-	

+	int m_commandID;

+	static int m_commandCounter;

 	

 public:

 	virtual std::string GetName();

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.cpp
index 9cd67d6..1ee067a 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.cpp
@@ -19,20 +19,20 @@
 Scheduler *Scheduler::_instance = NULL;

 

 Scheduler::Scheduler() :

-	m_buttonsLock(NULL),

-	m_additionsLock(NULL),

-	m_adding(false)

-{

-	m_buttonsLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);

-	m_additionsLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);

+	m_buttonsLock(NULL), m_additionsLock(NULL), m_adding(false) {

+	m_buttonsLock = semMCreate(

+			SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);

+	m_additionsLock = semMCreate(

+			SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);

 

-	nUsageReporting::report(nUsageReporting::kResourceType_Command, nUsageReporting::kCommand_Scheduler);

-	

+	nUsageReporting::report(nUsageReporting::kResourceType_Command,

+			nUsageReporting::kCommand_Scheduler);

+

+	m_table = NULL;

 	m_enabled = true;

 }

 

-Scheduler::~Scheduler()

-{

+Scheduler::~Scheduler() {

 	semTake(m_additionsLock, WAIT_FOREVER);

 	semDelete(m_additionsLock);

 

@@ -44,8 +44,7 @@
  * Returns the {@link Scheduler}, creating it if one does not exist.

  * @return the {@link Scheduler}

  */

-Scheduler *Scheduler::GetInstance()

-{

+Scheduler *Scheduler::GetInstance() {

 	if (_instance == NULL)

 		_instance = new Scheduler();

 	return _instance;

@@ -61,53 +60,47 @@
  * at the end of the pass, they are all scheduled.

  * @param command The command to be scheduled

  */

-void Scheduler::AddCommand(Command *command)

-{

+void Scheduler::AddCommand(Command *command) {

 	Synchronized sync(m_additionsLock);

-	if (std::find(m_additions.begin(), m_additions.end(), command) != m_additions.end())

+	if (std::find(m_additions.begin(), m_additions.end(), command)

+			!= m_additions.end())

 		return;

 	m_additions.push_back(command);

 }

 

-void Scheduler::AddButton(ButtonScheduler *button)

-{

+void Scheduler::AddButton(ButtonScheduler *button) {

 	Synchronized sync(m_buttonsLock);

 	m_buttons.push_back(button);

 }

 

-void Scheduler::ProcessCommandAddition(Command *command)

-{

+void Scheduler::ProcessCommandAddition(Command *command) {

 	if (command == NULL)

 		return;

 

 	// Check to make sure no adding during adding

-	if (m_adding)

-	{

+	if (m_adding) {

 		wpi_setWPIErrorWithContext(IncompatibleState, "Can not start command from cancel method");

 		return;

 	}

 

 	// Only add if not already in

 	CommandSet::iterator found = m_commands.find(command);

-	if (found == m_commands.end())

-	{

+	if (found == m_commands.end()) {

 		// Check that the requirements can be had

 		Command::SubsystemSet requirements = command->GetRequirements();

 		Command::SubsystemSet::iterator iter;

-		for (iter = requirements.begin(); iter != requirements.end(); iter++)

-		{

+		for (iter = requirements.begin(); iter != requirements.end(); iter++) {

 			Subsystem *lock = *iter;

-			if (lock->GetCurrentCommand() != NULL && !lock->GetCurrentCommand()->IsInterruptible())

+			if (lock->GetCurrentCommand() != NULL

+					&& !lock->GetCurrentCommand()->IsInterruptible())

 				return;

 		}

 

 		// Give it the requirements

 		m_adding = true;

-		for (iter = requirements.begin(); iter != requirements.end(); iter++)

-		{

+		for (iter = requirements.begin(); iter != requirements.end(); iter++) {

 			Subsystem *lock = *iter;

-			if (lock->GetCurrentCommand() != NULL)

-			{

+			if (lock->GetCurrentCommand() != NULL) {

 				lock->GetCurrentCommand()->Cancel();

 				Remove(lock->GetCurrentCommand());

 			}

@@ -118,6 +111,7 @@
 		m_commands.insert(command);

 

 		command->StartRunning();

+		m_runningCommandsChanged = true;

 	}

 }

 

@@ -133,30 +127,30 @@
  * <li> Add Defaults </li>

  * </ol>

  */

-void Scheduler::Run()

-{

+void Scheduler::Run() {

 	// Get button input (going backwards preserves button priority)

 	{

-		if (!m_enabled) return;

+		if (!m_enabled)

+			return;

 

 		Synchronized sync(m_buttonsLock);

 		ButtonVector::reverse_iterator rButtonIter = m_buttons.rbegin();

-		for (; rButtonIter != m_buttons.rend(); rButtonIter++)

-		{

+		for (; rButtonIter != m_buttons.rend(); rButtonIter++) {

 			(*rButtonIter)->Execute();

 		}

 	}

+	

+	m_runningCommandsChanged = false;

 

 	// Loop through the commands

 	CommandSet::iterator commandIter = m_commands.begin();

-	for (; commandIter != m_commands.end();)

-	{

+	for (; commandIter != m_commands.end();) {

 		Command *command = *commandIter;

 		// Increment before potentially removing to keep the iterator valid

 		commandIter++;

-		if (!command->Run())

-		{

+		if (!command->Run()) {

 			Remove(command);

+			m_runningCommandsChanged = true;

 		}

 	}

 

@@ -164,8 +158,7 @@
 	{

 		Synchronized sync(m_additionsLock);

 		CommandVector::iterator additionsIter = m_additions.begin();

-		for (; additionsIter != m_additions.end(); additionsIter++)

-		{

+		for (; additionsIter != m_additions.end(); additionsIter++) {

 			ProcessCommandAddition(*additionsIter);

 		}

 		m_additions.clear();

@@ -173,16 +166,14 @@
 

 	// Add in the defaults

 	Command::SubsystemSet::iterator subsystemIter = m_subsystems.begin();

-	for (; subsystemIter != m_subsystems.end(); subsystemIter++)

-	{

+	for (; subsystemIter != m_subsystems.end(); subsystemIter++) {

 		Subsystem *lock = *subsystemIter;

-		if (lock->GetCurrentCommand() == NULL)

-		{

+		if (lock->GetCurrentCommand() == NULL) {

 			ProcessCommandAddition(lock->GetDefaultCommand());

 		}

 		lock->ConfirmCommand();

 	}

-	

+

 	UpdateTable();

 }

 

@@ -191,10 +182,8 @@
  * if a default {@link Command} needs to be run.  All {@link Subsystem Subsystems} should call this.

  * @param system the system

  */

-void Scheduler::RegisterSubsystem(Subsystem *subsystem)

-{

-	if (subsystem == NULL)

-	{

+void Scheduler::RegisterSubsystem(Subsystem *subsystem) {

+	if (subsystem == NULL) {

 		wpi_setWPIErrorWithContext(NullParameter, "subsystem");

 		return;

 	}

@@ -205,10 +194,8 @@
  * Removes the {@link Command} from the {@link Scheduler}.

  * @param command the command to remove

  */

-void Scheduler::Remove(Command *command)

-{

-	if (command == NULL)

-	{

+void Scheduler::Remove(Command *command) {

+	if (command == NULL) {

 		wpi_setWPIErrorWithContext(NullParameter, "command");

 		return;

 	}

@@ -218,8 +205,7 @@
 

 	Command::SubsystemSet requirements = command->GetRequirements();

 	Command::SubsystemSet::iterator iter = requirements.begin();

-	for (; iter != requirements.end(); iter++)

-	{

+	for (; iter != requirements.end(); iter++) {

 		Subsystem *lock = *iter;

 		lock->SetCurrentCommand(NULL);

 	}

@@ -228,39 +214,49 @@
 }

 

 void Scheduler::RemoveAll() {

-	while(m_commands.size()>0){

+	while (m_commands.size() > 0) {

 		Remove(*m_commands.begin());

 	}

 }

 

+/**

+ * Update the network tables associated with the Scheduler object on the SmartDashboard

+ */

 void Scheduler::UpdateTable() {

 	CommandSet::iterator commandIter;

 	if (m_table != NULL) {

-		// Get the commands to cancel

+		// Get the list of possible commands to cancel

 		m_table->RetrieveValue("Cancel", *toCancel);

-		

-		for (commandIter = m_commands.begin(); commandIter != m_commands.end();) {

-			for (unsigned i = 0; i < toCancel->size(); i++) {

-				Command *c = *commandIter;

-				if ((unsigned)c == toCancel->get(i)) {

-					c->Cancel();

+//		m_table->RetrieveValue("Ids", *ids);

+

+		// cancel commands that have had the cancel buttons pressed

+		// on the SmartDashboad

+		if (toCancel->size() > 0) {

+			for (commandIter = m_commands.begin(); commandIter

+					!= m_commands.end(); ++commandIter) {

+				for (unsigned i = 0; i < toCancel->size(); i++) {

+					Command *c = *commandIter;

+					if (c->GetID() == toCancel->get(i)) {

+						c->Cancel();

+					}

 				}

 			}

+			toCancel->setSize(0);

+			m_table->PutValue("Cancel", *toCancel);

 		}

-		toCancel->setSize(0);

-		m_table->PutValue("Cancel", *toCancel);

-		

-		commands->setSize(0);

-		ids->setSize(0);

 		

 		// Set the running commands

-		for (commandIter = m_commands.begin(); commandIter != m_commands.end();) {

-			Command *c = *commandIter;

-			commands->add(c->GetName());

-			ids->add((unsigned)c);

+		if (m_runningCommandsChanged) {

+			commands->setSize(0);

+			ids->setSize(0);

+			for (commandIter = m_commands.begin(); commandIter != m_commands.end(); ++commandIter) {

+				Command *c = *commandIter;

+				commands->add(c->GetName());

+				ids->add(c->GetID());

+			}

+			m_table->PutValue("Names", *commands);

+			m_table->PutValue("Ids", *ids);

 		}

-		m_table->PutValue("Names", *commands);

-		m_table->PutValue("Ids", *ids);

 	}

 }

 

@@ -281,7 +277,7 @@
 	commands = new StringArray();

 	ids = new NumberArray();

 	toCancel = new NumberArray();

-	

+

 	m_table->PutValue("Names", *commands);

 	m_table->PutValue("Ids", *ids);

 	m_table->PutValue("Cancel", *toCancel);

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.h
index 2636ac6..deef356 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.h
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Scheduler.h
@@ -64,6 +64,7 @@
 	NumberArray *ids;

 	NumberArray *toCancel;

 	ITable *m_table;

+	bool m_runningCommandsChanged;

 };

 #endif

 

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.cpp
index dfd559c..c0d8c62 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.cpp
@@ -22,6 +22,7 @@
 	m_name = name;

 	Scheduler::GetInstance()->RegisterSubsystem(this);

 	m_table = NULL;

+	m_currentCommandChanged = true;

 }

 /**

  * Initialize the default command for this subsystem

@@ -106,6 +107,7 @@
 void Subsystem::SetCurrentCommand(Command *command)

 {

 	m_currentCommand = command;

+	m_currentCommandChanged = true;

 }

 

 /**

@@ -124,17 +126,20 @@
  */

 void Subsystem::ConfirmCommand()

 {

-	if (m_table != NULL)

-	{

-		if (m_currentCommand != NULL)

+	if (m_currentCommandChanged) {

+		if (m_table != NULL)

 		{

-			m_table->PutBoolean("hasCommand", true);

-			m_table->PutString("command", m_currentCommand->GetName());

+			if (m_currentCommand != NULL)

+			{

+				m_table->PutBoolean("hasCommand", true);

+				m_table->PutString("command", m_currentCommand->GetName());

+			}

+			else

+			{

+				m_table->PutBoolean("hasCommand", false);

+			}

 		}

-		else

-		{

-			m_table->PutBoolean("hasCommand", false);

-		}

+		m_currentCommandChanged = false;

 	}

 }

 

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.h
index b04616d..9ef4f76 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.h
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Commands/Subsystem.h
@@ -31,6 +31,7 @@
 	void ConfirmCommand();

 

 	Command *m_currentCommand;

+	bool m_currentCommandChanged;

 	Command *m_defaultCommand;

 	std::string m_name;

 	bool m_initializedDefaultCommand;

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Preferences.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Preferences.cpp
index 7948d9f..7a3d9ea 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/Preferences.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Preferences.cpp
@@ -44,9 +44,6 @@
 	m_readTask.Start((UINT32)this);

 	semTake(m_fileOpStarted, WAIT_FOREVER);

 

-	NetworkTable::GetTable(kTableName)->PutBoolean(kSaveField, false);

-	NetworkTable::GetTable(kTableName)->AddTableListener(this);

-

 	nUsageReporting::report(nUsageReporting::kResourceType_Preferences, 0);

 }

 

@@ -430,7 +427,7 @@
 			{

 				value = fgetc(file);

 			} while (value == ' ' || value == '\t');

-

+			

 			if (value == '\n' || value == ';')

 			{

 				if (value == '\n')

@@ -501,7 +498,7 @@
 				{

 					m_keys.push_back(name);

 					m_values.insert(std::pair<std::string, std::string>(name, value));

-					//NetworkTable::GetTable(kTableName)->PutString(name, value);

+					NetworkTable::GetTable(kTableName)->PutString(name, value);

 

 					if (!comment.empty())

 					{

@@ -525,6 +522,9 @@
 

 	if (!comment.empty())

 		m_endComment = comment;

+	

+	NetworkTable::GetTable(kTableName)->PutBoolean(kSaveField, false);

+	NetworkTable::GetTable(kTableName)->AddTableListener(this);

 }

 

 /**

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables/NetworkTable.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables/NetworkTable.cpp
index f14b590..daefd88 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables/NetworkTable.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables/NetworkTable.cpp
@@ -53,7 +53,7 @@
 

 void NetworkTable::SetClientMode(){

 	CheckInit();

-	mode = &NetworkTableMode::Server;

+	mode = &NetworkTableMode::Client;

 }

 

 void NetworkTable::SetServerMode(){

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/AbstractNetworkTableEntryStore.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/AbstractNetworkTableEntryStore.cpp
index dd1936d..f9ac35c 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/AbstractNetworkTableEntryStore.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/AbstractNetworkTableEntryStore.cpp
@@ -9,7 +9,8 @@
 #include "networktables2/TableKeyExistsWithDifferentTypeException.h"

 #include <map>

 #include <vector>

-

+#include <iostream>

+#include <stdio.h>

 

 	AbstractNetworkTableEntryStore::AbstractNetworkTableEntryStore(TableListenerManager& lstnManager): 

 			listenerManager(lstnManager){

@@ -32,14 +33,23 @@
 	NetworkTableEntry* AbstractNetworkTableEntryStore::GetEntry(std::string& name){

 		{ 

 			Synchronized sync(LOCK);

-			return namedEntries[name];//TODO check for not existing

+			std::map<std::string, NetworkTableEntry*>::iterator value_itr = namedEntries.find(name);

+			if(value_itr != namedEntries.end()) {

+				return value_itr->second;

+			}

+			return NULL;

 		}

 	}

 	

 	NetworkTableEntry* AbstractNetworkTableEntryStore::GetEntry(EntryId entryId){

 		{ 

 			Synchronized sync(LOCK);

-			return idEntries[entryId];//TODO check for not existing

+			

+			std::map<EntryId, NetworkTableEntry*>::iterator value_itr = idEntries.find(entryId);

+			if(value_itr != idEntries.end()) {

+				return value_itr->second;

+			}

+			return NULL;

 		}

 	}

 	

@@ -112,8 +122,8 @@
 			Synchronized sync(LOCK);

 			std::map<std::string, NetworkTableEntry*>::iterator index = namedEntries.find(name);

 			NetworkTableEntry* tableEntry;

-			if(index == namedEntries.end() || namedEntries[name]==NULL)//if the name does not exist in the current entries

-			  {//TODO why doesn't find correctly detect that the entry does not exist

+			if(index == namedEntries.end())//if the name does not exist in the current entries

+			  {

 				tableEntry = new NetworkTableEntry(name, type, value);

 				if(addEntry(tableEntry))

 				{

@@ -123,7 +133,7 @@
 			}

 			else

 			{

-				tableEntry = namedEntries[name];

+				tableEntry = index->second;

 				if(tableEntry->GetType()->id != type->id){

 					throw TableKeyExistsWithDifferentTypeException(name, tableEntry->GetType());

 				}

@@ -155,7 +165,7 @@
 			NetworkTableEntry* tableEntry;

 			if(addEntry(entry)){

 				if(itr != namedEntries.end()){

-					tableEntry = namedEntries[entry->name];

+					tableEntry = itr->second;

 				}

 				else{

 					tableEntry = entry;

@@ -190,8 +200,8 @@
 			std::map<std::string, NetworkTableEntry*>::iterator itr;

 			for(itr = namedEntries.begin(); itr != namedEntries.end(); itr++)

 			{

-				NetworkTableEntry* entry = namedEntries[(*itr).first];//this may seem odd, but its so we get the address of the list element, rather than the copy stored in the itr

-				listener->ValueChanged(table, (*itr).first, entry->GetValue(), true);

+				NetworkTableEntry* entry = itr->second;

+				listener->ValueChanged(table, itr->first, entry->GetValue(), true);

 			}

 		}

 	}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/type/NumberArray.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/type/NumberArray.cpp
index cdc69e8..ad51905 100644
--- a/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/type/NumberArray.cpp
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/networktables2/type/NumberArray.cpp
@@ -16,7 +16,7 @@
 }

 

 double NumberArray::get(int index){

-	return _get(index).b;

+	return _get(index).f;

 }

 

 void NumberArray::set(int index, double value){