Copyright © 2006-2007 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
List of Tables
Cette documentation contiens des informations à propos du URBI engine du iRobot Create (iRobot URBI engine, ou iRobot engine pour faire court).
Vous serez intéressé de lire des informations à propos du iRobot Create à irobot.com/create Si vous n'êtes pas encore familiarisé avec lui.
Le premier chapitre fournit des instructions pour un démarrage rapide et un petit tutoriel pour utiliser URBI sur le iRobot Create.
Le reste de la documentation contient une référence exhaustive pour le iRobot URBI engine et des exemples de script URBI plus avancés.
En premier, assurez vous que votre iRobot Create est opérationnel. Vous devriez jeter un oeil à : irobot.com/create si vous avez besoin d'aide pour cette étape...
Maintenant que vous avez un robot en état de marche vous pouvez
installer le iRobot engine. La procédure d'installation dépendra de
votre système, mais vous sera familière. Une fois que c'est fait, vous
trouverez un répertoire bin dans lequel se trouve
le binaire du urbi-server-irobot. D'autres fichiers
importants sont localisés dans le répertoire data.
Avant de lancer l'engine, vous devrez changer la valeur
system.comport dans le fichier data/config.u
. Il doit avoir une valeur comme COM1
sur MS Windows, /dev/cu.SLAB_USBtoUART sur Mac OS X
ou /dev/ttyUSB0 sur Linux. L'engine échouera si le
port spécifié est incorrect ou n'a pas les bonnes permissions.
Allez dans votre répertoire d'installation iRobot, passez dans le répertoire bin
et lancez urbi-server-irobot. Le message d'aide suivant apparaitra :
usage: ./urbi-server-irobot [options] period [path1 path2 ...] period : base URBI interval in milliseconds les item path(chemin) sont des éléments absolus ou relatifs où l'on recherche dans l'ordre quand 'load' est appelé. options: -p port : précise le port tcp qu'URBI écoutera. -b address: lie à l'adresse ip spécifiée. -n : n'autorise pas le travail en réseau. -r : autorise le report du temps pris par la boucle URBI pour s'exécuter -s <period>: shell-mode (pas de réseau) avec une période donnée -f : enable fast mode: le serveur tournera aussi vite que possible et émulera la période spécifiée
pour un lancement rapide du iRobot engine, tapez simplement :
./urbi-engine-irobot 50 ../data
L'engine affichera un header(en-tête) et dira que c'est prêt. Si tout va bien, rien de plus ne se produira. Si votre robot est éteint, ou injoignable, l'engine dira Waiting for robot initialisation.
Maintenant votre robot devrait fonctionner. Pour tester la connection, utilisez ou l'outil spécialement fournit par Gostai, ou un simple client telnet (notez que tout les URBI engine URBI ont le port 54000 par défaut).
telnet localhost 54000
S'il n'y a pas d'erreurs, votre client telnet devrait recevoir le même type d'en-tête que vous avez vu dans le engine window. La dernière ligne donnera votre id de connection et sera de la forme :
[65000000:ident] *** ID: U135766920 [65000011:notag] *** Connected to robot
Si ce n'est pas le cas, assurez vous que vous avez correctement installé l'engine et suivez les étapes suivantes. référez vous à Dépannage et FAQ si vous avez encore des difficultés pour lancer le serveur.
Vous êtes maintenant prêt à envoyer des commandes à votre robot par le iRobot URBI engine. Par exemple essayez :
vars; ... [00004004:notag] *** ledPlay = OBJ ...
La première ligne demande pour toutes les variables connues par le serveur et les lignes suivantes, dont vous n'avez pas à vous inquiéter pour l'instant, liste les symboles et leurs valeurs respectives.
Table of Contents
Ce chapitre introduira des concepts de base pour l'utilisation du iRobot Create URBI engine. Il peut être passé si vous êtes déjà familier avec les URBI engines.
Pour de plus amples instructions et informations sur les commandes URBI, lisez le premier chapitre du tutoriel URBI .
Avant tout autre chose, assurez vous du succès des étapes présentées dans le chapitre Démarrage rapide.
Voici une liste rapide des périphériques disponible pour le iRobot Create avec lesquels vous pouvez contrôler l'engine.
Si vous regarder attentivement aux fichiers
groups.u et aliases.u fournit avec le URBI engine,
vous verrez comment ces périphériques sont groupés et aliasés pour un accès simple et direct.
Table 3.1. caractéristiques des périphériques
| Nom | Type | Description |
|---|---|---|
| battery | Sensor | Etat de la batterie (charge, courant...) |
| bumperL | Sensor | pare-choc gauche |
| bumperR | Sensor | pare-choc droit |
| buttonA | Sensor | bouton d'avance |
| buttonP | Sensor | bouton play |
| cargobay | Sensor/Actor | Extra I/O |
| cliffsensorL | Sensor | capteur cliff gauche |
| cliffsensorFL | Sensor | Capteur cliff avant gauche |
| cliffsensorFR | Sensor | Capteur cliff avant droit |
| cliffsensorR | Sensor | capteur cliff droit |
| command | Actor | interface de commande |
| ir | Sensor | Récepteur d'Infrarouges |
| ledAdvance | Actor | led du bouton d'avance |
| ledPlay | Actor | Led du bouton play |
| ledPower | Actor | Led du bouton power |
| lsd0 | Actor | Low Side Driver 0 |
| lsd1 | Actor | Low Side Driver 1 |
| lsd2 | Actor | Low Side Driver 2 |
| odometry | Sensor | Odometry wrapper |
| speaker | Actor | Haut-parleur du robot |
| virtualwall | Sensor | détecteur de mur virtuel |
| wall | Sensor | détecteur de mur |
| wheelF | Actor | Roue avant |
| wheelL | Actor | Roue gauche |
| wheelR | Actor | Roue droite |
Essayez cette première commande dans votre cession telnet :
ledPlay; [00000476:notag] 0.000000
La première ligne demande la valeur de la led du bouton play. La seconde
est la réponse du iRobot engine. La première valeur integer est un timestamp(marqueur temporel)
pour la réponse (en millisecondes depuis le démarrage de l'engine). Elle est suivie d'un tag.
Référez vous au
tutoriel URBI
pour plus de détails. Ce qui est important ici c'est la virgule flottante finissant la ligne.
C'est la valeur stockée dans l'objet led.
Ici 0.000000 indique que la led est éteinte.
Donner la valeur 1 allumera la led.
N'oubliez pas le ';' à la fin de vos commandes.
Le serveur URBI attendra indéfiniment pour la commande à attendre si vous l'oubliez.
Les commandes suivantes introduiront la notion de +end.
Inclure vos commandes dans +end:{...};. Vous fera prévenir
de la fin d'une commande par l'engine.
Essayez ce qui suit :
+end:{wheels = 100 time:2s | wait (2s) | wheels = 0;};
[00002622:notag] *** end
wheels est un groupe de périphériques pour les roues droite
et gauche du robot. Votre robot accélérera jusqu'à 100 mm/s
en 2 secondes, et avancera tout droit en maintenant cette vitesse pendant 2 secondes
supplémentaires. Puis le robot s'arrêtera.
Vous devez maintenant essayer de le faire revenir à sa position initiale avec une commande similaire.
Ensuite, essayez ceci :
+end:{wheelL = -150 & wheelR = 150 | wait (2s) | wheels = 0;};
[00005095:notag] *** end
Votre robot tournera sur lui même pendant 2 secondes. Cette commande dit au robot de régler en même temps la vitesse de ses deux roues, puis d'attendre 2 secondes avant de s'arrêter complètement.
La dernière commande simple sera :
bumpRDetect:at (bumperR != 0) echo "Collision on right side";
Maintenant essayez de presser le bouton avant droit de votre iRobot. Vous obtiendrez un message du genre :
[00008215:notag] *** Collision on right side
Le mot-clé at vous permet de détecter des événements et
de faire agir votre iRobot Create en conséquence.
Le bumpRDetect: est appelé tag.
Il est utilisé pour donner un nom, ou un identifiant à une commande.
Vous pouvez utiliser des commandes spéciales comme
stop, freeze and unfreeze pour manipuler
les commandes en cours d'exécution. Essayez freeze bumpRDetect;.
Le message précédent ne sera plus affiché quand bumper est pressé.
La même commande avec unfreeze la rendra à nouveau opérationnelle..
Vous devriez à présent être capable de jouer avec votre iRobot URBI engine. Le chapitre suivant vous donnera des détails complets à propos de l'engine, mais ce que nous avons vu ici est suffisant pour utiliser le iRobot et URBI.
Une fois de plus, vous pouvez consulter le tutoriel complet d'URBI à le tutoriel.
Table of Contents
Ce chapitre listera tous les objets (UObjects) définis par le iRobot Create URBI engine. C'est une liste complète donnant seulement les attributs principaux ou les méthodes de ces objets ou périphériques.
Dans chaque cas, tapez le nom du périphérique dans une connection au serveur URBI
affichera la liste complète des attributs (vous aurez besoin de taper unalias dev
si un périphérique particulier est aliasé).
Chaque périphérique et attribut décrit dans iRobot Create Open Interface Specification sera accessible à partir du URBI engine.
Notez s'il vous plaît que le fichier config.u a une ligne
system.aliasmode = 1;. Quand la valeur n'est pas
0, plus d'alias sont définis dans aliases.u.
Dans ce qui suit nous considèrerons que c'est le cas.
Deux moteurs sont définis, wheelL, wheelR. Ils sont groupés dans
wheels pour un accès plus rapide lorsque la vitesse fixée est
la même pour les deux roues.
La vitesse des roues va de -500mm/s à 500mm/s.
Chaque moteur est aliasé à son attribut .val. Cet attribut donne
la vitesse actuelle en mm/s :
wheelL = 10;
est équivalent à
wheelL.val = 10;
L'attribut drop mémorise l'état actuel des roues.
C'est 0 si la roue est sur le sol, 1
si la roue n'est pas en contact avec le sol.
Par défaut, tous les capteurs sont aliasés à leur attribut .val.
Les capteurs sont groupés par type dans les groupes buttons, walls, cliffs et
bumpers. Ils sont aussi tous groupés dans le groupe sensors.
Gardez en mémoire que les groupes et les alias sont ici pour simplifier l'accès aux informations
les plus utiles des périphériques. Vous devrez apporter de légères modifications aux fichiers
aliases.u et groups.u pour adapter l'agencement des
périphérique du robot à votre usage personnel.
Bumpers bumperL et bumperR sont des périphériques d'entrée
placés sur le devant et les côtés du iRobot Create.
Ils ont la valeur 1 si appuyés, 0 autrement.
Le détecteur de mur dépend de l'objet wall.
Sa valeur dépends de la façon dont le mur est détecté et ne fait pas référence à la distance. Un mur noir aura un signal plus faible qu'un mur blanc même s'il est détecté à la même distance.
Le détecteur de mur virtuel dépend de l'objet virtualwall.
Sa valeur est définie à 1 si un mur virtuel est détecté,
0 autrement.
Les détecteurs de vide sont respectivement appelés cliffSensorL,
cliffSensorFL, cliffSensorFR,
cliffSensorR dépendant de leur position sur le robot (gauche,
avant gauche, avant droite, droite).
Leurs valeurs détectent les surfaces en dessous du robot. 0 il y a du sol,
1 est dans le cas d'une chute possible.
Les cliff detectors sont groupés dans cliffs.
L'attribut signal donne une valeur utile pour déterminer la distance
entre le capteur et le sol.
Le périphérique batterie est appelé battery.
L'objet battery donne les informations suivantes à propos de la batterie du iRobot.
L'attribut charge en mAh, l'estimation de la batterie et l'attribut
capacity en mAh. L'attribut temperatureinterne de
la batterie et son attribut source d'alimentation (none(aucun), power station ou adapter).
Il indique aussi le voltage actuel de la batterie en mV et son courant
(val ou current) en mA.
State indique si la batterie est en charge.
Les périphériques boutons sont appelés buttonP pour le bouton play et
buttonA pour le bouton advance.
Les valeurs de Button sont 1 quand appuyé, 0 autrement.
Le périphérique speaker(haut-parleur) est utilisé pour produire des notes de musique.
Une fois que la musique est rangée dans le speaker,
un appel à sa méthode play() produira des notes.
Les commandes suivantes :
speaker = [69,60,73,32]; speaker.play();
jouera la note 69 : LA (440Htz) avec une longueur de 1s (60/60s) et la note 73 : DO# (554.4Htz) pour à peu près la moitié d'une seconde (32/60s).
La liste complète du code des notes est donné dans iRobot Create Open Interface Specification
La liste donnée de valeur de speaker ou speaker.val
est une succession de couples note / duration composant une chanson.
Les durées de note sont données en 60ème de seconde.
Les chansons peuvent seulement être de 16 notes.
La commande speaker.play() retourne immédiatement. Si vous lancez une nouvelle
chanson alors qu'une chanson se joue encore, la commande sera ignorée.
L'UObject command n'est pas un périphérique réel. C'est une interface
logiciel utilisée pour envoyer des commandes directement à un iRobot Create.
Cet objet propose de modifier l'attribut de mode du robot.
Alors que le mode Full est utilisé la plupart du temps,
vous aurez besoin de basculer au mode Safe ou tout autre mode définit dans
iRobot Create Open Interface Specification
command peut aussi être utilisé pour gérer la demo intégrée avec
command.launchDemo(id) (lance la démo avec le id donné) et
command.stopDemo() (arrête la démo en cours, identique à lancer une démo avec id -1).
Cet objet a aussi des méthodes pour envoyer et recevoir des données directement au iRobot Create :
command.send(byte_list) et
command.request(byte_list, answer_size)
Par exemple :
command.send([136, 1]);
lancera la démo 1 de create.
Et :
command.request([142,8], 1);
retournera l'information du capteur wall detector.
Ces fonctions peuvent être utilisées pour accéder à chaque périphérique ou dispositif spécifié dans iRobot Create Open Interface Specification, et aux fonctionnalités que vous ajouterez à votre robot.
Notez que
[] (liste vide) est retournée quand la requête échoue.
Ces commandes sont prévues pour les utilisateurs experts. Si vous êtes nouveau avec URBI ou iRobot Create, les périphériques et méthodes standards fournirons l'accès à tous ce que vous avez besoin.
Référez vous à iRobot Create Open Interface Specification afin d'obtenir les codes des commandes et les valeurs de retour expectées.
L'UObject odometry est un périphérique spécial qui saisie la position
du iRobot Create dans son environnement.
Dans la variable odometry sont stockés :
val en mm) que le Create a parcouru
depuis le lancement du serveur
angle de rotation parcouru depuis le lancement du serveur
radius, angle
et velocity requis
Vous pouvez utiliser la fonction odometry.move(velocity, radius)
pour contrôler votre robot. C'est un accès direct à la commande 137 dans le protocole iRobot.
odometry.move(40, -200);
Cet exemple fera se déplacer votre robot à une vitesse globale de 40 mm/s et tourner vers la droite en parcourant un arc de cercle de radiant 200;
Table of Contents
Ce chapitre décrit les fonctions de base fournies avec le iRobot engine.
Vous pouvez accéder à leurs codes sources dans le répertoire data
fourni avec l'engine. Vous êtes libre de les utiliser pour construire des comportements
avancés pour votre iRobot Create.
Ces premières fonctions sont utilisées pour faire bouger votre robot. Le support de l'odiométrie doit encore être amélioré, aussi, si elles sont bien utilisées, les fonctions basées sur le temps sont plus précises pour le moment.
Les fonctions func.rotateAngleOdo (angleNeeded, velocity)
et func.moveStraightOdo (distance, velocity) font bouger
le robot en se basant sur les informations d'odométrie envoyées par le robot.
La fonction func.rotateAngleOdo fait tourner le robot sur
lui-même d'un angle donné, à une vitesse donnée.
La fonction func.moveStraightOdo fait suivre un ligne droite
au robot à une vitesse donnée sur une distance donnée.
Si speed(vitesse) est différent de 0, le robot bouge. Sinon, il attends de l'odometrie, la valeur attendue.
Comme précisé précédement, ces fonctions peuvent ne pas être précises, dépendant de la façon dont vous utilisez votre serveur URBI. Une période de 100ms ne donne pas de si mauvais résultats.
Les fonction suivantes
func.rotateAngleTime (angle, radius, velocity, go) et
function func.moveStraighTime (distance, velocity, go)
font bouger le robot en se basant sur le temps théorique nécessaire pour
exécuter le mouvement.
Notez que dans cette implémentation, func.rotateAngleTime
permet de définir l'angle de rotation.
L'argument go active le mouvement. si 0 est donné, la
fonction retourne le temps à attendre en ms pour finir le mouvement.
Si ce n'est pas 0 qui est donné, le robot bouge effectivement avant le
temps qui est retourné.
Cette mise en œuvre s'est avérée plus précise que la précédente. Mais notez qu'il ne l'est que dans de bonnes conditions, c'est-à-dire que l'interaction extérieur avec les roues ne sera pas prise en compte.
La fonction func.demo(demoId, duration) donne accès
aux démos intégrées.
Cette mise en œuvre permet de régler une tempo de démonstration.
Si duration est différente de 0, la demo est arrêtée après
un temps donné d'exécution. Si duration est de 0, La demo
tournera indéfiniment.
Notez que lancer une demo met le robot en mode Passive,
vous pouvez le remettre à Full en fin de demo.
Table of Contents
La FAQ pour URBI iRobot Create engine peut être consultée à : www.gostai.com/irobot_faq.html.
Vous serez aussi intéressé de parcourir notre forum à : forum.gostai.com/
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.