2018年8月27日 星期一

控制Tello: 直接用 Node.js 就夠啦!


介紹完 Scratch 控制 Tello 的方式後,我又仔細看了官網提供的 Tello.js 檔案,其實不一定要 Scratch,直接拿 Tello.js 改寫成命令列,或直接做成本地端的網頁就可以了。不多說,下面就來介紹一下到底要怎麼做。


Step 1. 下載 Node.js

相信有看過前一篇怎麼用 Scratch 去飛 Tello 的朋友,都已經裝上 Node.js 了。還沒裝的,不妨看看上一篇文章(傳送門在此),先把 Node.js 裝起來。要不然,下面都不用玩了。



Step 2. UDP通訊

不管你用哪個程式語言去寫,在沒有駭進 Tello 裡的狀況下,與 Tello 的通訊走的就是 UDP (用戶資料報協定,User Datagram Protocol)。我不是唸通訊的,詳細到底是怎麼溝通的我搞不懂,反正得用這個協定來寫程式才會動。所以在 Node.js 裡面,就得先把會用到的dgram擴充功能拉進來,用udp4的方式打開網路插座(socket)。

const dgram = require('dgram');
const socket = dgram.createSocket('udp4');


從官方的SDK可以看到,Tello 的 IP 是 192.168.10.1,用的通訊埠(port)則是8889,這時候順道再把這兩項參數設為常數。

const HOST = '192.168.10.1';
const PORT = 8889;


再過來,需要透過網路插座把指令送到 Tello ,這時候你需要 send() 這個動作。

socket.send(commandStr, PORT, HOST);

上面我沒有寫到 commandStr 是個字串,可以送出去的指令都在 Tello 的 SDK 裡面,包括 command, takeoff, land, flip, battery?等等,自己查一下印象會比較深刻。

最後,我們還得知道 Tello 收到指令之後做了什麼回應,這時就需要靠 message 這個事件處理來做,並利用 console.log() 將結果顯示出來。

socket.on('message', (msg, info) => {
    console.log('Data received from Tello: ' + msg.toString());

});

這麼一來,和 Tello 最基本的溝通工作就完成囉!


Step 3. 加入命令列互動

要加入命令列的互動,我們還需要另一個擴充功能 readline ,並且創造一個處理輸出輸入的界面(interface)。

const readline = require('readline');
const rl = readline.createInterface(
    process.stdin,
    process.stdout
);


為了要讓輸入的介面跳出來,這邊要使用到 prompt()。可以設一個自訂的開頭,方便辨識這是 Tello 的命令列。

rl.setPrompt('Tello> ');
rl.prompt();


再過來,要利用 line 事件,也就是按下 Enter 鍵之後,把輸入的指令送給 Tello 。因為經常會不小心多按到空白鍵,所以我們會加個字串的 trim() 功能把多出來的空格給忽略掉。

rl.on('line', (input) => {
    var commandStr = input.trim();
    console.log(`Command: {$commandStr}`);
    socket.send(commandStr, PORT, HOST);
});


到這裡,用命令列和 Tello 進行互動的功能基本上已經完成。再過來,我們多做一個結束的指令,也就輸入 quit 之後,把網路插座給關上並結束命令列。不需要寫太多,把上面那段改寫一下就可以。

rl.on('line', (input) => {
    var commandStr = input.trim();
    if (commandStr === 'quit') {
        socket.close();
        rl.close();
    }
    else {
        console.log(`Command: ${commandStr}`);
        socket.send(commandStr, PORT, HOST);
    }
});



Step 4. 執行命令列互動

完整的程式碼寫在這邊,用文字編輯器把它存成 TelloCommandLine.js。

const dgram = require('dgram');
const socket = dgram.createSocket('udp4');

const HOST = '192.168.10.1';
const PORT = 8889;

const readline = require('readline');
const rl = readline.createInterface(
    process.stdin,
    process.stdout
);

rl.setPrompt('Tello> ');
rl.prompt();

socket.on('message', (msg, info) => {
    console.log('Data received from Tello: ' + msg.toString());
    rl.prompt();
});

rl.on('line', (input) => {
    var commandStr = input.trim();
    if (commandStr === 'quit') {
        socket.close();
        rl.close();
    }
    else {
        console.log(`Command: ${commandStr}`);
        socket.send(commandStr, PORT, HOST);
    }
});


然後在同一個目錄下,輸入 node TelloCommandLLine.js ,就可以用命令列來控制 Tello 囉!


沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...