Le projet CrazyRoomba est un projet permettant de transformer la plateforme iCreate (v1) de iRobot en un robot compagnon connecté. Nous avons également intégrer un système permettant de récuperer la position du robot par rapport à sa position de départ.
Le système repose entièrement sur le protocol MQTT pour l'échange des données entre les differentes parties du projet et possiblement avec d'autres objets connectés.
Le projet repose en plus de la plateforme iCreate sur un raspberry pi pour gérer la récuperation et l'envoie de données au robot. Il utilise également une tablette pour permettre un affichage directement sur le robot ainsi que la récupération de l'angle (l'angle donné par la plateforme iCreate n'étant pas assez précis).
Pour ce projet, le matériel qui a été utilisé est le suivant:
- Gigabyte Tegra note 7
- Raspberry Pi 3 sous Raspbian
- Plateforme robotique iRobot iCreate 1
- PowerBank pour l'alimentation de la tablette et du Pi
Le projet est conçu autour du protocol MQTT. Pour le faire fonctionner, il vous faudra donc un broker MQTT fonctionnel. Nous avons fait le choix de emqtt.io qui est un broker écrit en erLang et permet d'effectuer une infrastructure distribuée très facilement. Il permet de gérer 4000 messages par secondes en entrée et 20000 messages par seconde en sortie par noeuds (sources). Il implémente le protocol MQTT V3.1.1 supporte à la fois une connexion directement via le protocole MQTT(port 1083 par défaut) ou via Websocket (port 8083 par défaut).
Le projet se base principalement sur le framework Angular. Il a donc été développé principalement en typeScript. Nous avons également utilisé nodeJs pour la partie serveur se trouvant sur le raspberry pi.
Ionic a aussi été utilisé (lui-même basé sur Angular) pour créer l'application tablette.
- MQTTjs
- Serialport (pour nodeJS)
Grâce a sa conception autour du protocol MQTT, nous avons pu découper facilement l'ensemble de notre projet en plusieurs applications.
C'est l'application qui va communiquer directement avec le robot. C'est elle qui va récuperer les différentes données des capteurs. Elle va également envoyer des commandes au robot. Elle utilise la librairie serialport.
C'est l'application qui tourne sur un client web. Elle se connecte à l'application Server.js via le broker MQTT.
C'est l'application qui permet la localisation aproximative du robot en fonction de son point de départ.
C'est l'application qui tourne sur la tablette associée au robot. Elle permet d'envoyer l'angle à l'application PointsAPP et également un affichage sur le robot.
/
contient tous les fichiers concernant le serveur notamment le point d'entrée: server.js
config
contiens le fichier de configuration
pointsApp
contiens l'application PointsApp
roomba-app
contiens l'application Angular RoombaAPP
roomba-app/jsLibrairies
est appelé sur http://localhost:3000/librairies
. C'est ici que sont stockées les bibliothèques javascript pour la partie client (notamment robot.js version client).
tabletApp/
ici ce trouve le code source de l'application tablette utilisant le framework Ionic
MQTT est un protocole basé sur le mécanisme de "publish"/"subscribe". On s'abonne à un évenement afin de pouvoir en être notifié. Et on publie afin de notifier les abonnés.
L'un des objectifs du projet était de créer un cluster (infra distribuée). Emqtt.io possède déjà cette possibilité. Pour cela il suffit de modifier le nom de noeud dans /etc/emq.conf
et changer la valeur de node.name
comme : node.name = emq@192.168.0.10
par exemple.
Ensuite pour joindre une instance (attention à l'ouverture de vos ports dans le parefeu) il suffit de taper la commande ./bin/emqttd_ctl cluster join emq@192.168.0.10
par exemple. Dans ce cas, l'instance sur laquelle vous exécutez la commande va être mise en cluster avec emq@192.168.0.10
. Elles vont travailler ensemble.
Il faudra tout d'abord installer angular-cli. Et également ionic pour pouvoir compiler l'application android de la tablette.
Il vous faudra également une instance de emqtt.io. Je vous conseille d'utiliser le bash pour ubuntu si vous êtes sous windows car cela rendra les choses plus simples pour la suite. Ensuite il vous faudra cloner le dépot github et installer tous les plugins nécessaires à son fonctionnement grâce à cette commande:
git clone https://github.com/bloudman/CrazyRoomba.git && cd CrazyRoobma && npm run setup
Ensuite vous pouvez taper la commande: npm start
pour le lancer .
Si vous voulez juste lancer le serveur:
npm run serve
Si vous voulez juste compiler l'application angular:
npm run build
Il existe un fichier de configuration dans le projet. Il se trouve dans: config/config.js
.
Ce fichier comporte le port série à utiliser avec le robot et l'addresse IP du broker MQTT+son port websocket à utiliser pour toutes les applications (sauf l'application de la tablette) ou vous pouvez bien sûr changer manuellement l'ip dans toutes les applications plutôt que d'utiliser celle de config.js.
C'est dans ce fichier que se trouve la déclaration du serveur web express.js. Il gère également la connexion avec le broker mqtt. Il appelle la classe robot.js (version serveur).
Il y a 2 classes Robot.js dans ce projet : l'une est utilisée par le serveur et est située à la racine et l'autre est utilisée par le client et est stockée dans roomba-app/jsLibrairies
Il s'agit de la classe qui gère la connexion avec le robot. Le robot parle via une communication série. La classe agit donc comme une interface qui peut être utilisée directement en js ou via le broker
Il permet d'utiliser les mêmes méthodes en apparence que sur le coté serveur.
Send a buffer command to the robot
Put roomba in passiveMode
Put roomba in safeMode
Put roomba in fullMode
Stop roomba's motors and the demo
Ask roomba to stream you sensors
Ask roomba to stream you all of his sensors
Pause the streaming
Resume streaming after pause
SensorName | ID | Unit |
---|---|---|
BumpsAndWheelDrops | 7 | |
CliffLeft | 8 | |
CliffFrontLeft | 10 | |
CliffFrontRight | 11 | |
CliffRight | 12 | |
VirtualWall | 13 | |
Overcurrents | 14 | |
IRByte | 17 | |
Buttons | 18 | |
Distance | 19 | mm |
Angle | 20 | mm |
ChargingState | 21 | |
Voltage | 22 | |
Current | 23 | |
BatteryTemperature | 24 | |
BatteryCharge | 25 | |
BatteryCapacity | 26 | |
WallSignal | 27 | |
CliffLeftSignal | 28 | |
CliffFrontLeftSignal | 29 | |
CliffFrontRightSignal | 30 | |
CliffRightSignal | 31 | |
UserDigitalInputs | 32 | |
UserAnalogInputs | 33 | |
ChargingSourcesAvailable | 34 | |
OIMode | 35 | |
SongNumber | 36 | |
SongPlaying | 37 | |
NumberOfStreamPackets | 38 | |
Velocity | 39 | |
Radius | 40 | |
RightVelocity | 41 | |
LeftVelocity | 42 |
EventName | Id |
---|---|
wheel-drop | 1 |
front-wheel-drop | 2 |
left-wheel-drop | 3 |
right-wheel-drop | 4 |
bump | 5 |
left-bump | 6 |
right-bump | 7 |
virtual-wall | 8 |
wall | 9 |
cliff | 10 |
left-cliff | 11 |
front-left-cliff | 12 |
front-right-cliff | 13 |
right-cliff | 14 |
home-base | 15 |
advance-button | 16 |
play-button | 17 |
digital-output-0 | 18 |
digital-output-1 | 19 |
digital-output-2 | 20 |
digital-output-3 | 21 |
passive | 22 |
DemoName | Id |
---|---|
abort | 255 |
cover | 0 |
cover-and-dock | 1 |
spot-cover | 2 |
mouse | 3 |
drive-figure-eight | 4 |
wimp | 5 |
home | 6 |
tag | 7 |
pachelbel | 8 |
banjo | 9 |
Cette classe est basée sur EventEmitter (côté client et côté serveur). Vous pouvez récuperer un évenement comme ceci:
roomba.on('event', function(data){
console.log(data);
});
Est déclenché lorsque le robot est connecté.
Récupere le tableau de données de tous les capteurs demandés (via streamSensors) toutes les 50ms (par défaut, voir changeEmission pour le modifier).
Donnée d'un seul capteur à la fois.
Le checksum de la dernière donnée remontée est incorrect.
La donnée reçue ne correspond à aucun capteur de la liste. On ne la prend pas en compte car elle est incorrecte.
Lorsque le robot n'est pas correctement connecté au serveur, il va se mettre en "FakeRobot mode". Il va envoyer au client des fausses données pour faciliter le debuggage.
Même si vous pouvez tout à fait inclure la version client de robot.js afin d'utiliser le robot avec les méthodes citées ci-dessus, l'intérêt du projet est que vous pouvez tout faire avec n'importe quelle librairie client d'MQTT et utiliser l'api intégrée. Lors de ce projet, nous avons utiliser mqttjs mais vous pouvez utiliser une librairie dans un autre langage pour contrôler le robot.
Nom | Paramètres | Utilisation |
---|---|---|
/roomba/datas | aucun | Récupère le tableau de données sous ce format:[{"name":"Velocity","value":0},{"name":"CliffFrontLeftSignal","value":0}... |
/roomba/getDistance | aucun | Demande le rafraîchissement de la distance et l'envoi de /roomba/distance |
/roomba/distance | aucun | Récupère la distance demandée avec /roomba/getDistance(attention distance depuis le départ du robot ou d'un reset) |
/roomba/getPhoneAngle | aucun | Demande le rafraîchissement et de retourner l'angle de la tablette sur : /roomba/angle |
/roomba/angle | aucun | c'est ici que l'angle de la tablette est récupéré |
/roomba/streamSensors | [id1, id2, id3...] | Permet d'accéder à la méthode streamSensors de robot.js |
/roomba/streamAllSensors | aucun | Stream tous les capteurs |
/roomba/strategy | StrategyNumber | Déclenche la stratégie: StrategyNumbersur la machine d'état |
/roomba/reset | aucun | Stoppe le robot et reset la distance |
/roomba/driveDirect | [motor1, motor2] | Met la puissance du moteur droit sur motor1 et celle du moteur gauche sur motor2 |
//WebSocket Connection from a browser:
var client = mqtt.connect('ws://localhost/mqtt');
//Or mqtt connection on nodeJS
var client = mqtt.connect('mqtt://localhost/');
client.on("connect", function(){
//Here you are connected to mqtt!
//Then you can publish data like that (here an example of driveDirect:
client.publish("/roomba/driveDirect", JSON.stringify([100,100])); //You'll need to use JSON.stringify because mqtt accept only strings!
//You can also subscribe (here we subscribe to /roomba/distance)
client.subscribe("/roomba/datas");
});
client.on("message", function(topic, message){
//Here we receive a message wich we subscribed to
if(topic == "/roomba/datas"){
let datas = JSON.parse(message);
console.log(datas); //We should have datas of sensors we asked!
}
});