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:
| Type | Access | Notes/Usage | |
| OUTSIM Car position | |||
| carX | UVar | Read | Get Car postion X, Y, Z (Y=UP) |
| carY | UVar | Read | |
| carZ | UVar | Read | |
| Pitch | UVar | Read | Get Pitch, Yaw, Roll |
| Yaw | UVar | Read | |
| Roll | UVar | Read | |
| accelX | UVar | Read | Get Local Acceleration. From car center, +X=left, +Y=up and +Z=back. |
| accelY | UVar | Read | |
| accelZ | UVar | Read | |
| GForce | UVar | Read | Get Pre-computed G-FORCE |
| OUTGAUGE Data Car dashboard status | |||
| rpm | UVar | write/read | Get/Set current engine rpm |
| gear | UVar | write/read | Get/Set current selected gear |
| maxrpm | UVar | write/read | Get/Set max engine rpm |
| speed | UVar | write/read | Get/Set current speed (m/s) |
| laptime | UVar | write/read | Get/Set current lap time |
| neutral | UVar | write/read | Get/Set neutral char (usualy \'n\') |
| reverse | UVar | write/read | Get/Set reverse char (usualy \'r\') |
| leftdigits | UVar | write | Set text to display on left digits (6 chars max) |
| rightdigits | UVar | write | Set text to display on right digits (6 chars max) |
| Buttons Status (16 buttons can be connected to each device) | |||
| btnslot1 | UVar | read | Get Slot 1 ( 8 buttons from 1 to 8) |
| btnslot2 | UVar | read | Get Slot 2 ( 8 buttons from 9 to 16) |
| Global Properties | |||
| isMPH | UVar | write/read | Get/Set Speed unit KPH=0 / MPH=1 |
| isAutoMode or val | UVar | write/read | Get/Set Flag autoMode, who control the device, uobject=1 or urbiscript=0 |
| isPaused | UVar | read | Get 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:
#[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;
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.
