• 検索結果がありません。

PowerPoint プレゼンテーション

N/A
N/A
Protected

Academic year: 2021

シェア "PowerPoint プレゼンテーション"

Copied!
36
0
0

読み込み中.... (全文を見る)

全文

(1)

はじめに

(1)動作環境

(2)飛行プラン

(3)ファイルからの飛行プランの読み

取り

(4)飛行プランの引数渡しとGrabber

(5)機能追加

droneプログラミング覚書

岐阜経済大学 経営学部 経営情報学科 井戸 伸彦

来歴:

0.0版 2018年5月10日 順次追加

スライドの構成

(2)

はじめに

本スライドは、JavaScriptを用いて、ドローンParrot Mamboを操

作するプログラムの作成に関わる覚書です。単独で教科書とな

ることは意図していません。

JavaScriptプログラムはブラウザ上で動作させることがほとんど

ですが、本スライドではnode.jsを用いてコンソール上から起動し

ます。

本スライドでは、JavaScriptについて次のスライドで学んでいる

ことを前提とします。本スライド中では、このスライドを、“JS覚

書”と記して参照します。

「JavaScript覚書」

http://staff.gifu-keizai.ac.jp/~ido/doc/web_text/javascript_text.pdf

JavaScriptについてきちんと勉強したい方は、プログラミング等

の講義を受講して頂くことをお願いします。

説明は直感的な分かりやすさを重視し、厳密には不正確な言

い方もしています。

(3)

(1.1)動作環境

本スライドでは、node.jsを用いてJavaScriptの動作環

境を構築することを前提としています。

次のサイトを参考に環境構築を行いました。

(1)全体像:「 Parrot Mambo Missionを動かす(github)」

