Doc URBI

Pour urbiengine-ePuck

Documentation des périphériques

(book compiled from )

Benjamin Renoust

Traduction de l'anglais Antoine (zelig) Hue

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

1. Introduction
2. Sample
3. UObject de périphériques disponibles
Wheel
Led
Micro
Selector
IR
Accelerometer
Camera
Colormap
Speaker
Command
Les instances
Groups
4. Comment utiliser l'agencement en usage
Introduction
Motors
Sensors
Bumper
Sonar
Decibel
Light
Battery
Beeper
Command
5. Comment personnaliser son agencement
Introduction
Motors
Sensors
Autres périphériques
6. Tutoriels (incomplet)
Comment faire des fonctions basiques de mouvement.
Tip :
Comment faire un déplacement aléatoire
A. Copyright

List of Tables

3.1. Les attributs de Wheel :
3.2. Les attributs de Led :
3.3. Les attributs du Sound sensor :
3.4. Les attributs du Selector :
3.5. Les attributs d'IR :
3.6. Les attributs d'Accelerometer :
3.7. Les attributs de Camera :
3.8. Les attributs de colormap :
3.9. Les méthodes de Speaker :
3.10. Les méthodes de Command :
3.11. Les caractéristiques de Servo
3.12. Liste de Groupe

Chapter 1. Introduction

Cette documentation contient des informations pour le URBI engine du robot ePuck's. Dans l'état, les périphériques disponibles sont résumés ici. Vous trouverez également de nombreux tutoriels sur la façon d'utiliser l'agencement actuel, comment faire votre propre agencement et plus.

Chapter 2. Sample

Ceci est un exemple simple qui explique comment utiliser le serveur URBI. Dans le répertoire src , écrivez:

./epuck.exe 50 ../data COM6

Dans ce cas, un serveur URBI est créé. Comme tout serveur, le port par défaut est 54000 et le path (chemin de répertoire) par défaut est . et ../data. Le dernier paramètre défini le port de connection, ce peut être n'importe quel port de COM où le robot est relié.

Chapter 3.  UObject de périphériques disponibles

La documentation sur les périphériques suivants est écrite pour le URBI engine du ePuck.

Wheel

L'UObject Wheel décrit un périphérique roue et contient les attributs suivants :

Table 3.1. Les attributs de Wheel :

NomDescription
ididentification de Wheel, il peut être "Left" ou "Right"
valLa vitesse de Wheel, de -1000 à 1000
positionLa position de Wheel, de -32000 à 32000.
init(id)

Le constructeur d'UObject.

id est une identification. (voir attribut précédent id).

Exemple:

wheel = new Wheel("Left");
reset()

Reset la position de Wheel à 0.

Exemple:

wheel.reset();

Led

L'UObject Led décrit un périphérique led et contient les attributs suivants :

Table 3.2. Les attributs de Led :

NomDescription
ididentification de la Led, les valeurs peuvent être de 0 à 9. Chaque valeur réfère à une led différente.
valL'état de la led. Il peut être 0 (off), 1 (on) ou 2 (switch).
init(id)

Le constructeur d'UObject.

id est un numéro d'identification. (voir attribut précédent id).

Exemple:

ledA = new Led(1);

Micro

L'UObject Micro décrit un périphérique microphone et contient les attributs suivants :

Table 3.3. Les attributs du Sound sensor :

NomDescription
idUne valeur d'identification, elle peut être "Left", "Right" ou "Back".
valLe niveau du son mesuré.
init(id)

Le constructeur d'UObject.

id est un numéro d'identification. (voir attribut précédent id).

Exemple:

mic = new Micro("Back");

Selector

L'UObject Selector décrit le petit switch selector sur le dessus du robot et contient les attributs suivants :

Table 3.4. Les attributs du Selector :

NomDescription
valLa position courante du (peut être 0 à 15).
init()

Le constructeur d'UObject.

Exemple:

sel = new Selector();

IR

L'UObject IR décrit les 8 périphériques infrarouges et contient les attributs suivants :

Table 3.5. Les attributs d'IR :

NomDescription
valLes valeurs de proximité d'IR. C'est une liste de 8 valeurs correspondantes à 8 distances de proximité.
lightLes valeurs de lumière IR. C'est une liste de 8 valeurs correspondantes à 8 intensités lumineuses ambiantes.
init()

Le constructeur d'UObject.

Exemple:

infraRed = new IR();

Accelerometer

L'UObject IR décrit les 3 périphériques accéléromètres et contient les attributs suivants :

Table 3.6. Les attributs d'Accelerometer :

NomDescription
valValeur de l'accélération verticale.
inclinationValeur de l'inclinaison.
orientationValeur de l'orientation.
init()

Le constructeur d'UObject

Exemple

acc = new Acceleromter();

Camera

L'UObject Camera décrit le périphérique caméra et contient les attributs suivants :

Table 3.7. Les attributs de Camera :

NomDescription
valL'image de la caméra.
zoomLa valeur du zoom. Par défaut, il est réglé à 8, mais il peut aussi être 4, 2 ou 1.
modeLa valeur du mode de camera. Par défaut, il est réglé à 1 (qui correspond à couleur), autrement il peut être à 0 (noir et blanc).
heightLa valeur hauteur de camera. Par défaut, elle est réglé à 40, il n'est pas recommandé de toucher cette valeur ce qui cause une grande instabilité dans le robot.
widthLa valeur largeur de camera. Par défaut, elle est réglé à 40, il n'est pas recommandé de toucher cette valeur ce qui cause une grande instabilité dans le robot.
init()

Le constructeur d'UObject

Exemple

c = new Camera();

Colormap

L'UObject Colormap quand il est lié au périphérique camera fournit un détecteur de taches de base et contient les attributs suivants :

Table 3.8. Les attributs de colormap :

NomDescription
xLa position x du centre de gravité de la tache.
yLa position y du centre de gravité de la tache.
visibleCette propriété est réglée à 1 quand la tache est visible.
ratioLe ratio de la tache.
thresholdLe seuil de la tache.
orientationl'orientation de la tache.
elongationAlongement de la tache.
yminValeur ymin de la couleur désirée. (Composante y de la couleur de la tache en YCbCr).
ymaxValeur ymax de la couleur désirée. (Composante Y de la couleur de la tache en YCbCr).
cbminValeur cbmin de la couleur désirée. (Composante Cb de la couleur de la tache en YCbCr).
cbmaxValeur cbmax de la couleur désirée. (Composante Cb de la couleur de la tache en YCbCr).
crminValeur crmin de la couleur désirée. (Composante Cr de la couleur de la tache en YCbCr).
crmaxValeur crmax de la couleur désirée. (Composante Cr de la couleur de la tache en YCbCr).
init(source, ymin, ymax, cbmin, cbmax, crmin, crmax, threshold)

Le constructeur d'UObject

source est le nom de l'image source (habituellement la caméra).

ymin, ymax, cbmin, cbmax, crmin, crmax sont les paramètres de la couleur de la tache.

threshold est le ratio minimum d'une couleur choisie pour considérer la tache visible.

Exemple

c = new Colormap("camera.val", 0, 255, 120, 190, 150, 230, 0.1););

which detects a pink ball.


Speaker

L'UObject Speaker décrit le périphérique haut-parleur, vous autorisant à utiliser :

Table 3.9. Les méthodes de Speaker :

NomDescription
play(sound)

Jouer un son d'usage.

sound peut être "wow", "waa", "ouch", "hit", "uh" or "off".

Exemple:

Speaker.play("wow");
stop()

appel de play("off") : il ferme le haut-parleur et coupe le bruit permanent du haut-parleur.

Exemple

Speaker.stop();

Command

L'UObject Command est conçu pour vous permettre d'utiliser des commandes spéciales :

Table 3.10. Les méthodes de Command :

NomDescription
reset()

Reset complètement le robot.

Exemple:

Command.reset();

.

stop()

Arrête le robot et éteint les leds.

Exemple:

Command.stop();

.

version()

imprime la version du firmware en cours.

Exemple:

Command.version();

.

calibrate()

Calibration du capteur IR.

Exemple:

Command.calibrate();

.


Les instances

Voici les différentes instances que nous avons choisi pour l'agencement en cours.

Table 3.11. Les caractéristiques de Servo

InstanceUObjectDescription
wheelLServoLeft wheel
wheelRServoRight wheel
clawServoClaw
sonarUltraSoundSensorDistance sensor
decibelSoundSensorSound sensor
lightLightSensorLight sensor
bumperSwitchTouch sensor
beeperBeeperEmits beeps
batteryBatteryBattery

Groups

Voici les différents groupes fournis dans l'agencement en cours.

Table 3.12. Liste de Groupe

Nom du groupeDescription
wheelsLes deux roues.
motorsTous les moteurs.
sensorsTous les capteurs.
hardwareTous les périphériques.

Chapter 4. Comment utiliser l'agencement en usage

Introduction

Cette documentation présente comment utiliser l'engine avec l'agencement en usage chargé (TriBot.ini). Vous trouverez des informations utiles à propos d'URBI sur http://gostai.com/doc/urbi-tutorial.htm.

Motors

Trois moteurs sont disponibles, wheelL, wheelR et claw. wheelL et wheelR sont groupés dans wheels. Chaque moteur est aliasé à son attribut .torque. aussi :

wheelL = 10; 

égale

wheelL.torque = 10;

et

wheels = 10;

égale

wheelL = 10 & wheelR = 10; 

L'attribut .torque vous autorise à régler la vitesse d'usage du moteur. Cette valeur est réglée entre -100 et 100. Aussi vous pouvez contrôler la vitesse des roues en tapant simplement :

    wheels.torque = 100; 
    

Une valeur négative inverse la rotation du moteur.

Vous pouvez lire la position du moteur (en degrés) en utilisant l'attribut .val. Cette attribut est réglé à 0 quand vous mettez en route le robot. Aussi vous pouvez récupérer la position d'usage de claw en tapant :

 claw.val,

. Dans le cas de claw ; nous avons ajouté un contrôle du PID, aussi vous pouvez régler une position.

claw.val = 360 ;

qui signifie que nous demandons une rotation entière du moteur de claw. Change les paramètres de claw.PGain, claw.IGain et claw.DGain pour obtenir un contrôle affiné de la position.

Sensors

Tous les capteurs sont aussi aliasés à leur attribut .val, donc par exemple vous avez juste à demander bumper pour obtenir bumper.val. Cela marche de la même façon avec l'objet battery.

Les capteurs sont groupés dans le groupe sensors et tous les périphériques matériels (sensors + motors + battery + beeper) sont groupés dans le groupe hardware.

Bumper

Le périphérique switch est appelé bumper dans notre agencement. Vous pouvez demander sa valeur ( pour savoir si il est on ou off) en demandant

bumper.val ;

1 est bumper on, 0 est off.

Sonar

Le capteur à ultrasons est appelé sonar. Vous pouvez obtenir la distance lue en demandant l'attribut .val.

sonar.val ;

retourne la distance mesurée par le capteur. On aura en retour une valeur comprise entre 0 et 255 cm. Quand la valeur lue fait défaut, elle retourne 255.

Decibel

Le capteur de son est appelé decibel dans notre agencement.

Vous pouvez obtenir la valeur lue en demandant l'attribut .val.

decibel.val ;

retourne une valeur normalisée entre 0 et 1. C'est une valeur brute proportionnelle à la quantité de décibels mesurés.

Vous pouvez régler le capteur de sons en deux modes différents en changeant l'attribut .mode. Deux valeurs sont disponibles, "DB" et "DBA" "DBA" est un mode ajusté mesurant seulement les fréquences comprises entre 200 et 14000Hz. "DB" mesure une bande de fréquences étendue. Règlez cette valeur en tapant :

 decibel.mode = "DB" ;

