この時点で、ドローンをコントロールしているスクリプトは以下のようなものです。もっと、細かい解説が必要ですが、その時間が取れないので、感じだけを味わってください。
------------------------ 以下 ----------------
############
# ユーザースクリプト
# 2021年8月8日 ver.26
# 2021年8月5日 ver.22 単位を全てメートルに変更
# 2021年7月18日 ver.0
############
@grammar
# 音声認識文法
# AmenboScriptと矛盾しない形で入れておく
0: Object + Object + Verb
0: Object + Object + Unit
0: Object + Object + Question
0: Subject + Verb
0: Verb + Negation
0: Subject + Adjective
1: Object + Verb
1: Verb + End
1: Object + End
1: Adjective + End
@concept
# 音声に含まれる概念
Subject : [僕,私]
Object : 顔,口,テスト,角度,周り,距離
Adjective : 嫌い,好き,終わり
Verb : [始め,一,はじめ],キス,見つけ,着陸,見なさ,回転,回り
Unit : メートル
Question : どれ,教え
End : [よ,ます,ましょう,なさい],か,です
Negation : 止め,やめ
@command
# 音声コマンド
始めるよ : ^takeoff() ^sleep(2000) はい、アメンボです。よろしくお願いします ^sleep(1000)
終わります : おわります ^landing()
着陸しなさい : 着陸します ^landing()
僕が好きですか : ^sleep(1000) はい、好きです ^yes()
僕が嫌いですか : ^sleep(1000) いいえ、好きです ^no()
顔を見つけなさい : ^sleep(1000) はい、顔を探します &searchface()
キスをしましょう : ^sleep(1000) はい、キスします &kiss()
テストをします : テストですね ^getaltitude()
口を見なさい : 口を見ます &shapeLip()
角度を見なさい : 角度を見ます &faceAngle()
回転しなさい : 回転します ^hloop(0.5,1.0)
回転止めなさい : 回転やめます ^stophloop()
# 関数やマクロ内の変数は全てグローバル変数
# $distには、&approachefaceで近づいた距離が入っているはず
顔の周りを回りなさい : 顔の周りを回ります &noseincircle($dist)
# $0,$1....の変数は同時にグローバル変数になる
# 関数の引数にはグローバル変数しか使えないので
顔までの距離を $0 メートルにしなさい : 顔まで $0 メートルにします &approacheface($0)
顔までの距離はどれくらいですか : 顔までの距離は $dist メートルです
@macro
# マクロの引数は、$macroarg_0, $macroarg_1,・・・の変数に入っている
# ノーズインサークルの自動実行
# 人の顔が真ん中にあることを前提にする
# 事前に、回転する半径を引数に入れておく
&noseincircle
let $radius = $macroarg_0
^print("マクロ: noseincircle の開始")
^speek("顔を中心に旋回をします")
^print("顔を中心に旋回をします。半径は",$radius,"メートルです")
^hloop($radius,1.0)
^print("マクロ: noseincircle を終了")
^speek("旋回を終えました")
&&
# 顔を画面の中心にしながら指定した距離まで顔に近づく
# 事前に、変数 $distface に近づく距離(メートル単位)を指定しておく
&approacheface
let $distface = $macroarg_0
^print("マクロ: approacheface の開始")
# 顔を真ん中にするのに成功していることが前提
# 顔を真ん中にしないと人との距離が図れない
^speek("顔との距離を調整します")
^print("顔との距離を",$distface,"メートルに調整します")
let $maxtry = 10
for $i=0 ; $i < $maxtry ;$i += 1 {
let $dist = ^checkface()
# 目標距離との差が0.1メートル以下になるまで 最大10回
if ^abs($dist - $distface) < 0.1 && $dist > 0.0 {
# $dist が -1 は、エラー
break
}
# 接近を刻む距離
let $unitdist = 0.1
if $dist > 1.0 {
## 1メートル以上離れていたら25センチ移動する
$unitdist = 0.25
}
let $diff = $dist - $distface
if $diff > 0.0 {
^speek($unitdist,"メートル近づきます")
^print("No.",$i," 距離差:",$diff," => ",$unitdist,"メートル接近")
^forward($unitdist)
## 距離の改訂 moveForFaceCenter の引数
let $reviseddist = $dist - $unitdist
}else{
^speek($unitdist,"メートル離れます")
^print("No.",$i," 距離差:",$diff," => ",$unitdist,"メートル離脱")
^backward($unitdist)
let $reviseddist = $dist + $unitdist
}
# 次のコマンドまで少し時間を空ける
^sleep(1000)
# ここで、再度、顔が正面になるように調整する
# $unitdist m近づいたので、その分差し引く
# 3回に1回は、顔の中心に、調整する
if $i % 3 == 1 {
^speek("顔が中心になるよう再設定します")
^print("顔が中心になるよう再設定します")
^moveForFaceCenter($reviseddist)
}
}
if ^abs($dist - $distface) < 0.1 && $dist > 0.0 {
^speek("距離の調整に成功しました")
^print("距離の調整に成功しました")
}else{
^speek("距離の調整に失敗しました")
^print("距離の調整に失敗しました")
}
&&
# 顔の角度で、機体を水平、垂直に動かす
&faceAngle
^print("マクロ: faceAngle の開始")
# 基本的移動距離を定める
let $movedist = 0.2
^print("教授の顔の傾きを観察します")
^startFaceStatus()
let $maxtry = 15 # この回数だけ反応します
for $i=0 ; $i < $maxtry ; $i += 1 {
if $i % 4 == 3 {
let $dist = ^checkface()
if $dist < 0 {
# 顔を見失っています
^print("顔を見失いました")
^sleep(1000)
}
# 4回に1回は顔中心の補正
#^speek("顔が中心になるよう再設定します")
^print("顔が中心になるよう再設定します")
^moveForFaceCenter($dist)
^sleep(500)
}else{
# 中心補正しない場合
# 1秒待機。これを怠ると、瞬間的に終わる可能性がある
^sleep(1000)
}
let $hdist = ^getHorizontalFaceAngle()
if $hdist > 9000 { # 距離は指数で見ている、メートルでもセンチでもない
^print("顔の水平傾斜が取れません ",$i,"回")
#^speek("顔の水平傾斜が取れません")
#continue # これがあると縦を見ない
}
if $hdist < 9000 && $hdist > 0.55 {
#^speek("右に動きます")
^print("右に",$movedist,"センチ動きます 回数 ",$i)
^right($movedist)
#continue # これがあると縦を見ない
}
if $hdist < 0.45 {
#^speek("左に動きます")
^print("左に",$movedist,"センチ動きます 回数 ",$i)
^left($movedist)
#continue # これがあると縦を見ない
}
let $vdist = ^getVerticalFaceAngle()
if $vdist > 9000 {
^print("顔の垂直傾斜が取れません ",$i,"回")
#^speek("顔の垂直傾斜が取れません")
continue
}
if $vdist > 0.6 {
#^speek("上に動きます")
^print("上に",$movedist,"センチ動きます 回数 ",$i)
^upward($movedist)
continue
}
if $vdist < 0.45 {
#^speek("下に動きます")
^print("下に",$movedist,"センチ動きます 回数 ",$i)
^downward($movedist)
continue
}
#^speek("顔の角度は通常です")
^print("顔の角度は通常です 回数 ",$i)
}
^speek("顔の角度の観察を停止します")
^print("顔の角度の観察を停止します")
^stopFaceStatus()
&&
# 口の形で前後に動かすマクロ
&shapeLip
^print("マクロ: shapeLip の開始")
# 基本的移動距離を定める
let $movedist = 0.2
^print("教授の口を観察します")
^startFaceStatus()
let $maxtry = 15 # この回数だけ口に反応します
for $i=0 ; $i < $maxtry ; $i += 1 {
if $i % 4 == 3 {
let $dist = ^checkface()
if $dist < 0 {
# 顔を見失っています
^print("顔を見失いました")
^sleep(1000)
}
# 4回に1回は顔中心の補正
#^speek("顔が中心になるよう再設定します")
^print("顔が中心になるよう再設定します")
^moveForFaceCenter($dist)
^sleep(500)
}else{
# 中心補正しない場合
# 1秒待機。これを怠ると、瞬間的に終わる可能性がある
^sleep(1000)
}
let $ldist = ^getLipDistance()
if $ldist < 0 {
^print("口の形が取れません ",$i,"回")
#^speek("口の形が取れません")
continue
}
if $ldist < 0.1 { # 距離は指数で見ている、メートルでもセンチでもない
#^speek("近づきます")
^print("キス型なので",$movedist,"センチ近づきます 回数 ",$i)
# $movedist m近づく
^forward($movedist)
# 次のコマンドまで少し時間を空ける
continue
}
if $ldist > 0.15 {
#^speek("離れます")
^print("口を開けているので",$movedist,"センチ離れます 回数 ",$i)
# $movedist cm離れる
^backward($movedist)
# 次のコマンドまで少し時間を空ける
continue
}
#^speek("口の形は通常です")
^print("口の形は通常です 回数 ",$i)
}
^speek("口の観察を停止します")
^print("口の観察を停止します")
^stopFaceStatus()
&&
# 顔を見つけることに限定したマクロ
&searchface
^print("マクロ: searchface の開始")
^print("身近な顔を探します")
# ドローンの高度を160センチの、人の標準的身長に設定する
^print("ドローンの高度を160センチにします。")
^altitude(1.6)
# FPVに顔がないかチェックする
# 30度刻みで回転する
let $flag = 0
for $i=0 ; $i < 12 ;$i += 1 {
^print("角度を 30度 左回転させます")
#^print("角度を " $i "度 右回転させます")
# $distは、少数以下が丸められている倍精度数
let $dist = ^checkface()
if $dist > 0.1 {
^speek("顔を見つけました")
^print("顔を見つけました。距離は ",$dist,"cm です")
$flag = 1
break
}
^turnleft(30)
#^rightangle($i)
}
if $flag <= 0.1 {
^speek("顔が見つかりませんでした")
^print("顔が見つかりませんでした")
}else{
^print("顔は見つかりました")
let $maxtry = 15
# 顔が見つかった場合の処理
let $count = $maxtry # $maxtry 回だけ試みる
^print("顔が真ん中になるように姿勢を制御します")
# 最大許容誤差の設定 pxel単位
let $maxdiffpixel = 70
# 修正ループの開始
while ^checkFaceCenter($maxdiffpixel) < 0.1 {
# まず、顔を真ん中にする
^print("顔を正面にします Try No. ",$maxtry-$count)
^moveForFaceCenter($dist)
# 次のコマンドまで少し時間を空ける
^sleep(500)
$count -= 1
if $count < 0.1 {
break
}
}
^print("顔を正面にする試みは終わりました 回数 ",$maxtry-$count)
if $count > 0.1 {
# 顔を真ん中にするのに成功した場合
# 顔を真ん中にしないと人との距離が図れない
^speek("顔を真ん中にしました")
^print("顔を真ん中にすることに成功しました")
}else{
^speek("顔を真ん中にできませんでした")
^print("顔を真ん中にできませんでした")
}
}
&&
# 一番近くの人とキスするマクロ
&kiss
^print("マクロ: kiss の開始")
^print("身近な顔を探します")
# ドローンの高度を160センチの、人の標準的身長に設定する
^print("ドローンの高度を160センチにします。")
^altitude(1.6)
# FPVに顔がないかチェックする
# 30度刻みで回転する
let $flag = 0
for $i=0 ; $i < 12 ;$i += 1 {
^print("角度を 30度 左回転させます")
#^print("角度を " $i "度 右回転させます")
# $distは、少数以下が丸められている倍精度数
let $dist = ^checkface()
if $dist > 0.1 {
^speek("顔を見つけました")
^print("顔を見つけました。距離は ",$dist,"cm です")
$flag = 1
break
}
^turnleft(30)
#^rightangle($i)
}
if $flag <= 0.1 {
^speek("顔が見つかりませんでした")
^print("顔が見つかりませんでした")
}else{
^print("顔は見つかりました")
let $maxtry = 15
# 顔が見つかった場合の処理
let $count = $maxtry # $maxtry 回だけ試みる
^print("顔が真ん中になるように姿勢を制御します")
# 45ピクセル以内にしている
while ^checkFaceCenter(45.0) < 0.1 {
# まず、顔を真ん中にする
^print("顔を正面にします Try No. ",$maxtry-$count)
^moveForFaceCenter($dist)
# 次のコマンドまで少し時間を空ける
^sleep(500)
$count -= 1
if $count < 0.1 {
break
}
}
^print("顔を正面にする試みは終わりました 回数 ",$maxtry-$count)
if $count > 0.1 {
# 顔を真ん中にするのに成功した場合
# 顔を真ん中にしないと人との距離が図れない
^speek("顔を真ん中にしました もっと近づきます")
^print("顔を真ん中にすることに成功しました。顔に近づいていきます")
for $i=0 ; $i < $maxtry ;$i += 1 {
let $dist = ^checkface()
# 25センチ以下になるまで近づく 最大10回
if $dist < 0.25 && $dist > 0.0 {
# $dist が -1 は、エラー
# 0.0 < $dist < 35.0 を最接近とする
break
}
^speek("10センチ近づきます")
^print("10センチ近づきます 回数 ",$maxtry-$count)
# 10cmずつ近づく
^forward(0.1)
# 次のコマンドまで少し時間を空ける
^sleep(1000)
# ここで、再度、顔が正面になるように調整する
# 10cm近づいたので、その分差し引く
# 3回に1回は、顔の中心に、調整する
if $i % 3 == 1 {
^speek("顔が中心になるよう再設定します")
^print("顔が中心になるよう再設定します")
^moveForFaceCenter($dist-0.25)
}
}
if $dist < 0.25 && $dist > 0.0 {
^speek("もう、キスできます")
^print("もう、キスできます")
}else{
^speek("近づくことができませんでした")
^print("近づくことができませんでした")
}
}else{
^speek("顔を真ん中にできませんでした")
^print("顔を真ん中にできませんでした")
}
}
&&
### Script End ###