Index: Tekkotsu/Behaviors/Controller.h
diff -c Tekkotsu/Behaviors/Controller.h:1.26 Tekkotsu/Behaviors/Controller.h:1.27
*** Tekkotsu/Behaviors/Controller.h:1.26	Tue Jan 20 22:52:39 2004
--- Tekkotsu/Behaviors/Controller.h	Thu Feb  5 18:33:10 2004
***************
*** 56,63 ****
   *  - '<tt>close</tt>\n
   *    <i>text:instancename</i>' - calls <tt>close()</tt> on an object previously created by a <tt>load</tt> message.
   *    The Java object is expected to contain a function <tt>void close()</tt>.
!  *  - '<tt>goodbye</tt>\n
!  *    Indicates the connection is about to be closed purposefully, to differentiate from an accidental cut off.
   *  
   *  bool types are expected to be numerical values, 0 for false,
   *  non-zero for true.
--- 56,62 ----
   *  - '<tt>close</tt>\n
   *    <i>text:instancename</i>' - calls <tt>close()</tt> on an object previously created by a <tt>load</tt> message.
   *    The Java object is expected to contain a function <tt>void close()</tt>.
!  *  - '<tt>goodbye</tt>' - Indicates the connection is about to be closed purposefully, to differentiate from an accidental cut off.
   *  
   *  bool types are expected to be numerical values, 0 for false,
   *  non-zero for true.
***************
*** 204,213 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.26 $
   * $State: Exp $
!  * $Date: 2004/01/21 03:52:39 $
   */
  
  #endif
--- 203,212 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.27 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:10 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Controls/HelpControl.cc
diff -c Tekkotsu/Behaviors/Controls/HelpControl.cc:1.5 Tekkotsu/Behaviors/Controls/HelpControl.cc:1.6
*** Tekkotsu/Behaviors/Controls/HelpControl.cc:1.5	Mon Jan 19 17:03:58 2004
--- Tekkotsu/Behaviors/Controls/HelpControl.cc	Wed Jan 21 15:18:49 2004
***************
*** 33,38 ****
--- 33,39 ----
  	unsigned int numlen=1;
  	if(slots.size()>1)
  		numlen=(int)(log(slots.size()-1)/log(10))+1;
+ 	//sout->printf("<ol>\n");
  	for(unsigned int i=0; i<slots.size(); i++) {
  		if(slots[i]==NULL)
  			continue;
***************
*** 50,55 ****
--- 51,57 ----
  			fmt="\33[1m%s%*d. %s\33[0m: %s\n";
  		else
  			fmt="%s%*d. %s: %s\n";
+ 		//fmt="%s<li><!--%*d--><code><b>%s</b>: %s";
  		sout->printf(fmt,prefix.c_str(),numlen,i,nm.c_str(),desc.substr(0,len).c_str());
  		while(len<desc.size() && isspace(desc[len])) len++;
  		desc=desc.substr(len);
***************
*** 66,77 ****
--- 68,82 ----
  				if(len>desc.size())
  					len=desc.size();
  			}
+ 			//sout->printf("\n%s",desc.substr(0,len).c_str());
  			sout->printf("%s%s\n",std::string(prefix.size(),' ').c_str(),desc.substr(0,len).c_str());
  			while(len<desc.size() && isspace(desc[len])) len++;
  			desc=desc.substr(len);
  		}
+ 		//sout->printf("</code></li>\n");
  		report(slots[i],pre,depth_remain-1);
  	}
+ 	//sout->printf("</ol>\n");
  }
  
  /*! @file
***************
*** 79,87 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/01/19 22:03:58 $
   */
  
--- 84,92 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/01/21 20:18:49 $
   */
  
Index: Tekkotsu/Behaviors/Controls/PostureEditor.cc
diff -c Tekkotsu/Behaviors/Controls/PostureEditor.cc:1.2 Tekkotsu/Behaviors/Controls/PostureEditor.cc:1.3
*** Tekkotsu/Behaviors/Controls/PostureEditor.cc:1.2	Sun Jan 11 02:30:02 2004
--- Tekkotsu/Behaviors/Controls/PostureEditor.cc	Thu Jan 29 20:48:02 2004
***************
*** 49,55 ****
  		MMAccessor<PostureMC>(poseID)->LoadFile(loadPose->getLastInput().c_str());
  	} else if(lastSlot==savePose || savePose->getLastInput().size()>0) {
  		// we just got back from the save menu
! 		MMAccessor<PostureMC>(poseID)->SaveFile((config->motion.root+"/"+savePose->getLastInput()).c_str());
  		savePose->takeInput("");
  	}
  	lastSlot=NULL;
--- 49,55 ----
  		MMAccessor<PostureMC>(poseID)->LoadFile(loadPose->getLastInput().c_str());
  	} else if(lastSlot==savePose || savePose->getLastInput().size()>0) {
  		// we just got back from the save menu
! 		MMAccessor<PostureMC>(poseID)->SaveFile(config->motion.makePath(savePose->getLastInput()).c_str());
  		savePose->takeInput("");
  	}
  	lastSlot=NULL;
***************
*** 77,84 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.2 $
   * $State: Exp $
!  * $Date: 2004/01/11 07:30:02 $
   */
--- 77,84 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.3 $
   * $State: Exp $
!  * $Date: 2004/01/30 01:48:02 $
   */
Index: Tekkotsu/Behaviors/Controls/SavePostureControl.h
diff -c Tekkotsu/Behaviors/Controls/SavePostureControl.h:1.8 Tekkotsu/Behaviors/Controls/SavePostureControl.h:1.9
*** Tekkotsu/Behaviors/Controls/SavePostureControl.h:1.8	Thu Jan  8 17:39:55 2004
--- Tekkotsu/Behaviors/Controls/SavePostureControl.h	Thu Jan 29 20:29:41 2004
***************
*** 5,11 ****
  #include "StringInputControl.h"
  #include "Motion/PostureEngine.h"
  