. La valeur par défaut est "DBA".

Light

Le capteur de lumière est appelé light.

On récupère la valeur mesurée en demandant l'attribut .val.

light.val,

La valeur retournée est normalisée (entre 0 et 1) représentant un pourcentage de la quantité de lumière mesurée.

Vous pouvez régler le capteur de lumière en trois différents modes en changeant l'attribut .mode. Les valeurs disponibles sont "Reflector", "Ambiant" et "Normal". La valeur par défaut dans notre exemple est "Reflector". "Reflector" signifie que le capteur de lumière allume sa led et mesure la lumière réfléchie. "Ambiant" éteins la led et mesure la lumière ambiante. "Normal" éteins la led et retourne la valeur brute mesurée. Vous pouvez le changer en tapant :

light.mode = "Ambiant",

Battery

Le périphérique batterie est tout simplement appelé battery.

Vous pouvez obtenir la puissance d'usage en demandant l'attribut .val.

battery.val

Beeper

Le périphérique bruiteur est appelé beeper.

Vous pouvez uniquement demander au beeper de jouer un son personnalisé, utilisez sa fonction :

play(frequency, time) ;

frequency est un integer entre 200 et 14000, qui est la fréquence du beep. time est un integer mesuré en millisecondes, qui est la durée du son. Si nous voulons jouer un son durant 1 seconde avec une fréquence de 200, nous ferons :

beeper.play(200, 1000),

Un temps de 0 est infini. De même la commande n'attends pas la fin du beep. Donc si vous voulez attendre jusqu'à la fin du beep, essayez quelque chose comme

{ beeper.play(myFrequency, myDuration) & wait(myDuration) },

Command

L'UObject command n'est pas un périphérique. Il autorise l'envoie direct de commandes comme vous le faites avec le SDK du NXT. Vous trouverez plus d'informations sur http://mindstorms.lego.com/Overview/NXTreme.asp.

Vous ne pouvez pas créer d'instances Command mais utilisez le comme :

Command.send(myBuff) ;

