From 5a25c303c2264038c51581accea078c78b3df7a8 Mon Sep 17 00:00:00 2001 From: kebhr <42484226+kebhr@users.noreply.github.com> Date: Thu, 27 Oct 2022 22:13:30 +0900 Subject: [PATCH 1/7] improve: ensure that commands are executed --- .../scratch3_tello/telloProcessor.js | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js b/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js index 52f15cd..368863c 100644 --- a/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js +++ b/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js @@ -13,20 +13,32 @@ class TelloProcessor { exclusive: true }); + this.flying = false; this.send('command'); - this.executing = true; this.client.on('message', (message, remote) => { const readableMessage = message.toString(); // Previous command executed - if (readableMessage === 'error' || readableMessage === 'ok') { + if (readableMessage === 'ok') { this.executing = false; + if (this.executingCommand === 'takeoff') this.flying = true; + if (this.executingCommand === 'land') this.flying = false; + // Dequeue this.queue.shift(); - // Send the next element + // Send next element + this.inquire(); + } else if (readableMessage.includes('error')) { + this.executing = false; + this.flying = false; + + // Dequeue + this.queue.shift(); + + // Send next element this.inquire(); } }); @@ -66,7 +78,13 @@ class TelloProcessor { send (cmd) { const msg = Buffer.from(cmd); + // While grounding, `command` and `takeoff` can only execute + if (!this.flying && cmd !== 'command' && cmd !== 'takeoff') { + this.queue.shift(); + return; + } this.executing = true; + this.executingCommand = cmd; this.client.send(msg, 0, msg.length, 8889, '192.168.10.1', (err, bytes) => { if (err) throw err; }); From 482d50c26fe4f77386501aeb5beb860195a73c85 Mon Sep 17 00:00:00 2001 From: kebhr <42484226+kebhr@users.noreply.github.com> Date: Sat, 29 Oct 2022 02:14:54 +0900 Subject: [PATCH 2/7] i18n: add French support (thanks to Ryan Perry) --- README.md | 1 + .../src/extensions/scratch3_tello/index.js | 74 ++++++++++++------- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 48c6b38..385bd78 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ You can download the binary [here](https://github.com/kebhr/scratch3-tello/relea - 日本語 - にほんご - Ру́сский (Thanks to [@cirodil](https://github.com/cirodil)) +- Français (Thanks to Ryan Perry) Feel free to create a pull request for adding more languages! diff --git a/scratch-vm/src/extensions/scratch3_tello/index.js b/scratch-vm/src/extensions/scratch3_tello/index.js index d27c3fc..3d7bf9b 100644 --- a/scratch-vm/src/extensions/scratch3_tello/index.js +++ b/scratch-vm/src/extensions/scratch3_tello/index.js @@ -24,145 +24,169 @@ const message = { 'ja': '離陸する', 'ja-Hira': 'りりくする', 'en': 'takeoff', - 'ru': 'взлёт' + 'ru': 'взлёт', + 'fr': 'décollage' }, land: { 'ja': '着陸する', 'ja-Hira': 'ちゃくりくする', 'en': 'land', - 'ru': 'посадка' + 'ru': 'посадка', + 'fr': 'atterrissage' }, up: { 'ja': '上に [X]cm 上がる', 'ja-Hira': 'うえに [X] センチあがる', 'en': 'up [X] cm', - 'ru': 'вверх [X] см' + 'ru': 'вверх [X] см', + 'fr': 'montée de [X] cm' }, down: { 'ja': '下に [X]cm 下がる', 'ja-Hira': 'したに [X] センチさがる', 'en': 'down [X] cm', - 'ru': 'вниз [X] см' + 'ru': 'вниз [X] см', + 'fr': 'descente de [X] cm' }, left: { 'ja': '左に [X]cm 動く', 'ja-Hira': 'ひだりに [X] センチうごく', 'en': 'move left [X] cm', - 'ru': 'влево [X] см' + 'ru': 'влево [X] см', + 'fr': 'voler à gauche [X] cm' }, right: { 'ja': '右に [X]cm 動く', 'ja-Hira': 'みぎに [X] センチうごく', 'en': 'move right [X] cm', - 'ru': 'вправо [X] см' + 'ru': 'вправо [X] см', + 'fr': 'voler à droite [X] cm' }, forward: { 'ja': '前に [X]cm 進む', 'ja-Hira': 'まえに [X] センチすすむ', 'en': 'move forward [X] cm', - 'ru': 'вперёд [X] см' + 'ru': 'вперёд [X] см', + 'fr': 'voler vers l\'avant [X] cm' }, back: { 'ja': '後ろに [X]cm 下がる', 'ja-Hira': 'うしろに [X] センチさがる', 'en': 'move back [X] cm', - 'ru': 'назад [X] см' + 'ru': 'назад [X] см', + 'fr': 'voler vers l\'arrière [X] cm' }, cw: { 'ja': '[X] 度右に回る', 'ja-Hira': '[X] どみぎにまわる', 'en': 'rotate [X] degrees right', - 'ru': 'повернуть на [X] градусов вправо' + 'ru': 'повернуть на [X] градусов вправо', + 'fr': 'tourner de [X] degrés vers la droite' }, ccw: { 'ja': '[X] 度左に回る', 'ja-Hira': '[X] どひだりにまわる', 'en': 'rotate [X] degrees left', - 'ru': 'повернуть на [X] градусов влево' + 'ru': 'повернуть на [X] градусов влево', + 'fr': 'tourner de [X] degrés vers la gauche' }, pitch: { 'ja': 'ピッチ', 'ja-Hira': 'ピッチ', 'en': 'pitch', - 'ru': 'наклон' + 'ru': 'наклон', + 'fr': 'tangage' }, roll: { 'ja': 'ロール', 'ja-Hira': 'ロール', 'en': 'roll', - 'ru': 'крен' + 'ru': 'крен', + 'fr': 'roulis' }, yaw: { 'ja': 'ヨー', 'ja-Hira': 'ヨー', 'en': 'yaw', - 'ru': 'вращение вокруг оси Z' + 'ru': 'вращение вокруг оси Z', + 'fr': 'lacet' }, vgx: { 'ja': 'x方向の速度', 'ja-Hira': 'xほうこうのはやさ', 'en': 'speed x', - 'ru': 'скорость x' + 'ru': 'скорость x', + 'fr': 'vitesse sur l\'axe X' }, vgy: { 'ja': 'y方向の速度', 'ja-Hira': 'yほうこうのはやさ', 'en': 'speed y', - 'ru': 'скорость y' + 'ru': 'скорость y', + 'fr': 'vitesse sur l\'axe Y' }, vgz: { 'ja': 'z方向の速度', 'ja-Hira': 'zほうこうのはやさ', 'en': 'speed z', - 'ru': 'скорость z' + 'ru': 'скорость z', + 'fr': 'vitesse sur l\'axe Z' }, tof: { 'ja': '地面からの高度', 'ja-Hira': 'じめんからのたかさ', 'en': 'height from ground', - 'ru': 'высота от земли' + 'ru': 'высота от земли', + 'fr': 'hauteur du sol' }, height: { 'ja': '離陸した場所からの高度', 'ja-Hira': 'りりくしたばしょからのたかさ', 'en': 'height from takeoff point', - 'ru': 'высота от точки взлёта' + 'ru': 'высота от точки взлёта', + 'fr': 'hauteur du point de décollage' }, bat: { 'ja': 'バッテリー残量', 'ja-Hira': 'バッテリーざんりょう', 'en': 'battery remaining', - 'ru': 'заряд батареи' + 'ru': 'заряд батареи', + 'fr': 'niveau de la batterie' }, baro: { 'ja': '気圧計による高さ', 'ja-Hira': 'きあつけいによるたかさ', 'en': 'height by barometer', - 'ru': 'высота по барометру' + 'ru': 'высота по барометру', + 'fr': 'altitude (baromètre)' }, time: { 'ja': '飛行時間', 'ja-Hira': 'ひこうじかん', 'en': 'flying time', - 'ru': 'время полёта' + 'ru': 'время полёта', + 'fr': 'durée du vol' }, agx: { 'ja': 'x方向の加速度', 'ja-Hira': 'xほうこうのかそくど', 'en': 'acceleration x', - 'ru': 'ускорение x' + 'ru': 'ускорение x', + 'fr': 'accélération sur l\'axe X' }, agy: { 'ja': 'y方向の加速度', 'ja-Hira': 'yほうこうのかそくど', 'en': 'acceleration y', - 'ru': 'ускорение y' + 'ru': 'ускорение y', + 'fr': 'accélération sur l\'axe Y' }, agz: { 'ja': 'z方向の加速度', 'ja-Hira': 'zほうこうのかそくど', 'en': 'acceleration z', - 'ru': 'ускорение z' + 'ru': 'ускорение z', + 'fr': 'accélération sur l\'axe Z' } }; @@ -191,7 +215,7 @@ class Scratch3Tello { * @returns {object} metadata for this extension and its blocks. */ getInfo () { - if (formatMessage.setup().locale === 'ja' || formatMessage.setup().locale === 'ja-Hira' || formatMessage.setup().locale === 'ru') { + if (formatMessage.setup().locale === 'ja' || formatMessage.setup().locale === 'ja-Hira' || formatMessage.setup().locale === 'ru' || formatMessage.setup().locale === 'fr') { this.locale = formatMessage.setup().locale; } else { this.locale = 'en'; From b72b760b2817edda771eee829d8a90feb18db1b9 Mon Sep 17 00:00:00 2001 From: kebhr <42484226+kebhr@users.noreply.github.com> Date: Sun, 30 Oct 2022 02:31:19 +0900 Subject: [PATCH 3/7] refactor: no need to define support languages for fallback --- scratch-vm/src/extensions/scratch3_tello/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scratch-vm/src/extensions/scratch3_tello/index.js b/scratch-vm/src/extensions/scratch3_tello/index.js index 3d7bf9b..bbca795 100644 --- a/scratch-vm/src/extensions/scratch3_tello/index.js +++ b/scratch-vm/src/extensions/scratch3_tello/index.js @@ -215,8 +215,9 @@ class Scratch3Tello { * @returns {object} metadata for this extension and its blocks. */ getInfo () { - if (formatMessage.setup().locale === 'ja' || formatMessage.setup().locale === 'ja-Hira' || formatMessage.setup().locale === 'ru' || formatMessage.setup().locale === 'fr') { - this.locale = formatMessage.setup().locale; + const currentLocale = formatMessage.setup().locale; + if (Object.keys(message).filter((key) => {return currentLocale in message[key]}).length > 0) { + this.locale = currentLocale; } else { this.locale = 'en'; } From fda5a5746be316eb6ce34863b8b766210dcd5194 Mon Sep 17 00:00:00 2001 From: kebhr <42484226+kebhr@users.noreply.github.com> Date: Mon, 31 Oct 2022 23:19:54 +0900 Subject: [PATCH 4/7] feat: support for Tello EDU's Mission Pad --- .../src/extensions/scratch3_tello/index.js | 437 +++++++++++++++++- .../scratch3_tello/telloProcessor.js | 10 +- 2 files changed, 420 insertions(+), 27 deletions(-) diff --git a/scratch-vm/src/extensions/scratch3_tello/index.js b/scratch-vm/src/extensions/scratch3_tello/index.js index bbca795..6277199 100644 --- a/scratch-vm/src/extensions/scratch3_tello/index.js +++ b/scratch-vm/src/extensions/scratch3_tello/index.js @@ -90,6 +90,54 @@ const message = { 'ru': 'повернуть на [X] градусов влево', 'fr': 'tourner de [X] degrés vers la gauche' }, + flip: { + 'ja': '[DIRECTION]に宙返りする', + 'ja-Hira': '[DIRECTION]にちゅうがえりする', + 'en': 'flip in [DIRECTION]', + 'fr': 'flip vers [DIRECTION]' + }, + go: { + 'ja': 'x:[X] y:[Y] z:[Z] に [SPEED]cm/s で飛ぶ', + 'ja-Hira': 'x:[X] y:[Y] z:[Z] に 1びょうで [SPEED] センチのはやさでとぶ', + 'en': 'fly to x:[X] y:[Y] z:[Z] in [SPEED]cm/s', + 'fr': 'voler à x:[X] y:[Y] z:[Z] à [SPEED]cm/s' + }, + curve: { + 'ja': 'x:[X1] y:[Y1] z:[Z1] から x:[X2] y:[Y2] z:[Z2] に [SPEED]cm/s でカーブしながら飛ぶ', + 'ja-hira': 'x:[X2] y:[Y2] z:[Z2] から x:[X2] y:[Y2] z:[Z2] に 1びょうで [SPEED] センチのはやさでカーブしながらとぶ', + 'en': 'fly in curve from x:[X1] y:[Y1] z:[Z1] to x:[X2] y:[Y2] z:[Z2] in [SPEED]cm/s', + 'fr': 'voler en courbe de x:[X1] y:[Y1] z:[Z1] à x:[X2] y:[Y2] z:[Z2] à [SPEED]cm/s' + }, + enable_mission_pad: { + 'ja': 'ミッションパッドを使う', + 'ja-Hira': 'ミッションパッドをつかう', + 'en': 'enable Mission Pad', + 'fr': 'activer le "Mission Pad"' + }, + edu_go: { + 'ja': '[MID]を検出していたら、ミッションパッドを基準に x:[X] y:[Y] z:[Z] に [SPEED]cm/s で飛ぶ', + 'ja-Hira': '[MID]がみつかっていたら、ミッションパッドからみて x:[X] y:[Y] z:[Z] に 1びょうで [SPEED] センチのはやさでとぶ', + 'en': 'when [MID] detected, fly to x:[X] y:[Y] z:[Z] based on the Mission Pad at [SPEED]cm/s', + 'fr': 'détecter [MID], ensuite voler à x:[X] y:[Y] z:[Z] à partir du Mission Pad à [SPEED]cm/s' + }, + edu_curve: { + 'ja': '[MID]を検出していたら、ミッションパッドを基準に x:[X1] y:[Y1] z:[Z1] から x:[X2] y:[Y2] z:[Z2] に [SPEED]cm/s でカーブしながら飛ぶ', + 'ja-hira': '[MID]がみつかっていたら、ミッションパッドからみて x:[X2] y:[Y2] z:[Z2] から x:[X2] y:[Y2] z:[Z2] に 1びょうで [SPEED] センチのはやさでカーブしながらとぶ', + 'en': 'when [MID] detected, fly in curve from x:[X1] y:[Y1] z:[Z1] to x:[X2] y:[Y2] z:[Z2] based on the Mission Pad at [SPEED]cm/s', + 'fr': 'détecter [MID], ensuite voler en courbe de x:[X] y:[Y] z:[Z] à x:[X] y:[Y] z:[Z] à partir du Mission Pad à [SPEED] cm/s' + }, + edu_jump: { + 'ja': '[MID1]と[MID2]を検出したら、1つ目のミッションパッドを基準に x:[X] y:[Y] z:[Z] に飛んだあと、2つ目のミッションパッドの上まで[SPEED]cm/sで飛び[YAW]度に向く', + 'ja-hira': '[MID1]と[MID2]がみつかったら、1つめのミッションパッドからみて x:[X] y:[Y] z:[Z] にとんだあと2つめのミッションパッドのうえまで 1びょうで [SPEED] センチのはやさでとび、[YAW]どにむく', + 'en': 'when [MID1] [MID2] detected, fly to x:[X] y:[Y] z:[Z] based on first mission pad then fly on second mission pad at [SPEED] cm/s and rotate [YAW] degrees', + 'fr': 'détecter [MID1] et [MID2], ensuite voler à x:[X] y:[Y] z:[Z] à partir du premier Mission Pad, faire une rotation de [YAW] degrés, et voler au deuxième Mission Pad à [SPEED] cm/s' + }, + clearQueue: { + 'ja': '実行待ちのコマンドをクリアする', + 'ja-Hira': 'うごくのをまっているコマンドをなくす', + 'en': 'clear command queue', + 'fr': 'effacer la séquence de commandes' + }, pitch: { 'ja': 'ピッチ', 'ja-Hira': 'ピッチ', @@ -188,7 +236,6 @@ const message = { 'ru': 'ускорение z', 'fr': 'accélération sur l\'axe Z' } - }; /** @@ -211,6 +258,11 @@ class Scratch3Tello { this.getState(); } + + _getText (key) { + return message[key][this.locale] || message[key]['en']; + } + /** * @returns {object} metadata for this extension and its blocks. */ @@ -230,18 +282,18 @@ class Scratch3Tello { blocks: [ { opcode: 'takeoff', - text: message.takeoff[this.locale], + text: this._getText('takeoff'), blockType: BlockType.COMMAND }, { opcode: 'land', - text: message.land[this.locale], + text: this._getText('land'), blockType: BlockType.COMMAND }, '---', { opcode: 'up', - text: message.up[this.locale], + text: this._getText('up'), blockType: BlockType.COMMAND, arguments: { X: { @@ -252,7 +304,7 @@ class Scratch3Tello { }, { opcode: 'down', - text: message.down[this.locale], + text: this._getText('down'), blockType: BlockType.COMMAND, arguments: { X: { @@ -263,7 +315,7 @@ class Scratch3Tello { }, { opcode: 'left', - text: message.left[this.locale], + text: this._getText('left'), blockType: BlockType.COMMAND, arguments: { X: { @@ -274,7 +326,7 @@ class Scratch3Tello { }, { opcode: 'right', - text: message.right[this.locale], + text: this._getText('right'), blockType: BlockType.COMMAND, arguments: { X: { @@ -285,7 +337,7 @@ class Scratch3Tello { }, { opcode: 'forward', - text: message.forward[this.locale], + text: this._getText('forward'), blockType: BlockType.COMMAND, arguments: { X: { @@ -296,7 +348,7 @@ class Scratch3Tello { }, { opcode: 'back', - text: message.back[this.locale], + text: this._getText('back'), blockType: BlockType.COMMAND, arguments: { X: { @@ -307,7 +359,7 @@ class Scratch3Tello { }, { opcode: 'cw', - text: message.cw[this.locale], + text: this._getText('cw'), blockType: BlockType.COMMAND, arguments: { X: { @@ -318,7 +370,7 @@ class Scratch3Tello { }, { opcode: 'ccw', - text: message.ccw[this.locale], + text: this._getText('ccw'), blockType: BlockType.COMMAND, arguments: { X: { @@ -327,79 +379,381 @@ class Scratch3Tello { } } }, + { + opcode: 'flip', + text: this._getText('flip'), + blockType: BlockType.COMMAND, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + defaultValue: 'f', + menu: 'DIRECTION' + } + } + }, + '---', + { + opcode: 'go', + text: this._getText('go'), + blockType: BlockType.COMMAND, + arguments: { + X: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + SPEED: { + type: ArgumentType.NUMBER, + defaultValue: 10 + }, + } + }, + { + opcode: 'curve', + text: this._getText('curve'), + blockType: BlockType.COMMAND, + arguments: { + X1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + X2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + SPEED: { + type: ArgumentType.NUMBER, + defaultValue: 10 + } + } + }, + '---', + { + opcode: 'enable_mission_pad', + text: this._getText('enable_mission_pad'), + blockType: BlockType.COMMAND, + }, + { + opcode: 'edu_go', + text: '(EDU) ' + this._getText('edu_go'), + blockType: BlockType.COMMAND, + arguments: { + X: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + SPEED: { + type: ArgumentType.NUMBER, + defaultValue: 10 + }, + MID: { + type: ArgumentType.STRING, + defaultValue: 'm1', + menu: 'MID' + } + } + }, + { + opcode: 'edu_curve', + text: '(EDU) ' + this._getText('edu_curve'), + blockType: BlockType.COMMAND, + arguments: { + X1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z1: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + X2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z2: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + SPEED: { + type: ArgumentType.NUMBER, + defaultValue: 10 + }, + MID: { + type: ArgumentType.STRING, + defaultValue: 'm1', + menu: 'MID' + } + } + }, + { + opcode: 'edu_jump', + text: '(EDU) ' + this._getText('edu_jump'), + blockType: BlockType.COMMAND, + arguments: { + X: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Y: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + Z: { + type: ArgumentType.NUMBER, + defaultValue: 50 + }, + SPEED: { + type: ArgumentType.NUMBER, + defaultValue: 10 + }, + YAW: { + type: ArgumentType.NUMBER, + defaultValue: 0 + }, + MID1: { + type: ArgumentType.STRING, + defaultValue: 'm1', + menu: 'MID' + }, + MID2: { + type: ArgumentType.STRING, + defaultValue: 'm1', + menu: 'MID' + } + } + }, + '---', + { + opcode: 'clearQueue', + text: this._getText('clearQueue'), + blockType: BlockType.COMMAND + }, '---', { opcode: 'pitch', - text: message.pitch[this.locale], + text: this._getText('pitch'), blockType: BlockType.REPORTER }, { opcode: 'roll', - text: message.roll[this.locale], + text: this._getText('roll'), blockType: BlockType.REPORTER }, { opcode: 'yaw', - text: message.yaw[this.locale], + text: this._getText('yaw'), blockType: BlockType.REPORTER }, { opcode: 'vgx', - text: message.vgx[this.locale], + text: this._getText('vgx'), blockType: BlockType.REPORTER }, { opcode: 'vgy', - text: message.vgy[this.locale], + text: this._getText('vgy'), blockType: BlockType.REPORTER }, { opcode: 'vgz', - text: message.vgz[this.locale], + text: this._getText('vgz'), blockType: BlockType.REPORTER }, { opcode: 'tof', - text: message.tof[this.locale], + text: this._getText('tof'), blockType: BlockType.REPORTER }, { opcode: 'height', - text: message.height[this.locale], + text: this._getText('height'), blockType: BlockType.REPORTER }, { opcode: 'bat', - text: message.bat[this.locale], + text: this._getText('bat'), blockType: BlockType.REPORTER }, { opcode: 'baro', - text: message.baro[this.locale], + text: this._getText('baro'), blockType: BlockType.REPORTER }, { opcode: 'time', - text: message.time[this.locale], + text: this._getText('time'), blockType: BlockType.REPORTER }, { opcode: 'agx', - text: message.agx[this.locale], + text: this._getText('agx'), blockType: BlockType.REPORTER }, { opcode: 'agy', - text: message.agy[this.locale], + text: this._getText('agy'), blockType: BlockType.REPORTER }, { opcode: 'agz', - text: message.agz[this.locale], + text: this._getText('agz'), blockType: BlockType.REPORTER } ], menus: { + DIRECTION: { + acceptReporters: true, + items: [ + { + text: (() => { + const msg = { + 'ja': '前', + 'ja-Hira': 'まえ', + 'en': 'forward', + 'fr': 'avant' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'f' + }, + { + text: (() => { + const msg = { + 'ja': '後ろ', + 'ja-Hira': 'うしろ', + 'en': 'back', + 'fr': 'arrière' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'b' + }, + { + text: (() => { + const msg = { + 'ja': '左', + 'ja-Hira': 'ひだり', + 'en': 'left', + 'fr': 'gauche' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'l' + }, + { + text: (() => { + const msg = { + 'ja': '右', + 'ja-Hira': 'みぎ', + 'en': 'right', + 'fr': 'droite' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'r' + } + ] + }, + MID: { + acceptReporters: true, + items: [ + { + text: 'm1', + value: 'm1' + }, + { + text: 'm2', + value: 'm2' + }, + { + text: 'm3', + value: 'm3' + }, + { + text: 'm4', + value: 'm4' + }, + { + text: 'm5', + value: 'm5' + }, + { + text: 'm6', + value: 'm6' + }, + { + text: 'm7', + value: 'm7' + }, + { + text: 'm8', + value: 'm8' + }, + { + text: (() => { + const msg = { + 'ja': 'ランダム', + 'ja-Hira': 'ランダム', + 'en': 'random', + 'fr': 'aléatoire' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'm-1' + }, + { + text: (() => { + const msg = { + 'ja': '最も近い', + 'ja-Hira': 'もっともちかい', + 'en': 'nearest', + 'fr': 'le plus proche' + }; + return msg[this.locale] || msg['en']; + })(), + value: 'm-2' + } + ] + } } }; } @@ -451,6 +805,39 @@ class Scratch3Tello { this.telloProcessor.request(`ccw ${Cast.toString(args.X)}`); } + flip (args) { + this.telloProcessor.request(`flip ${args.DIRECTION}`); + } + + go (args) { + this.telloProcessor.request(`go ${Cast.toString(args.X)} ${Cast.toString(args.Y)} ${Cast.toString(args.Z)} ${Cast.toString(args.SPEED)}`); + } + + curve (args) { + this.telloProcessor.request(`curve ${Cast.toString(args.X1)} ${Cast.toString(args.Y1)} ${Cast.toString(args.Z1)} ${Cast.toString(args.X2)} ${Cast.toString(args.Y2)} ${Cast.toString(args.Z2)} ${Cast.toString(args.SPEED)}`); + } + + enable_mission_pad () { + this.telloProcessor.request(`mon`); + this.telloProcessor.request(`mdirection 2`); + } + + edu_go (args) { + this.telloProcessor.request(`go ${Cast.toString(args.X)} ${Cast.toString(args.Y)} ${Cast.toString(args.Z)} ${Cast.toString(args.SPEED)} ${args.MID}`); + } + + edu_curve (args) { + this.telloProcessor.request(`curve ${Cast.toString(args.X1)} ${Cast.toString(args.Y1)} ${Cast.toString(args.Z1)} ${Cast.toString(args.X2)} ${Cast.toString(args.Y2)} ${Cast.toString(args.Z2)} ${Cast.toString(args.SPEED)} ${args.MID}`); + } + + edu_jump (args) { + this.telloProcessor.request(`jump ${Cast.toString(args.X)} ${Cast.toString(args.Y)} ${Cast.toString(args.Z)} ${Cast.toString(args.SPEED)} ${Cast.toString(args.YAW)} ${args.MID1} ${args.MID2}`); + } + + clearQueue () { + this.telloProcessor.resetQueue(); + } + pitch () { return this.state.pitch; } diff --git a/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js b/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js index 368863c..d818355 100644 --- a/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js +++ b/scratch-vm/src/extensions/scratch3_tello/telloProcessor.js @@ -78,8 +78,8 @@ class TelloProcessor { send (cmd) { const msg = Buffer.from(cmd); - // While grounding, `command` and `takeoff` can only execute - if (!this.flying && cmd !== 'command' && cmd !== 'takeoff') { + // While grounding, `command`, `mon`, `mdirection 2` and `takeoff` are only executable + if (!this.flying && cmd !== 'command' && cmd !== 'mon' && cmd !== 'mdirection 2' && cmd !== 'takeoff') { this.queue.shift(); return; } @@ -89,6 +89,12 @@ class TelloProcessor { if (err) throw err; }); } + + resetQueue () { + this.queue = []; + this.flying = false; + this.executing = false; + } } module.exports = TelloProcessor; From 190bc4b1ddc383d1ea6f32b159752c04cea6e13b Mon Sep 17 00:00:00 2001 From: kebhr <42484226+kebhr@users.noreply.github.com> Date: Tue, 1 Nov 2022 19:30:06 +0900 Subject: [PATCH 5/7] improve: fix japanese text --- scratch-vm/src/extensions/scratch3_tello/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scratch-vm/src/extensions/scratch3_tello/index.js b/scratch-vm/src/extensions/scratch3_tello/index.js index 6277199..fd8b9cc 100644 --- a/scratch-vm/src/extensions/scratch3_tello/index.js +++ b/scratch-vm/src/extensions/scratch3_tello/index.js @@ -121,13 +121,13 @@ const message = { 'fr': 'détecter [MID], ensuite voler à x:[X] y:[Y] z:[Z] à partir du Mission Pad à [SPEED]cm/s' }, edu_curve: { - 'ja': '[MID]を検出していたら、ミッションパッドを基準に x:[X1] y:[Y1] z:[Z1] から x:[X2] y:[Y2] z:[Z2] に [SPEED]cm/s でカーブしながら飛ぶ', + 'ja': '[MID]を検出していたら、ミッションパッドを基準に x:[X1] y:[Y1] z:[Z1] から x:[X2] y:[Y2] z:[Z2] に[SPEED]cm/s でカーブしながら飛ぶ', 'ja-hira': '[MID]がみつかっていたら、ミッションパッドからみて x:[X2] y:[Y2] z:[Z2] から x:[X2] y:[Y2] z:[Z2] に 1びょうで [SPEED] センチのはやさでカーブしながらとぶ', 'en': 'when [MID] detected, fly in curve from x:[X1] y:[Y1] z:[Z1] to x:[X2] y:[Y2] z:[Z2] based on the Mission Pad at [SPEED]cm/s', 'fr': 'détecter [MID], ensuite voler en courbe de x:[X] y:[Y] z:[Z] à x:[X] y:[Y] z:[Z] à partir du Mission Pad à [SPEED] cm/s' }, edu_jump: { - 'ja': '[MID1]と[MID2]を検出したら、1つ目のミッションパッドを基準に x:[X] y:[Y] z:[Z] に飛んだあと、2つ目のミッションパッドの上まで[SPEED]cm/sで飛び[YAW]度に向く', + 'ja': '[MID1]と[MID2]を検出していたら、1つ目のミッションパッドを基準に x:[X] y:[Y] z:[Z] に飛んだあと、2つ目のミッションパッドの上まで[SPEED]cm/sで飛び[YAW]度に向く', 'ja-hira': '[MID1]と[MID2]がみつかったら、1つめのミッションパッドからみて x:[X] y:[Y] z:[Z] にとんだあと2つめのミッションパッドのうえまで 1びょうで [SPEED] センチのはやさでとび、[YAW]どにむく', 'en': 'when [MID1] [MID2] detected, fly to x:[X] y:[Y] z:[Z] based on first mission pad then fly on second mission pad at [SPEED] cm/s and rotate [YAW] degrees', 'fr': 'détecter [MID1] et [MID2], ensuite voler à x:[X] y:[Y] z:[Z] à partir du premier Mission Pad, faire une rotation de [YAW] degrés, et voler au deuxième Mission Pad à [SPEED] cm/s' From 57cc05ac6c684e4d783c18f53fa1705a15c753f3 Mon Sep 17 00:00:00 2001 From: Kanta Ebihara <42484226+kebhr@users.noreply.github.com> Date: Wed, 2 Nov 2022 19:11:06 +0900 Subject: [PATCH 6/7] docs: update README --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 385bd78..91414ba 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,23 @@ ![image](https://user-images.githubusercontent.com/42484226/74595154-93dda080-5081-11ea-8ef0-59eec11274d3.png) +![GitHub all releases](https://img.shields.io/github/downloads/kebhr/scratch3-tello/total?style=for-the-badge) + ## Release -You can download the binary [here](https://github.com/kebhr/scratch3-tello/releases). +You can download the binary from [here](https://github.com/kebhr/scratch3-tello/releases). + +I am seeking sponsors on [Patreon](https://www.patreon.com/scratch3_tello) to continue the development of Scratch3-Tello. ### Instruction 1. Download the binary. -2. Connect to Tello wifi. +2. Connect to Tello's wifi. 3. Start the app. 4. Activate Tello extension. **NOTE:** - If you are having trouble connecting to Tello, close the app, restart Tello and start the app again. - Connect to Tello before launching the app. If you connect to Tello after the app is launched, the extension will **not** be able to send commands to Tello. +- If the drone does not take off after sending the `takeoff` command, use the `clear command queue` block. ## Supported languages - English From ce76c8436d7e6ab57f9da6016af5dcc31f453ff3 Mon Sep 17 00:00:00 2001 From: Kanta Ebihara <42484226+kebhr@users.noreply.github.com> Date: Wed, 2 Nov 2022 19:12:41 +0900 Subject: [PATCH 7/7] docs: update image in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91414ba..21fa4f6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ for more information: click this image -![image](https://user-images.githubusercontent.com/42484226/74595154-93dda080-5081-11ea-8ef0-59eec11274d3.png) +screenshot of scratch3-tello ![GitHub all releases](https://img.shields.io/github/downloads/kebhr/scratch3-tello/total?style=for-the-badge)