A node that can be used in Node-Red to control Parrot drones
npm install node-red-contrib-parrot-dronesThis project aims to provide a Nodes in Node-Red that can be used to control and monitor the data of Parrot drones based on Parrot ARDroneSDK3.
Two nodes is provided as explained below:
* drone-data: is an output node that can be used to read all the data received from the drone such as battery, status, etc ..
* drone-control: used to execute drone supported commands.
Additionally a configuration node drone-config is provided to group all the drone related settings and is accessible by the other nodes.
All the commands and events are tested with real drone to verify that it works as expected.
1. Parrot Jumping Mini Drones using existing node library.
npm i node-red-contrib-parrot-drones`
$3
The commands sent to the "drone-control" node is expected to be inside msg.command and the command parameters should be inside msg.payload.
Below are the supported commands categorized by drone type:
1. Jumping Mini Drones
*
`forward`
Move the drone forward at the specified speed (between 0 and 100). Required input msg.payload.speed
* `backward`
Move the drone backward at the specified speed (between 0 and 100). Required input msg.payload.speed
* `right`
Turn the drone right at the specified speed (between 0 and 100). Required input msg.payload.speed
* `left`
Turn the drone left at the specified speed (between 0 and 100). Required input msg.payload.speed
* `stop`
Tell the drone to stop moving.
* `posture-kicker`
Move the drone into the kicker posture. The drone jump mechanism is used to kick objects behind the drone.
* `posture-jumper`
Move the drone into the jumper posture. The drone jump mechanism is used to propel the drone into the air.
* `posture-standing`
Move the drone into the standing (on head) posture.
* `animation-slalom`
Make the drone drive in a slalom pattern.
* `animation-spiral`
Make the drone drive in a spiral.
* `animation-spin-to-posture`
Spin and then change posture.
* `animation-spin-jump`
Spin and then jump the drone.
* `animation-ondulation`
Perform the ondulation animation.
* `animation-metronome`
Perform the metronome animation.
* `animation-slow-shake`
Shake the drone from side-to-side.
* `animation-tap`
Tap the drone jump mechanism.
* `animation-spin`
Perform a spin.
* `animation-stop`
Stop the pre-programmed animation.
* `animation-long-jump-kicker`
Perform a long jump. The drone is in kicker posture before performing this animation.
* `animation-long-jump-jumper`
Perform a long jump. The drone is in jumper posture before performing this animation.
* `animation-high-jump`
Perform a high jump. The drone needs to be in the jumper posture to use this API.
* `take-picture`
Take picture and store it internally
* `get-video-stream`
Emits the MJPEG video stream. This will send the data representing the video as a stream of buffer data in object.payload.video
$3
This node will listen to multiple events triggered by the drone and publish the data to msg.payload object.
Below are the publish events categorized by drone type:
1. Jumping Mini Drones
batteryPercentage
A numeric value indicating the current battery level
batteryStatus
This can be two values based on the events received from the drone as explained below:
*
`critical`
Emitted when the battery is at a critically low level.
* `low`
Emitted when the battery is at a low level.
status
The status of the drone which can be
`ready` posture
The current posture of the drone, this can be 5 values based on the events received from the drone as explained below:
*
`standing`
Emitted when the drone changes to the standing posture. The event may be emitted slightly before the movement is complete so you may want to wait a short time before sending the drone further commands.
* `jumper`
Emitted when the drone changes to the jumper posture. The event may be emitted slightly before the movement is complete so you may want to wait a short time before sending the drone further commands.
* `kicker`
Emitted when the drone changes to the kicker posture. The event may be emitted slightly before the movement is complete so you may want to wait a short time before sending the drone further commands.
* `stuck`
Emitted when the drone is stuck.
* `unknown`
Emitted when the drone posture is unknown.
jumpLoad The jump loading status of the drone, this can be 6 values based on the events received from the drone as explained below:
*
`busy`
Emitted when the jump mechanism is busy (for example, if you tell the drone to jump while a jump is already in progress).
* `unloaded`
Emitted when the jump mechanism is unloaded (for example, after a jump or kick). The event may be emitted slightly before the movement is complete so you may want to wait a short time before sending the drone further commands.
* `loaded`
Emitted when the jump mechanism is retracted (for example, after a long jump while in the kicker posture). The event may be emitted slightly before the movement is complete so you may want to wait a short time before sending the drone further commands.
* `unknown`
Emitted when the load state of the jump mechanism is unknown.
* `unloaded and no jump due to battery Low`
Emitted when the jump mechanism is unloaded and the drone cannot perform the jump requested because the battery is low.
* `loaded and no jump due to battery Low`
Emitted when the jump mechanism is unloaded and the drone cannot perform the jump requested because the battery is low.
jumpMotor
The status of the jump motor of the drone, this can be three values based on the events received from the drone as explained below:
*
`ok`
Emitted when the jump motor is OK (it may have previously been blocked or overheated).
* `blocked`
Emitted when the jump motor is blocked.
* `overheated`
Emitted when the jump motor has overheated. message
A message sent from the drone, this can be two values based on the events received from the drone as explained below:
*
`image taken and stored internally`
Emitted when a photo is taken and stored internally (response to takePicture(opts)).
* `video frame is (the video frame)``The example flow below will show how to control a parrot drone using the "drone-control" node:
[{"id":"2225687d.0c5988","type":"drone-control","z":"128fc2a1.2fc64d","name":"Drone Control","settings":"c1e2cbff.a51ca8","x":619.5,"y":255,"wires":[["34fe3d0d.3a46a2"]]},{"id":"7747f1b8.aadc6","type":"function","z":"128fc2a1.2fc64d","name":"","func":"msg.command = msg.payload;\nmsg.payload = {};\n\nvar speed = flow.get('speed') || 0;\n\nmsg.payload.speed = speed;\nreturn msg;","outputs":1,"noerr":0,"x":413.5,"y":258,"wires":[["2225687d.0c5988"]]},{"id":"34fe3d0d.3a46a2","type":"debug","z":"128fc2a1.2fc64d","name":"","active":true,"console":"false","complete":"true","x":878.5,"y":260,"wires":[]},{"id":"34469adb.cdf3a6","type":"ui_text_input","z":"128fc2a1.2fc64d","tab":"aec1e0f8.c48b4","mode":"text","delay":300,"name":"Speed","topic":"speed","group":"Movement","order":1,"x":76.5,"y":146,"wires":[["98cd5977.c430c8"]]},{"id":"98cd5977.c430c8","type":"function","z":"128fc2a1.2fc64d","name":"","func":"\nflow.set('speed',msg.payload);\n\nreturn msg;","outputs":"1","noerr":0,"x":219,"y":145,"wires":[[]]},{"id":"ef8de3aa.e35a9","type":"ui_button_row","z":"128fc2a1.2fc64d","tab":"aec1e0f8.c48b4","name":"Up-Right","topic":"","group":"Movement","order":1,"toggle":false,"buttons":[{"payload":"forward","icon":"keyboard_arrow_up","color":"Blue","on_icon":"alarm_on","on_color":"red"},{"payload":"right","icon":"keyboard_arrow_right","color":"Blue","on_icon":"keyboard_arrow_down","on_color":"Blue"}],"inputs":0,"x":81.5,"y":204,"wires":[["7747f1b8.aadc6"]]},{"id":"457c0395.e4103c","type":"ui_button_row","z":"128fc2a1.2fc64d","tab":"aec1e0f8.c48b4","name":"Down-Left","topic":"","group":"Movement","order":1,"toggle":false,"buttons":[{"payload":"backward","icon":"keyboard_arrow_down","color":"Blue","on_icon":"alarm_on","on_color":"red"},{"payload":"left","icon":"keyboard_arrow_left","color":"Blue","on_icon":"keyboard_arrow_down","on_color":"Blue"}],"inputs":0,"x":81,"y":259,"wires":[["7747f1b8.aadc6"]]},{"id":"3c81b436.8cff3c","type":"ui_button_row","z":"128fc2a1.2fc64d","tab":"aec1e0f8.c48b4","name":"Stop","topic":"","group":"Movement","order":1,"toggle":false,"buttons":[{"payload":"stop","icon":"clear","color":"Blue","on_icon":"alarm_on","on_color":"red"}],"inputs":0,"x":71,"y":311,"wires":[["7747f1b8.aadc6"]]},{"id":"c0378e04.5fddd","type":"ui_template","z":"128fc2a1.2fc64d","tab":"aec1e0f8.c48b4","name":"Animations","group":"Animations","order":1,"format":"
And the below flow will show how to see all the drone data using the "drone-data" node:
[{"id":"1a312d3.7f9ead3","type":"drone-data","z":"c560f4ff.b48658","name":"Drone Data","settings":"c1e2cbff.a51ca8","x":124,"y":254,"wires":[["40d7160b.ec11b8","df9a2af4.9817d8"]]},{"id":"40d7160b.ec11b8","type":"debug","z":"c560f4ff.b48658","name":"","active":true,"console":"false","complete":"true","x":226.5,"y":405,"wires":[]},{"id":"d48ed1a5.b6436","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Posture Status","group":"Data","order":1,"format":"{{msg.payload.posture}}","x":747,"y":238,"wires":[]},{"id":"63758a61.c32d54","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Drone Status","group":"Data","order":1,"format":"{{msg.payload.status}}","x":734.5,"y":289,"wires":[]},{"id":"e8dc38cc.64e188","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Jump Load Status","group":"Data","order":1,"format":"{{msg.payload.jumpLoad}}","x":759.5,"y":343,"wires":[]},{"id":"9310d160.4c77d","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Jump Motor Status","group":"Data","order":1,"format":"{{msg.payload.jumpMotor}}","x":752.5,"y":402,"wires":[]},{"id":"d5ee8c50.8f28b","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Messages","group":"Data","order":1,"format":"{{msg.payload.message}}","x":730.5,"y":458,"wires":[]},{"id":"3742a1ee.5b2ebe","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Battery Status","group":"Data","order":1,"format":"{{msg.payload.batteryStatus}}","x":740.5,"y":185,"wires":[]},{"id":"df9a2af4.9817d8","type":"switch","z":"c560f4ff.b48658","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"batteryPercentage","vt":"str"},{"t":"eq","v":"batteryStatus","vt":"str"},{"t":"eq","v":"posture","vt":"str"},{"t":"eq","v":"status","vt":"str"},{"t":"eq","v":"jumpLoad","vt":"str"},{"t":"eq","v":"jumpMotor","vt":"str"},{"t":"eq","v":"message","vt":"str"}],"checkall":"true","outputs":7,"x":344,"y":255,"wires":[["8209fbee.1afdb8"],["3742a1ee.5b2ebe"],["d48ed1a5.b6436"],["63758a61.c32d54"],["e8dc38cc.64e188"],["9310d160.4c77d"],["d5ee8c50.8f28b","eb5f127c.3ed38","1ba3b1fb.5c0bce"]]},{"id":"eb5f127c.3ed38","type":"switch","z":"c560f4ff.b48658","name":"","property":"payload.buf","propertyType":"msg","rules":[{"t":"nnull"}],"checkall":"true","outputs":1,"x":368,"y":513,"wires":[["7e79f4c2.bfd0ec"]]},{"id":"c8897980.48bd18","type":"debug","z":"c560f4ff.b48658","name":"","active":true,"console":"false","complete":"true","x":719.5,"y":660,"wires":[]},{"id":"7e79f4c2.bfd0ec","type":"function","z":"c560f4ff.b48658","name":"","func":"var originalBuf = msg.payload.buf;\nvar buf = new Buffer(originalBuf);\nmsg.payload = buf;\nmsg.payload.image = true;\nreturn msg;\n","outputs":1,"noerr":0,"x":515,"y":521,"wires":[["da8b21cb.331d2","c8897980.48bd18"]]},{"id":"b7c91a07.d30a18","type":"ui_template","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"","group":"Image","order":1,"format":"","storeOutMessages":true,"fwdInMessages":true,"x":1002,"y":616,"wires":[[]]},{"id":"da8b21cb.331d2","type":"switch","z":"c560f4ff.b48658","name":"","property":"payload.image","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","outputs":1,"x":671,"y":521,"wires":[["86a6069c.3b2b18"]]},{"id":"1ba3b1fb.5c0bce","type":"debug","z":"c560f4ff.b48658","name":"","active":true,"console":"false","complete":"true","x":177.5,"y":579,"wires":[]},{"id":"86a6069c.3b2b18","type":"base64","z":"c560f4ff.b48658","name":"","x":861,"y":542,"wires":[["b7c91a07.d30a18"]]},{"id":"8209fbee.1afdb8","type":"ui_text","z":"c560f4ff.b48658","tab":"aec1e0f8.c48b4","name":"Battery Percentage","group":"Data","order":1,"format":"{{msg.payload.batteryPercentage}}","x":742.5,"y":126,"wires":[]},{"id":"c1e2cbff.a51ca8","type":"drone-config","z":"","ip":"192.168.2.1","droneType":"Jumping Drone"},{"id":"aec1e0f8.c48b4","type":"ui_tab","z":"","name":"Drone","icon":"dashboard","order":"1"}]
The flows will generate a UI that can be accessed using http://127.0.0.1:1880/ui which shown in the screen shot below: