UrbiOpenSourceContestProjects

Zappadoc

Salut,

En tant que fan de robotique et développeur C++, je m’intéresse à URBI évidemment. J'ai également une passion pour la course auto (F1, GTR et Rallye) et c'est ce qui m'amène à ce concours. L'idée est de faire un programme URBI qui gère à la fois les cartes d'interface USB de Leo Bodnar (http://www.leobodnar.com) utilisées sur des simulateurs de course et les soft de simulations et autres jeux de course.

En fait, c'est un prétexte pour apprendre URBI, j'ai donc contacté EK (http://www.eksimracing.com) le fournisseur officiel des softs de Leo Bodnar afin qu'il me donne les infos nécessaires. Il a été très cool en me fournissant tout ce dont j'avais besoin avec une réserve tout de même, c'est que cela reste confidentiel. C'est pourquoi l'UObject que j'ai développé est en freeware.

Il s'agit d'un "pont" à la fois pour piloter les cartes USB de Leo (IN pour les boutons / OUT pour l'affichage) et pour récupérer les données de télémétrie provenant des softs de simulation ou jeux (vitesse, temps, tours/mn, etc.).

Pour le concours, j'ai implémenté de quoi manager les cartes SLI-M et SLI-PRO et le soft de simulation de Simbin GTR2 (http://www.simbin.se). Il existe une demo de GTR2 que je fourni avec le projet. Je pourrai ajouter le support d'autres softs de simulation si suffisamment de personnes y trouvent un intérêt.

Comme vous pouvez le constater, ce projet est avant tout pédagogique et fun! :)

Les éléments bientôt à disposition:
- l'UOBject "simracing"
- les scripts URBI permettant de réaliser très facilement un programme de simulation de course en qqs lignes grâce à la puissance d'URBI!
- la demo de la simulation GTR2

Plutôt qu'un long discours, voici en images ce que ça peut donner. En tapant SLI-PRO sur youtube.com, j'ai trouvé un tas de gens comme moi fans de simulation qui ont réalisé des vidéos. Voici un exemple de configuration musclée utilisant une SLI-PRO avec le soft de EK:

L'UObject n'était pas terminé que déjà j'ai pu constater la puissance du SDK d'URBI et la facilité avec laquelle il gère le mutli-threading. C'est un régal! :)

Configuration requise:
- Windows XP/Vista/W7
- URBI SDK 2.3
- simracing UObject (inclu dans le pkg)
- une simulation de course de Simbin (la demo de GTR2 est fournie)
- périphérique(s) USB de Leo Bodnar SLI-PRO et/ou SLI-M


Périfériques supportés
Mon UObject support 2 périphériques USB de Leo Bodnar (http://www.leobodnar.com).

SLI-M

SLI-PRO


simracing UOBject:

 TypeAccessNotes/Usage
OUTSIM Car position  
carXUVarReadGet Car postion X, Y, Z (Y=UP)
carYUVarRead 
carZUVarRead 
PitchUVarReadGet Pitch, Yaw, Roll
YawUVarRead 
RollUVarRead 
accelXUVarReadGet Local Acceleration. From car center, +X=left, +Y=up and +Z=back.
accelYUVarRead 
accelZUVarRead 
GForceUVarReadGet Pre-computed G-FORCE
OUTGAUGE Data Car dashboard status  
rpmUVarwrite/readGet/Set current engine rpm
gearUVarwrite/readGet/Set current selected gear
maxrpmUVarwrite/readGet/Set max engine rpm
speedUVarwrite/readGet/Set current speed (m/s)
laptimeUVarwrite/readGet/Set current lap time
neutralUVarwrite/readGet/Set neutral char (usualy \'n\')
reverseUVarwrite/readGet/Set reverse char (usualy \'r\')
leftdigitsUVarwriteSet text to display on left digits (6 chars max)
rightdigitsUVarwriteSet text to display on right digits (6 chars max)
Buttons Status (16 buttons can be connected to each device)  
btnslot1UVarreadGet Slot 1 ( 8 buttons from 1 to 8)
btnslot2UVarreadGet Slot 2 ( 8 buttons from 9 to 16)
Global Properties  
isMPHUVarwrite/readGet/Set Speed unit KPH=0 / MPH=1
isAutoMode or valUVarwrite/readGet/Set Flag autoMode, who control the device, uobject=1 or urbiscript=0
isPausedUVarreadGet simulation paused status (1=paused)


Methodes

supported SLI-M USB devices - first call after instantiation of UObject int connectSLIM();
supported SLI-PRO USB devices - first call after instantiation of UObject int connectSLIPRO();
shutdown device - last call to end the session with the device void disconnect();
test device void testUnit();
stop test void stopTest();
get data from Simbin simulation (http://www.simbin.se)param: application name of the simulation (i.e. GTR2Demo.exe)void getSimbinData(const std::string& v);
stop fetching Simbin data void stopSimbin();
write report OUT - Set all OUTGAUGE variables (see above) then send your report to the device. void simReportOUT();



Sample code:

Commençons par respecter la tradition... ;)
#[0000005304] *** ********************************************************
#[0000005304] *** Urbi SDK version 2.3 rev. 9a84600
#[0000005304] *** Copyright (C) 2005-2010 Gostai S.A.S.
#[0000005304] ***
#[0000005304] *** This program comes with ABSOLUTELY NO WARRANTY. It can
#[0000005304] *** be used under certain conditions. Type `license;',
#[0000005304] *** `authors;', or `copyright;' for more information.
#[0000005304] ***
#[0000005304] *** Check our community site: http://www.urbiforge.org.
#[0000005304] *** ********************************************************
=> var sp = simracing.new;
simracing Initialized
#[0000028905] simracing_0x5507cc8
=> sp.connectSLIPRO;
SLI-PRO Device Registered And Ready
#[0000037502] 0
=> sp.gear = " ".toAscii;
#[0000053594] 32
=> sp.leftdigits = "HELLO ";
#[0000071853] "HELLO "
=> sp.rightdigits = "UUorld";
#[0000086512] "UUorld"
=> sp.rpm = 0;
#[0000094467] 0
=> sp.simReportOUT;
=> sp.disconnect;
Device Unregistred
shutdown;


Le resultat sur la SLI-PRO



Projet SLIBrige en action:

Démo de GTR2(simulation) avec mon UObject + urbiscript:

Dans la video ci-dessus, il s'agit d'instancier 2 fois mon UObject simracing pour faire fonctionner 2 périphériques USB (SLI-M et SLI-PRO) simultanément.

 var sp = simracing.new; 
 var sm = simracing.new; 

Ensuite, il faut connecter sp à la SLI-PRO et sm à la SLI-M.

// connect SLI-PRO
if(sp.connectSLIPRO==0){
	echo("use sp instance to manage the SLI-PRO device.");
	Global.sliproReady = true;
};
// connect SLI-M 
if(sm.connectSLIM==0){
	echo("use sm instance to manage the SLI-M device.");
	Global.slimReady = true;
};

il faudra d’ailleurs bien veiller à déconnecter les instances des périphériques à la fin de la session.

sp.disconnect() & sm.disconnect(); 

on peut maintenant utiliser la fonction qui se charge de gérer les softs de simulation de Simbin en indiquant le nom de l'application utilisée (la demo gratuite et distribuable de GTR2 étant fourni dans le pkg et pré-installée) :

if(Global.sliproReady)
 sp.getSimbinData("GTR2Demo.exe");

A ce stade, il y a 2 choix possibles pour gérer les données. Grâce à la propriété isAutoMode vous pouvez choisir entre le mode automatique ou le mode urbi.

Dans le mode auto c'est l'UObject qui gère la simulation et l'affichage sur le ou les périphériques, dans le mode urbi c'est le code URBI qui gère les données télémétriques en provenance de la simulation et l'affichage sur les périphériques.

Le mode automatique (isAutoMode=1):

L'exemple de code ci-dessous montre comment gérer la simulation et l'affichage avec un minimum de code.

function autoProcessData(uobj)
{
	// uobject take the control of the device
	uobj.isAutoMode = 1;

	// set unit KPH or MPH
	if( Global.unit == "MPH")
		uobj.isMPH=1
	else
		uobj.isMPH=0;

}|;

{
	if(sliproReady) {
		autoProcessData(sp);
		detach({startSimbinMgr(sp, simulation)})& 
	},
}&

{
	if(slimReady) {
		autoProcessData(sm);
		detach({startSimbinMgr(sm, simulation)}),
	},
},

Le mode URBI (isAutoMode=0):

Dans ce mode tout doit être gérer avec le code urbiscript, voici un exemple de gestion de la simulation et de l'affichage des données sur les périphériques:

	var Global.processData = function (uobj)
	{ 
		// not paused
		if(uobj.isPaused==0)
		{
			// update gear
			var g = uobj.gear.clone;

			// neutral
			if(g==0)
				g = "n".toAscii;
			// reverse
			if(g==-1)
				g = "r".toAscii;

			// set gear
			uobj.gear = g; 

			// set max engine rpm
			uobj.maxrpm = uobj.maxrpm;

			// update rpm
			uobj.rpm = uobj.rpm;

			// update speed (m/s)
			var s = uobj.speed.clone;

			// KPH or MPH convertion
			if(unit=="KPH")
				s = s * 3.6
			else
				s = s * 2.237;
			// set speed
			uobj.leftdigits = "-%3.0f-" % [s];

			// set lap time
			// update current lap time (float)
			var lt = timeParser(uobj.laptime);
			uobj.rightdigits = lt;

		}
		else
		{
			// Paused
			uobj.leftdigits = "SIMUL ";
			uobj.rightdigits = "PAUSED";
			uobj.gear = " ".toAscii;
			uobj.rpm = 0.0;
			uobj.speed = 0.0;

		};

		// send updated data to device
		uobj.simReportOUT();

	}|;

var Global.simulation = "GTR2Demo.exe";
var Global.unit = "KMH";

if(slimReady){
	// urbiscript take the control of the device
	sm.isAutoMode = 0;

	// set unit KPH or MPH
	if( Global.unit == "MPH")
		sm.isMPH=1
	else
		sm.isMPH=0;

	// manage btns
	getBtnStatus(sm)&

	// Simbin sim
	startSimbinMgr(sm, Global.simulation);
};

if(sliproReady){
	// urbiscript take the control of the device
	sp.isAutoMode = 0;

	// set unit KPH or MPH
	if( Global.unit == "MPH")
		sp.isMPH=1
	else
		sp.isMPH=0;

	// manage btns
	getBtnStatus(sp)&

	// Simbin sim
	startSimbinMgr(sp, Global.simulation);
};

// SLI-PRO	
whenever((sp.isActivated==1) 
&& Global.sliproReady ){processData(sp);}&
// SLI-M
whenever((sm.isActivated==1) 
&& Global.slimReady ){processData(sm);}&

// stop simulation managment
at(sp.isActivated==0 
&& Global.sliproReady){stopSimbinMgr(sp, Global.simulation);}&
at(sm.isActivated==0 
&& Global.slimReady){stopSimbinMgr(sm, Global.simulation);},

En parallèle, on peut afficher un certain nombre de donnée télémétrique concernant la voiture, par exemple:

Position x,y,z

Pitch: Yaw: Roll

Local.Accel x,y,z

GForce

function showOutsim(uobj){
	echo("\nCar Position x,y,z:" + uobj.carX + ", " + uobj.carY + ", " + uobj.carZ 
	+    "\nPitch: Yaw: Roll:  " + uobj.pitch + " : " + uobj.yaw + " : " + uobj.roll 
	+    "\nLocal.Accel x,y,z: " + sp.accelX + ", " + uobj.accelY + ", " + uobj.accelZ 
	+    "\nG-Force:           " + uobj.GForce);

}|;

at((sp.isActivated==1) 
&& (sp.isPaused==0) && (sp.rpm != 0.0)
&& (Global.sliproReady) ){showOutsim(sp)},	

Il faut maintenant détecter la fin de session pour quitter proprement, je test ici la propriété isActivated pour savoir si la simulation a été quitté:

function stopSimbinMgr(uobj)
{
	Global.simActive = false;
	echo("Stop fetching data from Simbin " + Global.simulation);

	uobj.stopSimbin();
}|;

at(sp.isActivated==0){stopSimbinMgr(sp)}&
at(sm.isActivated==0){stopSimbinMgr(sm)}&

et bien évidement on peut aussi détecté la fin de session pour quitter urbi:

var Global.stopSim = function ()
{
	// disconnect SLI-PRO from simulation
	sp.disconnect();
	// disconnect SLI-M from simulation
	sm.disconnect();


}|;

at((sp.isActivated==0) && (Global.outsim)) {stopSim; shutdown;},

On peut également récupérer l'état des boutons en testant la propriété btnslot1 et btnslot2 correspond au 16 buttons disponible sur chaque périphérique, ci-dessous un exemple simplifié:

function getBtnStatus(uobj)
{
 // snipet for one button
 at(uobj.btnslot1==1) {
	// manage btn 1 of the device 
	// to switch from MPH to KPH
	// btn down
 }
 onleave
 {
	// button released
	if(uobj.btnslot1==0){
		if(uobj.isMPH ==1) 
		{
			uobj.isMPH=0;
			echo("KMH\n");
		}
		else{
			uobj.isMPH=1;
			echo("MPH\n");
		};
	};
 },
}|;

Et beaucoup d'autres choses sont possibles que vous découvrirez par vous même en explorant le code urbiscricpt fourni.

Download
Cliquez ici: ICI pour télécharger le pkg complet avec la demo distribuable de GTR2 pré-installée (simulation de course de Simbin).
Cliquez ICI pour télécharger le projet seul.
La demo de la simulation GTR2 (NON PRE-INSTALLEE) est dispo également ICI

Conclusion
Si j'avais à conclure je dirais que l'objectif de départ est largement atteint:
- mon uobject associé au script urbi permet de contrôler les deux périphériques USB et dans extraire les données télémétriques.
- D'un point de vue purement pédagogique, je connais mieux les deux aspects et le potentiel du language URBI (développement d'UObject et URBISCRIPT) même s'il reste du chemin à parcourir...
- enfin, je me suis bien ammusé en réalisant ce projet, si bien que je suis entrain de finaliser un autre projet tout aussi amusant il s'agit d'un UObject qui permet de controler l'interface Kinect ( Kinect, ROS ) de Microsoft (je posterai les sources et le bin sur urbiforge asap).

Toutes les informations concernant le projet sur cette page sont sujet à des changements sans préavis.

Options: