Beispiel #1
0
VRPNClient::VRPNClient(VRDevice::Factory* sFactory,VRDeviceManager* sDeviceManager,Misc::ConfigurationFile& configFile)
	:VRDevice(sFactory,sDeviceManager,configFile),
	 VRPNConnection(configFile.retrieveString("./serverName").c_str(),configFile.retrieveValue<int>("./serverPort",3883)),
	 reportEvents(false),
	 trackerStates(0),trackerFlags(0),buttonStates(0),valuatorStates(0)
	{
	#ifdef VERBOSE
	printf("VRPNClient: Initializing senders...");
	fflush(stdout);
	#endif
	
	/* Check if the z axis if incoming position data needs to be flipped: */
	setFlipZAxis(configFile.retrieveValue<bool>("./flipZAxis",false));
	
	/* Retrieve list of sender names: */
	typedef std::vector<std::string> StringList;
	StringList senderNames=configFile.retrieveValue<StringList>("./senderNames");
	
	/* Process all senders: */
	int totalNumTrackers=0;
	int totalNumButtons=0;
	int totalNumValuators=0;
	for(StringList::const_iterator snIt=senderNames.begin();snIt!=senderNames.end();++snIt)
		{
		/* Go to the sender's section: */
		configFile.setCurrentSection(snIt->c_str());
		
		/* Read the number of trackers, buttons, and valuators for this sender: */
		int numTrackers=configFile.retrieveValue<int>("./numTrackers",0);
		if(numTrackers>0)
			{
			requestTrackers(snIt->c_str(),totalNumTrackers,numTrackers);
			totalNumTrackers+=numTrackers;
			}
		int numButtons=configFile.retrieveValue<int>("./numButtons",0);
		if(numButtons>0)
			{
			requestButtons(snIt->c_str(),totalNumButtons,numButtons);
			totalNumButtons+=numButtons;
			}
		int numValuators=configFile.retrieveValue<int>("./numValuators",0);
		if(numValuators>0)
			{
			requestValuators(snIt->c_str(),totalNumValuators,numValuators);
			totalNumValuators+=numValuators;
			}
		
		/* Go back to device's section: */
		configFile.setCurrentSection("..");
		}
	
	#ifdef VERBOSE
	printf(" done\n");
	fflush(stdout);
	#endif
	
	/* Set number of trackers, buttons, and valuators: */
	setNumTrackers(totalNumTrackers,configFile);
	setNumButtons(totalNumButtons,configFile);
	setNumValuators(totalNumValuators,configFile);
	
	/* Read the initial position/orientation for all trackers: */
	PositionOrientation defaultPosition=configFile.retrieveValue<PositionOrientation>("./defaultPosition",PositionOrientation::identity);
	
	/* Initialize the local state arrays: */
	trackerStates=new TrackerState[getNumTrackers()];
	trackerFlags=new int[getNumTrackers()];
	for(int i=0;i<getNumTrackers();++i)
		{
		trackerStates[i].positionOrientation=defaultPosition;
		trackerStates[i].linearVelocity=LinearVelocity::zero;
		trackerStates[i].angularVelocity=AngularVelocity::zero;
		trackerFlags[i]=0x0;
		}
	buttonStates=new ButtonState[getNumButtons()];
	for(int i=0;i<getNumButtons();++i)
		buttonStates[i]=false;
	valuatorStates=new ValuatorState[getNumValuators()];
	for(int i=0;i<getNumValuators();++i)
		valuatorStates[i]=ValuatorState(0);
	
	/* Start device communication thread: */
	startDeviceThread();
	}
Beispiel #2
0
InterSense::InterSense(VRDevice::Factory* sFactory,VRDeviceManager* sDeviceManager,Misc::ConfigurationFile& configFile)
	:VRDevice(sFactory,sDeviceManager,configFile),
	 serialPort(configFile.retrieveString("./serialPort").c_str()),
	 stations(0),
	 timers(0),notFirstMeasurements(0),oldPositionOrientations(0)
	{
	/* Set device port parameters: */
	int deviceBaudRate=configFile.retrieveValue<int>("./deviceBaudRate");
	serialPort.setSerialSettings(deviceBaudRate,8,Comm::SerialPort::PARITY_NONE,1,false);
	serialPort.setRawMode(1,0);
	
	if(configFile.retrieveValue<bool>("./resetDevice",false))
		{
		/* Reset device: */
		#ifdef VERBOSE
		printf("InterSense: Resetting device\n");
		fflush(stdout);
		#endif
		serialPort.writeByte('\31');
		delay(15.0);
		}
	else
		{
		/* Stop continuous mode (in case it's still active): */
		#ifdef VERBOSE
		printf("InterSense: Disabling continuous mode\n");
		fflush(stdout);
		#endif
		serialPort.writeByte('c');
		}
	
	/* Request status record to check if device is okey-dokey: */
	#ifdef VERBOSE
	printf("InterSense: Requesting status record\n");
	fflush(stdout);
	#endif
	serialPort.writeByte('S');
	if(!readStatusReply())
		{
		/* Try resetting the device, seeing if that helps: */
		#ifdef VERBOSE
		printf("InterSense: Resetting device\n");
		fflush(stdout);
		#endif
		serialPort.writeByte('\31');
		delay(15.0);
		
		/* Request another status record: */
		#ifdef VERBOSE
		printf("InterSense: Re-requesting status record\n");
		fflush(stdout);
		#endif
		serialPort.writeByte('S');
		if(!readStatusReply())
			Misc::throwStdErr("InterSense: Device not responding");
		}
	
	/* Get the array of station enable flags: */
	#ifdef VERBOSE
	printf("InterSense: Detecting enabled stations\n");
	fflush(stdout);
	#endif
	serialPort.writeString("l*\r\n");
	delay(0.1);
	char buffer[256];
	readLine(sizeof(buffer),buffer,Misc::Time(1.0));
	if(strncmp(buffer,"21l",3)!=0)
		Misc::throwStdErr("InterSense: Unable to detect enabled stations");
	
	/* Disable all stations: */
	for(int i=0;i<32;++i)
		{
		stationIdToIndex[i]=-1;
		if(buffer[i+3]=='1')
			{
			char command[20];
			snprintf(command,sizeof(command),"l%d,0\r\n",i+1);
			serialPort.writeString(command);
			delay(0.1);
			}
		}
	
	/* Probe the constellation configuration if asked: */
	if(configFile.retrieveValue<bool>("./probeConstellation",false))
		{
		/* Check if the device has a valid constellation configuration: */
		#ifdef VERBOSE
		printf("InterSense: Probing constellation configuration\n");
		fflush(stdout);
		#endif
		serialPort.writeString("MCF\r\n");
		delay(0.1);
		int numTransmitters=0;
		while(true)
			{
			/* Read the next transmitter line: */
			readLine(sizeof(buffer),buffer,Misc::Time(1.0));
			
			/* Check if it's a valid transmitter line: */
			int transmitterNum,transmitterId;
			double posX,posY,posZ,dirX,dirY,dirZ;
			if(sscanf(buffer,"31F %d %lf %lf %lf %lf %lf %lf %d",&transmitterNum,&posX,&posY,&posZ,&dirX,&dirY,&dirZ,&transmitterId)!=8)
				break;
			
			/* Increase the number of transmitters: */
			++numTransmitters;
			}
		#ifdef VERBOSE
		printf("InterSense: Detected %d configured transmitters\n",numTransmitters);
		fflush(stdout);
		#endif
		}
	
	/* Upload a constellation configuration if asked: */
	std::string constellationName=configFile.retrieveString("./uploadConstellationConfiguration","");
	if(constellationName!="")
		{
		#ifdef VERBOSE
		printf("InterSense: Uploading constellation configuration %s\n",constellationName.c_str());
		fflush(stdout);
		#endif
		
		/* Go to constellation configuration's section: */
		configFile.setCurrentSection(constellationName.c_str());
		
		Transmitter* transmitters=0;
		
		try
			{
			/* Get the number of configured transmitters and the base number for internal IDs: */
			int numTransmitters=configFile.retrieveValue<int>("./numTransmitters");
			int transmitterIdBase=configFile.retrieveValue<int>("./transmitterIdBase",5001);
			
			/* Get the conversion factor from configuration units to meters: */
			float unitSize=configFile.retrieveValue<float>("./unitSize",1.0f);
			
			/* Read all transmitter configurations to check for validity first: */
			transmitters=new Transmitter[numTransmitters];
			for(int i=0;i<numTransmitters;++i)
				{
				/* Read the transmitter's configuration: */
				char transmitterName[20];
				snprintf(transmitterName,sizeof(transmitterName),"./MCF%d",i+1);
				transmitters[i]=configFile.retrieveValue<Transmitter>(transmitterName);
				
				/* Convert the transmitter's position to meters: */
				for(int j=0;j<3;++j)
					transmitters[i].pos[j]*=unitSize;
				
				/* Normalize the transmitter's direction: */
				transmitters[i].dir.normalize();
				}
			
			/* Upload constellation configuration to device: */
			serialPort.writeString("MCC\r\n");
			delay(0.1);
			for(int i=0;i<numTransmitters;++i)
				{
				const Transmitter& t=transmitters[i];
				char transmitterLine[256];
				snprintf(transmitterLine,sizeof(transmitterLine),
				         "MCF%d, %8.4f, %8.4f, %8.4f, %6.3f, %6.3f, %6.3f, %d\r\n",
				         i+1,t.pos[0],t.pos[1],t.pos[2],t.dir[0],t.dir[1],t.dir[2],i+transmitterIdBase);
				serialPort.writeString(transmitterLine);
				delay(0.1);
				}
			serialPort.writeString("MCe\r\n");
			delay(0.1);
			}
		catch(std::runtime_error err)
			{
			printf("InterSense: Ignoring constellation configuration %s due to exception %s\n",constellationName.c_str(),err.what());
			}
		
		/* Clean up: */
		delete[] transmitters;
		
		/* Go back to device's section: */
		configFile.setCurrentSection("..");
		}
	
	/* Retrieve list of station names: */
	typedef std::vector<std::string> StringList;
	StringList stationNames=configFile.retrieveValue<StringList>("./stationNames");
	setNumTrackers(stationNames.size(),configFile);
	stations=new Station[numTrackers];
	int totalNumButtons=0;
	int totalNumValuators=0;
	
	/* Initialize all tracked stations: */
	#ifdef VERBOSE
	printf("InterSense: Initializing tracked stations\n");
	fflush(stdout);
	#endif
	for(int i=0;i<numTrackers;++i)
		{
		char command[80];
		
		/* Go to station's section: */
		configFile.setCurrentSection(stationNames[i].c_str());
		
		/* Read station's configuration: */
		stations[i].id=configFile.retrieveValue<int>("./id",i+1);
		stationIdToIndex[stations[i].id]=i;
		stations[i].numButtons=configFile.retrieveValue<int>("./numButtons",0);
		stations[i].firstButtonIndex=totalNumButtons;
		totalNumButtons+=stations[i].numButtons;
		stations[i].joystick=configFile.retrieveValue<bool>("./joystick",false);
		stations[i].firstValuatorIndex=totalNumValuators;
		if(stations[i].joystick)
			totalNumValuators+=2;
		
		/* Enable station: */
		snprintf(command,sizeof(command),"l%d,1\r\n",stations[i].id);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Reset station's alignment frame: */
		snprintf(command,sizeof(command),"R%d\r\n",stations[i].id);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Disable boresight mode: */
		snprintf(command,sizeof(command),"b%d\r\n",stations[i].id);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Reset station's tip offset: */
		snprintf(command,sizeof(command),"N%d,%8.4f,%8.4f,%8.4f\r\n",stations[i].id,0.0f,0.0f,0.0f);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Set station's output format: */
		snprintf(command,sizeof(command),"O%d,2,4,22,23,1\r\n",stations[i].id);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Set stations' motion prediction: */
		int predictionTime=configFile.retrieveValue<int>("./predictionTime",0);
		snprintf(command,sizeof(command),"Mp%d,%d\r\n",stations[i].id,predictionTime);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Set stations' perceptual enhancement level: */
		int perceptualEnhancement=configFile.retrieveValue<int>("./perceptualEnhancement",2);
		snprintf(command,sizeof(command),"MF%d,%d\r\n",stations[i].id,perceptualEnhancement);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Set station's rotational sensitivity: */
		int rotationalSensitivity=configFile.retrieveValue<int>("./rotationalSensitivity",3);
		snprintf(command,sizeof(command),"MQ%d,%d\r\n",stations[i].id,rotationalSensitivity);
		serialPort.writeString(command);
		delay(0.1);
		
		/* Go back to device's section: */
		configFile.setCurrentSection("..");
		}
	
	/* Enable/disable sonistrip LEDs: */
	if(configFile.retrieveValue<bool>("./enableLEDs",true))
		{
		/* Enable LEDs: */
		#ifdef VERBOSE
		printf("InterSense: Enabling sonistrip LEDs\n");
		fflush(stdout);
		#endif
		serialPort.writeString("ML1\r\n");
		delay(0.1);
		}
	else
		{
		/* Enable LEDs: */
		#ifdef VERBOSE
		printf("InterSense: Disabling sonistrip LEDs\n");
		fflush(stdout);
		#endif
		serialPort.writeString("ML0\r\n");
		delay(0.1);
		}
	
	/* Set unit mode to inches: */
	#ifdef VERBOSE
	printf("InterSense: Setting unit mode\n");
	fflush(stdout);
	#endif
	serialPort.writeByte('U');
	delay(0.1);
	
	/* Enable binary mode: */
	#ifdef VERBOSE
	printf("InterSense: Enabling binary mode\n");
	fflush(stdout);
	#endif
	serialPort.writeByte('f');
	
	/* Set number of buttons and valuators: */
	setNumButtons(totalNumButtons,configFile);
	setNumValuators(totalNumValuators,configFile);
	
	/* Create free-running timers: */
	timers=new Misc::Timer[numTrackers];
	notFirstMeasurements=new bool[numTrackers];
	oldPositionOrientations=new PositionOrientation[numTrackers];
	}