! //! Upon activation, saves the current position to a file name read from user (stored in /ms/data/motion/...)
  class SavePostureControl : public StringInputControl {
   public:
  	//! Constructor
--- 5,11 ----
  #include "StringInputControl.h"
  #include "Motion/PostureEngine.h"
  
! //! Upon activation, saves the current position to a file name read from user (default is /ms/data/motion...)
  class SavePostureControl : public StringInputControl {
   public:
  	//! Constructor
***************
*** 16,25 ****
  	virtual ControlBase * takeInput(const std::string& msg) {
  		if(msg.size()>0) {
  			std::string filename;
! 			if(msg[0]=='/')
! 				filename=msg;
! 			else
! 				filename=config->motion.root+msg;
  			PostureEngine post;
  			post.takeSnapshot();
  			post.SaveFile(filename.c_str());
--- 16,22 ----
  	virtual ControlBase * takeInput(const std::string& msg) {
  		if(msg.size()>0) {
  			std::string filename;
! 			filename=config->motion.makePath(msg);
  			PostureEngine post;
  			post.takeSnapshot();
  			post.SaveFile(filename.c_str());
***************
*** 29,42 ****
  };
  
  /*! @file
!  * @brief Defines SavePostureControl, which when activated, saves the current position to a file name read from user (stored in /ms/data/motion/...)
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.8 $
   * $State: Exp $
!  * $Date: 2004/01/08 22:39:55 $
   */
  
  #endif
--- 26,39 ----
  };
  
  /*! @file
!  * @brief Defines SavePostureControl, which when activated, saves the current position to a file name read from user (default is /ms/data/motion...)
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.9 $
   * $State: Exp $
!  * $Date: 2004/01/30 01:29:41 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Demos/AlanBehavior.h
diff -c Tekkotsu/Behaviors/Demos/AlanBehavior.h:1.5 Tekkotsu/Behaviors/Demos/AlanBehavior.h:1.9
*** Tekkotsu/Behaviors/Demos/AlanBehavior.h:1.5	Tue Dec 23 01:33:42 2003
--- Tekkotsu/Behaviors/Demos/AlanBehavior.h	Thu Feb  5 23:06:50 2004
***************
*** 10,15 ****
--- 10,16 ----
  #include "Events/EventRouter.h"
  #include "Motion/PostureMC.h"
  #include "Shared/ERS210Info.h"
+ #include "Shared/ERS7Info.h"
  
  //! just a little demo behavior which lifts a leg higher as more pressure is put on a head button
  /*! Based on an idea from Alan Chun-ho Ho for a basic demo program */
***************
*** 26,32 ****
  		//now do your code:
  		
  		// creates a PostureMC class to move the joint(s) and adds it to global MotionManager
! 		pose_id=motman->addMotion(SharedObject<PostureMC>());
  		// subscribe to sensor updated events through the global EventRouter
  		erouter->addListener(this,EventBase::sensorEGID,SensorSourceID::UpdatedSID);
  	}
--- 27,33 ----
  		//now do your code:
  		
  		// creates a PostureMC class to move the joint(s) and adds it to global MotionManager
! 		pose_id=motman->addMotion(SharedObject<PostureMC>(),false);
  		// subscribe to sensor updated events through the global EventRouter
  		erouter->addListener(this,EventBase::sensorEGID,SensorSourceID::UpdatedSID);
  	}
***************
*** 43,52 ****
  	virtual void processEvent(const EventBase& event) {
  		// to be more general, let's check that it's the right event:
  		if(event.getGeneratorID()==EventBase::sensorEGID) {
- 			//only really works on the 210 model - the others don't have a proper pressure sensor
- 			//(the 220's antenna-thing is close, but doesn't give a continuous range)
- 			if( !(state->robotDesign&WorldState::ERS210Mask) )
- 				return;
  			//we'll need to specify the ERS210Info namespace below when
  			//referencing the button offsets so that this will compile for
  			//the ERS-7 as well (which lacks front and back head buttons),
--- 44,49 ----
***************
*** 57,69 ****
  			// (this is the PostureMC we created in DoStart())
  			MMAccessor<PostureMC> pose_mc(pose_id);
  			
! 			//Joint offsets are defined in ERS210Info.h, ERS220Info.h and ERS2xxInfo.h
  			unsigned int joint=LFrLegOffset+RotatorOffset;
  			
  			//state is a global instantiation of WorldState, kept up to date by framework;
  			//pressure is in range 0 to 1 - we use the pressure on the front head button here
! 			float pressure=state->buttons[ERS210Info::HeadFrButOffset];
! 			std::cout << "HeadFrBut Pressure: " << pressure << std::endl;
  			
  			//outputRanges is a constant table, also defined in ERS210Info.h or ERS220Info.h
  			float angle=outputRanges[joint][MaxRange]*pressure;
--- 54,78 ----
  			// (this is the PostureMC we created in DoStart())
  			MMAccessor<PostureMC> pose_mc(pose_id);
  			
! 			//Joint offsets are defined in ERS210Info.h, ERS220Info.h, ERS2xxInfo.h, and ERS7Info.h
  			unsigned int joint=LFrLegOffset+RotatorOffset;
  			
  			//state is a global instantiation of WorldState, kept up to date by framework;
  			//pressure is in range 0 to 1 - we use the pressure on the front head button here
! 			float pressure=0;
! 			if(state->robotDesign&WorldState::ERS210Mask) {
! 				pressure=state->buttons[ERS210Info::HeadFrButOffset];
! 				std::cout << "HeadFrBut Pressure: " << pressure << std::endl;
! 			} else if(state->robotDesign&WorldState::ERS7Mask) {
! 				pressure=state->buttons[ERS7Info::HeadButOffset];
! 				std::cout << "HeadBut Pressure: " << pressure << std::endl;
! 			} else {
! 				//only really works on the ERS-210 or ERS-7 models - the others don't have a proper pressure sensor
! 				//(the 220's antenna-thing is close, but doesn't give a continuous range)
! 				std::cout << "Unknown model" << std::endl;
! 				erouter->forgetListener(this); // stops getting events (and timers, if we had any)
! 				return;
! 			}
  			
  			//outputRanges is a constant table, also defined in ERS210Info.h or ERS220Info.h
  			float angle=outputRanges[joint][MaxRange]*pressure;
***************
*** 74,80 ****
  			//let's do the whole thing again with the other head button for the other leg:
  			// (cutting out a some of the intermediary steps this time)
  			joint=RFrLegOffset+RotatorOffset;
! 			pose_mc->setOutputCmd(joint,outputRanges[joint][MaxRange]*state->buttons[ERS210Info::HeadBkButOffset]);
  
  			// notice that there's no "check in" for pose_mc
  			// MMAccessor's destructor does this automatically
--- 83,92 ----
  			//let's do the whole thing again with the other head button for the other leg:
  			// (cutting out a some of the intermediary steps this time)
  			joint=RFrLegOffset+RotatorOffset;
! 			if(state->robotDesign&WorldState::ERS210Mask)
! 				pose_mc->setOutputCmd(joint,outputRanges[joint][MaxRange]*state->buttons[ERS210Info::HeadBkButOffset]);
! 			else if(state->robotDesign&WorldState::ERS7Mask) //ERS7 doesn't have another head button, we'll use one of its back buttons
! 				pose_mc->setOutputCmd(joint,outputRanges[joint][MaxRange]*state->buttons[ERS7Info::FrontBackButOffset]);
  
  			// notice that there's no "check in" for pose_mc
  			// MMAccessor's destructor does this automatically
***************
*** 104,113 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2003/12/23 06:33:42 $
   */
  
  #endif
--- 116,125 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.9 $
   * $State: Exp $
!  * $Date: 2004/02/06 04:06:50 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Demos/CameraBehavior.cc
diff -c Tekkotsu/Behaviors/Demos/CameraBehavior.cc:1.2 Tekkotsu/Behaviors/Demos/CameraBehavior.cc:1.4
*** Tekkotsu/Behaviors/Demos/CameraBehavior.cc:1.2	Tue Jan 20 23:49:56 2004
--- Tekkotsu/Behaviors/Demos/CameraBehavior.cc	Thu Feb  5 18:33:27 2004
***************
*** 8,15 ****
--- 8,19 ----
  #include "SoundPlay/SoundManager.h"
  #include "Shared/Config.h"
  #include "Shared/ProjectInterface.h"
+ #include "Motion/LedMC.h"
+ #include "Motion/MMAccessor.h"
  
  #include "Vision/FilterBankGenerator.h"
+ #include "Vision/RawCameraGenerator.h"
+ #include "Vision/InterleavedYUVGenerator.h"
  #include "Vision/JPEGGenerator.h"
  
  #include <sys/types.h>
***************
*** 29,40 ****
--- 33,46 ----
  	}
  	initIndex();
  	sndman->LoadFile("camera.wav");
+ 	ledID=motman->addMotion(SharedObject<LedMC>());
  	erouter->addListener(this,camera_click);
  }
  
  void CameraBehavior::DoStop() {
  	erouter->forgetListener(this);
  	sndman->ReleaseFile("camera.wav");
+ 	motman->removeMotion(ledID);
  	BehaviorBase::DoStop();
  }
  
***************
*** 47,55 ****
  CameraBehavior::processEvent(const EventBase& e) {
  	if(e.shorterThan(camera_click))
  		return;
  	if(config->vision.rawcam_compression==Config::vision_config::COMPRESS_NONE) {
  		//this is our own odd little format, would be nice to save a TIFF or something instead
- 		FilterBankGenerator * gen=ProjectInterface::defRawCameraGenerator; // just an alias for readability
  
  		// open file
  		FILE * f=openNextFile(".raw");
--- 53,67 ----
  CameraBehavior::processEvent(const EventBase& e) {
  	if(e.shorterThan(camera_click))
  		return;
+ 
+ 	{
+ 		MMAccessor<LedMC> leds(ledID);
+ 		leds->cset(FaceLEDMask,2.0/3.0);
+ 		leds->set(TopBrLEDMask,1);
+ 	}
+ 
  	if(config->vision.rawcam_compression==Config::vision_config::COMPRESS_NONE) {
  		//this is our own odd little format, would be nice to save a TIFF or something instead
  
  		// open file
  		FILE * f=openNextFile(".raw");
***************
*** 58,75 ****
  
  		//! write actual image data
  		if(config->vision.rawcam_encoding==Config::vision_config::ENCODE_COLOR) {
! 			for(unsigned int chan=0; chan<3; chan++) {
! 				gen->selectSaveImage(ProjectInterface::doubleLayer,chan);
! 				unsigned int len=gen->SaveFile(f);
! 				if(len==0) {
! 					serr->printf("Error saving file\n");
! 					sndman->PlayFile(config->controller.error_snd);
! 					return;
! 				}
  			}
  		} else if(config->vision.rawcam_encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
  			gen->selectSaveImage(ProjectInterface::doubleLayer,config->vision.rawcam_channel);
! 			unsigned int len=gen->SaveFile(f);
  			if(len==0) {
  				serr->printf("Error saving file\n");
  				sndman->PlayFile(config->controller.error_snd);
--- 70,87 ----
  
  		//! write actual image data
  		if(config->vision.rawcam_encoding==Config::vision_config::ENCODE_COLOR) {
! 			FilterBankGenerator * gen=ProjectInterface::defInterleavedYUVGenerator; // just an alias for readability
! 			gen->selectSaveImage(ProjectInterface::doubleLayer,InterleavedYUVGenerator::CHAN_YUV);
! 			unsigned int len=gen->SaveFileStream(f);
! 			if(len==0) {
! 				serr->printf("Error saving file\n");
! 				sndman->PlayFile(config->controller.error_snd);
! 				return;
  			}
  		} else if(config->vision.rawcam_encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL) {
+ 			FilterBankGenerator * gen=ProjectInterface::defRawCameraGenerator; // just an alias for readability
  			gen->selectSaveImage(ProjectInterface::doubleLayer,config->vision.rawcam_channel);
! 			unsigned int len=gen->SaveFileStream(f);
  			if(len==0) {
  				serr->printf("Error saving file\n");
  				sndman->PlayFile(config->controller.error_snd);
***************
*** 114,119 ****
--- 126,142 ----
  			jpeg->setQuality(tmp_q);
  		}
  	}
+ 
+ 
+ 	{
+ 		MMAccessor<LedMC> leds(ledID);
+ 		leds->clear();
+ 		leds->flash(TopBrLEDMask,700);
+ 		leds->flash(TopLLEDMask|TopRLEDMask,500);
+ 		leds->flash(MidLLEDMask|MidRLEDMask,300);
+ 		leds->flash(BotLLEDMask|BotRLEDMask,100);
+ 	}
+ 
  	sout->printf("done\n");
  }
  
***************
*** 173,181 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.2 $
   * $State: Exp $
!  * $Date: 2004/01/21 04:49:56 $
   */
  
--- 196,204 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:27 $
   */
  
Index: Tekkotsu/Behaviors/Demos/CameraBehavior.h
diff -c Tekkotsu/Behaviors/Demos/CameraBehavior.h:1.6 Tekkotsu/Behaviors/Demos/CameraBehavior.h:1.7
*** Tekkotsu/Behaviors/Demos/CameraBehavior.h:1.6	Mon Jan 19 02:55:27 2004
--- Tekkotsu/Behaviors/Demos/CameraBehavior.h	Mon Feb  2 20:16:32 2004
***************
*** 3,12 ****
  #define INCLUDED_CameraBehavior_h_
  
  #include "Behaviors/BehaviorBase.h"
  
  //! Will take images and write to log file
  /*! Press the head button to take a picture, back button to write to memory
!  *  stick.
   *
   *  The reason for this is to provide sample code for accessing vision
   *  data, and also simply because we should have a way to save
--- 3,13 ----
  #define INCLUDED_CameraBehavior_h_
  
  #include "Behaviors/BehaviorBase.h"
+ #include "Motion/MotionManager.h"
  
  //! Will take images and write to log file
  /*! Press the head button to take a picture, back button to write to memory
!  *  stick.  The leds will flash when finished writing.
   *
   *  The reason for this is to provide sample code for accessing vision
   *  data, and also simply because we should have a way to save
***************
*** 23,29 ****
   public:
  	//! constructor, just sets up the variables
  	CameraBehavior()
! 		: BehaviorBase(), camera_click(EventBase::buttonEGID,0,EventBase::deactivateETID,150), index(0)
  	{}
  
  	//! Register for events
--- 24,30 ----
   public:
  	//! constructor, just sets up the variables
  	CameraBehavior()
! 		: BehaviorBase(), camera_click(EventBase::buttonEGID,0,EventBase::deactivateETID,150), index(0), ledID(MotionManager::invalid_MC_ID)
  	{}
  
  	//! Register for events
***************
*** 49,54 ****
--- 50,57 ----
  
  	EventBase camera_click; //!< event mask for taking a picture (head button)
  	unsigned int index; //!< the index to use for the next image saved
+ 	
+ 	MotionManager::MC_ID ledID; //!< the id of the LedMC used to signal completion
  };
  
  /*! @file
***************
*** 57,66 ****
   * @author ejt (rewrite for new vision system)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/01/19 07:55:27 $
   */
  
  #endif
--- 60,69 ----
   * @author ejt (rewrite for new vision system)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.7 $
   * $State: Exp $
!  * $Date: 2004/02/03 01:16:32 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc
diff -c Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc:1.3 Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc:1.4
*** Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc:1.3	Mon Jan 19 14:43:50 2004
--- Tekkotsu/Behaviors/Mon/HeadPointControllerBehavior.cc	Wed Feb  4 20:51:39 2004
***************
*** 20,32 ****
  	// Find out what type of command this is
  	switch(command[0]) {
  	case CMD_tilt:
! 		t = param*outputRanges[HeadOffset+TiltOffset][param>0?MaxRange:MinRange];
  		break;
  	case CMD_pan:
! 		p = param*outputRanges[HeadOffset+PanOffset][param>0?MaxRange:MinRange];
  		break;
  	case CMD_roll:
! 		r = param*outputRanges[HeadOffset+RollOffset][param>0?MaxRange:MinRange];
  		break;
  	default:
  		cout << "MECHA: unknown command " << command[0] << endl;
--- 20,32 ----
  	// Find out what type of command this is
  	switch(command[0]) {
  	case CMD_tilt:
! 		t = fabs(param)*outputRanges[HeadOffset+TiltOffset][param>0?MaxRange:MinRange];
  		break;
  	case CMD_pan:
! 		p = fabs(param)*outputRanges[HeadOffset+PanOffset][param>0?MaxRange:MinRange];
  		break;
  	case CMD_roll:
! 		r = fabs(param)*outputRanges[HeadOffset+RollOffset][param>0?MaxRange:MinRange];
  		break;
  	default:
  		cout << "MECHA: unknown command " << command[0] << endl;
***************
*** 123,131 ****
   * @author tss (Creator)
   * 
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.3 $
   * $State: Exp $
!  * $Date: 2004/01/19 19:43:50 $
   */
  
--- 123,131 ----
   * @author tss (Creator)
   * 
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/02/05 01:51:39 $
   */
  
Index: Tekkotsu/Behaviors/Mon/RawCamBehavior.cc
diff -c Tekkotsu/Behaviors/Mon/RawCamBehavior.cc:1.8 Tekkotsu/Behaviors/Mon/RawCamBehavior.cc:1.10
*** Tekkotsu/Behaviors/Mon/RawCamBehavior.cc:1.8	Wed Jan  7 17:51:49 2004
--- Tekkotsu/Behaviors/Mon/RawCamBehavior.cc	Thu Feb  5 14:11:26 2004
***************
*** 1,7 ****
  #include "RawCamBehavior.h"
  #include "Wireless/Wireless.h"
  #include "Events/EventRouter.h"
- #include "Shared/Config.h"
  #include "Vision/RawCameraGenerator.h"
  #include "Vision/JPEGGenerator.h"
  #include "Events/FilterBankEvent.h"
--- 1,6 ----
***************
*** 19,28 ****
    wireless->setDaemon(visRaw,true);
    wireless->listen(visRaw,config->vision.rawcam_port);
  	
! 	//we're going to make the ControllerGUI open these itself...
! 	//std::vector<std::string> args;
! 	//args.push_back("raw");
! 	//Controller::loadGUI("org.tekkotsu.mon.VisionGUI","RawVisionGUI",config->vision.rawcam_port,args);
  
  	erouter->addListener(this,EventBase::visRawCameraEGID,ProjectInterface::visRawCameraSID);
  	erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visColorJPEGSID);
--- 18,24 ----
    wireless->setDaemon(visRaw,true);
    wireless->listen(visRaw,config->vision.rawcam_port);
  	
! 	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","RawVisionGUI",config->vision.rawcam_port);
  
  	erouter->addListener(this,EventBase::visRawCameraEGID,ProjectInterface::visRawCameraSID);
  	erouter->addListener(this,EventBase::visJPEGEGID,ProjectInterface::visColorJPEGSID);
***************
*** 32,38 ****
  void
  RawCamBehavior::DoStop() {
  	erouter->forgetListener(this);
! 	//Controller::closeGUI("RawVisionGUI");
  
  	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
  	// it will try to listen again even though we explicitly closed the server socket...
--- 28,34 ----
  void
  RawCamBehavior::DoStop() {
  	erouter->forgetListener(this);
! 	Controller::closeGUI("RawVisionGUI");
  
  	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
  	// it will try to listen again even though we explicitly closed the server socket...
***************
*** 272,280 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.8 $
   * $State: Exp $
!  * $Date: 2004/01/07 22:51:49 $
   */
  
--- 268,276 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.10 $
   * $State: Exp $
!  * $Date: 2004/02/05 19:11:26 $
   */
  
Index: Tekkotsu/Behaviors/Mon/RawCamBehavior.h
diff -c Tekkotsu/Behaviors/Mon/RawCamBehavior.h:1.6 Tekkotsu/Behaviors/Mon/RawCamBehavior.h:1.8
*** Tekkotsu/Behaviors/Mon/RawCamBehavior.h:1.6	Sun Jan 18 05:16:57 2004
--- Tekkotsu/Behaviors/Mon/RawCamBehavior.h	Thu Feb  5 18:33:41 2004
***************
*** 3,14 ****
--- 3,33 ----
  #define INCLUDED_RawCamBehavior_h_
  
  #include "Behaviors/BehaviorBase.h"
+ #include "Shared/Config.h"
  
  class Socket;
  class FilterBankGenerator;
  class FilterBankEvent;
  
  //! Forwards images from camera over wireless
+ /*! The format used for serialization is basically defined by the
+  *  subclass of FilterBankGenerator being used.  I suggest looking at
+  *  that classes's documentation to determine the format used.
+  *
+  *  However, RawCamBehavior will add a few fields at the beginning of
+  *  each packet to assist in processing the image stream.
+  *
+  *  I emphasize: <i>beginning</i> of each Vision packet, <i>before</i> the FilterBankGenerator header. 
+  *  - <@c string:"TekkotsuImage">
+  *  - <<tt>Config::vision_config::encoding_t</tt>: rawcam_encoding> <i>(expect single or multiple channels, 0 means color (3 channels), 1 means intensity (1 channel))</i>
+  *  - <<tt>Config::vision_config::compression_t</tt>: rawcam_compression> <i>(0==none, 1==jpeg, 2==rle)</i>
+  *  - <@c unsigned @c int: width> <i>(this is the width of the largest channel - note different channels can be sent at different resolutions!  Provides cheap "compression" of chromaticity channels)</i>
+  *  - <@c unsigned @c int: height> <i>(similarly, height of largest channel)</i>
+  *  - <@c unsigned @c int: timestamp> <i>(time image was taken, milliseconds since boot)</i>
+  *  - <@c unsigned @c int: framenumber> <i>(incremented for each frame, so we can tell if/when we drop one)</i>
+  *
+  *  This is exactly the same protocol that is followed by the SegCamBehavior as well - the same code can parse either stream.
+  */ 
  class RawCamBehavior : public BehaviorBase {
  public:
  	//! constructor
***************
*** 24,33 ****
  
  	virtual std::string getName() const { return "RawCamServer"; }
  
! 	static std::string getClassDescription() { return "Forwards images from camera over wireless"; }
  	
  protected:
! 	bool openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer); //!< opens a new packet, writes header info; returns true if open, false if otherwise open (check cur==NULL for error)
  	bool writeColor(const FilterBankEvent& fbke); //!< writes a color image
  	bool writeSingleChannel(const FilterBankEvent& fbke); //!< writes a single channel
  	void closePacket(); //!< closes and sends a packet, does nothing if no packet open
--- 43,58 ----
  
  	virtual std::string getName() const { return "RawCamServer"; }
  
! 	static std::string getClassDescription() {
! 		char tmp[20];
! 		sprintf(tmp,"%d",config->vision.rle_port);
! 		return std::string("Forwards images from camera over port ")+tmp;
! 	}
  	
  protected:
! 	//! opens a new packet, writes header info; returns true if open, false if otherwise open (check cur==NULL for error)
! 	/*! see the class documentation for RawCamBehavior for the protocol documentation */
! 	bool openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer);
  	bool writeColor(const FilterBankEvent& fbke); //!< writes a color image
  	bool writeSingleChannel(const FilterBankEvent& fbke); //!< writes a single channel
  	void closePacket(); //!< closes and sends a packet, does nothing if no packet open
***************
*** 47,56 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:57 $
   */
  
  #endif
--- 72,81 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.8 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:41 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Mon/SegCamBehavior.cc
diff -c Tekkotsu/Behaviors/Mon/SegCamBehavior.cc:1.4 Tekkotsu/Behaviors/Mon/SegCamBehavior.cc:1.6
*** Tekkotsu/Behaviors/Mon/SegCamBehavior.cc:1.4	Wed Jan  7 17:51:49 2004
--- Tekkotsu/Behaviors/Mon/SegCamBehavior.cc	Thu Feb  5 14:11:26 2004
***************
*** 1,7 ****
  #include "SegCamBehavior.h"
  #include "Wireless/Wireless.h"
  #include "Events/EventRouter.h"
- #include "Shared/Config.h"
  #include "Events/FilterBankEvent.h"
  #include "Behaviors/Controller.h"
  #include "Shared/ProjectInterface.h"
--- 1,6 ----
***************
*** 20,29 ****
    wireless->setDaemon(visRLE,true);
    wireless->listen(visRLE,config->vision.rle_port);
  
! 	//we're going to make the ControllerGUI open these itself...
! 	//std::vector<std::string> args;
! 	//args.push_back("raw");
! 	//Controller::loadGUI("org.tekkotsu.mon.VisionGUI","SegVisionGUI",config->vision.rle_port,args);
  
  	erouter->addListener(this,EventBase::visSegmentEGID,ProjectInterface::visSegmentSID);
  	erouter->addListener(this,EventBase::visRLEEGID,ProjectInterface::visRLESID);
--- 19,25 ----
    wireless->setDaemon(visRLE,true);
    wireless->listen(visRLE,config->vision.rle_port);
  
! 	Controller::loadGUI("org.tekkotsu.mon.VisionGUI","SegVisionGUI",config->vision.rle_port);
  
  	erouter->addListener(this,EventBase::visSegmentEGID,ProjectInterface::visSegmentSID);
  	erouter->addListener(this,EventBase::visRLEEGID,ProjectInterface::visRLESID);
***************
*** 32,38 ****
  void
  SegCamBehavior::DoStop() {
  	erouter->forgetListener(this);
! 	//Controller::closeGUI("SegVisionGUI");
  
  	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
  	// it will try to listen again even though we explicitly closed the server socket...
--- 28,34 ----
  void
  SegCamBehavior::DoStop() {
  	erouter->forgetListener(this);
! 	Controller::closeGUI("SegVisionGUI");
  
  	// this could be considered a bug in our wireless - if we don't setDaemon(...,false)
  	// it will try to listen again even though we explicitly closed the server socket...
***************
*** 158,166 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/01/07 22:51:49 $
   */
  
--- 154,162 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/02/05 19:11:26 $
   */
  
Index: Tekkotsu/Behaviors/Mon/SegCamBehavior.h
diff -c Tekkotsu/Behaviors/Mon/SegCamBehavior.h:1.3 Tekkotsu/Behaviors/Mon/SegCamBehavior.h:1.5
*** Tekkotsu/Behaviors/Mon/SegCamBehavior.h:1.3	Sun Jan 18 05:16:57 2004
--- Tekkotsu/Behaviors/Mon/SegCamBehavior.h	Thu Feb  5 18:33:41 2004
***************
*** 3,14 ****
--- 3,44 ----
  #define INCLUDED_SegCamBehavior_h_
  
  #include "Behaviors/BehaviorBase.h"
+ #include "Shared/Config.h"
  
  class Socket;
  class FilterBankGenerator;
  class FilterBankEvent;
  
  //! Forwards segmented images from camera over wireless
+ /*! The format used for serialization is basically defined by the
+  *  subclass of FilterBankGenerator being used.  I suggest looking at
+  *  that classes's documentation to determine the format used.
+  *
+  *  However, SegCamBehavior will add a few fields at the beginning of
+  *  each packet to assist in processing the image stream.
+  *
+  *  I emphasize: <i>beginning</i> of each Vision packet, <i>before</i> the FilterBankGenerator header. 
+  *  - <@c string:"TekkotsuImage">
+  *  - <<tt>Config::vision_config::encoding_t</tt>: Config::vision_config::ENCODE_SINGLE_CHANNEL> <i>(always just sends a single channel)</i>
+  *  - <<tt>Config::vision_config::compression_t</tt>: Config::vision_config::COMPRESS_RLE> <i>(This is misleading - may actually be uncompressed, but this signals it's a segmented color image)</i>
+  *  - <@c unsigned @c int: width> <i>(this is the width of the largest channel - note different channels can be sent at different resolutions!  Provides cheap "compression" of chromaticity channels)</i>
+  *  - <@c unsigned @c int: height> <i>(similarly, height of largest channel)</i>
+  *  - <@c unsigned @c int: timestamp> <i>(time image was taken, milliseconds since boot)</i>
+  *  - <@c unsigned @c int: framenumber> <i>(incremented for each frame, so we can tell if/when we drop one)</i>
+  *
+  *  This is exactly the same protocol that is followed by the
+  *  RawCamBehavior as well - the same code can parse either stream.
+  *
+  *  However, odd bit - since the RLEGenerator doesn't save the color
+  *  information itself, SegCamBehavior will do it instead.  So, if
+  *  SegCamBehavior is using RLE compression, it will tack a footer at
+  *  the end of the packet: (from SegmentedColorGenerator::encodeColors())
+  *  - <@c unsigned @c int: num_cols> <i>(number of different colors available)</i>
+  *  - for each of num_col:
+  *    - <@c char: red> <i>red color to use for display of this index</i>
+  *    - <@c char: green> <i>green color to use for display of this index</i>
+  *    - <@c char: blue> <i>blue color to use for display of this index</i>
+  */ 
  class SegCamBehavior : public BehaviorBase {
  public:
  	//! constructor
***************
*** 24,33 ****
  
  	virtual std::string getName() const { return "SegCamServer"; }
  
! 	static std::string getClassDescription() { return "Forwards segmented images from camera over wireless"; }
  	
  protected:
! 	bool openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer); //!< opens a new packet, writes header info; returns true if open, false if otherwise open (check cur==NULL for error)
  	bool writeRLE(const FilterBankEvent& fbke); //!< writes a color image
  	bool writeSeg(const FilterBankEvent& fbke); //!< writes a color image
  	void closePacket(); //!< closes and sends a packet, does nothing if no packet open
--- 54,69 ----
  
  	virtual std::string getName() const { return "SegCamServer"; }
  
! 	static std::string getClassDescription() {
! 		char tmp[20];
! 		sprintf(tmp,"%d",config->vision.rle_port);
! 		return std::string("Forwards segmented images from camera over port ")+tmp;
! 	}
  	
  protected:
! 	//! opens a new packet, writes header info; returns true if open, false if otherwise open (check cur==NULL for error)
! 	/*! see the class documentation for SegCamBehavior for the protocol documentation */
! 	bool openPacket(FilterBankGenerator& fbkgen, unsigned int time, unsigned int layer); 
  	bool writeRLE(const FilterBankEvent& fbke); //!< writes a color image
  	bool writeSeg(const FilterBankEvent& fbke); //!< writes a color image
  	void closePacket(); //!< closes and sends a packet, does nothing if no packet open
***************
*** 47,56 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.3 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:57 $
   */
  
  #endif
--- 83,92 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:41 $
   */
  
  #endif
Index: Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc
diff -c Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc:1.1 Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc:1.2
*** Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc:1.1	Mon Jan 19 15:37:29 2004
--- Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.cc	Sat Jan 24 16:28:50 2004
***************
*** 34,40 ****
      wsPIDs->write((NumPIDJoints*3)*sizeof(float)+2*sizeof(unsigned int));
    }
    
!   buf=(char*)wsJoints->getWriteBuffer((NumPIDJoints*2+NumSensors+NumButtons)*sizeof(float)+3*sizeof(unsigned int));
    if (buf) {
      encode(&buf,state->lastSensorUpdateTime);
  		encode(&buf,NumPIDJoints);
--- 34,40 ----
      wsPIDs->write((NumPIDJoints*3)*sizeof(float)+2*sizeof(unsigned int));
    }
    
!   buf=(char*)wsJoints->getWriteBuffer((NumPIDJoints*2+NumSensors+NumButtons)*sizeof(float)+4*sizeof(unsigned int));
    if (buf) {
      encode(&buf,state->lastSensorUpdateTime);
  		encode(&buf,NumPIDJoints);
***************
*** 44,50 ****
  		encode(&buf,NumButtons);
      encode(&buf,state->buttons,NumButtons);
      encode(&buf,state->pidduties,NumPIDJoints);
!     wsJoints->write((NumPIDJoints*2+NumSensors+NumButtons)*sizeof(float)+3*sizeof(unsigned int));
    }
  }
  
--- 44,50 ----
  		encode(&buf,NumButtons);
      encode(&buf,state->buttons,NumButtons);
      encode(&buf,state->pidduties,NumPIDJoints);
!     wsJoints->write((NumPIDJoints*2+NumSensors+NumButtons)*sizeof(float)+4*sizeof(unsigned int));
    }
  }
  
***************
*** 53,60 ****
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.1 $
   * $State: Exp $
!  * $Date: 2004/01/19 20:37:29 $
   */
--- 53,60 ----
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.2 $
   * $State: Exp $
!  * $Date: 2004/01/24 21:28:50 $
   */
Index: Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.h
diff -c Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.h:1.1 Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.h:1.2
*** Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.h:1.1	Mon Jan 19 15:37:29 2004
--- Tekkotsu/Behaviors/Mon/WorldStateSerializerBehavior.h	Thu Feb  5 18:33:41 2004
***************
*** 9,15 ****
  
  //! Copies WorldState into a buffer for transmission over the network
  /*! To determine the communication protocol, just look in the
!  *  processEvent() function - it's pretty straightforward. */
  class WorldStateSerializerBehavior : public BehaviorBase {
  public:
    WorldStateSerializerBehavior(); //!< constructor
--- 9,16 ----
  
  //! Copies WorldState into a buffer for transmission over the network
  /*! To determine the communication protocol, just look in the
!  *  processEvent() function - it's pretty straightforward binary copy
!  *  of values */
  class WorldStateSerializerBehavior : public BehaviorBase {
  public:
    WorldStateSerializerBehavior(); //!< constructor
***************
*** 54,63 ****
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.1 $
   * $State: Exp $
!  * $Date: 2004/01/19 20:37:29 $
   */
  
  #endif
--- 55,64 ----
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.2 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:41 $
   */
  
  #endif
Index: Tekkotsu/MMCombo/MMCombo.cc
diff -c Tekkotsu/MMCombo/MMCombo.cc:1.48 Tekkotsu/MMCombo/MMCombo.cc:1.49
*** Tekkotsu/MMCombo/MMCombo.cc:1.48	Mon Jan 19 15:35:45 2004
--- Tekkotsu/MMCombo/MMCombo.cc	Mon Feb  2 15:55:50 2004
***************
*** 387,393 ****
  			// for instance, this virtual mode thing, which is global to all the affected LEDs
  			OLED3Mode curMode[NumFrames];
  			for(unsigned int frame=0; frame<NumFrames; frame++)
! 				curMode[frame]=(calcLEDValue(ERS7Info::LEDABModeOffset-LEDOffset,outputs[frame][ERS7Info::LEDABModeOffset])==oledON?oled3_MODE_B:oled3_MODE_A);
  			for(unsigned int i=ERS7Info::FaceLEDPanelOffset; i<LEDOffset+NumLEDs; i++)
  				if(open[i]) {
  					OLEDCommandValue3* jval = reinterpret_cast<OLEDCommandValue3*>(cmdVecData->GetData(used)->value);
--- 387,393 ----
  			// for instance, this virtual mode thing, which is global to all the affected LEDs
  			OLED3Mode curMode[NumFrames];
  			for(unsigned int frame=0; frame<NumFrames; frame++)
! 				curMode[frame]=(calcLEDValue(ERS7Info::LEDABModeOffset-LEDOffset,sqrt(clipRange01(outputs[frame][ERS7Info::LEDABModeOffset])))==oledON?oled3_MODE_B:oled3_MODE_A);
  			for(unsigned int i=ERS7Info::FaceLEDPanelOffset; i<LEDOffset+NumLEDs; i++)
  				if(open[i]) {
  					OLEDCommandValue3* jval = reinterpret_cast<OLEDCommandValue3*>(cmdVecData->GetData(used)->value);
***************
*** 730,739 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.48 $
   * $State: Exp $
!  * $Date: 2004/01/19 20:35:45 $
   */
  
  
--- 730,739 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.49 $
   * $State: Exp $
!  * $Date: 2004/02/02 20:55:50 $
   */
  
  
Index: Tekkotsu/MMCombo/MMCombo.h
diff -c Tekkotsu/MMCombo/MMCombo.h:1.24 Tekkotsu/MMCombo/MMCombo.h:1.25
*** Tekkotsu/MMCombo/MMCombo.h:1.24	Sun Jan 18 05:16:57 2004
--- Tekkotsu/MMCombo/MMCombo.h	Mon Feb  2 20:17:24 2004
***************
*** 102,107 ****
--- 102,108 ----
  	//! Motion only, maintains the activation level of the LEDs, returns whether it should be 'fired'
  	inline OLEDValue calcLEDValue(unsigned int i,float x) {
  		if(x<=0.0) {
+ 			ledActivation[i]*=.9; //decay activation... resets to keeps LEDs in sync, looks a little better
  			return oledOFF;
  		} else if(x>=1.0) {
  			return oledON;
***************
*** 137,146 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.24 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:57 $
   */
  
  #endif
--- 138,147 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.25 $
   * $State: Exp $
!  * $Date: 2004/02/03 01:17:24 $
   */
  
  #endif
Index: Tekkotsu/Motion/LedEngine.cc
diff -c Tekkotsu/Motion/LedEngine.cc:1.11 Tekkotsu/Motion/LedEngine.cc:1.12
*** Tekkotsu/Motion/LedEngine.cc:1.11	Fri Jan 16 18:55:19 2004
--- Tekkotsu/Motion/LedEngine.cc	Mon Feb  2 20:17:57 2004
***************
*** 140,154 ****
  	}
  }
  void LedEngine::cflash(LEDBitMask_t leds, float value, unsigned int ms) {
  	if(leds!=0) {
  		dirty=true;
  		unsigned int t = get_time();
  		if(t+ms<dirtyTime)
  			dirtyTime=t+ms;
! 		for(unsigned int i=0; i<NumLEDs; i++) {
! 			infos[i].flashvalue=((leds>>i)&1)*value;
! 			infos[i].flashtime=t+ms;
! 		}
  	}
  }
  void LedEngine::flash(LEDBitMask_t leds, unsigned int ms) {
--- 140,165 ----
  	}
  }
  void LedEngine::cflash(LEDBitMask_t leds, float value, unsigned int ms) {
+ 	dirty=true;
+ 	unsigned int t = get_time();
+ 	if(t+ms<dirtyTime)
+ 		dirtyTime=t+ms;
+ 	for(unsigned int i=0; i<NumLEDs; i++) {
+ 		infos[i].flashvalue=((leds>>i)&1)*value;
+ 		infos[i].flashtime=t+ms;
+ 	}
+ }
+ void LedEngine::flash(LEDBitMask_t leds, float value, unsigned int ms) {
  	if(leds!=0) {
  		dirty=true;
  		unsigned int t = get_time();
  		if(t+ms<dirtyTime)
  			dirtyTime=t+ms;
! 		for(unsigned int i=0; i<NumLEDs; i++)
! 			if((leds>>i)&1) {
! 				infos[i].flashvalue=value;
! 				infos[i].flashtime=t+ms;
! 			}
  	}
  }
  void LedEngine::flash(LEDBitMask_t leds, unsigned int ms) {
***************
*** 322,329 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.11 $
   * $State: Exp $
!  * $Date: 2004/01/16 23:55:19 $
   */
--- 333,340 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.12 $
   * $State: Exp $
!  * $Date: 2004/02/03 01:17:57 $
   */
Index: Tekkotsu/Motion/LedEngine.h
diff -c Tekkotsu/Motion/LedEngine.h:1.11 Tekkotsu/Motion/LedEngine.h:1.12
*** Tekkotsu/Motion/LedEngine.h:1.11	Tue Dec 23 01:33:42 2003
--- Tekkotsu/Motion/LedEngine.h	Mon Feb  2 20:17:57 2004
***************
*** 60,66 ****
  	//!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.  Clears ~leds
  	void cflash(LEDBitMask_t leds, float value, unsigned int ms);
  	//!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.
! 	void flash(LEDBitMask_t leds, unsigned int ms=500);
  	//!causes the leds specified by @a leds to cycle between low and high, clears others.  See cycle() for parameter documentation.
  	inline void ccycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0) { clear(); cycle(leds,period,amp,offset,phase); }
  	//!causes the leds specified by @a leds to cycle between low and high
--- 60,68 ----
  	//!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.  Clears ~leds
  	void cflash(LEDBitMask_t leds, float value, unsigned int ms);
  	//!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.
! 	void flash(LEDBitMask_t leds, float value, unsigned int ms);
! 	//!sets the leds specified by @a leds to either a much higher or much lower value for @a ms milliseconds, then sets back.
! 	void flash(LEDBitMask_t leds, unsigned int ms);
  	//!causes the leds specified by @a leds to cycle between low and high, clears others.  See cycle() for parameter documentation.
  	inline void ccycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0) { clear(); cycle(leds,period,amp,offset,phase); }
  	//!causes the leds specified by @a leds to cycle between low and high
***************
*** 161,170 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.11 $
   * $State: Exp $
!  * $Date: 2003/12/23 06:33:42 $
   */
  
  #endif
--- 163,172 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.12 $
   * $State: Exp $
!  * $Date: 2004/02/03 01:17:57 $
   */
  
  #endif
Index: Tekkotsu/Motion/PostureMC.h
diff -c Tekkotsu/Motion/PostureMC.h:1.5 Tekkotsu/Motion/PostureMC.h:1.6
*** Tekkotsu/Motion/PostureMC.h:1.5	Mon Jan  5 20:01:50 2004
--- Tekkotsu/Motion/PostureMC.h	Thu Feb  5 23:07:12 2004
***************
*** 7,12 ****
--- 7,18 ----
  #include "MotionManager.h"
  
  //! a MotionCommand shell for PostureEngine
+ /*! Will autoprune by default once it reaches the target pose.
+  * 
+  *  If you want to keep it alive so your behavior can use the posture
+  *  to move around, either call setAutoPrune(@c false), or pass
+  *  @c false to the MotionManager::addMotion() function.
+  */
  class PostureMC : public MotionCommand, public PostureEngine {
  public:
  	//!constructor
***************
*** 81,90 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/01/06 01:01:50 $
   */
  
  #endif
--- 87,96 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/02/06 04:07:12 $
   */
  
  #endif
Index: Tekkotsu/Shared/Config.h
diff -c Tekkotsu/Shared/Config.h:1.27 Tekkotsu/Shared/Config.h:1.28
*** Tekkotsu/Shared/Config.h:1.27	Tue Jan 20 22:31:08 2004
--- Tekkotsu/Shared/Config.h	Thu Jan 29 20:30:07 2004
***************
*** 136,142 ****
  
  		//!returns an absolute path if @a is relative (to root), otherwise just @a name
  		std::string makePath(std::string name) { 
! 			return (name[0]!='/')?root+"/"+name:name;
  		}
  
  		//!constructor
--- 136,147 ----
  
  		//!returns an absolute path if @a is relative (to root), otherwise just @a name
  		std::string makePath(std::string name) { 
! 			if(name[0]=='/')
! 				return name;
! 			if(root[root.size()-1]=='/')
! 				return root+name;
! 			else
! 				return root+"/"+name;
  		}
  
  		//!constructor
***************
*** 168,174 ****
  			
  		//!returns an absolute path if @a is relative (to root), otherwise just @a name
  		std::string makePath(std::string name) { 
! 			return (name[0]!='/')?root+"/"+name:name;
  		}
  
  		//!constructor
--- 173,184 ----
  			
  		//!returns an absolute path if @a is relative (to root), otherwise just @a name
  		std::string makePath(std::string name) { 
! 			if(name[0]=='/')
! 				return name;
! 			if(root[root.size()-1]=='/')
! 				return root+name;
! 			else
! 				return root+"/"+name;
  		}
  
  		//!constructor
***************
*** 199,208 ****
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.27 $
   * $State: Exp $
!  * $Date: 2004/01/21 03:31:08 $
   */
  
  #endif
--- 209,218 ----
   * @author alokl (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.28 $
   * $State: Exp $
!  * $Date: 2004/01/30 01:30:07 $
   */
  
  #endif
Index: Tekkotsu/Shared/LoadSave.cc
diff -c Tekkotsu/Shared/LoadSave.cc:1.3 Tekkotsu/Shared/LoadSave.cc:1.4
*** Tekkotsu/Shared/LoadSave.cc:1.3	Thu Sep 25 11:31:53 2003
--- Tekkotsu/Shared/LoadSave.cc	Mon Feb  2 20:19:05 2004
***************
*** 52,58 ****
  		std::cout << "*** WARNING could not open file for loading \"" << file << "\"" << std::endl;
  		return 0;
  	}
! 	unsigned int sz = LoadFile(f);
  	if(sz==0)
  		std::cout << "*** WARNING loading of " << file << " failed " << std::endl;
  	err=fclose(f);
--- 52,58 ----
  		std::cout << "*** WARNING could not open file for loading \"" << file << "\"" << std::endl;
  		return 0;
  	}
! 	unsigned int sz = LoadFileStream(f);
  	if(sz==0)
  		std::cout << "*** WARNING loading of " << file << " failed " << std::endl;
  	err=fclose(f);
***************
*** 70,76 ****
  		std::cout << "*** WARNING could not open file for saving \"" << file << "\"" << std::endl;
  		return 0;
  	}
! 	unsigned int sz = SaveFile(f);
  	if(sz==0)
  		std::cout << "*** WARNING saving of " << file << " failed " << std::endl;
  	err=fclose(f);
--- 70,76 ----
  		std::cout << "*** WARNING could not open file for saving \"" << file << "\"" << std::endl;
  		return 0;
  	}
! 	unsigned int sz = SaveFileStream(f);
  	if(sz==0)
  		std::cout << "*** WARNING saving of " << file << " failed " << std::endl;
  	err=fclose(f);
***************
*** 81,87 ****
  	return sz;
  }
  
! unsigned int LoadSave::LoadFile(FILE* f) {
  	unsigned int cap=128;
  	unsigned int sz=0;
  	unsigned int origpos=ftell(f);
--- 81,87 ----
  	return sz;
  }
  
! unsigned int LoadSave::LoadFileStream(FILE* f) {
  	unsigned int cap=128;
  	unsigned int sz=0;
  	unsigned int origpos=ftell(f);
***************
*** 111,117 ****
  		fseek(f,origpos+resp,SEEK_SET);
  	return resp;
  }
! unsigned int LoadSave::SaveFile(FILE* f) const {
  	unsigned int sz=getBinSize();
  	char * buf = new char[sz];
  	memset(buf,0xF0,sz);
--- 111,117 ----
  		fseek(f,origpos+resp,SEEK_SET);
  	return resp;
  }
! unsigned int LoadSave::SaveFileStream(FILE* f) const {
  	unsigned int sz=getBinSize();
  	char * buf = new char[sz];
  	memset(buf,0xF0,sz);
***************
*** 137,145 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.3 $
!  * $State: Rel $
!  * $Date: 2003/09/25 15:31:53 $
   */
  
--- 137,145 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.4 $
!  * $State: Exp $
!  * $Date: 2004/02/03 01:19:05 $
   */
  
Index: Tekkotsu/Shared/LoadSave.h
diff -c Tekkotsu/Shared/LoadSave.h:1.6 Tekkotsu/Shared/LoadSave.h:1.8
*** Tekkotsu/Shared/LoadSave.h:1.6	Sun Jan 18 05:16:58 2004
--- Tekkotsu/Shared/LoadSave.h	Thu Feb  5 18:33:45 2004
***************
*** 5,12 ****
  #include <string>
  
  //! Intended as an interface to allow easy and uniform file operations
! /*! Be mindful of version differences - better safe than sorry - put a
!  *  version number as the first field, just in case */
  class LoadSave {
   public:
  	//! This is the amount of extra space needed to store a string (int for len of string plus 1 for null term
--- 5,109 ----
  #include <string>
  
  //! Intended as an interface to allow easy and uniform file operations
! /*!
! 	
! 	Generally, for usage, all you need to know is to call
! 	<tt>SaveFile("/path/to/file.ext")</tt> or
! 	<tt>SaveBuffer(membuffer)</tt> in order to have the class serialize
! 	itself, and the LoadFile() / LoadBuffer() in order to reload the
! 	data.
! 	
! 	So, when SaveFile() is called, it checks that it
! 	can open the specified file, and then calls SaveFileStream()
! 	with the open file.  This will then check getBinSize(), create a
! 	buffer of that size, and call SaveBuffer() to do the actual work of
! 	serialization into that buffer.  If SaveBuffer is successful (make
! 	sure your getBinSize() doesn't underestimate!) SaveFileStream()
! 	copies the buffer out to the file, and then finally, SaveFile() will
! 	close the file.
! 	
!   This has the nice side effect that if you want to send the data over
!   the network instead of a file, you can call SaveBuffer() directly
!   and reuse the code.  However, if you have a lot of data to save, you
!   can override the SaveFileStream() function as well, and save into
!   the file directly.  So far I've only bothered to do that with
!   only a few classes.
! 	
! 	The recommended style for using LoadSave in classes with inheritance
! 	is to have each subclass first call the superclass's implementation,
! 	and then save their own local data.  This compartmentalizes the data
! 	access and makes it easy to maintain - the code that serializes is
! 	right in with the code that defines the structure.  If you change
! 	one, it's easy to see where to change the other.  And protection
! 	between levels of inheritance is retained.  (This is why I say it's
! 	highly flexible/maintainable, but poor readability since the
! 	serialization is all broken up.)
! 	
! 	I also recommend putting a little string header at the beginning of
! 	each class's info.  This will allow polymorphism when loading files
! 	(you can look at the string and create the appropriate type) but
! 	also is handy for checking field alignment... it's a lot easier to
! 	tell how much you're offset within a string than to do the same with
! 	a stream of binary values.  Further, you can use the string as
! 	version information if you want to be backward compatible in future
! 	versions of your code.
! 	
! 	LoadSave provides a series of encode and decode functions for all
! 	the primitive types.  This will handle copying the value into the
! 	buffer or file, and can provide platform independence through byte
! 	swapping if needed (there's a compiler flag you can set for
! 	platforms that have the opposite byte order).  Most of these are
! 	pretty straightfoward - an int is just 4 bytes and so on.
! 	
! 	However, there's one caveat that I want to make sure to point out if
! 	you have to write parsing code in say, Java.  Strings are encoded by
! 	first storing an int to hold the string's length, then the string
! 	itself, and then a null character.  This adds 5 bytes to the length
! 	of any string, but makes loading the files much easier/faster - you
! 	can call string library functions directly on the buffer if it's
! 	already in memory since the string is null terminated, or can
! 	allocate memory to hold the string during loading from a file if
! 	needed because you'll know the size of the string before you get to
! 	it.
! 	
! 	Of course, the string stuff is transparent if you just use
! 	LoadSave's encode/decode functions to parse it.  But if that's not
! 	available (for instance if your receiver is in Java, there's a
! 	readLoadSaveString() in VisionListener.java if that will help:
! 	http://cvs.tekkotsu.org/cgi-bin/viewcvs.cgi/Tekkotsu/tools/mon/org/tekkotsu/mon/VisionListener.java?rev=1.6&content-type=text/vnd.viewcvs-markup
! 	@code
! 	public boolean _isConnected;
! 
! 	public String readLoadSaveString(InputStream in) throws java.io.IOException {
! 		int creatorLen=readInt(in);
! 		if(!_isConnected) return ""; 
! 		String creator=new String(readBytes(in,creatorLen));
! 		if(!_isConnected) return "";
! 		if(readChar(in)!='\0')
! 			System.err.println("Misread LoadSave string? "+creator);
! 		return creator;
! 	}
! 
! 	public int readInt(InputStream in) throws IOException {
! 		int read=0;
! 		int last=0;
! 		byte[] buf=new byte[4];
! 		while (read<4 && last>=0) { last=in.read(buf,read,4-read); read+=last; }
! 		if(last<0)
! 			_isConnected=false;
! 		return (b2i(buf[3])<<24) | (b2i(buf[2])<<16) |
! 					 (b2i(buf[1])<< 8) | b2i(buf[0]);
! 	}
!   public byte[] readBytes(InputStream in, int bytes) throws IOException {
!     byte[] ret=new byte[bytes];
!     readBytes(ret, in, bytes);
!     return ret;
!   }
! 	public char readChar(InputStream in) throws IOException {
! 		return (char)in.read();
! 	}
! 	@endcode
! */
  class LoadSave {
   public:
  	//! This is the amount of extra space needed to store a string (int for len of string plus 1 for null term
***************
*** 53,59 ****
  	 *  leaf-level ones won't even get this call unless you override the ones
  	 *  above them - hence, this is all or nothing
  	 *	@return number of bytes read, 0 if error (or empty) */
! 	virtual unsigned int LoadFile(FILE* f);
  	//!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
  	/*! @param f a pointer to the file to save
  	 *  @warning could potentially be very inefficient if root-level objects
--- 150,156 ----
  	 *  leaf-level ones won't even get this call unless you override the ones
  	 *  above them - hence, this is all or nothing
  	 *	@return number of bytes read, 0 if error (or empty) */
! 	virtual unsigned int LoadFileStream(FILE* f);
  	//!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
  	/*! @param f a pointer to the file to save
  	 *  @warning could potentially be very inefficient if root-level objects
***************
*** 61,67 ****
  	 *  leaf-level ones won't even get this call unless you override the ones
  	 *  above them - hence, this is all or nothing
  	 *	@return number of bytes written, 0 if error (or empty) */
! 	virtual unsigned int SaveFile(FILE* f) const;
  	//@}
  
  	//! These are for putting creator codes at the beginning of your data to check for sanity, just optional
--- 158,164 ----
  	 *  leaf-level ones won't even get this call unless you override the ones
  	 *  above them - hence, this is all or nothing
  	 *	@return number of bytes written, 0 if error (or empty) */
! 	virtual unsigned int SaveFileStream(FILE* f) const;
  	//@}
  
  	//! These are for putting creator codes at the beginning of your data to check for sanity, just optional
***************
*** 108,115 ****
  	/*!@brief encode or decode with byte order consistancy*/
  	inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap)  { return x.SaveBuffer(buf,cap); }
  	inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap)  { return x.LoadBuffer(buf,cap); }
! 	inline static unsigned int encode(const LoadSave& x, FILE* f)                  { return x.SaveFile(f); }
! 	inline static unsigned int decode(LoadSave& x, FILE* f)                        { return x.LoadFile(f); }
  	
  	//I don't know what compiler flag to use - this one is fake.
  	//Ideally, we should be able to detect host orientation
--- 205,212 ----
  	/*!@brief encode or decode with byte order consistancy*/
  	inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap)  { return x.SaveBuffer(buf,cap); }
  	inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap)  { return x.LoadBuffer(buf,cap); }
! 	inline static unsigned int encode(const LoadSave& x, FILE* f)                  { return x.SaveFileStream(f); }
! 	inline static unsigned int decode(LoadSave& x, FILE* f)                        { return x.LoadFileStream(f); }
  	
  	//I don't know what compiler flag to use - this one is fake.
  	//Ideally, we should be able to detect host orientation
***************
*** 233,242 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:58 $
   */
  
  #endif
--- 330,339 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.8 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:45 $
   */
  
  #endif
Index: Tekkotsu/Shared/Profiler.h
diff -c Tekkotsu/Shared/Profiler.h:1.10 Tekkotsu/Shared/Profiler.h:1.11
*** Tekkotsu/Shared/Profiler.h:1.10	Fri Jan 16 02:39:30 2004
--- Tekkotsu/Shared/Profiler.h	Wed Feb  4 18:06:47 2004
***************
*** 20,45 ****
   *  That's handy so one process can collate all the profiling information across processes
   *  to give a summary report to the user.\n
   *  
!  *  Example usage: (two different methods, f() or g())
   *  @code
   *  ProfilerOfSize<2> prof; //A global manager for all the sections
   *  
   *  void f() {
!  *    static unsigned int id=prof.getNewID("f"); // *** YOU NEED THIS LINE for each section to profile
!  *    Profiler::Timer timer(id,&prof);           // *** YOU NEED THIS LINE for each section to profile
   *    //...
   *    if(rand()>RAND_MAX/2)
   *      return; // destruction of timer occurs automatically!
   *    //...
   *  } // if we didn't hit the return, timer will otherwise destruct here!
   *  
   *  void g() {
!  *    PROFSECTION("g",prof);   // Could also use this macro instead (recommended if you're
!  *    //...                    // not doing something fancy like conditional timers)
   *    f(); // will note f's time as g's child time
   *    //...
   *  }
   *  @endcode
   *  The idea is similar to that used by MMAccessor.  If you want to profile a section at smaller
   *  resolution than a function, you can use tricks shown in MMAccessor's documentation to limit
   *  the timer's scope.
--- 20,53 ----
   *  That's handy so one process can collate all the profiling information across processes
   *  to give a summary report to the user.\n
   *  
!  *  Example usage:
!  *  - Use a static variable to hold an id number for the code section (doesn't necessarily have to be static, but is faster that way)
!  *  - Create a Profiler::Timer object - its construction marks the 'start' time, and its destructor marks the 'stop' time.
!  *
   *  @code
   *  ProfilerOfSize<2> prof; //A global manager for all the sections
   *  
   *  void f() {
!  *    static unsigned int id=prof.getNewID("f"); // <== Get the ID number 
!  *    Profiler::Timer timer(id,&prof);           // <== start the timer
   *    //...
   *    if(rand()>RAND_MAX/2)
   *      return; // destruction of timer occurs automatically!
   *    //...
   *  } // if we didn't hit the return, timer will otherwise destruct here!
+  *  @endcode
+  *
+  *  However, there's a macro that makes this a one liner:
   *  
+  *  @code
   *  void g() {
!  *    PROFSECTION("g",prof);   // <== Most of the time, this is all you need
!  *    //...                    // (unless you're doing something fancy like conditional timers)
   *    f(); // will note f's time as g's child time
   *    //...
   *  }
   *  @endcode
+  *
   *  The idea is similar to that used by MMAccessor.  If you want to profile a section at smaller
   *  resolution than a function, you can use tricks shown in MMAccessor's documentation to limit
   *  the timer's scope.
***************
*** 73,80 ****
   *  header, but has the downside that accessing the info stored in the subclass from the super class
   *  is very much a hack.  If you think you can get around this, good luck!
   *
!  *  @note ~Profiler() isn't virtual - that's on purpose.\n
!  *  This could be made much prettier if we didn't care about the virtual function-shared
   *  memory problems... sigh
   */
  class Profiler {
--- 81,87 ----
   *  header, but has the downside that accessing the info stored in the subclass from the super class
   *  is very much a hack.  If you think you can get around this, good luck!
   *
!  *  @note This could be made much prettier if we didn't care about the virtual function-shared
   *  memory problems... sigh
   */
  class Profiler {
***************
*** 197,206 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.10 $
   * $State: Exp $
!  * $Date: 2004/01/16 07:39:30 $
   */
  
  #endif
--- 204,213 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.11 $
   * $State: Exp $
!  * $Date: 2004/02/04 23:06:47 $
   */
  
  #endif
Index: Tekkotsu/Vision/FilterBankGenerator.cc
diff -c Tekkotsu/Vision/FilterBankGenerator.cc:1.4 Tekkotsu/Vision/FilterBankGenerator.cc:1.5
*** Tekkotsu/Vision/FilterBankGenerator.cc:1.4	Sun Dec  7 19:21:06 2003
--- Tekkotsu/Vision/FilterBankGenerator.cc	Thu Feb  5 14:11:41 2004
***************
*** 128,140 ****
  
  
  /*! @file
!  * @brief Implements abstract base class for generators of FilterBankEvents
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2003/12/08 00:21:06 $
   */
  
--- 128,140 ----
  
  
  /*! @file
!  * @brief Implements abstract base class for generators of FilterBankEvent's
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/02/05 19:11:41 $
   */
  
Index: Tekkotsu/Vision/FilterBankGenerator.h
diff -c Tekkotsu/Vision/FilterBankGenerator.h:1.9 Tekkotsu/Vision/FilterBankGenerator.h:1.12
*** Tekkotsu/Vision/FilterBankGenerator.h:1.9	Wed Jan  7 21:22:34 2004
--- Tekkotsu/Vision/FilterBankGenerator.h	Thu Feb  5 18:33:48 2004
***************
*** 5,11 ****
  #include "Events/EventGeneratorBase.h"
  #include "Shared/LoadSave.h"
  
! //! Abstract base class for generators of FilterBankEvents
  /*! This is needed to provide an interface for the FilterBankEvent to
   *  call back when the actual image data is requested from it.  This
   *  facilitates lazy calculation of image data...  no sense in
--- 5,11 ----
  #include "Events/EventGeneratorBase.h"
  #include "Shared/LoadSave.h"
  
! //! Abstract base class for generators of FilterBankEvent's
  /*! This is needed to provide an interface for the FilterBankEvent to
   *  call back when the actual image data is requested from it.  This
   *  facilitates lazy calculation of image data...  no sense in
***************
*** 20,40 ****
   *  in a scaling pyramid, but you are free to store your own data
   *  however you wish.
   *
!  *  For serializing, FilterBankGenerators inherit from the LoadSave
!  *  interface.  Only one image (selected with setLoadSaveImage()) of
!  *  the bank will loaded or saved at a time.  The default LoadSave
!  *  will store some header information for you:
   *  
!  *  - Creator code: string ("\008FBkImage\0")
!  *  - Width: unsigned int
!  *  - Height: unsigned int
!  *  - Layer: unsigned int
!  *  - Channel: unsigned int
   *  
!  *  However, you will need to override the LoadSave functions (listed
!  *  below) to provide your own code for interpreting the image data
!  *  itself.  You may also want to add a few extra functions to allow
!  *  users to set compression/data format parameters.
   *
   *  If you're doing fancy memory stuff, you probably want to override
   *  the freeCaches() and destruct() functions so that the default
--- 20,90 ----
   *  in a scaling pyramid, but you are free to store your own data
   *  however you wish.
   *
!  *  <h3>Serialization Format</h3>
!  *
!  *  First, be sure to get a good overview of the LoadSave style.  Most
!  *  serialization is handled using this interface.
!  *
!  *  When, for instance, RawCameraGenerator::SaveBuffer() is called, it
!  *  first calls it's super class, FilterBankGenerator::SaveBuffer(),
!  *  which will write out the general image information, common to all
!  *  subclasses of FilterBankGenerator. (i'll cover the specifics in a
!  *  second) Once that's done, the RawCameraGenerator adds it's own bit
!  *  of header and then saves the image data itself.
!  *
!  *  Note that only a single channel is being saved at this point.  So
!  *  for instance, all the Y information.  No interleaving is going
!  *  on. (unless you're saving from InterleavedYUVGenerator of course,
!  *  which treats the 3 interleaved channels as a single image)
!  *  Otherwise,only one image (selected with selectSaveImage()) of the
!  *  bank will loaded or saved at a time.
   *  
!  *  So, anyway.  The first header will be the same for all
!  *  FilterBankGenerator subclasses.  In the specification below, I'm
!  *  going to use one field per line (the new lines are not literal,
!  *  it's a binary stream).  Each field is of the form '<@c type:name>
!  *  <i>(notes)</i>'
   *  
!  *  FilterBankGenerator Header: (from FilterBankGenerator::SaveBuffer())
!  *  - <@c string: "FbkImage">  <i>(remember a 'string' is len+str+0; so this is the literal "\010\0\0\0FbkImage\0"; also remember "\010" is octal for 8)</i>
!  *  - <@c unsigned @c int: width> 
!  *  - <@c unsigned @c int: height> 
!  *  - <@c unsigned @c int: image layer> 
!  *  - <@c unsigned @c int: image channel> <i>(so notice you can tell which channel it is after it's been saved)</i>
!  * 
!  *  Generator Specific Header (selected examples follow, or similarly, any of the other generators)
!  *  
!  *  - RawCameraGenerator: (from RawCameraGenerator::SaveBuffer())
!  *    - <@c string: "RawImage">
!  *    - <<tt>char[</tt>width<tt>*</tt>height<tt>]</tt>: image data> <i>(note, just once channel being stored)</i>
!  *  - InterleavedYUVGenerator: (from InterleavedYUVGenerator::SaveBuffer())
!  *    - <@c string: "InterleavedYUVImage">
!  *    - <<tt>char[</tt>width<tt>*</tt>height<tt>*3]</tt>: image data> <i>(in YVU order, technically YCbCr)</i>
!  *  - SegmentedColorGenerator: (from SegmentedColorGenerator::SaveBuffer())
!  *    - <@c string: "SegColorImage">
!  *    - <<tt>char[</tt>width<tt>*</tt>height<tt>]</tt>: image data> <i>(one byte per sample)</i>
!  *    - <@c unsigned @c int: num_cols> <i>(number of different colors available)</i>
!  *    - for each of num_col:
!  *      - <@c char: red> <i>red color to use for display of this index</i>
!  *      - <@c char: green> <i>green color to use for display of this index</i>
!  *      - <@c char: blue> <i>blue color to use for display of this index</i>
!  *  - RLEGenerator: (from RLEGenerator::SaveBuffer())
!  *    - <@c string: "RLEImage">  <i>(remember a 'string' is len+str+0; so this is the literal "\010\0\0\0RLEImage\0"; also remember "\010" is octal for 8)</i>
!  *    - <@c unsigned @c int: num_runs> <i>(how many runs will follow)</i>
!  *    - for each of num_runs:
!  *      - <@c char: color> <i>(index value of color of run)</i>
!  *      - <@c short: x> <i>(x position of start of run ("unknown" runs are skipped - assume index 0 for pixels which are jumped))</i>
!  *      - <@c short: width> <i>(length of run, will not exceed remaining width of image)</i>
!  *    - <i>notice there's no color information from RLE - it's not (shouldn't be) assuming anything about the data being compressed)</i>
!  *
!  *  However, while we're on the topic, I'll mention that although this
!  *  is the same image format used for streaming to VisionGUI, there's
!  *  a few more fields added by RawCamBehavior or SegCamBehavior at the
!  *  beginning of each packet.  See those classes for more information
!  *  on the wireless protocol. That should tell you everything you need
!  *  to know to interpret the vision stream as well.
!  *
!  *  <h3>Adding New FilterBankGenerator Subclasses</h3>
   *
   *  If you're doing fancy memory stuff, you probably want to override
   *  the freeCaches() and destruct() functions so that the default
***************
*** 43,49 ****
   *  your versions won't get called before the default implementation's
   *  does.
   *
!  *  @see RawCameraGenerator
   */
  class FilterBankGenerator : public EventGeneratorBase, public LoadSave {
  public:
--- 93,113 ----
   *  your versions won't get called before the default implementation's
   *  does.
   *
!  *  If you want to be able to transmit or save your images, you will
!  *  need to override the LoadSave functions (listed below) to provide
!  *  your own code for interpreting the image data itself, and then
!  *  create or modify a behavior to open a socket and transmit the
!  *  information.  (you could do that from within the generator itself
!  *  if you like)
!  *
!  *  You will probably also want to add a few extra functions to allow
!  *  users to set compression/data format parameters.
!  *
!  *  @see RawCameraGenerator, SegmentedColorGenerator for the basic
!  *  image access
!  * 
!  *  @see RLEGenerator, RegionGenerator for some relatively simple
!  *  examples of vision stages if you want to make some of your own.
   */
  class FilterBankGenerator : public EventGeneratorBase, public LoadSave {
  public:
***************
*** 147,160 ****
  	 *  its available resolutions at run time. */
  	virtual void setNumImages(unsigned int nLayers, unsigned int nChannels);
  
! 	//! create new image data storage area for the cache - this is only called when the corresponding entry in images is NULL
  	/*! You should return the pointer you want stored in images to be
  	 *  returned by any calls to getFirstRow.  Interpretation of the
  	 *  data it points to is dependant on the the generator which
  	 *  creates it */
  	virtual unsigned char * createImageCache(unsigned int layer, unsigned int channel) const=0;
  
! 	//! should calculate new image data, only called when imageValids indicates the image being requested is dirty
  	/*! This is where you'll want to put your user-specific code for calculating the image data */
  	virtual void calcImage(unsigned int layer, unsigned int channel) const=0;
  
--- 211,224 ----
  	 *  its available resolutions at run time. */
  	virtual void setNumImages(unsigned int nLayers, unsigned int nChannels);
  
! 	//! create new image data storage area for the cache - this called by getImage() only when the corresponding entry in images is NULL
  	/*! You should return the pointer you want stored in images to be
  	 *  returned by any calls to getFirstRow.  Interpretation of the
  	 *  data it points to is dependant on the the generator which
  	 *  creates it */
  	virtual unsigned char * createImageCache(unsigned int layer, unsigned int channel) const=0;
  
! 	//! should calculate new image data, called by getImage() only when #imageValids indicates the image being requested is dirty (and only after getImage() has already called createImageCache())
  	/*! This is where you'll want to put your user-specific code for calculating the image data */
  	virtual void calcImage(unsigned int layer, unsigned int channel) const=0;
  
***************
*** 196,209 ****
  };
  
  /*! @file
!  * @brief Describes abstract base class for generators of FilterBankEvents
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.9 $
   * $State: Exp $
!  * $Date: 2004/01/08 02:22:34 $
   */
  
  #endif
--- 260,273 ----
  };
  
  /*! @file
!  * @brief Describes abstract base class for generators of FilterBankEvent's
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.12 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:48 $
   */
  
  #endif
Index: Tekkotsu/Vision/InterleavedYUVGenerator.h
diff -c Tekkotsu/Vision/InterleavedYUVGenerator.h:1.7 Tekkotsu/Vision/InterleavedYUVGenerator.h:1.10
*** Tekkotsu/Vision/InterleavedYUVGenerator.h:1.7	Sun Jan 18 05:16:59 2004
--- Tekkotsu/Vision/InterleavedYUVGenerator.h	Thu Feb  5 18:33:48 2004
***************
*** 7,17 ****
  //! Generates FilterBankEvents containing raw camera images with interleaved pixels (YVUYVUYVU... instead of YYY...UUU...VVV...)
  /*! @note That's not a typo - the byte ordering is YVU, @e not YUV
   *
!  *  Sorry about the misleading name... This @a takes YUV images,
!  *  however, the main reason for this class is to interleave the image
!  *  in order to pass it to the jpeg compression routines.  JPEG expect
!  *  YCrCb, which is apparently YVU order.  *shrug* I dunno, there's
!  *  something weird there.
   *
   *  There's only one channel, which holds the interleaved data.  The
   *  increment is set to 3, but if you want to access each component in
--- 7,22 ----
  //! Generates FilterBankEvents containing raw camera images with interleaved pixels (YVUYVUYVU... instead of YYY...UUU...VVV...)
  /*! @note That's not a typo - the byte ordering is YVU, @e not YUV
   *
!  *  Sorry about the misleading name... This @a takes filter banks
!  *  containing YUV information, however, the main reason for this
!  *  class is to interleave the image in order to pass it to the jpeg
!  *  compression routines.  JPEG expect YCbCr, which corresponds to YVU
!  *  order.
!  *
!  *  Also, I should point out that mathematically, V!=Cb, and U!=Cr,
!  *  but they do carry the same information.  It's just a matter of
!  *  scaling and offset.  These comments use the "Y", "U", and "V"
!  *  labels loosely.
   *
   *  There's only one channel, which holds the interleaved data.  The
   *  increment is set to 3, but if you want to access each component in
***************
*** 24,29 ****
--- 29,36 ----
   *  general.
   *
   *	should receive FilterBankEvents from any standard format FilterBankGenerator (like RawCameraGenerator)
+  *
+  *  @see FilterBankGenerator for information on serialization format
   */
  class InterleavedYUVGenerator : public FilterBankGenerator {
  public:
***************
*** 66,75 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.7 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:59 $
   */
  
  #endif
--- 73,82 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.10 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:48 $
   */
  
  #endif
Index: Tekkotsu/Vision/RLEGenerator.cc
diff -c Tekkotsu/Vision/RLEGenerator.cc:1.5 Tekkotsu/Vision/RLEGenerator.cc:1.6
*** Tekkotsu/Vision/RLEGenerator.cc:1.5	Fri Jan 16 02:39:51 2004
--- Tekkotsu/Vision/RLEGenerator.cc	Wed Feb  4 21:37:09 2004
***************
*** 132,147 ****
  	}
  }
  
  unsigned char *
  RLEGenerator::createImageCache(unsigned int layer, unsigned int /*chan*/) const {
  	return reinterpret_cast<unsigned char*>(new run[maxRuns[layer]]);
  }
  
  void
  RLEGenerator::calcImage(unsigned int layer, unsigned int chan) const {
  	PROFSECTION("RLEGenerator::calcImage(...)",state->mainProfile);
    numRuns[layer][chan] = CMVision::EncodeRuns(reinterpret_cast<run*>(images[layer][chan]),src->getImage(layer,chan),getWidth(layer),getHeight(layer),maxRuns[layer]);
! 	imageValids[layer][chan]=true;
  }
  
  void
--- 132,149 ----
  	}
  }
  
+ //! simply creates a new data region and returns it
  unsigned char *
  RLEGenerator::createImageCache(unsigned int layer, unsigned int /*chan*/) const {
  	return reinterpret_cast<unsigned char*>(new run[maxRuns[layer]]);
  }
  
+ //! a single call to the CMVision library to do the work, and we're done.
  void
  RLEGenerator::calcImage(unsigned int layer, unsigned int chan) const {
  	PROFSECTION("RLEGenerator::calcImage(...)",state->mainProfile);
    numRuns[layer][chan] = CMVision::EncodeRuns(reinterpret_cast<run*>(images[layer][chan]),src->getImage(layer,chan),getWidth(layer),getHeight(layer),maxRuns[layer]);
! 	imageValids[layer][chan]=true; // <--- don't forget to do this, otherwise you'll recompute on every access, even if the cache is still valid
  }
  
  void
***************
*** 161,169 ****
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/01/16 07:39:51 $
   */
  
--- 163,171 ----
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/02/05 02:37:09 $
   */
  
Index: Tekkotsu/Vision/RLEGenerator.h
diff -c Tekkotsu/Vision/RLEGenerator.h:1.4 Tekkotsu/Vision/RLEGenerator.h:1.6
*** Tekkotsu/Vision/RLEGenerator.h:1.4	Sun Jan 18 05:16:59 2004
--- Tekkotsu/Vision/RLEGenerator.h	Thu Feb  5 18:33:48 2004
***************
*** 10,15 ****
--- 10,18 ----
  //! Generates RLE compressed FilterBankEvents (generally from indexed color images from, say, SegmentedColorGenerator)
  /*! Uses the CMVision library for main processing.
   *
+  *  getImage() will return the first run, from the upper left hand
+  *  corner.  The type is RLEGenerator::run.
+  *
   *  The RLE produced isn't quite optimal in terms of size.  To make it
   *  easier to directly process the RLE for recognition tasks, each run
   *  will be broken at the end of the row.  So a solid image will still
***************
*** 39,44 ****
--- 42,65 ----
   *  flat color.  However, if you have some kind of other preprocessing
   *  that also provides suitable data, this can encode it for you.
   *  
+  *  The format used for serialization is: (code is in SaveBuffer())
+  *  - <@c FilterBankGenerator: superclass header> <i>(First saves the superclass's info)</i>
+  *  - <@c string: "RLEImage">  <i>(remember a 'string' is len+str+0; so this is the literal "\010\0\0\0RLEImage\0"; also remember "\010" is octal for 8)</i>
+  *  - <@c unsigned @c int: num_runs> <i>(how many runs will follow)</i>
+  *  - for each of num_runs:
+  *    - <@c char: color> <i>(index value of color of run)</i>
+  *    - <@c short: x> <i>(x position of start of run ("unknown" runs are skipped - assume index 0 for pixels which are jumped))</i>
+  *    - <@c short: width> <i>(length of run, will not exceed remaining width of image)</i> 
+  *
+  *  Note that the RLEGenerator doesn't save the color infomation
+  *  regarding what each index value "means".  This is just a
+  *  compression stage, pure and simple.  You'll need to look at the
+  *  RLEGenerator's source (@e probably SegmentedColorGenerator, but
+  *  doesn't @e have to be) to determine how to interpret the indicies.
+  *
+  *  @see SegCamBehavior for information on transmission over wireless.
+  *
+  *  @see FilterBankGenerator more information on serialization
   */
  class RLEGenerator : public FilterBankGenerator {
  public:
***************
*** 97,106 ****
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:59 $
   */
  
  #endif
--- 118,127 ----
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:48 $
   */
  
  #endif
Index: Tekkotsu/Vision/RawCameraGenerator.cc
diff -c Tekkotsu/Vision/RawCameraGenerator.cc:1.11 Tekkotsu/Vision/RawCameraGenerator.cc:1.14
*** Tekkotsu/Vision/RawCameraGenerator.cc:1.11	Fri Jan 16 02:39:51 2004
--- Tekkotsu/Vision/RawCameraGenerator.cc	Thu Feb  5 19:06:31 2004
***************
*** 93,100 ****
  			images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
  		unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
  		used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
! 		if(used>len)
! 			return 0;
  		memcpy(img,buf,used);
  		len-=used; buf+=used;
  		imageValids[selectedSaveLayer][selectedSaveChannel]=true;
--- 93,99 ----
  			images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
  		unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
  		used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
! 		ASSERTRETVAL(used<=len,"buffer too small",0);
  		memcpy(img,buf,used);
  		len-=used; buf+=used;
  		imageValids[selectedSaveLayer][selectedSaveChannel]=true;
***************
*** 113,128 ****
  	
  	unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
  	used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
! 	if(used>len)
! 		return 0;
  	unsigned int inc=getIncrement(selectedSaveLayer);
  	if(inc==1) {
  		//special case, straight copy
  		for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
! 			unsigned char* const rowend=img+widths[selectedSaveLayer];
! 			while(img!=rowend)
! 				*buf++=*img++;
! 			img+=getSkip(selectedSaveLayer);
  		}
  	} else {
  		//otherwise, interleaved or subsampling
--- 112,125 ----
  	
  	unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
  	used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
! 	ASSERTRETVAL(used<=len,"buffer too small",0);
  	unsigned int inc=getIncrement(selectedSaveLayer);
  	if(inc==1) {
  		//special case, straight copy
  		for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
! 			memcpy(buf,img,widths[selectedSaveLayer]);
! 			buf+=widths[selectedSaveLayer];
! 			img+=getStride(selectedSaveLayer);
  		}
  	} else {
  		//otherwise, interleaved or subsampling
***************
*** 140,145 ****
--- 137,203 ----
  	return origlen-len;
  }
  
+ unsigned int
+ RawCameraGenerator::SaveFileStream(FILE * f) const {
+ 	unsigned int totalused=0;
+ 	unsigned int used;
+ 	{ //sigh, inheritance has failed me (I wouldn't want FilterBankGenerator::SaveFileStream() to call the virtuals...)
+ 		unsigned int sz=FilterBankGenerator::getBinSize();
+ 		char * buf = new char[sz];
+ 		memset(buf,0xF0,sz);
+ 		if(buf==NULL) {
+ 			std::cout << "*** WARNING could not allocate " << sz << " bytes for LoadFile";
+ 			return 0;
+ 		}
+ 		unsigned int resp=FilterBankGenerator::SaveBuffer(buf,sz);
+ 		if(resp==0) {
+ 			std::cout << "*** WARNING SaveBuffer didn't write any data (possibly due to overflow or other error)" << std::endl;
+ 			fwrite(buf,1,sz,f);
+ 		}	else {
+ 			unsigned int wrote=fwrite(buf,1,resp,f);
+ 			if(wrote!=resp)
+ 				std::cout << "*** WARNING short write (wrote " << wrote << ", expected " << resp << ")" << std::endl;
+ 		}
+ 		delete [] buf;
+ 		used=resp;
+ 	}
+ 	if(0==used) return 0;
+ 	totalused+=used;
+ 	if(0==(used=encode("RawImage",f))) return 0;
+ 	totalused+=used;
+ 	
+ 	unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
+ 	used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
+ 	unsigned int inc=getIncrement(selectedSaveLayer);
+ 	if(inc==1) {
+ 		//special case, straight copy
+ 		sout->printf("Saving %d by %d\n",widths[selectedSaveLayer],heights[selectedSaveLayer]);
+ 		for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
+ 			if(fwrite(img,widths[selectedSaveLayer],1,f)==0) {
+ 				serr->printf("short write on image data - ran out of space?\n");
+ 				return 0;
+ 			}
+ 			img+=getStride(selectedSaveLayer);
+ 		}
+ 	} else {
+ 		//otherwise, interleaved or subsampling
+ 		for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
+ 			unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
+ 			while(img!=rowend) {
+ 				if(fputc(*img,f)==EOF) {
+ 					serr->printf("short write on image data - ran out of space?\n");
+ 					return 0;
+ 				}
+ 				img+=inc;
+ 			}
+ 			img+=getSkip(selectedSaveLayer);
+ 		}
+ 	}
+ 	totalused+=used;
+ 	
+ 	return totalused;
+ }
+ 
  void
  RawCameraGenerator::setDimensions() {
  	freeCaches();
***************
*** 157,163 ****
  
  void 
  RawCameraGenerator::freeCaches() {
! 	for(unsigned int i=0; i<numLayers-1; i++) {
  		for(unsigned int j=0; j<numChannels; j++) {
  			images[i][j]=NULL;
  			imageValids[i][j]=false;
--- 215,221 ----
  
  void 
  RawCameraGenerator::freeCaches() {
! 	for(unsigned int i=0; i<numLayers; i++) {
  		for(unsigned int j=0; j<numChannels; j++) {
  			images[i][j]=NULL;
  			imageValids[i][j]=false;
***************
*** 181,189 ****
  }
  
  unsigned char *
! RawCameraGenerator::createImageCache(unsigned int layer, unsigned int /*chan*/) const {
  	if(layer==numLayers-1) {
! 		return new unsigned char[widths[layer]*heights[layer]];
  	} else
  		return NULL; // calcImage will set the cache itself
  }
--- 239,247 ----
  }
  
  unsigned char *
! RawCameraGenerator::createImageCache(unsigned int layer, unsigned int chan) const {
  	if(layer==numLayers-1) {
! 		return const_cast<unsigned char*>(&dblRes[chan][0][0]);
  	} else
  		return NULL; // calcImage will set the cache itself
  }
***************
*** 367,375 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.11 $
   * $State: Exp $
!  * $Date: 2004/01/16 07:39:51 $
   */
  
--- 425,433 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.14 $
   * $State: Exp $
!  * $Date: 2004/02/06 00:06:31 $
   */
  
Index: Tekkotsu/Vision/RawCameraGenerator.h
diff -c Tekkotsu/Vision/RawCameraGenerator.h:1.10 Tekkotsu/Vision/RawCameraGenerator.h:1.13
*** Tekkotsu/Vision/RawCameraGenerator.h:1.10	Sun Jan 18 05:16:59 2004
--- Tekkotsu/Vision/RawCameraGenerator.h	Thu Feb  5 18:33:48 2004
***************
*** 10,16 ****
  //! Generates FilterBankEvents containing raw camera images directly from the system (doesn't make a copy)
  class RawCameraGenerator : public FilterBankGenerator {
  public:
! 	//!constructor, numRawLayers is the number of real layers passed from the system, numCalcLayers is the total number of layers to make available
  	/*! The extra calculated layers are simply created by giving larger
  	 *  increments, they reference the same data (no computational cost,
  	 *  marginal memory costs... it's just nice to have more layers in
--- 10,16 ----
  //! Generates FilterBankEvents containing raw camera images directly from the system (doesn't make a copy)
  class RawCameraGenerator : public FilterBankGenerator {
  public:
! 	//! constructor, numRawLayers is the number of real layers passed from the system, numCalcLayers is the total number of layers to make available
  	/*! The extra calculated layers are simply created by giving larger
  	 *  increments, they reference the same data (no computational cost,
  	 *  marginal memory costs... it's just nice to have more layers in
***************
*** 23,29 ****
  	 *  The top most layer (largest index) is a double-scale image.  For
  	 *  the Y-channel, it is reconstructed from the 4 Y channels.  For
  	 *  the other channels, it just does a fast scaling (but these
! 	 *  operations do cost, so use the top layer conservatively. */
  	RawCameraGenerator(unsigned int numRawLayers, unsigned int numCalcLayers, EventBase::EventGeneratorID_t gid, unsigned int sid, unsigned int mysid);
  
  	//! destructor
--- 23,32 ----
  	 *  The top most layer (largest index) is a double-scale image.  For
  	 *  the Y-channel, it is reconstructed from the 4 Y channels.  For
  	 *  the other channels, it just does a fast scaling (but these
! 	 *  operations do cost, so use the top layer conservatively.
! 	 *
! 	 *  @see FilterBankGenerator for information on serialization format
! 	 */
  	RawCameraGenerator(unsigned int numRawLayers, unsigned int numCalcLayers, EventBase::EventGeneratorID_t gid, unsigned int sid, unsigned int mysid);
  
  	//! destructor
***************
*** 54,60 ****
--- 57,79 ----
  
  	virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
  
+ 	virtual unsigned int SaveFileStream(FILE* f) const; //!< overrridden to allow saving direct to file without an extra buffer copy
+ 
  protected:
+ 	//! ohh, this is so yucky.  But we need to get around heap allocation bugs with large regions in Aperios :(
+ 	/*! So we store the double size images statically within the class.
+ 	 *  What a waste of memory since we're probably not using these very
+ 	 *  much, and they are rather large... :(
+ 	 * 
+ 	 *  The 2.0 release had the proper dynamic allocation
+ 	 *  implementation, but has been replaced in 2.0.1 with this static
+ 	 *  allocation so it won't crash.
+ 	 *
+ 	 *  Of course, if the memory allocation bug is never fixed, and
+ 	 *  camera sizes increase in later models, this will have to be
+ 	 *  modified. */
+ 	unsigned char dblRes[NUM_CHANNELS][416][320]; 
+ 
  	virtual void setNumImages(unsigned int nLayers, unsigned int nChannels);
  
  	virtual void setDimensions(); //!< resets the width, height, skip and stride values
***************
*** 93,102 ****
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.10 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:59 $
   */
  
  #endif
--- 112,121 ----
   * @author ejt (Creator)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.13 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:48 $
   */
  
  #endif
Index: Tekkotsu/Vision/RegionGenerator.cc
diff -c Tekkotsu/Vision/RegionGenerator.cc:1.5 Tekkotsu/Vision/RegionGenerator.cc:1.6
*** Tekkotsu/Vision/RegionGenerator.cc:1.5	Fri Jan 16 02:39:51 2004
--- Tekkotsu/Vision/RegionGenerator.cc	Wed Feb  4 21:46:41 2004
***************
*** 212,237 ****
  
  unsigned char *
  RegionGenerator::createImageCache(unsigned int layer, unsigned int chan) const {
  	regions[layer][chan]=new region[MAX_REGIONS];
  	region_stats * stats=new region_stats[srcNumColors];
  	//initialize the region parameters (held in color definition...)
  	memcpy(stats,srcColors,srcNumColors*sizeof(region_stats));
  	return reinterpret_cast<unsigned char*>(stats);
  }
  
  void
  RegionGenerator::calcImage(unsigned int layer, unsigned int chan) const {
  	PROFSECTION("RegionGenerator::calcImage(...)",state->mainProfile);
! 	const RLEGenerator& srcRLE=dynamic_cast<const RLEGenerator&>(*src);
! 	RLEGenerator::run * rmap=reinterpret_cast<RLEGenerator::run*>(srcRLE.getImage(layer,chan));
! 	region_stats * stats=reinterpret_cast<region_stats*>(images[layer][chan]);
  
    CMVision::ConnectComponents(rmap,srcRLE.getNumRuns(layer,chan));
    unsigned int numReg = CMVision::ExtractRegions(regions[layer][chan],MAX_REGIONS,rmap,srcRLE.getNumRuns(layer,chan));
    unsigned int maxArea = CMVision::SeparateRegions(stats,srcNumColors,regions[layer][chan],numReg);
    CMVision::SortRegions(stats,srcNumColors,maxArea);
    CMVision::MergeRegions(stats,(int)srcNumColors,rmap); //yes that (int) is necessary or compiler complains of ambiguous function call
  
  	imageValids[layer][chan]=true;
  }
  
--- 212,247 ----
  
  unsigned char *
  RegionGenerator::createImageCache(unsigned int layer, unsigned int chan) const {
+ 	//this is where we'll store the linked list of regions for this image
  	regions[layer][chan]=new region[MAX_REGIONS];
+ 
+ 	//this is where we store the head of each list as well as some general stats of each image
+ 	//this is what will be returned as getImage()
  	region_stats * stats=new region_stats[srcNumColors];
+ 	
  	//initialize the region parameters (held in color definition...)
  	memcpy(stats,srcColors,srcNumColors*sizeof(region_stats));
+ 	
  	return reinterpret_cast<unsigned char*>(stats);
  }
  
  void
  RegionGenerator::calcImage(unsigned int layer, unsigned int chan) const {
  	PROFSECTION("RegionGenerator::calcImage(...)",state->mainProfile);
! 	
! 	//some shorthand to make the rest of the code more readable
! 	const RLEGenerator& srcRLE=dynamic_cast<const RLEGenerator&>(*src); //source generator
! 	RLEGenerator::run * rmap=reinterpret_cast<RLEGenerator::run*>(srcRLE.getImage(layer,chan)); //the RLE encoded image from source
! 	region_stats * stats=reinterpret_cast<region_stats*>(images[layer][chan]); //our top level region stats array (which is what users get from getImage())
  
+ 	//do the actual calculations
    CMVision::ConnectComponents(rmap,srcRLE.getNumRuns(layer,chan));
    unsigned int numReg = CMVision::ExtractRegions(regions[layer][chan],MAX_REGIONS,rmap,srcRLE.getNumRuns(layer,chan));
    unsigned int maxArea = CMVision::SeparateRegions(stats,srcNumColors,regions[layer][chan],numReg);
    CMVision::SortRegions(stats,srcNumColors,maxArea);
    CMVision::MergeRegions(stats,(int)srcNumColors,rmap); //yes that (int) is necessary or compiler complains of ambiguous function call
  
+ 	//and set the flag so we don't recompute if getImage() is called again before the next frame
  	imageValids[layer][chan]=true;
  }
  
***************
*** 250,258 ****
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/01/16 07:39:51 $
   */
  
--- 260,268 ----
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.6 $
   * $State: Exp $
!  * $Date: 2004/02/05 02:46:41 $
   */
  
Index: Tekkotsu/Vision/RegionGenerator.h
diff -c Tekkotsu/Vision/RegionGenerator.h:1.3 Tekkotsu/Vision/RegionGenerator.h:1.4
*** Tekkotsu/Vision/RegionGenerator.h:1.3	Sun Jan 18 05:16:59 2004
--- Tekkotsu/Vision/RegionGenerator.h	Wed Feb  4 21:46:41 2004
***************
*** 8,13 ****
--- 8,18 ----
  
  //! Connects regions of CMVision format runs in RLEGenerator
  /*! Uses the CMVision library for main processing.
+  *
+  *  getImage() will return an array of RegionGenerator::region_stats -
+  *  one entry per color.  This will give you some statistics on colors
+  *  present, as well as the head of a linked list through regions of
+  *  each color in the image.
   *  
   *  Uses fields in the RLEGenerator's runs to store region
   *  information.  This means we don't have to make an extra copy of
***************
*** 71,80 ****
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.3 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:59 $
   */
  
  #endif
--- 76,85 ----
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/02/05 02:46:41 $
   */
  
  #endif
Index: Tekkotsu/Vision/SegmentedColorGenerator.h
diff -c Tekkotsu/Vision/SegmentedColorGenerator.h:1.4 Tekkotsu/Vision/SegmentedColorGenerator.h:1.5
*** Tekkotsu/Vision/SegmentedColorGenerator.h:1.4	Sun Jan 18 05:16:59 2004
--- Tekkotsu/Vision/SegmentedColorGenerator.h	Thu Feb  5 18:33:48 2004
***************
*** 36,41 ****
--- 36,53 ----
   *
   *  Uses the CMVision library for main processing
   *
+  *  The format used for serialization is: (code is in SaveBuffer())
+  *  - <@c FilterBankGenerator: superclass header> <i>(First saves the superclass's info)</i>
+  *  - <@c string: "SegColorImage"> <i>(remember a 'string' is len+str+0; so this is the literal "\015\0\0\0SegColorImage\0"; also remember "\015" is octal for 13)</i>
+  *  - <<tt>char[</tt>width<tt>*</tt>height<tt>]</tt>: image data> <i>(one byte per sample)</i>
+  *  - <@c unsigned @c int: num_cols> <i>(number of different colors available)</i>
+  *  - for each of num_col:
+  *    - <@c char: red> <i>red color to use for display of this index</i>
+  *    - <@c char: green> <i>green color to use for display of this index</i>
+  *    - <@c char: blue> <i>blue color to use for display of this index</i>
+  *
+  *  For more information on serialization, see FilterBankGenerator
+  *
   */
  class SegmentedColorGenerator : public FilterBankGenerator {
  public:
***************
*** 126,135 ****
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0 $
!  * $Revision: 1.4 $
   * $State: Exp $
!  * $Date: 2004/01/18 10:16:59 $
   */
  
  #endif
--- 138,147 ----
   * @author ejt (reorganized)
   *
   * $Author: ejt $
!  * $Name: tekkotsu-2_0_1 $
!  * $Revision: 1.5 $
   * $State: Exp $
!  * $Date: 2004/02/05 23:33:48 $
   */
  
  #endif
Index: Tekkotsu/docs/doxygencfg
diff -c Tekkotsu/docs/doxygencfg:1.27 Tekkotsu/docs/doxygencfg:1.28
*** Tekkotsu/docs/doxygencfg:1.27	Wed Jan  7 00:30:37 2004
--- Tekkotsu/docs/doxygencfg	Wed Jan 21 15:18:59 2004
***************
*** 23,29 ****
  # This could be handy for archiving the generated documentation or 
  # if some version control system is used.
  
! PROJECT_NUMBER         = 2.0
  
  # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
  # base path where the generated documentation will be put. 
--- 23,29 ----
  # This could be handy for archiving the generated documentation or 
  # if some version control system is used.
  
! PROJECT_NUMBER         = 2.0.1
  
  # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
  # base path where the generated documentation will be put. 
Index: Tekkotsu/docs/benchmarks/STARTUP_2.0.txt
diff -c /dev/null Tekkotsu/docs/benchmarks/STARTUP_2.0.txt:1.1
*** /dev/null	Thu Feb  5 23:36:01 2004
--- Tekkotsu/docs/benchmarks/STARTUP_2.0.txt	Wed Feb  4 16:56:11 2004
***************
*** 0 ****
--- 1 ----
+ !root "Mode Switch" "StareAtBallBehavior" ; !root "Status Reports" ; !next
\ No newline at end of file
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.1.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.1.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.1.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.1.txt:1.1	Wed Jan 21 01:50:25 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.1.txt	Wed Feb  4 16:54:44 2004
***************
*** 1,3 ****
--- 1,7 ----
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
  ~~~ Main: ~~~
  Profiling information since: 15.876455 to 288.321160
  ReadySendJoints():
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.4.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.4.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.4.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.4.txt:1.1	Wed Jan 21 01:50:25 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.4.txt	Wed Feb  4 16:54:44 2004
***************
*** 8,13 ****
--- 8,18 ----
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
  
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
+ 
  ~~~ Main: ~~~
  Profiling information since: 16.514395 to 298.147164
  ReadySendJoints():
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.5.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.5.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.5.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.5.txt:1.1	Wed Jan 21 01:50:26 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210A_1.5.txt	Wed Feb  4 16:54:44 2004
***************
*** 3,14 ****
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
! 	Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
  
  ~~~ Main: ~~~
  Profiling information since: 19.001622 to 299.518935
--- 3,19 ----
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!   Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
+ 
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
  
  ~~~ Main: ~~~
  Profiling information since: 19.001622 to 299.518935
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210A_2.0.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210A_2.0.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210A_2.0.txt:1.3
*** Tekkotsu/docs/benchmarks/profilerun_ERS210A_2.0.txt:1.1	Wed Jan 21 01:49:37 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210A_2.0.txt	Wed Feb  4 16:55:32 2004
***************
*** 1,9 ****
  Setup:
!   Default build for ERS-2xx
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!         Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
--- 1,9 ----
  Setup:
!   Default build for ERS-2xx (TGT_ERS2xx)
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!   Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
***************
*** 95,114 ****
          Inter: 6556 6809 7 0 0 0 0 0 6685 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  Bucket distribution (in ms):
          0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
- ~~~ Motion: ~~~
- Profiling information since: 19.785633 to 298.247647
- ReadySendJoints():
-         8666 calls
-         1.455931 ms avg
-         1.370247 ms exp.avg
-         0.000000 ms avg child time (0.000000%)
-         32.018965 ms avg inter (31.231490 fps)
-         32.089188 ms exp.avg (31.163143 fps)
-         Exec: 0 0 5 8617 26 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-         Inter: 0 0 0 0 0 0 0 8647 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- Bucket distribution (in ms):
-         0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
- 04,
  ~~~ Motion: ~~~
  Profiling information since: 19.785633 to 298.247647
  ReadySendJoints():
--- 95,100 ----
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210_1.1.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210_1.1.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210_1.1.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210_1.1.txt:1.1	Wed Jan 21 01:50:26 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210_1.1.txt	Wed Feb  4 16:54:44 2004
***************
*** 1,3 ****
--- 1,7 ----
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
  ~~~ Main: ~~~
  Profiling information since: 17.301167 to 495.839409
  ReadySendJoints():
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210_1.4.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210_1.4.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210_1.4.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210_1.4.txt:1.1	Wed Jan 21 01:50:26 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210_1.4.txt	Wed Feb  4 16:54:44 2004
***************
*** 8,13 ****
--- 8,18 ----
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
  
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
+ 
  ~~~ Main: ~~~
  Profiling information since: 17.873253 to 297.798167
  ReadySendJoints():
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210_1.5.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS210_1.5.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS210_1.5.txt:1.2
*** Tekkotsu/docs/benchmarks/profilerun_ERS210_1.5.txt:1.1	Wed Jan 21 01:50:26 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210_1.5.txt	Wed Feb  4 16:54:44 2004
***************
*** 3,14 ****
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
! 	Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
  
  ~~~ Main: ~~~
  Profiling information since: 21.308397 to 301.154604
--- 3,19 ----
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!   Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
+ 
+ Note: The profile reporting code for this version contained a bug -
+   the inter-call times shown here are in seconds, not milliseconds as
+   they should be.  Frames per second (fps) are accurate however.
+ 
  
  ~~~ Main: ~~~
  Profiling information since: 21.308397 to 301.154604
Index: Tekkotsu/docs/benchmarks/profilerun_ERS210_2.0.txt
diff -c /dev/null Tekkotsu/docs/benchmarks/profilerun_ERS210_2.0.txt:1.1
*** /dev/null	Thu Feb  5 23:36:01 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS210_2.0.txt	Wed Feb  4 16:55:32 2004
***************
*** 0 ****
--- 1,110 ----
+ Setup:
+   Default build for ERS-2xx (TGT_ERS2xx)
+   Pink ball in view (8.5in from snout)
+   Press power button, start timer
+   Telnet to system console (port 59000)
+   Connect ControllerGUI
+   STARTUP script:
+     Launch StareAtBallBehavior (leave E-Stop ON)
+     Navigate to Status Reports -> Profiler
+   Wait until 5 minutes from initial press of power button.
+   Recorded profiler run shown below
+  
+ ~~~ Main: ~~~
+ Profiling information since: 22.360923 to 297.996532
+ ReadySendJoints():
+         2131 calls
+         0.540960 ms avg
+         0.457356 ms exp.avg
+         0.002564 ms avg child time (0.400000%)
+         128.976324 ms avg inter (7.753361 fps)
+         127.247513 ms exp.avg (7.858700 fps)
+         Exec: 0 0 1713 412 4 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 1 1 0 0 0 0 0 0 1 1719 406 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
+ GotSensorFrame():
+         8512 calls
+         1.015543 ms avg
+         1.263109 ms exp.avg
+         0.000000 ms avg child time (0.000000%)
+         32.255509 ms avg inter (31.002456 fps)
+         34.675621 ms exp.avg (28.838705 fps)
+         Exec: 0 0 3446 4341 723 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 1 1705 2404 4399 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
+ GotImage():
+         6793 calls
+         19.973807 ms avg
+         20.604860 ms exp.avg
+         17.484691 ms avg child time (87.500000%)
+         40.369013 ms avg inter (24.771475 fps)
+         40.013283 ms exp.avg (24.991701 fps)
+         Exec: 0 0 2 14 37 11 5629 1100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 1 2 4 6784 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
+ PowerEvent():
+         48 calls
+         53.819062 ms avg
+         1.865914 ms exp.avg
+         0.000000 ms avg child time (0.000000%)
+         5662.596208 ms avg inter (0.176597 fps)
+         4460.506836 ms exp.avg (0.224190 fps)
+         Exec: 0 0 39 7 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 0 0 0 0 0 0 1 0 8 0 0 0 0 0 0 6 12 0 0 0 6 0 2 0 1 0 11
+ BallDetection::processEvent():
+         20361 calls
+         5.833383 ms avg
+         5.349741 ms exp.avg
+         5.637487 ms avg child time (96.600000%)
+         13.342345 ms avg inter (74.949346 fps)
+         12.608443 ms exp.avg (79.311935 fps)
+         Exec: 6328 6915 303 86 1 0 6708 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 6421 331 92 2 0 7726 5739 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ RegionGenerator::calcImage(...):
+         6728 calls
+         17.060771 ms avg
+         17.218710 ms exp.avg
+         10.590478 ms avg child time (62.000000%)
+         40.086258 ms avg inter (24.946205 fps)
+         40.083950 ms exp.avg (24.947641 fps)
+         Exec: 0 0 0 0 0 0 6723 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 0 0 1 6726 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ RLEGenerator::calcImage(...):
+         6728 calls
+         10.590478 ms avg
+         11.163483 ms exp.avg
+         6.884777 ms avg child time (65.000000%)
+         40.086576 ms avg inter (24.946007 fps)
+         40.083817 ms exp.avg (24.947723 fps)
+         Exec: 0 0 0 0 0 3369 3359 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 0 0 1 6726 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ SegmentedColorGenerator::calcImage(...):
+         6728 calls
+         6.884777 ms avg
+         6.973531 ms exp.avg
+         0.039570 ms avg child time (0.500000%)
+         40.086349 ms avg inter (24.946148 fps)
+         40.083889 ms exp.avg (24.947680 fps)
+         Exec: 0 0 0 0 0 6727 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 0 0 1 6726 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ RawCameraGenerator::calcImage(...):
+         20184 calls
+         0.013190 ms avg
+         0.011211 ms exp.avg
+         0.000000 ms avg child time (0.000000%)
+         13.358101 ms avg inter (74.860942 fps)
+         11.271330 ms exp.avg (88.720680 fps)
+         Exec: 12971 7078 134 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 13193 262 1 0 0 0 1 6726 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ Bucket distribution (in ms):
+         0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
+ ~~~ Motion: ~~~
+ Profiling information since: 22.362415 to 298.016580
+ ReadySendJoints():
+         8564 calls
+         2.516969 ms avg
+         2.582997 ms exp.avg
+         0.000000 ms avg child time (0.000000%)
+         32.070305 ms avg inter (31.181493 fps)
+         31.978659 ms exp.avg (31.270855 fps)
+         Exec: 0 0 0 3116 5405 23 0 2 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+         Inter: 0 0 0 0 0 0 1 8545 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ Bucket distribution (in ms):
+         0<0.00802, <0.133, <0.686, <2.2, <5.43, <11.4, <21.2, <36.4, <58.7, <90, <132, <188, <260, <352, <465, <604, <772, <973, <1.21e+03, <1.49e+03, <1.82e+03, <2.19e+03, <2.63e+03, <3.12e+03, <3.68e+03, <4.31e+03, <5.03e+03, <5.82e+03, <6.71e+03, <7.7e+03, <8.79e+03, <1e+04,
Index: Tekkotsu/docs/benchmarks/profilerun_ERS7_2.0.txt
diff -c Tekkotsu/docs/benchmarks/profilerun_ERS7_2.0.txt:1.1 Tekkotsu/docs/benchmarks/profilerun_ERS7_2.0.txt:1.3
*** Tekkotsu/docs/benchmarks/profilerun_ERS7_2.0.txt:1.1	Wed Jan 21 01:49:37 2004
--- Tekkotsu/docs/benchmarks/profilerun_ERS7_2.0.txt	Wed Feb  4 16:55:32 2004
***************
*** 1,14 ****
  Setup:
!   Default build for ERS-2xx
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!         Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
  ~~~ Main: ~~~
  Profiling information since: 17.877452 to 298.174793
  ReadySendJoints():
--- 1,15 ----
  Setup:
!   Default build for ERS-7 (TGT_ERS7)
    Pink ball in view (8.5in from snout)
    Press power button, start timer
    Telnet to system console (port 59000)
!   Connect ControllerGUI
    STARTUP script:
      Launch StareAtBallBehavior (leave E-Stop ON)
      Navigate to Status Reports -> Profiler
    Wait until 5 minutes from initial press of power button.
    Recorded profiler run shown below
+ 
  ~~~ Main: ~~~
  Profiling information since: 17.877452 to 298.174793
  ReadySendJoints():
Index: Tekkotsu/docs/html/index.html
diff -c Tekkotsu/docs/html/index.html:1.23 Tekkotsu/docs/html/index.html:1.27
*** Tekkotsu/docs/html/index.html:1.23	Mon Nov 10 23:35:58 2003
--- Tekkotsu/docs/html/index.html	Thu Feb  5 22:33:08 2004
***************
*** 81,87 ****
  want
  to visit the <a target="_top" href="../Overview.html">overview</a>.</p>
        <ul style="margin-left: 40px;">
!         <li><a href="classes.htm">Alphabetical Index</a> - Lists all
  classes and structs<br>
          </li>
          <li><a href="annotated.html">Compound List</a> - Gives a short
--- 81,87 ----
  want
  to visit the <a target="_top" href="../Overview.html">overview</a>.</p>
        <ul style="margin-left: 40px;">
!         <li><a href="classes.html">Alphabetical Index</a> - Lists all
  classes and structs<br>
          </li>
          <li><a href="annotated.html">Compound List</a> - Gives a short
***************
*** 94,100 ****
  variables and macros which aren't in namespaces<br>
          </li>
          <li><a href="pages.html">Related Pages</a> - Links to the <a
!  href="todo.html">todo</a> and <a href="bug.htm">bug</a> lists.</li>
          <li>You can also search the framework:<br>
            <form action="http://cvs.tekkotsu.org/search.php" method="get" name="doxyform"><input
   value="0" name="page" type="hidden"><input value="" maxlength="1000"
--- 94,100 ----
  variables and macros which aren't in namespaces<br>
          </li>
          <li><a href="pages.html">Related Pages</a> - Links to the <a
!  href="todo.html">todo</a> and <a href="bug.html">bug</a> lists.</li>
          <li>You can also search the framework:<br>
            <form action="http://cvs.tekkotsu.org/search.php" method="get" name="doxyform"><input
   value="0" name="page" type="hidden"><input value="" maxlength="1000"
***************
*** 121,128 ****
  static copies of the documentation, there are two formats:<br>
        </p>
        <ul style="margin-left: 40px;">
!         <li><a href="../media/Tekkotsu_doc_1.5.tar.gz">HTML</a> (v1.5,
! 5.4MB)</li>
        </ul>
        <div style="margin-left: 40px;">If you're using the most recent
  version from the <a href="http://cvs.tekkotsu.org/">CVS repository</a>,
--- 121,128 ----
  static copies of the documentation, there are two formats:<br>
        </p>
        <ul style="margin-left: 40px;">
!         <li><a href="../media/Tekkotsu_doc_2.0.1.tar.gz">HTML</a> (v2.0.1,
! 3.8MB)</li>
        </ul>
        <div style="margin-left: 40px;">If you're using the most recent
  version from the <a href="http://cvs.tekkotsu.org/">CVS repository</a>,
Index: Tekkotsu/project/Makefile
diff -c Tekkotsu/project/Makefile:1.56 Tekkotsu/project/Makefile:1.59
*** Tekkotsu/project/Makefile:1.56	Tue Dec 23 01:33:44 2003
--- Tekkotsu/project/Makefile	Mon Feb  2 17:36:51 2004
***************
*** 126,132 ****
  CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makelowercase
  
  BINSUFFIX=.bin
! INSTALLDIR=ms/open-r/mw/objs
  MMCOMBOBIN=mmcombo.bin
  MAINFORK=mainobj.bin
  MOTOFORK=motoobj.bin
--- 126,133 ----
  CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makelowercase
  
  BINSUFFIX=.bin
! MSIMGDIR=ms
! INSTALLDIR=$(MSIMGDIR)/open-r/mw/objs
  MMCOMBOBIN=mmcombo.bin
  MAINFORK=mainobj.bin
  MOTOFORK=motoobj.bin
***************
*** 134,140 ****
  else
  
  PROCESSES=MMCOMBO TINYFTPD SNDPLAY
! MMCOMBO_OBJS:=$(MAIN_SRCS:$(SRCSUFFIX)=.o) $(MAIN_SRCS:$(SRCSUFFIX)=.a) $(TEKKOTSU_ROOT)/$(BUILDDIR)/MMCombo.o
  MMCOMBO_OCF:=$(TEKKOTSU_ROOT)/MMCombo/MMCombo.ocf
  TINYFTPD_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/TinyFTPD.o
  TINYFTPD_OCF:=$(TEKKOTSU_ROOT)/TinyFTPD/TinyFTPD.ocf
--- 135,141 ----
  else
  
  PROCESSES=MMCOMBO TINYFTPD SNDPLAY
! MMCOMBO_OBJS:=$(MAIN_SRCS:$(SRCSUFFIX)=.o) $(TEKKOTSU_ROOT)/$(BUILDDIR)/MMCombo.o
  MMCOMBO_OCF:=$(TEKKOTSU_ROOT)/MMCombo/MMCombo.ocf
  TINYFTPD_OBJS:=$(TEKKOTSU_ROOT)/$(BUILDDIR)/TinyFTPD.o
  TINYFTPD_OCF:=$(TEKKOTSU_ROOT)/TinyFTPD/TinyFTPD.ocf
***************
*** 143,149 ****
  CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makeuppercase
  
  BINSUFFIX=.BIN
! INSTALLDIR=MS/OPEN-R/MW/OBJS
  MMCOMBOBIN=MMCOMBO.BIN
  MAINFORK=MAINOBJ.BIN
  MOTOFORK=MOTOOBJ.BIN
--- 144,151 ----
  CONVERTCASE=$(TEKKOTSU_ROOT)/tools/makeuppercase
  
  BINSUFFIX=.BIN
! MSIMGDIR=MS
! INSTALLDIR=$(MSIMGDIR)/OPEN-R/MW/OBJS
  MMCOMBOBIN=MMCOMBO.BIN
  MAINFORK=MAINOBJ.BIN
  MOTOFORK=MOTOOBJ.BIN
***************
*** 241,247 ****
  		echo "Copying system files..." ; \
  		cp -r $(OPENRSDK_ROOT)/OPEN_R/MS/WCONSOLE/nomemprot $$image ; \
  		chmod -R u+w $$image ; \
! 		$(CONVERTCASE) -r $$image ; \
  		rm -f $$image/open-r/mw/conf/connect.cfg $$image/open-r/mw/conf/object.cfg $$image/open-r/system/conf/wlandflt.txt ; \
  		curt=`date +%Y%m%d%H%M`; \
  		find $$image -exec touch -ft $$curt \{\} \; ; \
--- 243,249 ----
  		echo "Copying system files..." ; \
  		cp -r $(OPENRSDK_ROOT)/OPEN_R/MS/WCONSOLE/nomemprot $$image ; \
  		chmod -R u+w $$image ; \
! 		(cd $$image; $(CONVERTCASE) -r . ); \
  		rm -f $$image/open-r/mw/conf/connect.cfg $$image/open-r/mw/conf/object.cfg $$image/open-r/system/conf/wlandflt.txt ; \
  		curt=`date +%Y%m%d%H%M`; \
  		find $$image -exec touch -ft $$curt \{\} \; ; \
***************
*** 407,440 ****
  
  #INSTALL_BINS:     (compressed executables, in proper location in image directory)
  $(INSTALLDIR)/%$(BINSUFFIX): $(BUILDDIR)/%$(BINSUFFIX)
  	@echo "Compressing $< -> $@"
  	@gzip -c $< > $@;
  
  $(INSTALLDIR)/$(MMCOMBOBIN): $(INSTALLDIR)/$(MAINFORK) $(INSTALLDIR)/$(MOTOFORK)
  
  $(INSTALLDIR)/$(MAINFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
  	@echo "Compressing $< ~> $@"
  	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MainObj | gzip -c > $@
  #	@sed 's/MMCombo/MainObj/g;s/mmcombo/mainobj/g' $< | gzip -c > $@
  
  $(INSTALLDIR)/$(MOTOFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
  	@echo "Compressing $< ~> $@"
  	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MotoObj | gzip -c > $@
  #	@sed 's/MMCombo/MotoObj/g;s/mmcombo/motoobj/g' $< | gzip -c > $@
  
  install: compile
  	@echo "Installing files to memory stick at $(MEMSTICK_ROOT)"
! 	@$(TEKKOTSU_ROOT)/tools/cpymem --all --img ms --tgt $(MEMSTICK_ROOT) --tools $(TEKKOTSU_ROOT)/tools
  
  update: compile $(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime
! 	@echo "Syncing ms and $(MEMSTICK_ROOT)"
! 	@$(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime `find ms`
  	@$(TEKKOTSU_ROOT)/tools/mntmem $(MEMSTICK_ROOT)
  	@if [ $(STRICT_MEMSTICK_IMAGE) ] ; then \
  		echo "Strict image copy is on." ; \
! 		rsync -rLtWCv --delete ms/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
  	else \
! 		rsync -rLtWCv ms/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
  	fi;
  	@$(TEKKOTSU_ROOT)/tools/umntmem $(MEMSTICK_ROOT)
  
--- 409,454 ----
  
  #INSTALL_BINS:     (compressed executables, in proper location in image directory)
  $(INSTALLDIR)/%$(BINSUFFIX): $(BUILDDIR)/%$(BINSUFFIX)
+ 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
+ 		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+ 		exit 1; \
+ 	fi;
  	@echo "Compressing $< -> $@"
  	@gzip -c $< > $@;
  
  $(INSTALLDIR)/$(MMCOMBOBIN): $(INSTALLDIR)/$(MAINFORK) $(INSTALLDIR)/$(MOTOFORK)
  
  $(INSTALLDIR)/$(MAINFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
+ 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
+ 		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+ 		exit 1; \
+ 	fi;
  	@echo "Compressing $< ~> $@"
  	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MainObj | gzip -c > $@
  #	@sed 's/MMCombo/MainObj/g;s/mmcombo/mainobj/g' $< | gzip -c > $@
  
  $(INSTALLDIR)/$(MOTOFORK): $(BUILDDIR)/$(MMCOMBOBIN) $(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap
+ 	@if [ \! -d "$(INSTALLDIR)" ] ; then \
+ 		echo "I can't find $(INSTALLDIR).  You may need to run '$(TEKKOTSU_ROOT)/tools/makeuppercase -r ms'."; \
+ 		exit 1; \
+ 	fi;
  	@echo "Compressing $< ~> $@"
  	@$(TEKKOTSU_ROOT)/tools/binstrswap/binstrswap $< MMCombo MotoObj | gzip -c > $@
  #	@sed 's/MMCombo/MotoObj/g;s/mmcombo/motoobj/g' $< | gzip -c > $@
  
  install: compile
  	@echo "Installing files to memory stick at $(MEMSTICK_ROOT)"
! 	@$(TEKKOTSU_ROOT)/tools/cpymem --all --img $(MSIMGDIR) --tgt $(MEMSTICK_ROOT) --tools $(TEKKOTSU_ROOT)/tools
  
  update: compile $(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime
! 	@echo "Syncing $(MSIMGDIR) and $(MEMSTICK_ROOT)"
! 	@$(TEKKOTSU_ROOT)/tools/evenmodtime/evenmodtime `find $(MSIMGDIR)`
  	@$(TEKKOTSU_ROOT)/tools/mntmem $(MEMSTICK_ROOT)
  	@if [ $(STRICT_MEMSTICK_IMAGE) ] ; then \
  		echo "Strict image copy is on." ; \
! 		rsync -rLtWCv --delete $(MSIMGDIR)/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
  	else \
! 		rsync -rLtWCv $(MSIMGDIR)/* $(BUILDDIR)/$(notdir $(MEMSTICK_ROOT))/* $(MEMSTICK_ROOT) ; \
  	fi;
  	@$(TEKKOTSU_ROOT)/tools/umntmem $(MEMSTICK_ROOT)
  
Index: Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc
diff -c Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc:1.15 Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc:1.17
*** Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc:1.15	Wed Jan 21 00:48:58 2004
--- Tekkotsu/project/StartupBehavior_SetupModeSwitch.cc	Thu Feb  5 18:57:40 2004
***************
*** 26,32 ****
  		BehaviorSwitchControlBase::BehaviorGroup * bg = new BehaviorSwitchControlBase::BehaviorGroup();
  
  		//put behaviors here:
! 		if(state->robotDesign&WorldState::ERS210Mask) //this one only really works on the 210
  			addItem(new BehaviorSwitchControl<AlanBehavior>("AlanBehavior",bg,false));
  		addItem(new BehaviorSwitchControl<FollowHeadBehavior>("FollowHeadBehavior",bg,false));
  		addItem(new BehaviorSwitchControl<SoundTestBehavior>("SoundTestBehavior",bg,false));
--- 26,32 ----
  		BehaviorSwitchControlBase::BehaviorGroup * bg = new BehaviorSwitchControlBase::BehaviorGroup();
  
  		//put behaviors here:
! 		if(state->robotDesign&(WorldState::ERS210Mask|WorldState::ERS7Mask)) //this one only really works on the 210 or 7
  			addItem(new BehaviorSwitchControl<AlanBehavior>("AlanBehavior",bg,false));
  		addItem(new BehaviorSwitchControl<FollowHeadBehavior>("FollowHeadBehavior",bg,false));
  		addItem(new BehaviorSwitchControl<SoundTestBehavior>("SoundTestBehavior",bg,false));
Index: Tekkotsu/project/StartupBehavior_SetupVision.cc
diff -c Tekkotsu/project/StartupBehavior_SetupVision.cc:1.11 Tekkotsu/project/StartupBehavior_SetupVision.cc:1.12
*** Tekkotsu/project/StartupBehavior_SetupVision.cc:1.11	Tue Jan 20 22:53:28 2004
--- Tekkotsu/project/StartupBehavior_SetupVision.cc	Thu Feb  5 14:35:47 2004
***************
*** 54,60 ****
  
  	defGrayscaleJPEGGenerator = new JPEGGenerator(EventBase::visRawCameraEGID,visRawCameraSID,visGrayscaleJPEGSID,JPEGGenerator::SRC_AUTO);
  	defGrayscaleJPEGGenerator->DoStart();
! 	defGrayscaleJPEGGenerator->setName("ColorGrayscaleGenerator");
  	spawned.push_back(defGrayscaleJPEGGenerator);
  
  	// the hardware level CDT generator allows faster, but less flexible
--- 54,60 ----
  
  	defGrayscaleJPEGGenerator = new JPEGGenerator(EventBase::visRawCameraEGID,visRawCameraSID,visGrayscaleJPEGSID,JPEGGenerator::SRC_AUTO);
  	defGrayscaleJPEGGenerator->DoStart();
! 	defGrayscaleJPEGGenerator->setName("GrayscaleJPEGGenerator");
  	spawned.push_back(defGrayscaleJPEGGenerator);
  
  	// the hardware level CDT generator allows faster, but less flexible
Index: Tekkotsu/project/ms/config/7red.tm
Index: Tekkotsu/tools/buildRelease
diff -c Tekkotsu/tools/buildRelease:1.30 Tekkotsu/tools/buildRelease:1.34
*** Tekkotsu/tools/buildRelease:1.30	Wed Jan 21 02:42:14 2004
--- Tekkotsu/tools/buildRelease	Thu Feb  5 22:33:21 2004
***************
*** 39,50 ****
  
  cd Tekkotsu_$1;
  
! #if [ `grep -c default.tm project/ms/config/tekkotsu.cfg` -gt 0 ] ; then
! #	echo "You forgot to switch the thresholds file to the more general ball one";
! #	exit 1;
! #fi;
  
! if [ `grep PROJECT_NUMBER docs/doxygencfg | grep -c $1` -eq 0 ] ; then
  	echo "Version mismatch with docs/doxygencfg - you forgot to update PROJECT_NUMBER";
  	exit 1;
  fi;
--- 39,50 ----
  
  cd Tekkotsu_$1;
  
! if [ `grep PROJECT_NUMBER docs/doxygencfg | grep -c "$1"` -eq 0 ] ; then
! 	echo "Version mismatch with docs/doxygencfg - you forgot to update PROJECT_NUMBER";
! 	exit 1;
! fi;
  
! if [ `grep -c "$1" docs/html/index.html` -eq 0 ] ; then
  	echo "Version mismatch with docs/doxygencfg - you forgot to update PROJECT_NUMBER";
  	exit 1;
  fi;
***************
*** 59,65 ****
  	echo "Checking for docs/benchmarks/profilerun_${x}_$1.txt..."
  	if [ ! -f "docs/benchmarks/profilerun_${x}_$1.txt" ] ; then
  		echo "You forgot to include updated profile runs (docs/benchmarks)"
! 		exit 1;
  	fi;
  done;
  
--- 59,65 ----
  	echo "Checking for docs/benchmarks/profilerun_${x}_$1.txt..."
  	if [ ! -f "docs/benchmarks/profilerun_${x}_$1.txt" ] ; then
  		echo "You forgot to include updated profile runs (docs/benchmarks)"
! 		read -p "Press return to ignore... (^C to stop)"
  	fi;
  done;
  
Index: Tekkotsu/tools/makelowercase
diff -c Tekkotsu/tools/makelowercase:1.2 Tekkotsu/tools/makelowercase:1.3
*** Tekkotsu/tools/makelowercase:1.2	Sun Mar  9 02:41:38 2003
--- Tekkotsu/tools/makelowercase	Mon Feb  2 17:19:22 2004
***************
*** 1,6 ****
  #!/bin/sh
  
! # will convert specified files to lowercase names
  
  if [ "$1" = "-r" ] ; then
  	recurse=1; shift;
--- 1,6 ----
  #!/bin/sh
  
! # will convert specified files to lower names
  
  if [ "$1" = "-r" ] ; then
  	recurse=1; shift;
***************
*** 12,19 ****
  	if [ -r "$x" ] ; then
  		conv="`echo $x | tr '[A-Z]' '[a-z]'`";
  		if [ "$x" != "$conv" ] ; then
! 			mv $x ${x}.tmpcase;
! 			mv ${x}.tmpcase $conv;
  		fi;
  		if [ $recurse -gt 0 -a -d "$conv" ] ; then
  			$0 -r $conv/*;
--- 12,23 ----
  	if [ -r "$x" ] ; then
  		conv="`echo $x | tr '[A-Z]' '[a-z]'`";
  		if [ "$x" != "$conv" ] ; then
! 			if [ -e $conv ] ; then
! 				echo "ERROR: $conv already exists (from $x)";
! 				echo "exiting..."
! 				exit 1;
! 			fi;
! 			mv "$x" "$conv";
  		fi;
  		if [ $recurse -gt 0 -a -d "$conv" ] ; then
  			$0 -r $conv/*;
Index: Tekkotsu/tools/makeuppercase
diff -c Tekkotsu/tools/makeuppercase:1.2 Tekkotsu/tools/makeuppercase:1.3
*** Tekkotsu/tools/makeuppercase:1.2	Sun Mar  9 02:41:38 2003
--- Tekkotsu/tools/makeuppercase	Mon Feb  2 17:19:22 2004
***************
*** 1,6 ****
  #!/bin/sh
  
! # will convert specified files to lowercase names
  
  if [ "$1" = "-r" ] ; then
  	recurse=1; shift;
--- 1,6 ----
  #!/bin/sh
  
! # will convert specified files to uppercase names
  
  if [ "$1" = "-r" ] ; then
  	recurse=1; shift;
***************
*** 12,19 ****
  	if [ -r "$x" ] ; then
  		conv="`echo $x | tr '[a-z]' '[A-Z]'`";
  		if [ "$x" != "$conv" ] ; then
! 			mv $x ${x}.tmpcase;
! 			mv ${x}.tmpcase $conv;
  		fi;
  		if [ $recurse -gt 0 -a -d "$conv" ] ; then
  			$0 -r $conv/*;
--- 12,23 ----
  	if [ -r "$x" ] ; then
  		conv="`echo $x | tr '[a-z]' '[A-Z]'`";
  		if [ "$x" != "$conv" ] ; then
! 			if [ -e $conv ] ; then
! 				echo "ERROR: $conv already exists (from $x)";
! 				echo "exiting..."
! 				exit 1;
! 			fi;
! 			mv "$x" "$conv";
  		fi;
  		if [ $recurse -gt 0 -a -d "$conv" ] ; then
  			$0 -r $conv/*;
Index: Tekkotsu/tools/untag.txt
diff -c Tekkotsu/tools/untag.txt:1.7 Tekkotsu/tools/untag.txt:removed
*** Tekkotsu/tools/untag.txt:1.7	Fri Oct 10 14:22:50 2003
--- Tekkotsu/tools/untag.txt	Thu Feb  5 23:36:02 2004
***************
*** 1,4 ****
- project/SampleBehavior.h
- project/SampleMC.h
- Behaviors/Demos/PaceTargetsMachine.h
- Behaviors/Demos/PaceTargetsMachine.cc
--- 0 ----
Index: Tekkotsu/tools/mon/c_statejoints.m
diff -c Tekkotsu/tools/mon/c_statejoints.m:1.1 Tekkotsu/tools/mon/c_statejoints.m:1.2
*** Tekkotsu/tools/mon/c_statejoints.m:1.1	Thu Feb 20 14:51:18 2003
--- Tekkotsu/tools/mon/c_statejoints.m	Wed Jan 28 15:38:50 2004
***************
*** 63,72 ****
  ypos=ypos+ystep;
  [pos(13),duty(13)]=addjoint(0.05,ypos,'Head','Tilt',linedata);
  [pos(16),duty(16)]=addjoint(0.55,ypos,'Misc','Tail Tilt',linedata);
  drawnow;
  statejoints.lines_pos=pos;
  statejoints.lines_duty=duty;
! statejoints.obj=WorldStateJointsListener(conf.ip,conf.port_statejoints);
  
  function iter
  global statejoints
--- 63,76 ----
  ypos=ypos+ystep;
  [pos(13),duty(13)]=addjoint(0.05,ypos,'Head','Tilt',linedata);
  [pos(16),duty(16)]=addjoint(0.55,ypos,'Misc','Tail Tilt',linedata);
+ ypos=ypos+ystep;
+ [but(1),but(2),but(3),but(4)]=addbuttons(0.05,ypos,'Buttons','Buttons 1-4',linedata);
+ [but(5),but(6),but(7),but(8)]=addbuttons(0.55,ypos,'Buttons','Buttons 5-8',linedata);
  drawnow;
  statejoints.lines_pos=pos;
  statejoints.lines_duty=duty;
! statejoints.lines_but=but;
! statejoints.obj=org.tekkotsu.mon.WorldStateJointsListener(conf.ip,conf.port_statejoints);
  
  function iter
  global statejoints
***************
*** 74,85 ****
--- 78,94 ----
    data=statejoints.obj.getData;
    positions=double(data.positions);
    duties=double(data.duties);
+   buttons=double(data.buttons);
    for i=1:18
      ydata=get(statejoints.lines_pos(i),'YData');
      set(statejoints.lines_pos(i),'YData',[ydata(2:300) positions(i)]);
      ydata=get(statejoints.lines_duty(i),'YData');
      set(statejoints.lines_duty(i),'YData',[ydata(2:300) duties(i)]);
    end
+   for i=1:8
+     ydata=get(statejoints.lines_but(i),'YData');
+     set(statejoints.lines_but(i),'YData',[ydata(2:300) (buttons(i)/2+mod(i-1,4))]);
+   end
  end
  
  function stop
***************
*** 103,105 ****
--- 112,129 ----
  hold on
  pos=plot(initplot,'Color','b');
  duty=plot(initplot,'Color','r');
+ 
+ function [but1,but2,but3,but4]=addbuttons(xpos,ypos,name1,name2,initplot)
+ p=subplot('Position',[xpos ypos 0.4 0.075]);
+ set(p,'XTick',[]);
+ set(p,'YTick',-1:2:1);
+ set(p,'YTickLabel',{'1','2','3','4'});
+ set(p,'YLim',[0 4.5]);
+ ylabel(name2);
+ title(name1);
+ hold on
+ but1=plot(initplot,'Color','r');
+ but2=plot(initplot,'Color','g');
+ but3=plot(initplot,'Color','b');
+ but4=plot(initplot,'Color','m');
+ 
Index: Tekkotsu/tools/mon/config.m
diff -c Tekkotsu/tools/mon/config.m:1.12 Tekkotsu/tools/mon/config.m:1.13
*** Tekkotsu/tools/mon/config.m:1.12	Sun Aug  3 17:56:06 2003
--- Tekkotsu/tools/mon/config.m	Wed Jan 28 15:38:50 2004
***************
*** 3,9 ****
  
  %eventually parse single config file
  
! conf.ip='192.168.0.7'; % Aibo's IP address
  
  conf.port_stdout=10001;
  conf.port_stderr=10002;
--- 3,9 ----
  
  %eventually parse single config file
  
! conf.ip='172.16.1.2'; % Aibo's IP address
  
  conf.port_stdout=10001;
  conf.port_stderr=10002;
Index: Tekkotsu/tools/mon/ers220info.m
diff -c /dev/null Tekkotsu/tools/mon/ers220info.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/ers220info.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,28 ----
+ info.FrameTime=8;
+ info.NumFrames=4;
+ info.SlowFrameTime=128;
+ info.NumSlowFrames=1;
+ info.SoundBufferTime=32;
+ info.NumPIDJoints=15
+ info.NumBinJoints=0;
+ info.NumLEDs=20;
+ info.NumOutputs=info.NumPIDJoints + info.NumBinJoints + info.NumLEDs;
+ info.isFastOutput=zeros(info.NumOutputs)+1; %all ok!
+ info.isRealERS220=info.isFastOutput %umm they're the same
+ info.JointsPerLeg=3;
+ info.NumLegs=4;
+ info.NumLegJoints=info.JointsPerLeg*info.NumLegs;
+ info.NumTailJoints=0;
+ info.NumMouthJoints=0;
+ info.NumEarJoints=0;
+ info.NumButtons=11;
+ info.NumSensors=1+3+1+5;
+ % offset data
+ info.LogOffset.positions=2;
+ info.LogOffset.duties=info.LogOffset.positions+info.NumPIDJoints;
+ info.LogOffset.sensors=info.LogOffset.duties+info.NumPIDJoints;
+ info.LogOffset.buttons=info.LogOffset.sensors+6;
+ info.SensorOffsetOf.IRDist=0;
+ info.SensorOffsetOf.BAccelOffset=1;
+ info.SensorOffsetOf.LAccelOffset=2;
+ info.SensorOffsetOf.DAccelOffset=3;
Index: Tekkotsu/tools/mon/ers2xxinfo.m
diff -c /dev/null Tekkotsu/tools/mon/ers2xxinfo.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/ers2xxinfo.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,59 ----
+ info.FrameTime=8;
+ info.NumFrames=4;
+ info.SlowFrameTime=128;
+ info.NumSlowFrames=1;
+ info.SoundBufferTime=32;
+ info.NumPIDJoints=18;
+ info.NumBinJoints=2;
+ info.NumLEDs=22;
+ info.NumOutputs=info.NumPIDJoints + info.NumBinJoints + info.NumLEDs;
+ info.isFastOutput=zeros(info.NumOutputs)+1; %this is a lie. but who cares?
+ info.isRealERS220=info.isFastOutput; %also a lie
+ info.JointsPerLeg=3;
+ info.NumLegs=4;
+ info.NumLegJoints=info.JointsPerLeg*info.NumLegs;
+ info.NumHeadJoints=3;
+ info.NumTailJoints=2;
+ info.NumMouthJoints=1;
+ info.NumEarJoints=2;
+ info.NumButtons=11;
+ info.NumSensors=1+3+1+5;  % 1 dist, 3 accel, 1 thermo, 5 from power, see SensorOffset_t
+ % offset data
+ info.legOrder={'lf'  'rf'  'lb'  'rb'};
+ info.legJointOrder={'Rotator' 'Elevator' 'Knee'};
+ info.headJointOrder={'Tilt' 'Pan' 'Roll'};
+ info.LogOffset.positions=2;
+ info.LogOffset.duties=info.LogOffset.positions+info.NumPIDJoints;
+ info.LogOffset.sensors=info.LogOffset.duties+info.NumPIDJoints;
+ info.LogOffset.buttons=info.LogOffset.sensors+6;
+ info.SensorOffsetOf.IRDist=0;
+ info.SensorOffsetOf.BAccelOffset=1;
+ info.SensorOffsetOf.LAccelOffset=2;
+ info.SensorOffsetOf.DAccelOffset=3;
+ 
+ %%%%old
+ %info.limbs.f_body_to_shoulder=[59.5 59.2 0];
+ %info.limbs.f_leg_shoulder_to_knee=[12.8 .5 -64];
+ %info.limbs.f_leg_knee_to_ball=[-18 0 -67.23];
+ %info.limbs.h_body_to_shoulder=[59.5 59.2 0];
+ %info.limbs.h_leg_shoulder_to_knee=[-12.8 .5 -64];
+ %info.limbs.h_leg_knee_to_ball=[-18 0 -74.87];
+ 
+ 
+ %note: these coordinates are off 90deg (forward left up)
+ info.limbs.f_body_to_shoulder=[59.5 59.2 0];
+ info.limbs.f_leg_shoulder_to_knee=[12.8 .5 -64];
+ info.limbs.f_leg_knee_to_ball=[-18 0 -67.23];
+ info.limbs.h_body_to_shoulder=[-59.5 59.2 0];
+ info.limbs.h_leg_shoulder_to_knee=[-12.8 .5 -64];
+ info.limbs.h_leg_knee_to_ball=[-18 0 -74.87];
+ 
+ %format: leg,joint,xyz (where +x=forward, +y=left, +z=up)
+ info.limblen=zeros(4,3,3);
+ info.limblen(1,:,:)=[ info.limbs.f_body_to_shoulder; info.limbs.f_leg_shoulder_to_knee; info.limbs.f_leg_knee_to_ball ] ; %lf 
+ %%%right is mirror of left
+ info.limblen(2,:,:)=[info.limblen(1,:,1)' , -info.limblen(1,:,2)' , info.limblen(1,:,3)' ]; %rf
+ info.limblen(3,:,:)=[info.limbs.h_body_to_shoulder; info.limbs.h_leg_shoulder_to_knee; info.limbs.h_leg_knee_to_ball ]  ; %lb
+ info.limblen(4,:,:)=[info.limblen(3,:,1)' , -info.limblen(3,:,2)' , info.limblen(3,:,3)' ]; %rf
+ 
+ info.walkheight=160;
Index: Tekkotsu/tools/mon/lognow
diff -c /dev/null Tekkotsu/tools/mon/lognow:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/lognow	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,2 ----
+ #!/bin/sh
+ java org/tekkotsu/mon/JointLogger $*
Index: Tekkotsu/tools/mon/plotlog.m
diff -c /dev/null Tekkotsu/tools/mon/plotlog.m:1.2
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/plotlog.m	Thu Feb  5 19:45:57 2004
***************
*** 0 ****
--- 1,319 ----
+ function plotlog(logfilein)
+      global logfile info jpl plotops legh ploth subp timeslider window aibopos jgraph pgraph posgraph bodyangle updatego legpos legspos samplecount bodypos extra plotlog_inited;
+      updatego=0;
+      ploth=[];
+      subp=[];
+      if(isempty(plotops))
+        plotops=struct('drawbuttons',1);
+      end
+      logfile=logfilein;
+   ers2xxinfo;
+ bodyangle=.20944;
+ samplecount=size(logfile,1);
+ aibopos=zeros(4,3,samplecount);
+ legpos=zeros(4,3,samplecount);
+ jpl=info.JointsPerLeg; %because it's used so much...
+   plotlog_inited=1;
+   jgraph=figure(1);
+   pgraph=figure(2);
+   posgraph=figure(3);
+   extra=figure(4);
+ 
+   set(jgraph,'Name','Joint positions');
+   set(pgraph,'Name','Aibo Feet Accumulator');
+   set(posgraph,'Name','Foot trajectory');
+   set(extra,'Name','Extra data');
+ 
+   figure(jgraph);
+ 
+ clf;
+ 
+   window=struct('size',logfile(end,1)-logfile(1,1),'start',logfile(1,1),'zoomfactor',1);
+ 
+   timeslider=uicontrol('style','slider','position',[100,0,100,20],'callback','setslide;');
+   zoomin=uicontrol('style','pushbutton','position',[250,0,50,20],'string','Zoom in','callback','zoomin;');
+   zoomout=uicontrol('style','pushbutton','position',[350,0,50,20],'string','Zoom out','callback','zoomout;');
+ 
+   for leg=1:4
+     plotleg(leg,getJointAngles(leg),getDuties(leg),getButton(leg));
+   end
+ 
+   legh=legend(info.legJointOrder{:},0);
+   posnow=get(legh,'position');
+   posnow(1:2)=[0 0];
+   set(legh,'position',posnow);
+   
+   %%%%basic stuff done
+ 
+ bodypos=trackMovement;
+ 
+ figure(pgraph);
+ clf;
+ plotpath;
+ figure(posgraph);
+ clf;
+ plotpos;
+ drawBody(bodypos);
+ 
+ %extra
+ figure(extra);
+ %rot=mod(bodypos(:,4),360);
+ rot=bodypos(:,4);
+ plot(rot);
+ 
+ %fit graph
+ 
+ updatego=1;
+ updateAxes; %really just fix slider
+ 
+ function plotleg(leg,position,duties,button)
+ global logfile info jpl ploth subp plotops window defax hb aibopos pgraph jgraph legpos;
+ ontime=extractButtonOn(button);
+   subp(end+1)=subplot(2,4,leg);
+   hb=plot(logfile(:,1),position)';
+   title([info.legOrder{leg} ' pos']);
+   if(plotops.drawbuttons~=0)
+     hold on
+     hb=[hb plot(logfile(ontime,1),position(ontime,:),'o')'];
+ plot(logfile(:,1),button,':k');
+   end
+   ploth=[ploth hb];
+   subp(end+1)=subplot(2,4,leg+4);
+   hb=plot(logfile(:,1),duties)';
+   title([info.legOrder{leg}, ' duties']);
+   if(plotops.drawbuttons~=0)
+     hold on
+     hb=[hb plot(logfile(ontime,1),duties(ontime,:),'o')'];
+   end
+   ploth=[ploth hb];
+   defax=axis;
+ 
+   %forward kinematics tracking:
+   for step=1:length(button)
+     legPoint(step,leg); %precalc legpositions
+   end
+   altbutton=getButton(mod(leg+2,4)+1);
+   for step=2:(length(button))
+ %    if(button(step)>0 | altbutton(step)>0) %counts feet as "down" if either front or back is on. this turns out to be bad
+     if(button(step)>0)
+       delta=legpos(leg,:,step)-legpos(leg,:,step-1);
+     else
+       delta=[0 0 0];
+     end
+     aibopos(leg,:,step)=aibopos(leg,:,step-1)-delta; %%aibo moves opposite of foot push
+   end
+ 
+ %aibopos=legpos; %%% testing hack!
+ 
+ function pos=getJointAngles(leg)
+      global logfile info jpl;
+ leg=leg-1;
+     pos=logfile(:,info.LogOffset.positions+leg*jpl:1:info.LogOffset.positions+((leg+1)*jpl-1));
+ 
+ function duties=getDuties(leg)
+      global logfile info jpl;
+ leg=leg-1;
+   duties=logfile(:,(leg*jpl+info.LogOffset.duties):1:((leg+1)*jpl+info.LogOffset.duties-1));
+      
+ function buttons=getButton(leg)
+      global logfile info jpl;
+ leg=leg-1;
+   buttons=logfile(:,info.LogOffset.buttons+leg);
+ 
+ function onidx=extractButtonOn(button)
+    onidx=find(button>0);
+ 
+ function onidx=findButtonOn(leg)
+    global logfile info jpl;
+    button=getButton(leg);
+    onidx=find(button>0);
+ 
+ %%%%%%%%%%%%%
+ %% gui stuff
+ %%%%%%%%%%%%%
+ 
+ 
+ 
+ %%%%%%%%%
+ %% Forward kinematics stuff
+ %%%%%%%%%
+ 
+ function R=rotate(x,y,z,theta)
+   c=cos(theta);
+   s=sin(theta);
+   t=1-cos(theta);
+   R=[t*x^2+c, t*x*y-s*z, t*x*z+s*y, 0; ...
+      t*x*y+s*z, t*y^2+c, t*y*z-s*x, 0; ...
+      t*x*z-s*y, t*y*z+s*x, t*z^2+c, 0; ...
+      0, 0, 0, 1 ];
+ 
+ function T=translate(t)
+   x=t(1);
+  y=t(2);
+ z=t(3);
+   T=[1, 0, 0, x ; ...
+      0, 1, 0, y ; ...
+      0, 0, 1, z ; ...
+      0, 0, 0, 1 ];
+ 
+ function dpt=diffPoints(t1,t2,leg)
+   global logfile info jpl legpos;
+   pos=getJointAngles(leg);
+   buttons=getButton(leg);
+ 
+   limblen=info.limblen(leg,:,:);
+   pos1=pos(t1,:);
+   pos2=pos(t2,:);
+   pt=[0 0 0 1]; %homogenous point baby
+   M=eye(4);
+ % my coordinate system: y+ = forward, x+ = right, z+ = up
+   M=M*translate( -limblen(:,:,1) ); %initial position separated from body
+   M=M*rotate(1,0,0,pos1(1)); %rotator - around x 
+   M=M*rotate(0,1,0,pos1(2)); %elevator - around y
+   M=M*translate( -limblen(:,:,2) );
+   M=M*rotate(1,0,0,pos1(3)); %knee - around x
+   M=M*translate( -limblen(:,:,3) );
+   groundpt1=M*pt';
+ 
+ %	   legpos(leg,:,t1)=groundpt1(1:3);
+ 
+   M=eye(4);
+   M=M*translate( -limblen(:,:,1) ); %initial position separated from body
+   M=M*rotate(1,0,0,pos1(1)); %rotator - around x 
+   M=M*rotate(0,1,0,pos1(2)); %elevator - around y
+   M=M*translate( -limblen(:,:,2) );
+   M=M*rotate(1,0,0,pos1(3)); %knee - around x
+   M=M*translate( -limblen(:,:,3) );
+   groundpt2=M*pt';
+ 
+ %	   legpos(leg,:,t1)=groundpt2(1:3);
+ 
+ %  if(buttons(t1)<1) % foot starting in air
+ %    dpt=[0,0,0]; %no movement
+ %    return; 
+ %else
+   dpt=groundpt1-groundpt2;
+ %end
+ 
+ ;  toerotateX=(pos1(3)-pos1(1))-(pos2(3)-pos2(1));
+ ;	   toerotateY=(pos1(2)-pos2(2));
+ ;  M=M*rotate(1,0,0,toerotateX); %assuming shoulder stays even height, and flat ground, parallel lines are your friend. this is basically change in toe-tilt
+ ;%  M=M*rotate(0,1,0,toerotateY);
+ ;  M=M*translate( limblen(:,:,3) );
+ ;  M=M*rotate(1,0,0,pos2(3)); %knee - around x
+ ;  M=M*translate( limblen(:,:,2) );
+ ;  M=M*rotate(0,1,0,pos2(2)); %elevator - around y
+ ;  M=M*rotate(1,0,0,pos2(1)); %rotator - around x 
+ ;  M=M*translate( limblen(:,:,1) );
+ ;  bodypt2=M*pt';
+ ;  dpt=bodypt2(1:3)';
+ 
+ 
+ function footpoint=legPoint(t1,leg)
+ global logfile info jpl legpos;
+ pos=getJointAngles(leg);
+ buttons=getButton(leg);
+ 
+ limblen=info.limblen(leg,:,:);
+ pos1=pos(t1,:);
+ pt=[0 0 0 1]; %homogenous point baby
+ M=eye(4);
+ if(leg>2) %if it's a back foot
+       pos1(1)=-pos1(1); %flip it's y rotation
+       pos1(3)=-pos1(3); %flip it's y rotation
+ end
+ % my coordinate system: x+ = forward, y+ = right, z+ = up
+ M=M*translate( limblen(:,1,:) ); %initial position separated from body
+ M=M*rotate(0,1,0,-pos1(1)); %rotator - around y (but +pos(1) means back on dog)
+ if(mod(leg,2)==0) %if it's a right foot...
+       pos1(2)=-pos1(2); %flip it's x rotation
+ end
+ M=M*rotate(1,0,0,pos1(2)); %elevator - around x
+ M=M*translate( limblen(:,2,:) );
+ M=M*rotate(0,1,0,-pos1(3)); %knee - around y
+ M=M*translate( limblen(:,3,:) );
+ footpoint=M*pt';
+ footpoint(2)=-footpoint(2); %flip the y data for our sanity...
+     legpos(leg,:,t1)=footpoint(1:3);
+ return;
+ 
+ 
+ function bodypos=trackMovement()
+ global logfile info jpl legpos aibopos samplecount;
+ 
+ centroid=orbitCenter;
+ ydiff=mean(centroid(1:2,3))-mean(centroid(3:4,3));
+ xdiff=mean(centroid(1:2,1))-mean(centroid(3:4,1));
+ downrot=-atan(ydiff/xdiff)/pi*180;
+ 
+ buttons=zeros(4,samplecount);
+ for leg=1:4
+   buttons(leg,:)=getButton(leg)';
+ end
+ 
+ bodypos=zeros(samplecount,6); % time, xyz pos | xyz rot
+ %pt=[0 0 0 1];
+ %M=eye(4);
+ %M=M*rotate(0,1,0,downrot); %standard 'cause our aibo points down usually and walks on flat ground
+ %for step=2:samplecount
+ %  delta=aibopos(:,:,step)-aibopos(:,:,step-1);
+ %  posdelta=legpos(:,:,step-1)-legpos(:,:,step);
+ %  posdelta=adjustDelta(M,posdelta);
+ %  buttonsOn=buttons(3,step) + buttons(4,step); % count of rear buttons on
+ % if(buttonsOn~=1) %if it only has 1 foot on the ground, it probably won't spin
+ %xdiff=delta([2 4],2)-delta([1 3],2);
+ %ydiff=delta([2 4],1)-delta([1 3],1);
+ % end
+ %%%%%%arrrr lost
+ %end
+ 
+ %%alternate sum method (straight forward distance traveled: GO!)
+ for step=2:samplecount
+   delta=aibopos(:,:,step)-aibopos(:,:,step-1);
+   dl=norm(delta(3,:));
+   dr=norm(delta(4,:));
+   rot=0;
+   if(buttons(3,step))
+     pairmag=dot(norm(delta(1,:)),norm(delta(3,:)));
+     twist=[delta(1,1)-delta(3,1), delta(1,2)-delta(3,2), delta(1,3)-delta(3,3)];
+     if(twist(1)==0)
+       degtwist=0;
+     else
+       degtwist=atan(twist(2)/twist(1))/pi*180;
+     end
+     rot=rot+degtwist;
+   end
+   if(buttons(4,step))
+     pairmag=dot(norm(delta(2,:)),norm(delta(4,:)));
+     twist=[delta(2,1)-delta(4,1), delta(2,2)-delta(4,2), delta(2,3)-delta(4,3)];
+     if(twist(1)==0)
+       degtwist=0;
+     else
+       degtwist=atan(twist(2)/twist(1))/pi*180;
+     end
+     rot=rot-degtwist;
+   end  
+   bodypos(step,1)=dl+dr+bodypos(step-1,1);
+   bodypos(step,4)=rot+bodypos(step-1,4);
+ end
+   
+   
+ function centers=orbitCenter()
+ global logfile info jpl legpos aibopos samplecount;
+ pos=zeros(3);
+ centers=permute(mean(permute(legpos,[3 1 2])),[2 3 1]) %yes it's a bitch, but it works
+ return;
+ 
+ function outpos=adjustDelta(M,inpos)
+ zeros(4,3);
+ for i=1:4
+   pt=[inpos(i,:) 1];
+   outpos(i,:)=pt*M;
+ end;
+ 
+ function drawBody(bodypos)
+ global logfile info jpl legpos aibopos samplecount pgraph;
+ 
+ figure(pgraph);
+ 
+ plot3(bodypos(:,1),bodypos(:,2),bodypos(:,3));
Index: Tekkotsu/tools/mon/plotpath.m
diff -c /dev/null Tekkotsu/tools/mon/plotpath.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/plotpath.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,27 ----
+ global aibopos timetags window;
+ clf;
+ grid on;
+ hold on;
+ %T=viewmtx(-20,56);
+ T=viewmtx(0,0);
+ %wtf doesn't this work?
+ view(T);
+ specs=['m' 'g' 'r' 'b'];
+ timetags=zeros(4,2);
+ for leg=1:4
+ %%hack to plot leg position instead
+ bob=permute(aibopos(leg,:,:),[3 2 1]);%
+ %bob=permute(legpos(leg,:,:),[3 2 1]);
+ plot3(bob(:,1),bob(:,2),bob(:,3),specs(leg));
+ end
+ legend('lf','rf','lb','rb');
+ ylabel('left-right');
+ xlabel('back-forward');
+ zlabel('down-up');
+ 
+ for leg=1:4
+ bob=permute(aibopos(leg,:,:),[3 2 1]);
+ %bob=permute(legpos(leg,:,:),[3 2 1]);
+ timetags(leg,:)=plot3(bob(1,1),bob(1,2),bob(1,3), [specs(leg) 'x'], ...
+     bob(end,1),bob(end,2),bob(end,3), [specs(leg) 'x'], 'MarkerSize',12)';
+ end
Index: Tekkotsu/tools/mon/plotpos.m
diff -c /dev/null Tekkotsu/tools/mon/plotpos.m:1.2
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/plotpos.m	Thu Feb  5 19:45:57 2004
***************
*** 0 ****
--- 1,51 ----
+ function plotpos
+ global aibopos trtimetags window plotops legpos bodypos;
+ clf;
+ grid on;
+ hold on;
+ T=viewmtx(0,0);
+ %wtf doesn't this work?
+ view(T);
+ specs=['m' 'g' 'r' 'b'];
+ timetags=zeros(4,2);
+ for leg=1:4
+   %%draw leg trajectory
+   bob=permute(legpos(leg,:,:),[3 2 1]);
+   plot3(bob(:,1),bob(:,2),bob(:,3),specs(leg));
+ end
+ if(plotops.drawbuttons~=0)
+   for leg=1:4
+     %%plot button-on
+     bob=permute(legpos(leg,:,:),[3 2 1]);
+     button=getButton(leg);
+     ontime=extractButtonOn(button);
+     hold on;
+     plot3(bob(ontime,1),bob(ontime,2),bob(ontime,3),[specs(leg) 'o']);
+   end
+ end
+ legend('lf','rf','lb','rb');
+ ylabel('left-right');
+ xlabel('back-forward');
+ zlabel('down-up');
+ 
+ %add time ticks
+ for leg=1:4
+ bob=permute(legpos(leg,:,:),[3 2 1]);
+ trtimetags(leg,:)=plot3(bob(1,1),bob(1,2),bob(1,3), [specs(leg) 'x'], ...
+     bob(end,1),bob(end,2),bob(end,3), [specs(leg) 'x'], 'MarkerSize',32)';
+ end
+ 
+ %plot heading
+ 
+ function buttons=getButton(leg)
+      global logfile info jpl;
+ leg=leg-1;
+   buttons=logfile(:,info.LogOffset.buttons+leg);
+ 
+ function onidx=extractButtonOn(button)
+    onidx=find(button>0);
+ 
+ function onidx=findButtonOn(leg)
+    global logfile info jpl;
+    button=getButton(leg);
+    onidx=find(button>0);
Index: Tekkotsu/tools/mon/setslide.m
diff -c /dev/null Tekkotsu/tools/mon/setslide.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/setslide.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,3 ----
+ function setslide()
+      global logfile window subp;
+ updateAxes;
Index: Tekkotsu/tools/mon/updateAxes.m
diff -c /dev/null Tekkotsu/tools/mon/updateAxes.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/updateAxes.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,43 ----
+ global timeslider pgraph jgraph trtimetags legpos;
+      mint=logfile(1,1);
+      maxt=logfile(end,1);
+      p=get(timeslider,'value');
+      view=window.size/window.zoomfactor;
+ window.start=p*(maxt-mint-view)+mint;
+ view=window.size/window.zoomfactor;
+ window.stop=window.start+view;
+ set(timeslider,'sliderstep',[view/5/window.size,view/window.size]);
+ for i=1:length(subp)
+      ax=axis(subp(i));
+      axis(subp(i),[window.start,window.stop, ax(3),ax(4)]);
+ end
+ 
+ global aibopos timetags updatego;
+ %if(updatego>0)
+ posstart=min(find(logfile(:,1) >= window.start));
+ posend=max(find(logfile(:,1) <= window.stop));
+ startframe=aibopos(:,:,posstart);
+ stopframe=aibopos(:,:,posend);
+ trstartframe=legpos(:,:,posstart);
+ trstopframe=legpos(:,:,posend);
+ if(ishandle(timetags(1,1))>0)
+ for leg=1:4
+ set(timetags(leg,1),'XData',startframe(leg,1));
+ set(timetags(leg,1),'YData',startframe(leg,2));
+ set(timetags(leg,1),'ZData',startframe(leg,3));
+ set(timetags(leg,2),'XData',stopframe(leg,1));
+ set(timetags(leg,2),'YData',stopframe(leg,2));
+ set(timetags(leg,2),'ZData',stopframe(leg,3));
+ 
+ %%trajectory
+ 
+ set(trtimetags(leg,1),'XData',trstartframe(leg,1));
+ set(trtimetags(leg,1),'YData',trstartframe(leg,2));
+ set(trtimetags(leg,1),'ZData',trstartframe(leg,3));
+ set(trtimetags(leg,2),'XData',trstopframe(leg,1));
+ set(trtimetags(leg,2),'YData',trstopframe(leg,2));
+ set(trtimetags(leg,2),'ZData',trstopframe(leg,3));
+ 
+ end
+ end
+ %end
Index: Tekkotsu/tools/mon/zoomin.m
diff -c /dev/null Tekkotsu/tools/mon/zoomin.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/zoomin.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,4 ----
+ function zoomin()
+      global logfile window subp;
+      window.zoomfactor=window.zoomfactor*1.1;
+      updateAxes;
Index: Tekkotsu/tools/mon/zoomout.m
diff -c /dev/null Tekkotsu/tools/mon/zoomout.m:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/zoomout.m	Wed Jan 28 16:07:44 2004
***************
*** 0 ****
--- 1,4 ----
+ function zoomout()
+      global window subp logfile;
+      window.zoomfactor=window.zoomfactor*.9;
+ updateAxes;
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java:1.11 Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java:1.13
*** Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java:1.11	Sat Jan 10 15:11:22 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerGUI.java	Wed Feb  4 20:52:06 2004
***************
*** 158,176 ****
  		}
  	}
   	
- 	public class ReenableOnClose extends WindowAdapter {
- 		JButton but;
- 		public ReenableOnClose(JButton b) { but=b; }
- 		public void windowClosing(WindowEvent e) {
- 			if(but.getActionCommand().equals("raw"))
- 				comm.sendInput("!root \"TekkotsuMon\" \"RawCamServer\"");
- 			else
- 				comm.sendInput("!root \"TekkotsuMon\" \"SegCamServer\"");
- 			e.getWindow().dispose();
- 			but.setEnabled(true);
- 		}
- 	}
- 
  	void lostConnection() {
  		updated();
  	}
--- 158,163 ----
***************
*** 190,199 ****
  			status.setText("Reconnecting...");
  		} else {
  			if(comm._connectCount>0) {
! 				if(comm._connectCount==1)
  					for(int i=0; i<scriptsModel.getSize(); i++)
  						if(scriptsModel.get(i).toString().equals("STARTUP"))
  							comm.sendInput(((ScriptEntry)scriptsModel.get(i)).cmd);
  				for(int i=0; i<scriptsModel.getSize(); i++)
  					if(scriptsModel.get(i).toString().equals("CONNECT"))
  						comm.sendInput(((ScriptEntry)scriptsModel.get(i)).cmd);
--- 177,191 ----
  			status.setText("Reconnecting...");
  		} else {
  			if(comm._connectCount>0) {
! 				if(comm._connectCount==1) {
  					for(int i=0; i<scriptsModel.getSize(); i++)
  						if(scriptsModel.get(i).toString().equals("STARTUP"))
  							comm.sendInput(((ScriptEntry)scriptsModel.get(i)).cmd);
+ 					//restart servers for any windows we still have open
+ 					Iterator mons=comm.dynObjSrcs.values().iterator();
+ 					while(mons.hasNext())
+ 						comm.sendInput("!root "+(String)mons.next());
+ 				}
  				for(int i=0; i<scriptsModel.getSize(); i++)
  					if(scriptsModel.get(i).toString().equals("CONNECT"))
  						comm.sendInput(((ScriptEntry)scriptsModel.get(i)).cmd);
***************
*** 255,277 ****
  		} else if(evt.getSource()==reconnectBut) {
  			int port=comm._port;
  			String addr=comm._host;
  			comm.kill();
  			comm = new ControllerListener(addr,port);
  			comm.listener=this;
  			estop.close();
  			estop.open();
  		} else if(evt.getActionCommand().equals("raw") || evt.getActionCommand().equals("rle")) {
! 			if(evt.getActionCommand().equals("raw"))
  				comm.sendInput("!root \"TekkotsuMon\" \"RawCamServer\"");
! 			else
  				comm.sendInput("!root \"TekkotsuMon\" \"SegCamServer\"");
! 			String[] tmp=new String[1];
! 			tmp[0]=evt.getActionCommand();
! 			VisionGUI vis=new VisionGUI(comm._host,tmp);
! 			((JButton)evt.getSource()).setEnabled(false);
! 			vis.addWindowListener(new ReenableOnClose((JButton)evt.getSource()));
! 			vis.show();
! 			vis.toFront();
  		} else if(evt.getActionCommand().equals("addbookmark")) {
  			int sel=comm.firstSelected();
  			if(sel==-1 || !comm._isConnected) {
--- 247,271 ----
  		} else if(evt.getSource()==reconnectBut) {
  			int port=comm._port;
  			String addr=comm._host;
+ 			HashMap dynObjs=comm.dynObjs;
+ 			HashMap dynObjSrcs=comm.dynObjSrcs;
+ 			HashMap dynObjPorts=comm.dynObjPorts;
  			comm.kill();
  			comm = new ControllerListener(addr,port);
  			comm.listener=this;
+ 			comm.dynObjs=dynObjs;
+ 			comm.dynObjSrcs=dynObjSrcs;
+ 			comm.dynObjPorts=dynObjPorts;
  			estop.close();
  			estop.open();
  		} else if(evt.getActionCommand().equals("raw") || evt.getActionCommand().equals("rle")) {
! 			if(evt.getActionCommand().equals("raw")) {
  				comm.sendInput("!root \"TekkotsuMon\" \"RawCamServer\"");
! 				comm.dynObjSrcs.put("RawVisionGUI","\"TekkotsuMon\" \"RawCamServer\"");
! 			} else {
  				comm.sendInput("!root \"TekkotsuMon\" \"SegCamServer\"");
! 				comm.dynObjSrcs.put("SegVisionGUI","\"TekkotsuMon\" \"SegCamServer\"");
! 			}
  		} else if(evt.getActionCommand().equals("addbookmark")) {
  			int sel=comm.firstSelected();
  			if(sel==-1 || !comm._isConnected) {
***************
*** 516,523 ****
  		ControllerGUI gui;
  		CloseVisionAdapter(ControllerGUI gui) {this.gui=gui;}
  		public void windowClosing(WindowEvent e) {
! 			prefs.putInt("ControllerGUI.location.x",getLocation().x+getInsets().left);
! 			prefs.putInt("ControllerGUI.location.y",getLocation().y+getInsets().top);
  			prefs.putInt("ControllerGUI.numScripts",scriptsModel.getSize());
  			for(int i=0; i<scriptsModel.getSize(); i++) {
  				prefs.put("ControllerGUI.script"+i+".title",((ScriptEntry)scriptsModel.get(i)).title);
--- 510,520 ----
  		ControllerGUI gui;
  		CloseVisionAdapter(ControllerGUI gui) {this.gui=gui;}
  		public void windowClosing(WindowEvent e) {
! 			prefs.putInt("ControllerGUI.location.x",getLocation().x);
! 			prefs.putInt("ControllerGUI.location.y",getLocation().y);
! 			//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 			//prefs.putInt("ControllerGUI.location.x",getLocation().x+getInsets().left);
! 			//prefs.putInt("ControllerGUI.location.y",getLocation().y+getInsets().top);
  			prefs.putInt("ControllerGUI.numScripts",scriptsModel.getSize());
  			for(int i=0; i<scriptsModel.getSize(); i++) {
  				prefs.put("ControllerGUI.script"+i+".title",((ScriptEntry)scriptsModel.get(i)).title);
***************
*** 525,530 ****
--- 522,528 ----
  			}
  			for(int i=0; i<MAX_STORE_INPUT_HIST; i++)
  				prefs.put("inputFieldHistory"+i,(String)inputFieldHistory.get(inputFieldHistory.size()-MAX_STORE_INPUT_HIST+i));
+ 			gui.comm.removeDynObjs();
  			gui.comm.kill();
  			estop.close();
  			while(gui.comm.isConnected())
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java:1.5 Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java:1.6
*** Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java:1.5	Mon Jan 12 15:06:28 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/ControllerListener.java	Wed Feb  4 20:52:06 2004
***************
*** 19,24 ****
--- 19,26 ----
  	PrintStream _out;
  	ControllerGUI listener;
  	HashMap dynObjs=new HashMap();
+ 	HashMap dynObjSrcs=new HashMap();
+ 	HashMap dynObjPorts=new HashMap();
  	InputStream sin;
  	int _connectCount=0;
  	
***************
*** 137,146 ****
  			_out.println("!refresh");
  			while (true) {
  				String msgtype=readLine(sin);
! 				if(!_isConnected) {
! 					removeDynobjs();
  					break;
- 				}
  				//				System.out.println("Received: "+msgtype);
  				synchronized(_menus) {
  					if(msgtype.equals("push")) {
--- 139,146 ----
  			_out.println("!refresh");
  			while (true) {
  				String msgtype=readLine(sin);
! 				if(!_isConnected)
  					break;
  				//				System.out.println("Received: "+msgtype);
  				synchronized(_menus) {
  					if(msgtype.equals("push")) {
***************
*** 183,189 ****
  						if(!_isConnected) break;
  						continue;
  					} else if(msgtype.equals("goodbye")) {
! 						removeDynobjs();
  						System.out.println("Remote is shutting down.");
  					} else if(msgtype.equals("reset")) {
  						_menus.clear();
--- 183,189 ----
  						if(!_isConnected) break;
  						continue;
  					} else if(msgtype.equals("goodbye")) {
! 						//removeDynObjs();
  						System.out.println("Remote is shutting down.");
  					} else if(msgtype.equals("reset")) {
  						_menus.clear();
***************
*** 203,208 ****
--- 203,211 ----
  						if(!_isConnected) break;
  						String[] argArr=parseArgs(args);
  						if(!_isConnected) break;
+ 						if(dynObjPorts.get(name)!=null) //it's already open
+ 							if(((Integer)dynObjPorts.get(name)).intValue()==port) //and on the same port
+ 								continue; //so don't reopen it
  						Class objClass=null;
  						try {
  							objClass=Class.forName(type);
***************
*** 219,224 ****
--- 222,246 ----
  							Constructor objCons=objClass.getConstructor(consArgClasses);
  							Object obj=objCons.newInstance(consArgs);
  							dynObjs.put(name,obj);
+ 							dynObjPorts.put(name, new Integer(port));
+ 							if(dynObjSrcs.get(name)==null) { //check the GUI didn't already assign a src (for VisionGUI)
+ 								//find out who launched this (not infallable - dynamic controls launching windows may not have stable launch points...)
+ 								int minsel=-1;
+ 								Vector menuitems=(Vector)_menus.get(_menus.size()-2);
+ 								for(int i=0; i<menuitems.size(); i++)
+ 									if(((ControllerListener.MenuEntry)menuitems.get(i)).selected) {
+ 										minsel=i;
+ 										break;
+ 									}
+ 								String title=((ControllerListener.MenuEntry)((Vector)_menus.get(_menus.size()-2)).get(minsel)).title;
+ 								Vector path=buildSelectionPath();
+ 								String cmd=new String();
+ 								for(int i=1; i<path.size()-1; i++)
+ 									cmd=cmd+"\""+path.get(i)+"\" ";
+ 								cmd=cmd+"\""+title+"\"";
+ 								System.out.println("Launched by: "+cmd);
+ 								dynObjSrcs.put(name,cmd);
+ 							}
  						}
  					} else if(msgtype.equals("close")) {
  						String name=readLine(sin);
***************
*** 233,238 ****
--- 255,262 ----
  							} catch (Exception e) {}
  						}
  						dynObjs.remove(name);
+ 						dynObjSrcs.remove(name);
+ 						dynObjPorts.remove(name);
  					} else {
  						System.err.println("ControllerListener - Invalid message type:"+msgtype);
  					}
***************
*** 263,274 ****
  		//try { Thread.sleep(5000); } catch (Exception ex) {}
  	}
  
! 	public void kill() {
! 		removeDynobjs();
! 		super.kill();
! 	}
! 
! 	public void removeDynobjs() {
  		Iterator it=dynObjs.values().iterator();
  		while(it.hasNext()) {
  			Object obj=it.next();
--- 287,293 ----
  		//try { Thread.sleep(5000); } catch (Exception ex) {}
  	}
  
! 	public void removeDynObjs() {
  		Iterator it=dynObjs.values().iterator();
  		while(it.hasNext()) {
  			Object obj=it.next();
***************
*** 278,283 ****
--- 297,304 ----
  			} catch(Exception ex) {}
  		}
  		dynObjs.clear();
+ 		dynObjPorts.clear();
+ 		dynObjSrcs.clear();
  	}
   
  	public boolean hasData() {
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/EStopGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/EStopGUI.java:1.1 Tekkotsu/tools/mon/org/tekkotsu/mon/EStopGUI.java:1.2
*** Tekkotsu/tools/mon/org/tekkotsu/mon/EStopGUI.java:1.1	Fri Sep 26 00:36:19 2003
--- Tekkotsu/tools/mon/org/tekkotsu/mon/EStopGUI.java	Wed Feb  4 18:28:42 2004
***************
*** 109,116 ****
  		}
  	}
  	public void close() {
! 		prefs.putInt("EStopGUI.location.x",getLocation().x+getInsets().left);
! 		prefs.putInt("EStopGUI.location.y",getLocation().y+getInsets().top);
  		estop.remove();
  		estop.comm.removeUpdatedListener(this);
  		dispose();
--- 109,119 ----
  		}
  	}
  	public void close() {
! 		prefs.putInt("EStopGUI.location.x",getLocation().x);
! 		prefs.putInt("EStopGUI.location.y",getLocation().y);
! 		//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 		//prefs.putInt("EStopGUI.location.x",getLocation().x+getInsets().left);
! 		//prefs.putInt("EStopGUI.location.y",getLocation().y+getInsets().top);
  		estop.remove();
  		estop.comm.removeUpdatedListener(this);
  		dispose();
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java:1.1 Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java:1.2
*** Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java:1.1	Fri Sep 26 00:36:19 2003
--- Tekkotsu/tools/mon/org/tekkotsu/mon/EditScriptGUI.java	Wed Feb  4 18:28:42 2004
***************
*** 139,146 ****
  	}
  
  	public void close() {
! 		prefs.putInt("EditScriptGUI.location.x",getLocation().x+getInsets().left);
! 		prefs.putInt("EditScriptGUI.location.y",getLocation().y+getInsets().top);
  		dispose();
  	}
  
--- 139,149 ----
  	}
  
  	public void close() {
! 		prefs.putInt("EditScriptGUI.location.x",getLocation().x);
! 		prefs.putInt("EditScriptGUI.location.y",getLocation().y);
! 		//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 		//prefs.putInt("EditScriptGUI.location.x",getLocation().x+getInsets().left);
! 		//prefs.putInt("EditScriptGUI.location.y",getLocation().y+getInsets().top);
  		dispose();
  	}
  
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/HeadPointGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/HeadPointGUI.java:1.1 Tekkotsu/tools/mon/org/tekkotsu/mon/HeadPointGUI.java:1.2
*** Tekkotsu/tools/mon/org/tekkotsu/mon/HeadPointGUI.java:1.1	Fri Sep 26 00:36:19 2003
--- Tekkotsu/tools/mon/org/tekkotsu/mon/HeadPointGUI.java	Wed Feb  4 18:28:42 2004
***************
*** 58,65 ****
  	}
  
  	public void close() {
! 		prefs.putInt("HeadPointGUI.location.x",getLocation().x+getInsets().left);
! 		prefs.putInt("HeadPointGUI.location.y",getLocation().y+getInsets().top);
  		comm.kill();
  		dispose();
  	}
--- 58,68 ----
  	}
  
  	public void close() {
! 		prefs.putInt("HeadPointGUI.location.x",getLocation().x);
! 		prefs.putInt("HeadPointGUI.location.y",getLocation().y);
! 		//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 		//prefs.putInt("HeadPointGUI.location.x",getLocation().x+getInsets().left);
! 		//prefs.putInt("HeadPointGUI.location.y",getLocation().y+getInsets().top);
  		comm.kill();
  		dispose();
  	}
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/JointLogger.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/JointLogger.java:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/JointLogger.java	Wed Jan 28 16:08:46 2004
***************
*** 0 ****
--- 1,9 ----
+ package org.tekkotsu.mon;
+ 
+ import java.io.*;
+ 
+ public class JointLogger {
+     public static void main(String s[]){
+ 	JointWriter writer=new JointWriter(s); //that's it. stupid class...
+     }
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/JointRelay.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/JointRelay.java:1.1
*** /dev/null	Thu Feb  5 23:36:02 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/JointRelay.java	Wed Jan 28 16:08:46 2004
***************
*** 0 ****
--- 1,69 ----
+ package org.tekkotsu.mon;
+ 
+ import java.io.InputStream;
+ import java.net.Socket;
+ 
+ public class JointRelay extends TCPListener {
+   boolean _updatedFlag=false;
+   Joints _data;
+   Joints _outd;
+     JointRequestor requestor;
+ 
+   public void connected(Socket socket) {
+     _isConnected=true;
+     _data=new Joints();
+     _outd=new Joints();
+     try {
+       InputStream in=socket.getInputStream();
+       while (true) {
+         _data.timestamp=readInt(in);
+         for (int i=0; i<18; i++)
+           _data.positions[i]=readFloat(in);
+         for (int i=0; i<6; i++)
+           _data.sensors[i]=readFloat(in);
+         for (int i=0; i<8; i++)
+           _data.buttons[i]=readFloat(in);
+         for (int i=0; i<18; i++)
+           _data.duties[i]=readFloat(in);
+ 
+         synchronized(_outd) {
+           Joints temp=_data;
+           _data=_outd;
+           _outd=temp;
+           _updatedFlag=true;
+ 	  if(requestor!=null){
+ 	      requestor.dataArrival(_outd);
+ 	  }
+         }
+       }
+     } catch (Exception ex) { }
+ 
+     try { socket.close(); } catch (Exception ex) { }
+     _isConnected=false;
+   }
+  
+   public boolean hasData() {
+     return _updatedFlag;
+   }
+ 
+   public Joints getData() {
+     synchronized (_outd) {
+       _updatedFlag=false;
+       return _outd;
+     }
+   }
+ 
+   public boolean isConnected() {
+     return _isConnected;
+   }
+ 
+   public JointRelay() { super(); }
+   public JointRelay(int port) { super(port); }
+   public JointRelay(String host, int port) { super(host,port); }
+     public JointRelay(String host, int port,JointRequestor ob) { super(host,port);
+     registerRequestor(ob);
+     }
+     public void registerRequestor(JointRequestor ob){
+ 	requestor=ob;
+     }
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/JointRequestor.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/JointRequestor.java:1.1
*** /dev/null	Thu Feb  5 23:36:03 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/JointRequestor.java	Wed Jan 28 16:08:46 2004
***************
*** 0 ****
--- 1,5 ----
+ package org.tekkotsu.mon;
+ 
+ public interface JointRequestor {
+     public void dataArrival(Joints data);
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/JointWriter.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/JointWriter.java:1.1
*** /dev/null	Thu Feb  5 23:36:03 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/JointWriter.java	Wed Jan 28 16:08:46 2004
***************
*** 0 ****
--- 1,103 ----
+ package org.tekkotsu.mon;
+ 
+ import java.io.*;
+ 
+ public class JointWriter implements JointRequestor{
+     JointRelay joints;
+     boolean inited=false;
+     BufferedWriter outlog;
+     int counter=0;float start=-1,lasttime=0;    
+     protected boolean init(String ip,int port){
+ 	if(inited)return true;
+ 	joints=new JointRelay(ip,port,this);
+ 	return true;
+     }
+ 
+     public void dataArrival(Joints data){
+ 	try{
+ 	    synchronized(outlog){
+ 		if(start==-1){
+ 		    start=data.timestamp;
+ 		    lasttime=start;
+ 		}
+ 		String ret=""+(data.timestamp-start)+" "+
+ 		    catArray(data.positions)+
+ 		    catArray(data.duties)+
+ 		    catArray(data.sensors)+
+ 		    catArray(data.buttons);
+ 		outlog.write(ret);
+ 		outlog.newLine();
+ 		counter+=ret.length()+1;
+ 		System.out.println(data.timestamp-start+" (+"+(data.timestamp-lasttime)+") msec. "+counter+" bytes ("+((float)counter/(data.timestamp-start))+" bytes/s)");
+ 		lasttime=data.timestamp;
+ 	    }
+ 	}
+ 	catch(IOException e){
+ 	    System.err.println(e);
+ 	}
+     }
+ 
+     public static File findNextLog(String prefix){
+ 	File quick;
+ 	int i=0;
+ 	do{
+ 	    i++;
+ 	    quick=new File(prefix+i+".log");
+ 	}while(quick.exists());
+ 	return quick;
+     }
+ 
+     public JointWriter(){
+ 	String s[]=new String[0];
+ 	launch(s);
+     }
+ 
+     public JointWriter(String s[]){
+ 	launch(s);
+     }
+ 
+     protected void launch(String s[]){
+ 	String ip="172.16.1.1",filename="aibo";
+ 	for(int i=0;i<s.length;i++){
+ 	    if(s[i].startsWith("-i"))
+ 		ip=s[i].substring(2);
+ 	    else if(s[i].startsWith("-f"))
+ 		filename=s[i].substring(2);
+ 	}
+ 	File outfile=findNextLog(filename);
+ 	try {
+ 	    outlog=new BufferedWriter(new FileWriter(outfile));
+ 	    System.out.println("Writing to: "+outfile);
+ 	    if(!init(ip,10031)){
+ 		System.err.println("Init failed. Very sad...");
+ 		System.exit(1);
+ 		return;
+ 	    }
+ 	    while(true){
+ 		if(System.in.available()>0){ //keyhit
+ 		     int b=System.in.read();
+ 		     System.out.print("read "+b+": ");
+ 		     if(b=='q'){
+ 			 System.out.println("User aborted.\n");
+ 			 synchronized(outlog){
+ 			     outlog.close();
+ 			     joints.close();
+ 			     System.out.println("Finished writing to: "+outfile);
+ 			     System.exit(0);
+ 			 }
+ 			 break;
+ 		     }
+ 		}
+ 	    }
+ 	}
+ 	catch(IOException e){
+ 	    System.err.println(e);
+ 	}
+     }
+     public String catArray(float []array){
+ 	String ret="";
+ 	for(int i=0;i<array.length;i++)
+ 	    ret+=array[i]+" ";
+ 	return ret;
+     }
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/SketchGUI.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/SketchGUI.java:1.1
*** /dev/null	Thu Feb  5 23:36:03 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/SketchGUI.java	Thu Jan 29 21:13:10 2004
***************
*** 0 ****
--- 1,323 ----
+ package org.tekkotsu.mon;
+ 
+ import java.awt.event.*;
+ import javax.swing.*;
+ import javax.swing.tree.*;
+ import javax.swing.event.*;
+ import java.lang.String;
+ //import java.util.LinkedList;
+ import java.awt.*;
+ import javax.imageio.ImageIO;
+ import java.awt.image.BufferedImage;
+ import java.awt.image.IndexColorModel;
+ import java.util.Date;
+ import java.util.Vector;
+ import java.io.PrintWriter;
+ import java.io.FileOutputStream;
+ import java.util.prefs.Preferences;
+ import java.io.File;
+ import java.net.*;
+ import java.io.*;
+ import java.util.StringTokenizer;
+ 
+ public class SketchGUI extends JFrame implements ActionListener,TreeSelectionListener {
+     VisionPanel sketch;
+     JButton spawnBut;
+     JButton refreshBut;
+     JButton saveImageBut;
+ 	JButton refreshListBut;
+     JTree sketchTree;
+ 	DefaultMutableTreeNode root= new DefaultMutableTreeNode("camspace");
+     JLabel status;
+     float mspf=0;
+     float mspfGamma=.9f;
+     String state="";
+     String host;
+     int port;
+     static int defSketchPort = 5873; // Default Port
+     static int defListPort = 5874; // Default Port
+     static Preferences prefs = Preferences.userNodeForPackage(SketchGUI.class);
+ 	// the socket over which listings are retrieved and Sketch commands are sent
+ 	Socket listingSocket=null;
+ 	PrintWriter netout = null; // network output
+     BufferedReader netin = null; // network input
+ 
+     public static void main(String args[]) {
+ 	if(args.length<1)
+ 	     usage();
+ 
+ 	int port = defListPort;
+ 	if(args.length>1)
+ 	     port=Integer.parseInt(args[1]);
+ 
+ 	SketchGUI gui = new SketchGUI(args[0],port);
+ 	gui.addWindowListener(new WindowAdapter() {
+ 		 public void windowClosing(WindowEvent e) {}});
+ 	gui.show();
+     }
+ 		
+     public static void usage() {
+ 	System.out.println("Usage: java SketchGUI host [port]");
+ 	System.out.println("       if port is not specified, it defaults to: [12345]"); // Default port
+ 	System.exit(2);
+     }
+ 			
+     public void actionPerformed(ActionEvent e) {
+ 	if(e.getActionCommand().compareTo("spawn")==0) {
+ 	    SketchGUI gui = new SketchGUI(host,port);
+ 	    gui.addWindowListener(new WindowAdapter() {
+ 		     public void windowClosing(WindowEvent e) {
+ //			 System.exit(0);
+ 		     }});
+ 	    gui.show();
+ 	} else if(e.getActionCommand().compareTo("refresh")==0) {
+ 	    // Refresh the sketch tree list:
+ 	    
+ 	    // Refresh the sketch based on which are checked:
+ //	    Vector sketches = new Vector();
+ //	    sketch.update(sketches);
+ 	} else if(e.getActionCommand().compareTo("saveimg")==0) {
+ 	    File cursavepath = new File(prefs.get("cursavepath",""));
+ 	    JFileChooser dia=new JFileChooser(cursavepath);
+ 	    dia.setDialogTitle("Save Image...");
+ 	    Component cur=this;
+ 	    while(cur.getParent()!=null)
+ 		 cur=cur.getParent();
+ 	    if(dia.showSaveDialog(cur)==JFileChooser.APPROVE_OPTION) {
+ 		prefs.put("cursavepath",dia.getCurrentDirectory().getPath());
+ 		String base=dia.getSelectedFile().getName();
+ 		String format;
+ 		if(base.lastIndexOf('.')==-1) {
+ 		    format="png";
+ 		} else {
+ 		    int i=base.lastIndexOf(".");
+ 		    format=base.substring(i+1);
+ 		    base=base.substring(0,i);
+ 		}
+ 		try {
+ 			FileOutputStream fileout=new FileOutputStream(dia.getSelectedFile().getParent()+File.separator+base+"."+format);
+ 			ImageIO.write(sketch.getListener().getImage(),format,fileout);
+ 		} catch(Exception ex) {}
+ 	    }
+ 	} else if(e.getActionCommand().compareTo("refreshlist")==0) {
+ 		// send command to refresh the sketch tree list
+ 		netout.println("list");
+ //		DefaultMutableTreeNode root = new DefaultMutableTreeNode("camspace");
+ 		root.removeAllChildren();
+ 		// read in new sketch listing
+ 		try {
+ 			String inputLine;
+ 			System.out.println(inputLine = netin.readLine());
+ 			while((inputLine=netin.readLine()).compareTo("list end") != 0) {
+ 				// parse name
+ 				StringTokenizer st = new StringTokenizer(inputLine,": ");
+ 				st.nextToken();
+ 				String name = st.nextToken();
+ 
+ 				// parse id
+ 				inputLine = netin.readLine();
+ 				st = new StringTokenizer(inputLine,": ");
+ 				st.nextToken();
+ 				int id = Integer.parseInt(st.nextToken());
+ 				
+ 				//parse parentId
+ 				inputLine = netin.readLine();
+ 				st = new StringTokenizer(inputLine,": ");
+ 				st.nextToken();
+ 				int parentId = Integer.parseInt(st.nextToken());
+ 			
+ 				// add node
+ 				System.out.println("id:"+id+"parentId:"+parentId+"name:"+name);
+ 				DefaultMutableTreeNode newnode = new DefaultMutableTreeNode(new SketchInfo(id, parentId, name));
+ 				root.add(newnode);
+ 			}
+ 			System.out.println(inputLine);
+ 			//sketchTree = new JTree(root); // is this right?
+ 			//JScrollPane treeView = new JScrollPane(sketchTree);
+ //			sketchTree.removeAll();
+ //			sketchTree.add(root);
+ 			sketchTree.updateUI();
+ 		} catch(IOException ioe) {
+ 			System.err.println("Transfer error");
+ 		}
+ 	}
+     }
+ 
+     public SketchGUI(String host, int port) {
+ 	super();
+ 	this.host = host;
+ 	this.port = port;
+ 
+ 	// network setup
+ 	try {
+ 		System.out.println("Trying to open socket...");
+ 		listingSocket = new Socket(host,port);
+ 		netout = new PrintWriter(listingSocket.getOutputStream(), true);
+   		netin = new BufferedReader(new InputStreamReader(
+ 					listingSocket.getInputStream()));
+ 	} catch (UnknownHostException e) {
+ 		System.err.println("Don't know about host:"+host);
+ 		System.exit(1);
+ 	} catch (IOException e) {
+ 		System.err.println("Couldn't get I/O for "
+ 				+ "the connection to:" + host + ".");
+ 		System.exit(1);
+ 	}
+ 
+ 	init();
+     }
+ 
+ 
+     public void init() {
+ 	int strutsize=10;
+ 	int sepsize=5;
+ 	getContentPane().setLayout(new BorderLayout());
+ 	getContentPane().add(Box.createVerticalStrut(strutsize),BorderLayout.NORTH);
+ 	getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.WEST);
+ 	getContentPane().add(Box.createHorizontalStrut(strutsize),BorderLayout.EAST);
+ 		
+ 	setTitle("TekkotsuMon: Sketch");
+ 	sketch=new VisionPanel(new VisionListener(host, defSketchPort));
+ 	
+ 	sketch.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
+ 	sketch.setPreferredSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2));
+ 	sketch.setLockAspectRatio(true);
+ 	getContentPane().add(sketch,BorderLayout.CENTER);
+ 
+ 	{
+ 	    Box tmp1 = Box.createHorizontalBox();
+ 	    tmp1.add(Box.createHorizontalStrut(strutsize));
+ 	    {
+ 		Box tmp2 = Box.createVerticalBox();
+ 
+ 		tmp2.add(Box.createVerticalStrut(strutsize));
+ 
+ 		{
+ 		    Box tmp3 = Box.createHorizontalBox();
+ 		    tmp3.add(status=new JLabel(state));
+ 		    tmp3.add(Box.createHorizontalGlue());
+ 
+ 		    spawnBut = new JButton("Spawn New");
+ 		    spawnBut.setAlignmentX(0.5f);
+ 		    spawnBut.addActionListener(this);
+ 		    spawnBut.setActionCommand("spawn");
+ 		    spawnBut.setEnabled(true);
+ 		    spawnBut.setToolTipText("Spawns a new sketch monitor;");
+ 		    tmp3.add(spawnBut);
+ 
+ 		    tmp3.add(Box.createHorizontalStrut(strutsize));
+ 		
+ 		    refreshBut = new JButton("Refresh Image");
+ 		    refreshBut.setAlignmentX(0.5f);
+ 		    refreshBut.addActionListener(this);
+ 		    refreshBut.setActionCommand("refresh");
+ 		    refreshBut.setEnabled(true);
+ 		    refreshBut.setToolTipText("Refreshes the displayed sketch;");
+ 		    tmp3.add(refreshBut);
+ 
+ 		    tmp3.add(Box.createHorizontalStrut(strutsize));
+ 		    
+ 		    saveImageBut = new JButton("Save Image");
+ 		    saveImageBut.setAlignmentX(0.5f);
+ 		    saveImageBut.addActionListener(this);
+ 		    saveImageBut.setActionCommand("saveimg");
+ 		    saveImageBut.setEnabled(true);
+ 		    saveImageBut.setToolTipText("Saves sketch to a file - use .jpg or .png extension to choose format;");
+ 		    tmp3.add(saveImageBut);
+ 			tmp3.add(Box.createHorizontalStrut(strutsize));
+ 
+ 
+ 			refreshListBut = new JButton("Refresh Listing");
+ 			refreshListBut.setAlignmentX(0.5f);
+ 			refreshListBut.addActionListener(this);
+ 			refreshListBut.setActionCommand("refreshlist");
+ 			refreshListBut.setEnabled(true);
+ 			refreshListBut.setToolTipText("Refreshes the sketch listing;");
+ 			tmp3.add(refreshListBut);
+ 		    tmp2.add(tmp3, BorderLayout.CENTER);
+ 		}
+ 
+ 		tmp2.add(Box.createVerticalStrut(strutsize));
+ 		// Sketch Tree:
+ 		sketchTree = new JTree(new DefaultTreeModel(initSketchTree(host, port)));
+ 		tmp2.add(new JScrollPane(sketchTree));
+ 		// set up sketch node selection
+ 		sketchTree.getSelectionModel().setSelectionMode
+ 		            (TreeSelectionModel.SINGLE_TREE_SELECTION);
+ 		//Listen for when the selection changes.
+ 	    sketchTree.addTreeSelectionListener(this);
+ 
+ //		JFrame sketchFrame = new JFrame("Sketches");
+ //		sketchFrame.setSize(200,400);
+ //		sketchFrame.getContentPane().add(new JScrollPane(sketchTree));
+ //		JScrollPane sketchPane = new JScrollPane(sketchTree);
+ //		sketchPane.setSize(200,100);
+ //		tmp2.add(sketchPane);
+ 		tmp2.add(Box.createVerticalStrut(strutsize));
+ 		tmp2.add(new JSeparator());
+ 		tmp2.add(Box.createVerticalStrut(strutsize-sepsize));
+ 		{
+ 		    Box tmp4 = Box.createHorizontalBox();
+ 		    tmp4.add(status=new JLabel(state));
+ 		    tmp4.add(Box.createHorizontalGlue());
+ 		    tmp2.add(tmp4);
+ 		}
+ 		tmp2.add(Box.createVerticalStrut(strutsize));
+ 		tmp1.add(tmp2);
+ 	    }
+ 	    tmp1.add(Box.createHorizontalStrut(strutsize));
+ 	    getContentPane().add(tmp1,BorderLayout.SOUTH);
+ 	}
+ 	pack();
+ 	
+ 	String name="SketchGUI"+".location";
+ 	setLocation(prefs.getInt(name+".x",50),prefs.getInt(name+".y",50));
+     }
+ 
+     public TreeNode initSketchTree(String host, int port) {
+ //	MutableTreeNode root = new DefaultMutableTreeNode("camspace");
+ 
+ 	// Just for demonstration:
+ 	DefaultMutableTreeNode cam = new DefaultMutableTreeNode("cam");
+ 	DefaultMutableTreeNode pmask = new DefaultMutableTreeNode("pmask");
+ 	DefaultMutableTreeNode filled = new DefaultMutableTreeNode("filled");
+ 	DefaultMutableTreeNode skel = new DefaultMutableTreeNode("skel");
+ 	DefaultMutableTreeNode all_lines = new DefaultMutableTreeNode("all_lines");
+ 	DefaultMutableTreeNode b_ellipse_render = new DefaultMutableTreeNode("b_ellipse_render");
+ 	root.insert(cam,0);
+ 	cam.insert(pmask,0);
+ 	pmask.insert(filled,0);
+ 	filled.insert(skel,0);
+ 	skel.insert(all_lines,0);
+ 	cam.insert(b_ellipse_render,1);
+ //	for(int i = 0; i < 5; i++)
+ //	     root.insert(new DefaultMutableTreeNode("Sketch("+i+")"), i);
+ 
+ 	return root;
+     }
+ 
+ 	// gets called when a Sketch selection is clicked
+ 	public void valueChanged(TreeSelectionEvent e) {
+ 		DefaultMutableTreeNode node = (DefaultMutableTreeNode)
+ 			sketchTree.getLastSelectedPathComponent();
+ 
+ 		if (node == null) return;
+ 
+ 		Object nodeInfo = node.getUserObject();
+ 		if (node.isLeaf()) {
+ 			SketchInfo sinfo = (SketchInfo)nodeInfo;
+ 			System.out.println("id clicked:"+sinfo.id);
+ 			netout.println("get "+sinfo.id);
+ 			try {
+ 				String inputLine;
+ 				while((inputLine=netin.readLine()).compareTo("get end") != 0) {
+ 					System.out.println(inputLine);
+ 				}
+ 			} catch (IOException ioe) {
+ 			System.err.println("Transfer error");
+ 			}
+ 		} else {
+ 			//displayURL(helpURL); 
+ 		}
+ 	}
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/SketchInfo.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/SketchInfo.java:1.1
*** /dev/null	Thu Feb  5 23:36:03 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/SketchInfo.java	Thu Jan 29 21:13:10 2004
***************
*** 0 ****
--- 1,24 ----
+ package org.tekkotsu.mon;
+ 
+ 
+ // stores info for a Sketch, to use as UserObject for DefaultMutableTreeNode
+ public class SketchInfo {
+ 	int id;
+ 	int parentId;
+ 	String name;
+ 
+ 	public SketchInfo(int _id, int _parentId, String _name) {
+ 		id = _id;
+ 		parentId = _parentId;
+ 		name = _name;
+ 	}
+ 
+ 	public int getId() { return id; }
+ 	public int getParentId() { return parentId; }
+ 	public String getName() { return name; }
+ 
+ 	public String toString() {
+ 		return (name + "(id " + id + ", parentId " + parentId + ")");
+ 	}
+ }
+ 
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/SketchPanel.java
diff -c /dev/null Tekkotsu/tools/mon/org/tekkotsu/mon/SketchPanel.java:1.1
*** /dev/null	Thu Feb  5 23:36:03 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/SketchPanel.java	Thu Jan 29 21:13:10 2004
***************
*** 0 ****
--- 1,79 ----
+ package org.tekkotsu.mon;
+ 
+ import java.util.Vector;
+ import javax.swing.JPanel;
+ import java.awt.image.BufferedImage;
+ import java.awt.Graphics;
+ import java.awt.Color;
+ import java.awt.Dimension;
+ import java.awt.FontMetrics;
+ 
+ public class SketchPanel extends JPanel {
+     String host;
+     int port;
+     BufferedImage _image;
+     boolean lockAspect=true;
+     Vector sketches;
+     static int width = 176;
+     static int height = 144;
+     float tgtAspect = 176/(float)144;
+ 
+     protected SketchPanel(String host, int port) {
+ 	this.host = host;
+ 	this.port = port;
+ 	setBackground(Color.BLACK);
+ 	setForeground(Color.WHITE);
+ 	setOpaque(!lockAspect);
+ 	_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ 
+ 	// Create a blank frame:
+ 	update(new Vector());
+     }
+ 
+     public BufferedImage getImage() {
+ 	return _image;
+     }
+ 
+     // Takes in a Vector of int arrays of pixels to composite:
+     public void update(Vector sketches) {
+ 	int [] data = new int[width*height];
+ 
+ 	// Get new Sketchs and compose them:
+ 	this.sketches = sketches;
+ 	for(int i = 0; i < sketches.size(); i++) {
+ 	    
+ 	}
+ 	_image.setRGB(0,0,width,height,data,0,width);
+     }
+ 
+     public void paint(Graphics graphics) {
+ 	super.paint(graphics);
+ 	Dimension sz=getSize();
+ 
+ 	float curasp=sz.width/(float)sz.height;
+ 	if(curasp>tgtAspect) {
+ 	    int width=(int)(sz.height*tgtAspect);
+ 	    drawImage(graphics,_image, (sz.width-width)/2, 0, width, sz.height);
+ 	} else if(curasp<tgtAspect) {
+ 	    int height=(int)(sz.width/tgtAspect);
+ 	    drawImage(graphics,_image, 0, (sz.height-height)/2, sz.width, height);
+ 	} else {
+ 	    drawImage(graphics,_image, 0, 0, sz.width, sz.height);
+ 	}
+     }
+     
+     protected void drawImage(Graphics g, BufferedImage img, int x, int y, int w, int h) {
+ 	if(img!=null)
+ 	     g.drawImage(img,x,y,w,h,null);
+ 	else {
+ 	    g.setColor(getBackground());
+ 	    g.fillRect(x,y,w,h);
+ 	    FontMetrics tmp=g.getFontMetrics();
+ 	    String msg="No image";
+ 	    int strw=tmp.stringWidth(msg);
+ 	    int strh=tmp.getHeight();
+ 	    g.setColor(getForeground());
+ 	    g.drawString(msg,(getSize().width-strw)/2,(getSize().height-strh)/2+tmp.getAscent());
+ 	}
+     }
+ }
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java:1.9 Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java:1.12
*** Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java:1.9	Tue Jan 20 15:05:31 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/VisionGUI.java	Thu Feb  5 14:12:31 2004
***************
*** 90,96 ****
  			args[0]=s[1];
  			port=VisionListener.defRawPort;
  		} else {
- 			args[0]="RAW";
  			port=Integer.parseInt(s[1]);
  		}
  		if(s.length>2) {
--- 90,95 ----
***************
*** 100,106 ****
  			else if(s[2].toUpperCase().compareTo("RAW")==0)
  				port=VisionListener.defRawPort;
  		}
! 		VisionGUI gui=new VisionGUI(s[0],port,args);
  		gui.addWindowListener(new WindowAdapter() {
  				public void windowClosing(WindowEvent e) { System.exit(0); } });
  	}
--- 99,109 ----
  			else if(s[2].toUpperCase().compareTo("RAW")==0)
  				port=VisionListener.defRawPort;
  		}
! 		VisionGUI gui;
! 		if(args[0].length()==0)
! 			gui=new VisionGUI(s[0],port,new String[0]);
! 		else
! 			gui=new VisionGUI(s[0],port,args);
  		gui.addWindowListener(new WindowAdapter() {
  				public void windowClosing(WindowEvent e) { System.exit(0); } });
  	}
***************
*** 212,219 ****
  
  	public void close() {
  		String name="VisionGUI"+(isRaw?".raw":"")+(isRLE?".rle":"")+".location";
! 		prefs.putInt(name+".x",getLocation().x+getInsets().left);
! 		prefs.putInt(name+".y",getLocation().y+getInsets().top);
  		this.vision.close();
  		if(this.imgWrite!=null && this.imgWrite.isAlive()) {
  			if(!this.imgWrite.isInterrupted() && !this.imgWrite.stopping)
--- 215,225 ----
  
  	public void close() {
  		String name="VisionGUI"+(isRaw?".raw":"")+(isRLE?".rle":"")+".location";
! 		prefs.putInt(name+".x",getLocation().x);
! 		prefs.putInt(name+".y",getLocation().y);
! 		//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 		//prefs.putInt(name+".x",getLocation().x+getInsets().left);
! 		//prefs.putInt(name+".y",getLocation().y+getInsets().top);
  		this.vision.close();
  		if(this.imgWrite!=null && this.imgWrite.isAlive()) {
  			if(!this.imgWrite.isInterrupted() && !this.imgWrite.stopping)
***************
*** 313,334 ****
  				vision=new VisionPanel(new VisionListener(host,port));
  				isRLE=true;
  				isRaw=false;
  			} else if(args[i].toUpperCase().compareTo("RAW")==0) {
  				setTitle("TekkotsuMon: Vision Raw");
  				vision=new VisionPanel(new VisionListener(host,port));
  				isRaw=true;
  				isRLE=false;
  			} else
  				System.err.println("VisionGUI: Unrecognized argument: "+args[i]);
  		}
  		if(vision==null) {
! 			System.err.println("VisionGUI: Error: Vision mode not specified");
! 		} else {
! 			vision.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
! 			vision.setPreferredSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2));
! 			vision.setLockAspectRatio(true);
! 			getContentPane().add(vision,BorderLayout.CENTER);
  		}
  		{
  			Box tmp2=Box.createHorizontalBox();
  			tmp2.add(Box.createHorizontalStrut(strutsize));
--- 319,350 ----
  				vision=new VisionPanel(new VisionListener(host,port));
  				isRLE=true;
  				isRaw=false;
+ 				break;
  			} else if(args[i].toUpperCase().compareTo("RAW")==0) {
  				setTitle("TekkotsuMon: Vision Raw");
  				vision=new VisionPanel(new VisionListener(host,port));
  				isRaw=true;
  				isRLE=false;
+ 				break;
  			} else
  				System.err.println("VisionGUI: Unrecognized argument: "+args[i]);
  		}
  		if(vision==null) {
! 			vision=new VisionPanel(new VisionListener(host,port));
! 			if(port==VisionListener.defRLEPort) {
! 				setTitle("TekkotsuMon: Vision RLE");
! 				isRLE=true;
! 				isRaw=false;
! 			} else {
! 				setTitle("TekkotsuMon: Vision Raw");
! 				isRLE=false;
! 				isRaw=true;
! 			}
  		}
+ 		vision.setMinimumSize(new Dimension(VisionListener.DEFAULT_WIDTH/2, VisionListener.DEFAULT_HEIGHT/2));
+ 		vision.setPreferredSize(new Dimension(VisionListener.DEFAULT_WIDTH*2, VisionListener.DEFAULT_HEIGHT*2));
+ 		vision.setLockAspectRatio(true);
+ 		getContentPane().add(vision,BorderLayout.CENTER);
  		{
  			Box tmp2=Box.createHorizontalBox();
  			tmp2.add(Box.createHorizontalStrut(strutsize));
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java:1.3 Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java:1.4
*** Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java:1.3	Tue Jan 20 15:05:31 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/VisionPanel.java	Wed Feb  4 21:00:56 2004
***************
*** 106,112 ****
  			float curasp=sz.width/(float)sz.height;
  			float tgtasp=getAspectRatio();
  			if(tgtasp<0)
! 				tgtasp=curasp;
  			if(curasp>tgtasp) {
  				int width=(int)(sz.height*tgtasp);
  				drawImage(graphics,_image, (sz.width-width)/2, 0, width, sz.height);
--- 106,112 ----
  			float curasp=sz.width/(float)sz.height;
  			float tgtasp=getAspectRatio();
  			if(tgtasp<0)
! 				tgtasp=_image.getWidth()/(float)_image.getHeight();
  			if(curasp>tgtasp) {
  				int width=(int)(sz.height*tgtasp);
  				drawImage(graphics,_image, (sz.width-width)/2, 0, width, sz.height);
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/WalkGUI.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/WalkGUI.java:1.2 Tekkotsu/tools/mon/org/tekkotsu/mon/WalkGUI.java:1.3
*** Tekkotsu/tools/mon/org/tekkotsu/mon/WalkGUI.java:1.2	Mon Jan 19 14:44:43 2004
--- Tekkotsu/tools/mon/org/tekkotsu/mon/WalkGUI.java	Wed Feb  4 18:28:42 2004
***************
*** 56,63 ****
  	}
  
  	public void close() {
! 		prefs.putInt("WalkGUI.location.x",getLocation().x+getInsets().left);
! 		prefs.putInt("WalkGUI.location.y",getLocation().y+getInsets().top);
  		comm.kill();
  		dispose();
  	}
--- 56,66 ----
  	}
  
  	public void close() {
! 		prefs.putInt("WalkGUI.location.x",getLocation().x);
! 		prefs.putInt("WalkGUI.location.y",getLocation().y);
! 		//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 		//prefs.putInt("WalkGUI.location.x",getLocation().x+getInsets().left);
! 		//prefs.putInt("WalkGUI.location.y",getLocation().y+getInsets().top);
  		comm.kill();
  		dispose();
  	}
Index: Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemory.java
diff -c Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemory.java:1.4 Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemory.java:1.5
*** Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemory.java:1.4	Thu Oct  9 20:46:58 2003
--- Tekkotsu/tools/mon/org/tekkotsu/mon/WatchableMemory.java	Wed Feb  4 18:28:42 2004
***************
*** 278,285 ****
  		WMregistry gui;
  		CloseAdapter(WMregistry gui) {this.gui=gui;}
  		public void windowClosing(WindowEvent e) {
! 			gui.prefs.putInt("WatchableMemory."+gui.name+".location.x",gui.getLocation().x+gui.getInsets().left);
! 			gui.prefs.putInt("WatchableMemory."+gui.name+".location.y",gui.getLocation().y+gui.getInsets().top);
  		}
  	}
  
--- 278,288 ----
  		WMregistry gui;
  		CloseAdapter(WMregistry gui) {this.gui=gui;}
  		public void windowClosing(WindowEvent e) {
! 			gui.prefs.putInt("WatchableMemory."+gui.name+".location.x",gui.getLocation().x);
! 			gui.prefs.putInt("WatchableMemory."+gui.name+".location.y",gui.getLocation().y);
! 			//I think I had needed to add getInsets() to keep the window from moving when reopening it, but now it *causes* it to move... weird.  what changed?
! 			//gui.prefs.putInt("WatchableMemory."+gui.name+".location.x",gui.getLocation().x+gui.getInsets().left);
! 			//gui.prefs.putInt("WatchableMemory."+gui.name+".location.y",gui.getLocation().y+gui.getInsets().top);
  		}
  	}
  
Index: Tekkotsu/tools/seg/VisionTrain.java
diff -c Tekkotsu/tools/seg/VisionTrain.java:1.4 Tekkotsu/tools/seg/VisionTrain.java:1.6
*** Tekkotsu/tools/seg/VisionTrain.java:1.4	Tue Jan 20 22:32:26 2004
--- Tekkotsu/tools/seg/VisionTrain.java	Mon Feb  2 13:31:25 2004
***************
*** 72,82 ****
  
      ImageData imageData=new ImageData();
  
  		if(isRGB)
! 			imageData.loadFullRGBFiles(files);
  		else 
! 			imageData.loadFullYUVFiles(files);
!     trainCanvas.plotImage(imageData.getHS(), imageData.getRGB());
    }
  }
  
--- 72,83 ----
  
      ImageData imageData=new ImageData();
  
+ 		//Thanks to martin.mueller at mni.fh-giessen.de for the bug fix:
  		if(isRGB)
! 			imageData.loadFullRGBFilesAsRGB(files);
  		else 
! 			imageData.loadFullYUVFilesAsRGB(files);
!     trainCanvas.plotImage(imageData.getHS(), imageData.getPixels());
    }
  }
  
