Copyright © 2008 Gostai
This document is released under the Attribution-NonCommercial-NoDerivs 2.0 Creative Commons licence (http://creativecommons.org/licenses/by-nc-nd/2.0/deed.en).
Table of Contents
Liburbi-java est une library créée pour encapsuler une connexion URBI. Elles gère la connexion TCP avec avec le serveur URBI, et la répartition des messages qu'il envoie. La library est thread-safe et rentrant. Cette library est générée à partir de la source Liburbi-c++ avec swig.
la library consiste en deux main classes Java, liburbi.UClient et
liburbi.USyncClient, et quelques fonctions utiles.
Nous supposerons le lecteur familiarisé avec la syntaxe URBI.
Table of Contents
Liburbi Java est une library générée à partir de la liburbi C++ avec l'outil appelé
swig. Swig génère des
classes wrapper en java pour toutes les classes C++ que nous voulons exporter. Il génère aussi du code
JNI pour faire le lien entre java et la library C++.
Avec cela en tête, vous comprendrez mieux que pour utiliser la liburbi java, vous aurez de toutes façon
charger le code C++ JNI dans votre application. Nous fournissons ce code C++ dans une library partagée
appelée urbijava.dll sous Windows, liburbijava.so sous Linux, et liburbijava.dylib sous MacOs.
Pour charger la library dans votre code java, utilisez la fonction système .loadLibrary.
Par exemple placez cet appel dans votre classe main comme ci-dessous:
// Toutes les classes liburbi se situent dans le package liburbi
import liburbi.main.UClient;
import liburbi.main.liburbi;
public class Main {
static {
System.loadLibrary("urbijava");
}
NB: Le chemin vers la library que vous chargez 'urbijava' doit être dans votre chemin pour que votre programme puisse la trouver. Sous Windows assurez vous que la variable d'environnement contiens le chemin vers la library urbijava. Sous Unix assurez vous que votre LD_LIBRARY_PATH contiens le chemin de la library urbijava.
Pour se connecter à un serveur URBI, créez simplement une nouvelle instance de liburbi.main.UClient
( ou liburbi.main.USyncClient si vous voulez utiliser les fonctions synchrones décrites plus bas),
en passant le nom ou l'adresse du serveur comme premier paramètre, et optionnellement le port comme second paramètre:
public static void main (String[] arg) {
UClient client = new UClient("myrobot.ensta.fr");
// un wrapper est disponible aussi dans la classe liburbi.main.liburbi:
// UClient client = liburbi.connect("myrobot.ensta.fr");
Le constructeur debutera un thread indépendant qui sera en attente de messages venant du serveur URBI.
Vous pouvez vérifier si la connection a été établie avec succès en appellant la fonction error,
qui retourne la valeur zero en cas de succès, ou un code différent d ezero en cas d'erreur.
if (client.error() != 0)
{
System.err.println("Couldn't connect to the URBI server.");
return;
}
La méthode send est le moyen le plus simple d'envoyer des commandes au serveur URBI.
Il prends une String comme paramètre:
int sleeptime = 50;
client.send("motoron;");
for (float val=0; val<=1; val+=0.05)
client->send("neck.val = " + val + ";wait (" + sleeptime ");");
Quelques fonctions statiques sont définies dans la classe liburbi.liburbi: 'getComma ()', 'getSemicolon()', 'getPipe()' et 'getParallel()' et elles retournent les caractères ',', ';', '|' et '&' respectivement.
Pour envoyer des data binaires au robot, la méthode sendBin doit être utilisée.
Elle prends comme paramètres le buffer à envoyer (nous supportons uniquement le type byte[] pour le moment)
et sa taille, et en option une en-tête.
client->sendBin(soundData, soundDataSize,
"speaker.val = BIN " + soundDataSize + " raw 2 16000 16 1;");
De la même façon vous pouvez utiliser sendBin pour jouer un son sur le robot,
une méthode spécifique et efficace a été écrite à cet effet: sendSound.
client->sendSound("speaker", sound, "endsound");
Le premier paramètre est le périphérique son auquel envoyer nous envoyons le son, le second
paramètre est une classe liburbi.main.USound décrivant le son à envoyer.
Le troisième est un tag optionnel qui sera utilisé par le serveur pour émettre un message système "stop"
quand le son sera fini. La fonction convert (in liburbi.liburbi class)
peut être utilisée pour les conversions entre les différents formats de sons.
Il n'y a aucune limite à la taille du buffer de son, celui-ci étant automatiquement découpé en tronçons par la library. Les data sont copiés par la library: le paramètre USound et ses data associés peuvent être libérés en toute sécurité dés le retour de la fonction.
Table of Contents
La plupart des messages reçus du serveur URBI sont le résultat d'une commande envoyée précédemment.
Le fonctionnement des tags URBI autorise à lier un message à sa réponse: à chaque commande est associé
un tag, et ce tag est répété dans le message de réponse. La classe liburbi.main.UClient
gère la réception de ces messages dans le thread indépendant créé par le constructeur, les parse et remplis
une structure UMessage.
Dans votre programme java, vous pouvez avoir des extensions de classes liburbi.main.UCallbackInterface et
redéfinir sa méthode onMessage. Vous pouvez enregistrer ces classes avec la méthode
UClient setCallback et les associer avec un tag.
puis chaque fois qu'un message avec ce tag est envoyé au serveur, la fonction redéfinie onMessage
sera appelée avec une classe liburbi.main.UMessage comme paramètre.
La classe liburbi.main.UCallbackInterface est définie ainsi:
package liburbi.main;
public class UCallbackInterface {
public UCallbackAction onMessage(UMessage msg);
}
La fonction onMessage prends comme paramètre un liburbi.main.UMessage
et retourne un enum: liburbi.main.UCallbackAction qui peut avoir deux valeurs:
liburbi.main.UCallbackAction.URBI_CONTINUE ou
liburbi.main.UCallbackAction.URBI_REMOVE (dans un tel cas le retour est enlevé, et ne sera
plus appelé, même si vous recevez un message avec le même tag).
La fonction setCallback est définie ainsi:
package liburbi.main;
public class UClient {
[...]
public long setCallback(UCallbackInterface ref, String tag);
}
donnez comme premier paramètre votre classe redéfinie liburbi.main.UCallbackInterface,
et donnez comme second argument une String correspondant au tag auquel vous voulez associer le retour.
La structure UMessage peut stocker les informations contenues dans toutes sortes de messages URBI en utilisant une fonction "getType" et une UValue (union de classes). Ces deux classes sont définies ainsi:
package liburbi.main;
public enum UMessageType {
MESSAGE_SYSTEM, /// Message système
MESSAGE_ERROR, /// Message d'erreur
MESSAGE_DATA; /// Message contenant des data dans la UValue
}
public class UMessage {
/// Server-side timestamp.
public int getTimestamp();
/// Tag associé.
public String getTag();
/// Type de la UValue contenue dans le UMessage
public UMessageType getType();
/// UValue contenue dans le UMessage
public UValue getValue();
public String getMessage();
/// Raw message sans les data binaires.
public String getRawMessage();
/// Client d'où provient le message.
public UAbstractClient getClient();
}
le champ type UMessageType peut être MESSAGE_SYSTEM, MESSAGE_ERROR ou MESSAGE_DATA. Si le type est MESSAGE_DATA, le message contiens une UValue.
package liburbi.main;
public enum UDataType {
DATA_DOUBLE,
DATA_STRING,
DATA_BINARY,
DATA_LIST,
DATA_OBJECT,
DATA_VOID;
}
public class UValue {
public UDataType getType();
/// valeur si de type UDataType.DATA_STRING
/// vérifiez que cette chaîne n'est pas null (c'est possible du côté C++,
/// souvenez vous que liburbijava est batie au-dessus de liburbic++)
/// avec 'isStringNull ()'
public String getString();
public boolean isStringNull();
/// valeur si de type UDataType.DATA_DOUBLE
public double getDouble();
/// valeur si de type UDataType.DATA_BINARY
public UBinary getUBinary();
/// valeur si de type UDataType.DATA_LIST
public UList getUList();
/// utilisé pour afficher correctement la UValue
public String toString();
}
La UValue contiens un UDataType qui peut prendre les valeurs: DATA_DOUBLE, DATA_STRING, DATA_BINARY, DATA_LIST, DATA_OBJECT, DATA_VOID. Dependant de ce champ, la valeur correspondante dans la UValue sera réglée. Si la UValue est de type binaire, elle contient une classe UBinary définie ci-après. Le UBinaryType dans la structure UBinary donnera des informations additionnelles sur le type des data (BINARY_NONE, BINARY_UNKNOWN, BINARY_IMAGE, BINARY_SOUND), et la structure de son ou d'image adaptée sera complétée.
package liburbi.main;
public enum UBinaryType {
BINARY_NONE,
BINARY_UNKNOWN,
BINARY_IMAGE,
BINARY_SOUND;
}
public class UBinary {
public UBinaryType getType();
/// valeur si de type BINARY_IMAGE
public UImage getUImage();
/// valeur si de type BINARY_SOUND
public USound getUSound();
/// Taille des data
public int getSize();
public String getMessage();
public String getExtraHeader();
}
package liburbi.main;
public enum USoundFormat {
SOUND_RAW,
SOUND_WAV,
SOUND_MP3,
SOUND_OGG,
SOUND_UNKNOWN;
}
public enum USoundSampleFormat {
SAMPLE_SIGNED(1),
SAMPLE_UNSIGNED(2);
}
public class USound {
/// taille total en byte
public long getSize();
/// Nombres de canaux audio
public int getChannels();
/// rate en Hertz
public int getRate();
/// taille du sample en bit
public int getSampleSize();
/// format des sound data
/// (SOUND_RAW, SOUND_WAV, SOUND_MP3...)
public USoundFormat getSoundFormat();
/// format du sample
public USoundSampleFormat getSampleFormat();
/// data du sound dans une table de byte
public byte[] getDataAsByte();
}
package liburbi.main;
public enum UImageFormat {
IMAGE_RGB(1),
IMAGE_YCbCr(2),
IMAGE_JPEG(3),
IMAGE_PPM(4),
IMAGE_UNKNOWN;
}
public class UImage {
/// taille de l'image en byte
public long getSize();
/// largeur d'image
public long getWidth();
/// hauteur d'image
public long getHeight();
/// IMAGE_RGB, IMAGE_YCbCr, IMAGE_JPEG...
public UImageFormat getImageFormat();
/// data de l'image data dans une table de byte
public byte[] getDataAsByte();
}
import liburbi.main.*;
/// Callback pour des images
class onImage extends UCallbackInterface {
public UCallbackAction onMessage(UMessage msg) {
if (!(UMessageType.MESSAGE_DATA == msg.getType ()))
return UCallbackAction.URBI_CONTINUE;
UValue value = msg.getValue ();
if (!(UDataType.DATA_BINARY == value.getType ()))
return UCallbackAction.URBI_CONTINUE;
UBinary bin = value.getUBinary ();
if (!(UBinaryType.BINARY_IMAGE == bin.getType ()))
return UCallbackAction.URBI_CONTINUE;
UImage img = bin.getUImage ();
byte[] data = img.getDataAsByte ();
System.out.println("Image of size " + img.getWidth () + "x"
+ img.height + " received");
/// myDisplay*Image sont des fonctions customisées qui ne font pas parties de liburbi-java
/// replacez par votre propre code
if (img.imageFormat == UImageFormat.IMAGE_JPEG)
myDisplayJPEGImage (data, img.getWidth (), img.getHeight ());
else if (img.imageFormat == UImageFormat.IMAGE_YCbCr)
myDisplayYCbCrImage (data, img.getWidth (), img.getHeight ());
else if (img.imageFormat == UImageFormat.IMAGE_RGB)
myDisplayRGBImage (data, img.getWidth (), img.getHeight ());
return UCallbackAction.URBI_CONTINUE;
}
}
/// Callback pour un sound
class onSound extends UCallbackInterface {
public UCallbackAction onMessage(UMessage msg) {
if (!(UMessageType.MESSAGE_DATA == msg.getType ()))
return UCallbackAction.URBI_CONTINUE;
UValue value = msg.getValue ();
if (!(UDataType.DATA_BINARY == value.getType ()))
return UCallbackAction.URBI_CONTINUE;
UBinary bin = value.getUBinary ();
if (!(UBinaryType.BINARY_SOUND == bin.getType ()))
return UCallbackAction.URBI_CONTINUE;
USound sound = bin.getUSound ();
byte[] data = img.getDataAsByte ();
System.out.println("Sound received");
return UCallbackAction.URBI_CONTINUE;
}
}
/// Callback pour des valeurs d'articulation
class onJoint extends UCallbackInterface {
public UCallbackAction onMessage(UMessage msg) {
if (!(UMessageType.MESSAGE_DATA == msg.getType ()))
return UCallbackAction.URBI_CONTINUE;
UValue value = msg.getValue ();
if (!(UDataType.DATA_DOUBLE == value.getType ()))
return UCallbackAction.URBI_CONTINUE;
System.out.println("The joint value is " + value.getDouble ());
return UCallbackAction.URBI_CONTINUE;
}
}
public class test {
static {
/// Chargez la library C++ liburbi et le code jni.
System.loadLibrary("urbijava");
}
public static void main(String argv[]) {
UClient c = new UClient(argv[1]);
if (c.error() != 0)
{
System.out.println("Couldn't connect to the URBI server.");
System.exit(1);
}
onImage oi = new onImage ();
onJoint oj = new onJoint ();
onSound os = new onSound ();
c.setCallback (oi, "img");
c.setCallback (oj, "snd");
c.setCallback (os, "joint");
c.send("img: camera.val;");
c.send("loop snd: micro.val,");
c.send("joint: headPan.val;");
liburbi.execute (); /// fonction qui fait une veille infinie
}
}
Table of Contents
![]() |
![]() |
![]() |
![]() |
Le projet liburbi java est chargé. Vous pouvez voir les trois packages de liburbi: liburbi.main, liburbi.image et liburbi.sound. A partir de la source dans ces trois packages, nous avons fait liburbijava.jar, que vous pouvez utiliser dans vos applications. Vous pouvez voir aussi les sources des différents exemples que nous fournissons. Nous les avons déposé dans les packages examples.nameofexample. Vous pouvez vous inspirer de ces exemples dans vos applications. Ici, nous allons voir comment les compiler et les faire tourner dans Eclipse
NB: Si Eclipse se plaint d'erreurs dans le code source, ce peut être que le niveau de compliance de votre compilateur est trop bas. Vous avez à régler le niveau de compliance du compilateur au moins sur Java 5 (Windows/Preferences/Java/Compiler).
![]() |
![]() |
![]() |
En dehors des cas ou ce que vous faites est simple, essayez de ne pas utiliser les fonctions sync*. Elles sont moins efficaces que les asynchrones.
Les fonctions avec retour devrons retourner aussi vite que possible, les retours étant tous appellé par le même thread. Si vous avez des opérations gourmandes en temps d'exécution, vous devriez les lancer dans un autre thread et utiliser des mécanismes de synchronisation comme les sémaphores ou les mutexes.
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE
TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR
"LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE
LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE
OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS
YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF
SUCH TERMS AND CONDITIONS.
1. Definitions
1. "Collective Work" means a work, such as a periodical issue,
anthology or encyclopedia, in which the Work in its entirety in
unmodified form, along with a number of other contributions,
constituting separate and independent works in themselves, are
assembled into a collective whole. A work that constitutes a
Collective Work will not be considered a Derivative Work (as
defined below) for the purposes of this License. 2. "Derivative
Work" means a work based upon the Work or upon the Work and other
pre-existing works, such as a translation, musical arrangement,
dramatization, fictionalization, motion picture version, sound
recording, art reproduction, abridgment, condensation, or any other
form in which the Work may be recast, transformed, or adapted,
except that a work that constitutes a Collective Work will not be
considered a Derivative Work for the purpose of this License. For
the avoidance of doubt, where the Work is a musical composition or
sound recording, the synchronization of the Work in timed-relation
with a moving image ("synching") will be considered a Derivative
Work for the purpose of this License. 3. "Licensor" means the
individual or entity that offers the Work under the terms of this
License. 4. "Original Author" means the individual or entity who
created the Work. 5. "Work" means the copyrightable work of
authorship offered under the terms of this License. 6. "You" means
an individual or entity exercising rights under this License who
has not previously violated the terms of this License with respect
to the Work, or who has received express permission from the
Licensor to exercise rights under this License despite a previous
violation.
2. Fair Use Rights. Nothing in this license is intended to reduce,
limit, or restrict any rights arising from fair use, first sale or
other limitations on the exclusive rights of the copyright owner under
copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
1. to reproduce the Work, to incorporate the Work into one or more
Collective Works, and to reproduce the Work as incorporated in the
Collective Works; 2. to distribute copies or phonorecords of,
display publicly, perform publicly, and perform publicly by means
of a digital audio transmission the Work including as incorporated
in Collective Works;
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights
in other media and formats, but otherwise you have no rights to make
Derivative Works. All rights not expressly granted by Licensor are
hereby reserved, including but not limited to the rights set forth in
Sections 4(d) and 4(e).
4. Restrictions.The license granted in Section 3 above is expressly
made subject to and limited by the following restrictions:
1. You may distribute, publicly display, publicly perform, or
publicly digitally perform the Work only under the terms of this
License, and You must include a copy of, or the Uniform Resource
Identifier for, this License with every copy or phonorecord of the
Work You distribute, publicly display, publicly perform, or
publicly digitally perform. You may not offer or impose any terms
on the Work that alter or restrict the terms of this License or the
recipients' exercise of the rights granted hereunder. You may not
sublicense the Work. You must keep intact all notices that refer to
this License and to the disclaimer of warranties. You may not
distribute, publicly display, publicly perform, or publicly
digitally perform the Work with any technological measures that
control access or use of the Work in a manner inconsistent with the
terms of this License Agreement. The above applies to the Work as
incorporated in a Collective Work, but this does not require the
Collective Work apart from the Work itself to be made subject to
the terms of this License. If You create a Collective Work, upon
notice from any Licensor You must, to the extent practicable,
remove from the Collective Work any reference to such Licensor or
the Original Author, as requested. 2. You may not exercise any of
the rights granted to You in Section 3 above in any manner that is
primarily intended for or directed toward commercial advantage or
private monetary compensation. The exchange of the Work for other
copyrighted works by means of digital file-sharing or otherwise
shall not be considered to be intended for or directed toward
commercial advantage or private monetary compensation, provided
there is no payment of any monetary compensation in connection with
the exchange of copyrighted works. 3. If you distribute, publicly
display, publicly perform, or publicly digitally perform the Work,
You must keep intact all copyright notices for the Work and give
the Original Author credit reasonable to the medium or means You
are utilizing by conveying the name (or pseudonym if applicable) of
the Original Author if supplied; the title of the Work if supplied;
and to the extent reasonably practicable, the Uniform Resource
Identifier, if any, that Licensor specifies to be associated with
the Work, unless such URI does not refer to the copyright notice or
licensing information for the Work. Such credit may be implemented
in any reasonable manner; provided, however, that in the case of a
Collective Work, at a minimum such credit will appear where any
other comparable authorship credit appears and in a manner at least
as prominent as such other comparable authorship credit. 4.
For the avoidance of doubt, where the Work is a musical
composition: 1. Performance Royalties Under Blanket
Licenses. Licensor reserves the exclusive right to collect,
whether individually or via a performance rights society
(e.g. ASCAP, BMI, SESAC), royalties for the public
performance or public digital performance (e.g. webcast) of
the Work if that performance is primarily intended for or
directed toward commercial advantage or private monetary
compensation. 2. Mechanical Rights and Statutory
Royalties. Licensor reserves the exclusive right to collect,
whether individually or via a music rights agency or
designated agent (e.g. Harry Fox Agency), royalties for any
phonorecord You create from the Work ("cover version") and
distribute, subject to the compulsory license created by 17
USC Section 115 of the US Copyright Act (or the equivalent in
other jurisdictions), if Your distribution of such cover
version is primarily intended for or directed toward
commercial advantage or private monetary compensation.
5. Webcasting Rights and Statutory Royalties. For the
avoidance of doubt, where the Work is a sound recording,
Licensor reserves the exclusive right to collect, whether
individually or via a performance-rights society
(e.g. SoundExchange), royalties for the public digital
performance (e.g. webcast) of the Work, subject to the
compulsory license created by 17 USC Section 114 of the US
Copyright Act (or the equivalent in other jurisdictions), if
Your public digital performance is primarily intended for or
directed toward commercial advantage or private monetary
compensation.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR
OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE,
MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR
THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF
ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO
NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY
NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY
APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY
LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR
EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK,
EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
1. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this
License. Individuals or entities who have received Collective Works
from You under this License, however, will not have their licenses
terminated provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
survive any termination of this License. 2. Subject to the above
terms and conditions, the license granted here is perpetual (for
the duration of the applicable copyright in the
Work). Notwithstanding the above, Licensor reserves the right to
release the Work under different license terms or to stop
distributing the Work at any time; provided, however that any such
election will not serve to withdraw this License (or any other
license that has been, or is required to be, granted under the
terms of this License), and this License will continue in full
force and effect unless terminated as stated above.
8. Miscellaneous
1. Each time You distribute or publicly digitally perform the Work
or a Collective Work, the Licensor offers to the recipient a
license to the Work on the same terms and conditions as the license
granted to You under this License. 2. If any provision of this
License is invalid or unenforceable under applicable law, it shall
not affect the validity or enforceability of the remainder of the
terms of this License, and without further action by the parties to
this agreement, such provision shall be reformed to the minimum
extent necessary to make such provision valid and enforceable.
3. No term or provision of this License shall be deemed waived and
no breach consented to unless such waiver or consent shall be in
writing and signed by the party to be charged with such waiver or
consent. 4. This License constitutes the entire agreement between
the parties with respect to the Work licensed here. There are no
understandings, agreements or representations with respect to the
Work not specified here. Licensor shall not be bound by any
additional provisions that may appear in any communication from
You. This License may not be modified without the mutual written
agreement of the Licensor and You.