VRDeviceManager::VRDeviceManager(Misc::ConfigurationFile& configFile)
	:deviceFactories(configFile.retrieveString("./deviceDirectory",VRDEVICEDAEMON_CONFIG_VRDEVICESDIR),this),
	 calibratorFactories(configFile.retrieveString("./calibratorDirectory",VRDEVICEDAEMON_CONFIG_VRCALIBRATORSDIR)),
	 numDevices(0),
	 devices(0),trackerIndexBases(0),buttonIndexBases(0),valuatorIndexBases(0),
	 fullTrackerReportMask(0x0),trackerReportMask(0x0),trackerUpdateNotificationEnabled(false),
	 trackerUpdateCompleteCond(0)
	{
	/* Allocate device and base index arrays: */
	typedef std::vector<std::string> StringList;
	StringList deviceNames=configFile.retrieveValue<StringList>("./deviceNames");
	numDevices=deviceNames.size();
	devices=new VRDevice*[numDevices];
	trackerIndexBases=new int[numDevices];
	buttonIndexBases=new int[numDevices];
	valuatorIndexBases=new int[numDevices];
	
	/* Initialize VR devices: */
	for(currentDeviceIndex=0;currentDeviceIndex<numDevices;++currentDeviceIndex)
		{
		/* Save the device's base indices: */
		trackerIndexBases[currentDeviceIndex]=int(trackerNames.size());
		buttonIndexBases[currentDeviceIndex]=int(buttonNames.size());
		valuatorIndexBases[currentDeviceIndex]=int(valuatorNames.size());
		
		/* Go to device's section: */
		configFile.setCurrentSection(deviceNames[currentDeviceIndex].c_str());
		
		/* Retrieve device type: */
		std::string deviceType=configFile.retrieveString("./deviceType");
		
		/* Initialize device: */
		#ifdef VERBOSE
		printf("VRDeviceManager: Loading device %s of type %s\n",deviceNames[currentDeviceIndex].c_str(),deviceType.c_str());
		fflush(stdout);
		#endif
		DeviceFactoryManager::Factory* deviceFactory=deviceFactories.getFactory(deviceType);
		devices[currentDeviceIndex]=deviceFactory->createObject(configFile);
		
		if(configFile.hasTag("./trackerNames"))
			{
			StringList deviceTrackerNames=configFile.retrieveValue<StringList>("./trackerNames");
			int trackerIndex=trackerIndexBases[currentDeviceIndex];
			int numTrackers=trackerNames.size();
			for(StringList::iterator dtnIt=deviceTrackerNames.begin();dtnIt!=deviceTrackerNames.end()&&trackerIndex<numTrackers;++dtnIt,++trackerIndex)
				trackerNames[trackerIndex]=*dtnIt;
			}
		
		/* Override device's button names: */
		if(configFile.hasTag("./buttonNames"))
			{
			StringList deviceButtonNames=configFile.retrieveValue<StringList>("./buttonNames");
			int buttonIndex=buttonIndexBases[currentDeviceIndex];
			int numButtons=buttonNames.size();
			for(StringList::iterator dtnIt=deviceButtonNames.begin();dtnIt!=deviceButtonNames.end()&&buttonIndex<numButtons;++dtnIt,++buttonIndex)
				buttonNames[buttonIndex]=*dtnIt;
			}
		
		/* Override device's valuator names: */
		if(configFile.hasTag("./valuatorNames"))
			{
			StringList deviceValuatorNames=configFile.retrieveValue<StringList>("./valuatorNames");
			int valuatorIndex=valuatorIndexBases[currentDeviceIndex];
			int numValuators=valuatorNames.size();
			for(StringList::iterator dtnIt=deviceValuatorNames.begin();dtnIt!=deviceValuatorNames.end()&&valuatorIndex<numValuators;++dtnIt,++valuatorIndex)
				valuatorNames[valuatorIndex]=*dtnIt;
			}
		
		/* Return to parent section: */
		configFile.setCurrentSection("..");
		}
	#ifdef VERBOSE
	printf("VRDeviceManager: Managing %d trackers, %d buttons, %d valuators\n",int(trackerNames.size()),int(buttonNames.size()),int(valuatorNames.size()));
	fflush(stdout);
	#endif
	
	/* Set server state's layout: */
	state.setLayout(trackerNames.size(),buttonNames.size(),valuatorNames.size());
	
	/* Read names of all virtual devices: */
	StringList virtualDeviceNames=configFile.retrieveValue<StringList>("./virtualDeviceNames",StringList());
	
	/* Initialize virtual devices: */
	for(StringList::iterator vdnIt=virtualDeviceNames.begin();vdnIt!=virtualDeviceNames.end();++vdnIt)
		{
		/* Create a new virtual device descriptor by reading the virtual device's configuration file section: */
		Vrui::VRDeviceDescriptor* vdd=new Vrui::VRDeviceDescriptor;
		vdd->load(configFile.getSection(vdnIt->c_str()));
		
		/* Store the virtual device descriptor: */
		virtualDevices.push_back(vdd);
		}
	#ifdef VERBOSE
	printf("VRDeviceManager: Managing %d virtual devices\n",int(virtualDevices.size()));
	fflush(stdout);
	#endif
	}