myBuff est un buffer de command valide (liste d'integers entre 200 et 14000).

Command.send([3, 10, 10, 0 , 0]);

jouera un beep.

answer = Command.request(myBuff, size) ;

myBuff est un buffer de command valide (attendant une réponse). size est la taille du buffer de retour (il doit être de la taille exacte, trop petit il bloquera tout le serveur, et trop grand il fera échouer votre requête). answer est le buffer de retour (c'est une liste, [] est retourné quand la requête échoue). Cette commande a été créée pour les utilisateurs experts qui demande plus d'URBI. IL n'est pas recommandée de l'utiliser si vous ne savez pas ce que vous faites et peut faire planter tout le serveur. Utilisez le à vos propres responsabilités. Voici un exemple :

answer = Command.request([7,0], 15); 

qui retourne les informations sur port d'entrée 1.

Chapter 5. Comment personnaliser son agencement

Introduction

Voici un exemple simple qui explique comment écrire votre propre agencement. Avant de le construire, vous devrez jeter un coup d'oeil au tutoriel URBI (http://www.gostai.com/doc/urbi-tutorial.htm).

Il y a 3 sortes de périphériques fournis par le serveur : moteurs, capteurs et autres périphériques. Il y a un type de moteur appelé Servo. Il y a 4 types de capteurs: Switch, SoundSensor, UltraSonicSensoret LightSensor. 2 autres périphériques sont disponibles: Battery et Beeper.

Ecrire un agencement consiste simplement à instancer des objets périphériques à partir des classes de base ci dessus. Nous allons maintenant vous montrer comment le faire :

Motors

Le constructeur d'initialisation de Servo a la syntaxe suivante:

 myServoObject = new Servo(myPort);

Vous pouvez créer 3 objets Servo différents lié aux 3 différents ports ("A","B" et "C" ).

Dans le TriBot.ini en cours, nous créons nos objets Servo :

    wheelL = new Servo("C");
    wheelR = new Servo("A");
    claw = new Servo("B");
    

La roue gauche est sur le port C, la roue droite sur le A et la pince sur le port B.

Le PID contrôle étant fournis avec ce moteur, vous pouvez le lier à un objet Servo approprié pour le contrôler par la position. Utiliser la syntaxe suivante pour lier le contrôle du PID.

 myServoObject inherits PID;

Puis réglez vos propres paramètres de PID :

 
    myServoObject.PGain     = 0.01;
    myServoObject.IGain     = 0.01;
    myServoObject.DGain     = 0.01;
    myServoObject.precision = 0.01; 
    

N'hésitez pas à changer ces paramètres pour changer le comportement de votre PID. Maintenant vous pouvez lancer le contrôle du PID par :

myServoObject.setPID("myServoObject.val", "myServoObject.torque");

Dans notre exemple, nous utilisons le PID de cette façon :

claw inherit PID;
    claw.PGain     = 0.01;
    claw.IGain     = 0.01;
    claw.DGain     = 0.01;
    claw.precision = 0.00;
    claw.setPID("claw.val", "claw.torque");
    

Qui signifie que le PID tourne en permanence, où claw.torque contrôle claw.val (Nous récupérons une position sur claw.val , et la vitesse en dépendant est automatiquement réglée).

Le contrôle du PID s'arrêtera quand la précision que vous attendez est atteinte, si vous voulez autoriser un contrôle permanent, réglez la précision sur 0.

Sensors

Maintenant vous pouvez créer vos objets capteurs.

Commençons avec l'objet Switch. Pour le créer suivez la syntaxe :

    mySwitchObject = new Switch(myPort);
    

myPort peut être 1, 2, 3 ou 4.

Dans notre exemple, nous voulons utiliser le switch comme un bumper branché sur le port 4, aussi nous faisons :

bumper  = new Switch(4);

C'est exactement la même façon pour créer un objet UltraSonicSensor :

    myUSSObject = new UltraSonicSensor(myPort);
    

myPort peut être 1, 2, 3 ou 4.

Vous pouvez voir dans notre TriBot.ini un capteur ultrasonic sur le port 2:

sonar   = new UltraSonicSensor(2);

Maintenant nous allons créer un objet SoundSensor :

    mySoundObject = new SoundSensor(myPort, myMode);
    

Comme d'habitude, myPort peut être 1, 2, 3 ou 4. myMode définit le mode de fonctionnement du capteur. Il peut être "DB" ou "DBA", signifiant "décibel" ou "décibel équilibré" (le dernier enregistre les sons dans le spectre audible des fréquences 400-14000Hz).

Aussi dans l'exemple nous créons un capteur de son sur le port 1 en utilisant décibel adjusted:

 decibel = new SoundSensor(1,"DBA"); 

Le dernier capteur est le LightSensor, vous pouvez le créer avec la ligne :

    myLightObject = new LightSensor(myPort, myMode);
    

avec myPort dans 1, 2, 3 ou 4. MyMode définit encore le mode de fonctionnement du capteur et il peut être "Ambiant" (ici le capteur mesure la lumière ambiante), "Reflector" (le capteur allume sa led et mesure la lumière réfléchie) et "Normal" (le capteur retourne sa valeur brute).

Nous avons choisi d'utiliser le capteur de lumière en mode reflector sur le port 1 aussi nous faisons :

light   = new LightSensor(3,"Reflector");

Autres périphériques

Maintenant nous pouvons ajouter deux autres périphériques à notre agencement.

Le périphérique Battery nous permet de lire le niveau de la batterie. Tapez simplement :

myBattery = new Battery();

Nous le créons de cette façon :

    battery = new Battery();
    

Le périphérique Beeper nous permet d'émettre des beeps personnalisés à partir du haut-parleur du NXT. créons le :

myBeeper = new Beeper();

Nous créons le beeper dans l'exemple :

    beeper  = new Beeper();
    

Chapter 6. Tutoriels (incomplet)

Comment faire des fonctions basiques de mouvement.

Une chose agréable qui rend la vie plus facile avec URBI est de coder des fonctions simples de haut niveau. Cela vous permet de déplacer votre robot facilement juste en appelant ces fonctions. On commence avec la fonction forward() qui fait avancer votre robot... en avant!

  fonction global.forward()
  {
     wheels = 10;
  },
  

Ici nous déclarons une fonction forward() de portée (scope) global. Déclarer la fonction dans un scope (vous pouvez l'appeler comme vous voulez), l'autorise a la rendre visible à partir de n'importe quelle connection d'où vous l'exécutez.

wheels = 10; règle la vitesse des roues à 10.

Tip :

Pour ne pas toujours appeler global.forward(), vous pouvez créer une classe global et y ranger dedans toutes vos méthodes et attributs :

class global
{
  var defaultSpeed ;
  var x ;
  var y ;
  function forward() ;
  function randomMove() ;
} ;
function global.forward()
{
  //définition de la fonction;
} ;
function global.randomMove()
{
  //définition de la fonction ;
  forward() ; //appelée sans global
} ;

Maintenant, nous pouvons améliorer ce code permettant une vitesse personnalisée. Voici une bonne façon de le faire:

global.defaultSpeed = 10;

function global.forward()
{
   wheels = global.defaultSpeed;
},

Ici nous définissons une variable dans le scope global qui définissent la vitesse personnalisée. Cela vous permet de définir la vitesse à chaque fois que vous le voulez (très utile lors de tests sur votre propre programme).

Enfin, nous pouvons ajouter un timer à cette fonction, utile pour se déplacer durant une période de temps fixe:


global.defaultSpeed = 10;

function global.forward(timer)
{
  wheels = global.defaultSpeed |
  wait(timer)|
  wheels = 0;
},

Ici nous ajoutons un paramètre timer qui est le temps voulu de rotation des roues. La syntaxe wheels = global.defaultSpeed | wait(timer) exécute sequentiellement wheels = global.defaultSpeed PUIS wait(timer). Quand vous séparez un groupe d'un autre (e.g. : wheels = 0 - qui arrête les roues) utilisant le séparateur |, qui fait attendre l'instruction pour l'instruction précédente. Donc wheels = 0 sera exécuté APRES la fin du timer. Aussi cet appel fait avancer le robot en avant pendant une seconde puis s'arrêter.

global.forward(1000),

Ce qui suit est un exemple venant du fichier std.u qui définit des fonctions de mouvement de base.

class global ;

global.defaultSpeed = 10;

function global.forward()
{
   wheels = global.defaultSpeed;
},

function global.backward()
{
   wheels = -global.defaultSpeed;
},

function global.turnleft()
{
   wheelL = - global.defaultSpeed &
   wheelR = global.defaultSpeed;
},

function global.turnright()
{
   wheelR = - global.defaultSpeed &
   wheelL = global.defaultSpeed;
},

Comment faire un déplacement aléatoire

Ici, nous allons voir comment créer une fonction qui va générer un déplacement au hasard du robot. Cette fonction sera utile pour la prochaine partie de notre didacticiel. Cette fonction est destinée à faire réagir le robot à un événement. Donc, l'idée est de faire un mouvement de recul, puis à changer la direction au hasard. Nous avons également besoin de 2 paramètres, une constante de temps, ce qui fera tourner le robot pendant ce laps de temps (Ce qui évitera de ne pas tourner assez ); Et une base de temps randomisée qui est le temps maximum de rotation qui sera généré. Voici le code :

function global.randomMoves(constantTime, randomTime)
{
  {backward() & wait(2s)}
 |
  {
   {if (random(2) == 1) left()
    else right()
   }
   &
   wait( (constantTime+random(randomTime))*100)
  }
  |
  forward()
},

{backward() & wait(2s)} Aussi en premier

Appendix A. Copyright


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.