(以下のスライドでは、このサイトからのファイル等を“元ネタ”と記します。) (https://github.com/hiko2msp/play_with_parrot_mambo) (2)node.js/npmのインストール:「Node.js / npmをインストールする」 (https://qiita.com/taiponrock/items/9001ae194571feb63a5e) (3)gitのインストール: 「初心者でもWindowsやMacでできる、Gitのインストールと基本的な使い方」 (http://www.atmarkit.co.jp/ait/articles/1603/31/news026.html) (4)proxy関係(大学内の環境下では必要):

「Proxy環境下でのGit for Windows設定」

(https://qiita.com/yujimny/items/08f02d9dfb670f0e9ddf) 「[Node.js] npm の proxy と registry 設定」

(https://qiita.com/LightSpeedC/items/b273735e909bd381bcf1) (5)Bluetoothドライバの書き換え(Zadig):

(4)

(1.2)動作確認

大学で用いるタブレットPCでは、ユーザ名“drone”で

サインインしてください。ユーザ名“岐阜経済大学”とな

っていた場合はサインアウトして、 “drone”に切り替え

てください。

次のディレクトリ(フォルダ)にてプログラムを実行しま

す。

~/drone/play_with_parrot_mambo/

(”~”は、ユーザのホームディレクトリ)

前記(1)のwebページ(

「 Parrot Mambo Missionを動かす(

github)」

)に記載のプログラムを、次のように起動出来る

状態にします(ドローンの名前の設定はページの記述

に従ってください。 )。

(5)

(1.3)作業フォルダ

今後、作成したプログラムは、タブレットPC上の次のフ

ォルダ(ディレクトリ)に置くことにします。

[コンピュータ]-[ユーザー]-[drone]-[drone]-[play_with_parrot_mambo]-[drone_programming]

(~/drone/play_with_parrot_mambo/drone_programming/)

情報実習室パソコンからのコピーは、次のフォルダ経

由で行います(

赤字

の部分は、年度とゼミに合わせます

)。

[public]-[ido]-[student]-[

2018se2

]-[グループ名]

最初に、[ドキュメント]配下の“ファイルサーバ認証”を起動し

て、ネットワークドライブを割り当てておいてください。

(6)

(1.4)コマンド入力(Git Bash)

コマンドは、次のように起動した

Git Bash上で行います。

[スタート]-[git]-[Git Bash]

起動後、“cd”コマンドを次のように入力して、作業ディ

レクトリに移動します(

linuxコマンドについては別途説明)。

(7)

(2.1)飛行プランのプログラミング

元ネタにあるプログラム“testFlight.js”を書き換

えた次のプログラムを参考にして、自分で考えた飛行

プランによりドローンを飛ばしてください。ファイルは、

ネットワークドライブにあります。

dronejs.connect(DRONE_NAME) .then(() => dronejs.flatTrim()) // 飛ぶ前に一度平坦な状態を覚える .then(() => dronejs.takeOff()) // 離陸

.then(() => {console.log(DRONE_NAME+' take off.');}) .then(() => dronejs.flatTrim())

.then(() => dronejs.turnRight(50, 20))

.then(() => {console.log(DRONE_NAME+' turnRight.');}) .then(() => dronejs.flatTrim())

.then(() => dronejs.land()) // 着陸する

.then(() => {console.log(DRONE_NAME+' land.');})

.then(() => dronejs.disconnect()) // 接続解除 .then(() => {

// 正常終了した場合、プログラムを終了する

(8)

(2.2)プログラミングに関して

ch21_test_drive.jsのプログラムの内容は、スライド「JS

覚書」中の次の点に注意して理解してください。

(12)関数

(8)分岐、if文

(3)変数

以降でも、このスライドの参照が必要ですが、そのたびに上

記のように参照することはしません。

ch21_test_drive.jsのプログラムの次の内容については

、当面、“そのように書くもの”と理解しておいてください

。別の機会に説明します。

アロー関数(“()=>”)

thenメソッド

(9)

(2.3)課題

ch21_test_drive.jsのプログラムを書き換えて、

自分が考えた飛行プランでドローンを飛ばしてください

(10)

(3.1)ファイルからの読み取り

ブラウザ上で動作するJavaScriptでは、そのPCのファ

イルを読むことは出来ません。次のプログラムは、

node.jsでのみ動作します。

var fs = require('fs’); // ファイル操作モジュール fs.readFile('ch31_test.txt’, // 読み出すファイルのパス名 'utf8’, // ファイルの文字コード function(err,data){ // 読出後に実行される処理(コールバック関数) // ファイルの内容の出力 console.log(data); } // 関数の終わり ); abcd efg hijklmn

<ch31_test.txt>

C:¥> node ch31_read_file.js abcd efg hijklmn

<実行結果>

<ch31_read_file.js>

①起動

②読取

③出力

(11)

(3.2)1行ごとの処理

本スライドでは大きなファイルは扱いませんので、ファ

イルごと読み込んだ文字列を1行ごとの配列に格納し

て処理します。

function (err, data) { // 読み出して実行される処理(関数) // ファイル内容の文字列を改行コードで配列に分割 var lines=data.split(/¥r¥n|¥r|¥n/); for(var i=0;i<lines.length;i++){// 配列の要素(=各行)ごとに繰り返し console.log((i+1)+':'+lines[i]); // 行番号を付加して行を出力 } } // 関数の終わり C:¥> node ch32_each_line.js 1:abcd 2:efg 3:hijklmn

<実行結果>

<ch32_each_line.js((3.1)のコールバック関数部分のみ)>

“abcd efg

hijklmn” “abcd¥r¥nefg¥r¥nhijklmn” [“abcd”,

“efg”,

“hijklmn”]

(12)

(3.3)練習問題

次のようなブラウザ上で動作するJavaScriptプログラ

ムを作成してください。

下の図の右のようなファイルから読み込んだつもりで、左

のような文字列を宣言します。

ブラウザ上に下のようなグラフを出力します。

項目の数は3つ(A、B、C)の固定としてOKです。

形式が間違っているファイルに対する考慮も無用です。

A

12

B

28

C

20

var str=“A

¥n¥r

12

¥n¥r

n¥r

28

¥n¥r

C

¥n¥r

20”;

(13)

(3.4.1)ファイルを用いた飛行プランー1ー

次の2つのファイルを参考にして、ファイルに記述した

飛行プランによりドローンを飛ばしてください。ファイル

は、ネットワークドライブにあります。

ch34_planed_flight.js

ch34_flight_plan.txt

ひとつめのファイルがプログラムであり、次スライド以

降に示します。次スライドに示すプログラムは、

ch21_test_drive.jsの74行目あたりまで同じで、その後

の部分を示しています。

ふたつめのファイルが飛行プランを記したファイルで

す。

(14)

(3.4.2)ファイルを用いた飛行プランー2ー

var flight_plan=new Array();

function loadFlightPlan(fileName){

var fs = require('fs'); //ファイル操作モジュール fs.readFile(fileName, 'utf8’,

function (err, data) { // 読み出して実行される処理(関数)

var lines=data.split(/¥r¥n|¥r|¥n/); //文字列を改行コードで配列に分割 for(var i=0;i<lines.length;i++){ //配列の要素(各行)ごとに繰り返し

var line=lines[i].replace(/¥s+/g,‘’); //空白除去してlineに代入 if(line==‘’||line.charAt(0)==‘#’)continue; //空行等は読み飛ばし var action; if(line.indexOf(':')>0){ var items=line.split(':'); // 1行を”:”(カンマ)で区切る。 // オブジェクト(連想配列)を作成。 action={method:items[0],params:items[1].split(',')}; }else{ action={method:line}; } flight_plan.push(action); } } // 関数の終わり ); } <次のスライドに続く>

<ch34_planed_flight.js(74行目以降)>

(15)

(3.4.3)ファイルを用いた飛行プランー3ー

<前のスライドからの続き> function schedule(){ var action=flight_plan.shift(); if(action==null){ console.log("#P#schedule.disconnect"); dronejs.disconnect() .then(() => {process.stdin.pause();console.log("end");process.exit();})

.catch((e) => {console.log('e=' + e);process.stdin.pause();process.exit();}); return;

}

console.log("#P#schedule.action.method="+action.method); if(action.method=='flatTrim'){

dronejs.flatTrim().then(()=>schedule())

.catch((e) => {console.log('e=' + e);process.stdin.pause();process.exit();}); }else if(action.method=='takeOff'){

dronejs.takeOff().then(()=>schedule())

.catch((e) => {console.log('e=' + e);process.stdin.pause();process.exit();}); }else if(action.method=='land'){

dronejs.land().then(()=>schedule())

.catch((e) => {console.log('e=' + e);process.stdin.pause();process.exit();}); }else if(action.method=='turnRight'){

dronejs.turnRight(action.params[0],action.params[1]).then(()=>schedule()) .catch((e) => {console.log('e=' + e);process.stdin.pause();process.exit();}); }else{

console.log("#E#schedule. illegal method. action.method="+action.method); }

}

(16)

(3.4.4)ファイルを用いた飛行プランー4ー

function main() {

// 飛行プランの読み取り

loadFlightPlan('ch34_flight_plan.txt’); console.log('start’)

const navDataStream = dronejs.getNavDataStream(); navDataStream.subscribe((data) => { console.log(data); }, e => debug(e), () => debug('complete') ); dronejs.connect(DRONE_NAME) .then(()=>schedule()) .catch((e) => { // 以上終了した場合、エラーの内容をコンソールに表示し、終了する console.log('エラー: ' + e); process.stdin.pause(); process.exit(); }); } main(); // 関数を実行します

(17)

(3.4.5)ファイルを用いた飛行プランー5ー

次のような飛行プランのテキストファイルを読み込み

ますが、次の点に注意してください。

行の先頭に“#”(シャープ)を書くと、その行はコメント行にな

ります。行の途中から“#”(シャープ)を書くと、それ以降がコ

メントと見なされます。

空白行は読み飛ばします。

flatTrim takeoff flatTrim turnRight:50, 20 flatTrim land

<ch34_flight_plan.txt>

(18)

(3.5)課題

“ch34_planed_flight.js”のプログラムを書き

換えて、すべてのコマンドが飛行プランで実行できるよ

うにしてください。

ファイル名は、“ch35_planed_flight.js”としま

す。

(19)

(4.1)コマンドライン引数

スライド(3.1)のプログラムを書き換えて、読み出すファ

イル名を指定出来るようにします。

var fs = require('fs’); // ファイル操作モジュール

var file_name = process.argv[2];

fs.readFile(file_name, // 読み出すファイルのパス名 'utf8’, // ファイルの文字コード function(err,data){ // 読出後に実行される処理(コールバック関数) // ファイルの内容の出力 console.log(data); } // 関数の終わり );

<ch41_read_file.js>

opqr stuvwxyz

<ch41_test.txt>

C:¥> node ch31_read_file.js ch41_test.txt

opqr

stuvwxyz

C:¥> node ch31_read_file ch31_test.txt abcd efg hijklmn

<実行結果>

abcd efg hijklmn

<ch31_test.txt>

①コマンドライン引数

②ファイル名

③出力

(20)

(4.2)process.argv

process.argvの配列には、インデックス“2”から指定し

たコマンドライン引数が入ることに注意してください。

C:¥> node ch42_arg_test.js

aaa bbb ccc ddd

<ch42_arg_test.js>

index 0 : C:¥...¥node.exe

index 1 : C:¥ ch42_arg_test.js

index 2 : aaa

index 3 : bbb

index 4 : ccc

index 5 : ddd

console.log('index 0 : ‘+ process.argv[0]); console.log('index 1 : ‘+ process.argv[1]); console.log('index 2 : ‘+ process.argv[2]); console.log('index 3 : ‘+ process.argv[3]); console.log('index 4 : ‘+ process.argv[4]); console.log('index 5 : ‘+ process.argv[5]);

node.jsの実行ファイル

実行された

プログラム

ファイル

コマンド

ライン引数

(21)

(4.3)飛行プランの引数での指定

スライド(3.5) の“ch35_planed_flight.js”を変

更して、飛行プランのファイルをコマンドラインの引数と

して指定出来るようにします。

ファイル名は“ch43_planed_flight.js”とし、次のよう

に実行出来るようにします。

変更は次の2か所で行います。

C:¥> node ch43_planed_flight.js ch34_flight_plan.txt

(旧) main(); // 関数を実行します

(新) main(process.argv[2]); // 関数を実行します (新)function main(file_name) {

// 飛行プランの読み取り

loadFlightPlan(file_name); (旧)function main() {

// 飛行プランの読み取り

(22)

(4.4)Grabber

元ネタにあるプログラム“testGrab.js”では、次の

ようにGrabberの操作を記述しています。

スライド(4.3) の“ch43_planed_flight.js”にて、

次の飛行プランを指定すると、同じことが出来ます。

(disconnectは、 “ch43_planed_flight.js”にて、プラン

の終了後に必ず実行するようにしています。)

dronejs.connect(DRONE_NAME)

.then(() => dronejs.grabClose()) // 腕を閉じる

.then(() => dronejs.grabOpen()) // 腕を開く

.then(() => dronejs.disconnect()) // 接続解除

.then(() => {

<testGrab.js>

grabClose

# 腕を閉じる

grabOpen

# 腕を開く

<ch44_plan_grab.txt>

(23)

(4.5)タイミング

利用させて頂いているネタ元の環境では、ドローンの

着陸後にすぐ離陸することは難しいようです。

少しタイミングを取るためのプランの記述と、これを実

行するプログラムの機能とを追加します。

}else if(action.method=='checkAllStates'){ dronejs.checkAllStates().then(()=>schedule()) .catch((e) => {console.log('e=‘ +…… }else if(action.method=='timing'){ setTimeout(schedule,action.params[0]); }else{

console.log("#E#schedule. illegal method.……

<ch45_operation.js(181行あたり)>

flatTrim takeOff flatTrim forward:10,10 land timing:2000 flatTrim takeOff flatTrim backward:10,10 land

<ch45_plan_timing.txt>

追加

2000msだけ

タイミングを取る

(24)

(4.6)課題

“ch45_operation.js”を用いて次のような動作を

行う飛行プランを作成してください。

物(丸めた紙)をつかむ。

離陸する。

少し前進する。

着陸する。

物を離す。

(ここでタイミングを取る)

離陸、後進、着陸して、元の場所に戻る。

ファイル名は、“ch46_carry_obj.txt”とします。

(25)

(5)機能追加

次の機能追加を行います。

ドローン名をファイルから読み込むことにする。

プランの実行前にプランの記述に誤りが無いかをチェックし、

誤りが見つかった場合は実行を行わない。

移動における強さの上限を設定し、プランにおいてそれを超

える値が設定されていても、制限内の強さで移動を行う。

(室内での飛行を想定しているので、安全対策として行う。)

(26)

(5.1.1)ドローン名のファイルへの記述

次のように飛行プランファイル内にドローン名を記述

することにします。

:droneName:

Mambo_742xxx

:plan:

flatTrim

takeOff

# 離陸する。

flatTrim

forward:10,10

# 少し前進する。

land

# 着陸する。

<ch50_plan_timing.txt>

ドローン名

この記述の後が

飛行プラン

(27)

(5.1.2)プログラムでのドローン名の読み取り

飛行プランを読み取っている場合を表す変数を導入し

ます。

var on_reading_plan=false; // 飛行プランの読み取り中の時にtrue

for(var i=0;i<lines.length;i++){ // 配列の要素(=各行)ごとに繰り返し (中略) if(on_reading_plan){ // 飛行プランを読取中の場合 // 従来とおりの飛行プランの読み取り (中略) }else{ // 飛行プラン以外(ドローン名など)を読取 (中略) if(line.indexOf(‘:droneName:’)==0){ // ドローン名の行 // ドローン名の取得 DRONE_NAME=line.substring(‘:dronName:’.length+1); (中略) }else if(line.indexOf(':plan:')==0){ on_reading_plan=true; // 飛行プラン読取中に移行 (中略) } }

<ch50_operation.js>

(28)

(5.2.1)パラメータチェック用のテーブル

次のようなテーブルでパラメータをチェックします。

const PARAMS_C={ 'takeOff' :[],'flatTrim':[],'land':[], 'forward' :[{min:0,max:20},{min:0,max:50}], 'backward' :[{min:0,max:20},{min:0,max:50}], 'right' :[{min:0,max:20},{min:0,max:50}], 'left' :[{min:0,max:20},{min:0,max:50}], 'up' :[{min:0,max:20},{min:0,max:50}], 'down' :[{min:0,max:20},{min:0,max:50}], 'turnRight':[{min:0,max:20},{min:0,max:50}], 'turnLeft' :[{min:0,max:20},{min:0,max:50}], 'grabClose':[],grabOpen:[], 'frontFlip':[],'backFlip':[],'rightFlip':[],'leftFlip':[], 'takePicture':[],'listAllPictures':[],'downloadPicture':[], 'deletePicture':[], 'enableLogging':[],'checkAllStates':[], 'timing':[{min:0,max:10000000}]};

<ch50_operation.js>

これらのコマンド

には、パラメータ

が無い

これらのコマンド

には、パラメータ

が2つあり、

値には下限と上

限がある

(29)

(5.2.2)パラメータチェックのプログラム

ch50_operation.js(抜粋)

if(PARAMS_C[action.method]==null){ // メソッドが飛行プランチェック用テーブルに無い場合 return; // 処理を中止する -> 飛行プランの読み取りは中断。 } if(items.length>1){ //パラメータがある場合 var params=items[1].split(‘,‘); // カンマで区切ってパラメータ毎に分ける if(params.length>0 || PARAMS_C[action.method].length>0){ if(params.length!=PARAMS_C[action.method].length){ // パラメータの数が一致しない場合 return; // 処理を中止する -> 飛行プランの読み取りは中断。 } for(var i_para=0;i_para<params.length;i_para++){ // 各パラメータ if(params[i_para]>PARAMS_C[action.method][i_para].max){ // 上限より大きい場合、上限の値に設定 params[i_para]=PARAMS_C[action.method][i_para].max }else if(params[i_para]<PARAMS_C[action.method][i_para].min){ // 下限より小さい場合、下限の値に設定 params[i_para]=PARAMS_C[action.method][i_para].min; } } }

(30)

(6)カメラ

現状、ドローン(Parrot社Mambo)からPCへの画像取

得がうまく行かないため、カメラに利用は当面見送りま

す(2018.09.25)。

(参考URL:写真取得不可が未解決な現状を示す)

https://forum.tynker.com/t/parrot-mambo-fetching-pictures/361/8

(31)

(7)webサーバ

カメラの利用を当面見送ることから、代替の題材とし

てwebサーバを利用したdroneの操作を実施します。

ドローンを制御するプログラムをwebサーバと連携さ

せ、webページからドローンを操作します。この枠組み

の中で、ゲームを行うプログラムの開発を行います。

<ノートPC>

<ドローン>

(Mambo)

web

サーバ

ドローン

制御

連携

操作

対戦ゲーム

<端末>

(32)

(7.1)webサーバの環境設定等

次のサイトを参考にしています。

(1)webサーバ関連:「node.js 超入門①~④」

https://qiita.com/ritukiii/items/7f28554369d63eb373c3

・同じ内容の次の動画を見て勉強します。

https://dotinstall.com/lessons/basic_nodejs

webサーバとは直接関係しませんが、次のサイトも参

考にします。

(2)node.js関連:「Node.js 実践講座 〜基礎編〜」

https://qiita.com/loremipsumjp/items/3d32a44fe80c9a2febbe

(3)Visual Studio Code関連:「Visual Studio Codeによる

Node.jsのデバッグ」

(33)

(7.2)端末での操作画面

ログイン画面

次のURLにアクセスしてログインします。

http://172.17.xxx.xxx:3000/entry

ドローン操作画面

ログインすると操作画面が現れます。

コマンドを入力して、[登録]をクリック

します。実行できるコマンドは次の

とおりです。

t(takeOff)、l(land)、tl(trunLeft)、

tr(turnRight)、f(forward)、e(終了)

操作画面や実行出来るコマンドを、学生の皆さんが改良して

いきます。

(34)

(7.3)操作のルール

ドローンを操作するユーザは、何人でもログイン出来

ます。

ユーザはコマンドを続けて登録出来ますが、一つのコ

マンドが終了するまで次のコマンドは実行されません。

コマンドを登録した後の削除は出来ません(出来るよう

に改良することは可能です)。

複数ユーザがコマンドを登録したとき:

優先権のあるユーザのコマンドが実行され、実行された後、

優先件は次のユーザに移ります。

優先権のあるユーザのコマンド登録が無かった場合:

他のユーザからのにコマンド登録があればそれが実行され、

優先権はスキップされて他のユーザに渡ります。

(35)

(7.4)ファイル構成

作成したプログラムは、ノートPC上の次のフォルダ(デ

ィレクトリ)に置くことにします。

[コンピュータ]-[ユーザー]-[drone]-[drone]-[play_with_parrot_mambo]-[drone2018]

(~/drone/play_with_parrot_mambo/drone2018/)

ファイル一覧

JavaScriptプログラム

main.js、jr_server.js、drone_operation.js

設定ファイル

jr_config.js、command2actionLine.txt

webページ(のひな形)

dr_entry.ejs、dr_cont.ejs

起動の仕方

C:¥> node main.js

(36)

(7.5)ファイルの役割

main.js

・起動

・サーバと

ドローン制御

の連携

dr_config.js

・パラメータ保持

drone_operation.js

・ドローンの制御

command2actionLine.txt

・コマンドからアクション

への変換表

dr_server.js

・webサーバ

・ユーザの管理

dr_entry.ejs

・ログイン画面

dr_cont.ejs

・操作画面

起動

起動

起動

コマンド取得

アクション取得

参照

関連したドキュメント

⑴ 次のうち十分な管理が困難だと感じるものは ありますか。 (複数回答可) 特になし 87件、その他 2件(詳細は後述) 、

イヌワシは晩秋に繁殖行動を開始します。オスとメスが一緒に飛んだり、オス が波状飛行を繰り返します。その後、12月から

このように雪形の名称には特徴がありますが、その形や大きさは同じ名前で

被保険者証等の記号及び番号を記載すること。 なお、記号と番号の間にスペース「・」又は「-」を挿入すること。

備考 1.「処方」欄には、薬名、分量、用法及び用量を記載すること。

高さについてお伺いしたいのですけれども、4 ページ、5 ページ、6 ページのあたりの記 述ですが、まず 4 ページ、5

この届出者欄には、住所及び氏名を記載の上、押印又は署名のいずれかを選択す

今までの少年院に関する筆者の記述はその信瀝性が一気に低下するかもしれ