~ 芸術衛星特集 ~
今回は2月28日に打ち上げに成功した芸術衛星(げいじゅつえいせい) ARTSAT(アートサット) INVADER(インベーダー)特集です。
無線ロボットのMI100を、宇宙で地球の周りを回っている芸術衛星のINVADERと連動させてみましょう。
芸術衛星INVADER(インベーダー)のくわしい説明はここにあります。
今までのプログラミング講座でまだやっていない見なれない命令(めいれい)がでてきます。でも、今回は、おなじみのrobo.から始まるMI100を動かす命令や、今まで講座でやった命令だけに注目するようにしましょう。見なれない命令については後でかくにんしましょうね。
プログラムを動かしたときのMI100の動画をYouTubeで公開しています。
どんなプログラム?
プログラムされたINVADERを見る場所、観測点(かんそくてん)を調べます。
近所の有名な建物や駅名などを選んで観測点をプログラムします。もちろん実際にその場所に行く必要はありません。プログラムはそこからINVADERを見ているように動きます。例では「東京都現代美術館」を使います。注意)コンピューターに住所や電話番号をいれないようにしましょう。コンピューターに住所や名前、電話番号をむやみに入れないくせを付けておきましょうね。
INVADERの居場所を調べます。
INVADERが地球のどこの真上にいるのかを教えてくれる、ウェブ・アプリケーション・インタフェースとよばれるプログラムのための道具を使って、INVADERの居場所を調べます。INVADERのいる、緯度(いど)と経度(けいど)と呼ばれる、地球の場所をあらわす数(角度)を教えてくれます。INVADERの真下に住所や地名があればputsで画面に出します。
距離を計算します。
「東京都現代美術館」とINVADERとの距離(きょり)を計算します。
方角を調べます。
「東京都現代美術館」からみて、INVADERがどの方角(東西南北)にいるのかを調べます。
MI100を動かします。
距離や方角をモールス信号音(ピピピピー)で話します。
INVADERが近くにいると(真上など)、MI100がダンスします。近いほど激しくダンスします。
INVADERが近いほどフルカラーLEDが点滅する回数が増します。
INVADERが近づいてくるとMI100が少しずつ前進します。近くにいるほど移動速度が速くなります。
INVADERが遠のいていくとMI100が少しずつ後進します。近くにいるほど移動速度が速くなります。
INVADERの方向でフルカラーLEDの色が変わります。次のような色になります。
東:紫 西:黄緑 南:赤 北:青緑
INVADERの真下(ました)に地名や住所があるときは、MI100が”HELLO WORLD!”とモールス信号音で話します。
プログラム
今回は下のプログラムをKidsRubyのエディターに入れて動かしてみましょう。
プログラムを動かす前の準備
動かす前に、距離の計算などを助けてくれる、あらかじめ用意されている命令の集まり(ライブラリ)をパソコンにインストールします。この手順は一度だけやります。
コマンドプロンプト (=>Windowsでコマンドプロンプトを出すには) で次の gem (ジェム) コマンドを実行します。
C:>gem update mi100<Enter (エンター)>
C:>gem install geocoder<Enter (エンター)>
C:>gem install color<Enter (エンター)>
プログラミング
プログラムの下の部分だけを変えます。 LOCAL_POINT = "東京都現代美術館" COM_PORT = "COM5"
LOCAL_POINTの” “で囲まれたところに、”東京駅” など近所の有名な建物の名前を入れます。
COM_PORTの” “で囲まれたCOM5の部分は、今までの講座と同じように、MI100の接続の手順で調べた名前に変えましょう。
ノート
ウェブ・アプリケーション・インタフェースでは約6分ごとに、INVADERの居場所を教えてくれます。INVADERは6分で2500kmくらい移動します。北海道の端から九州の端の長さがおよそ2500kmとも言われていますので、たったの6分で北海道の端から九州の端まで移動してしまうことになります。MI100のダンスを見れた人は本当にラッキーですね。
注意
例では、INVADERの居場所を調べて、MI100を動かすことを、約6分間隔で5回繰り返しています。より多くの人が快適にウェブ・アプリケーション・インタフェース使うことができるように、繰り返しの間隔は6分より短くしないようにしましょうね。
# coding: utf-8
# KidsRubyから動かすときはここから下のみでOK
# artsat.rb
# Copyright (c) 2014 Masami Yamakawa
#
# This software is released under the MIT License.
# http://opensource.org/licenses/MIT
#
require 'open-uri'
require 'json'
require 'geocoder'
require 'color'
require 'time'
require 'mi100'
LOCAL_POINT = "東京都現代美術館"
COM_PORT = "COM5"
MAX_DURATION_MILLIS = 100
SLEEP_TIME_SEC = 3
CIRCUMFERENCE_KM = 40075
MOVE_DISTANCE_KM = 10000
DANCE_DISTANCE_KM = 500
MAX_DISTANCE_LEVEL = 10
MAX_ROCK_LEVEL = 10
ARTSAT_API = 'http://api.artsat.jp/web/v2/invader/sensor_data.json?sensor=lat,lon'
FETCH_PERIOD_SEC_DO_NOT_CHANGE = (6 * 60) + rand(20) + 10
Geocoder.configure(:language=>:ja, :units=>:km)
local_lat_lon = Geocoder.coordinates(LOCAL_POINT)
uri = URI.parse(ARTSAT_API)
robo = Mi100.new COM_PORT
last_distance = nil
5.times do
json = open(uri).read
invader = JSON.parse(json,{:symbolize_names => true})
invader_time = Time.parse(invader[:results][0][:closest_available_time_iso_string])
next_fetch_time = invader_time + FETCH_PERIOD_SEC_DO_NOT_CHANGE
invader_lat_lon =[]
invader_lat_lon << invader[:results][0][:sensors][:lat][:value]
invader_lat_lon << invader[:results][0][:sensors][:lon][:value]
address = Geocoder.address(invader_lat_lon)
distance = Geocoder::Calculations.distance_between(local_lat_lon, invader_lat_lon,{:units=>:km})
compass = Geocoder::Calculations.bearing_between(local_lat_lon, invader_lat_lon,{:method=>:spherical})
complementary_color = compass >= 180 ? compass - 180 : compass + 180
compass_word = Geocoder::Calculations.compass_point(compass)
compass_hsl = Color::HSL.new complementary_color, 100, 50
compass_rgb = compass_hsl.to_rgb
puts "TIME : #{invader_time.to_s}"
puts "LOCAL : lat %f lon %f"%local_lat_lon
puts "INVADER : lat %f lon %f"%invader_lat_lon
puts "ADDRESS : %s"%(address || 'No street address...')
puts "DISTANCE: #{distance.round.to_s} km"
puts "COMPASS : #{compass.to_s} #{compass_word}"
puts ""
robo.talk "ASAS "
robo.talk distance.round.to_s + " " + compass_word + " "
last_distance ||= distance
distance_level = (MAX_DISTANCE_LEVEL - ((MAX_DISTANCE_LEVEL * distance) / (CIRCUMFERENCE_KM / 2))).round
begin
robo.talk "HELLO WORLD!" if address
distance_level.times do
robo.blink compass_rgb.red_p.round, compass_rgb.green_p.round, compass_rgb.blue_p.round, 100
sleep 0.2
end
if distance.round < DANCE_DISTANCE_KM
rock_level = (MAX_ROCK_LEVEL - ((MAX_ROCK_LEVEL * distance) / DANCE_DISTANCE_KM)).round
rock_level.times do
robo.spin_right MAX_DURATION_MILLIS
robo.spin_left MAX_DURATION_MILLIS
end
end
if distance.round < MOVE_DISTANCE_KM
duration = (MAX_DURATION_MILLIS - ((MAX_DURATION_MILLIS * distance.round) / MOVE_DISTANCE_KM)).round
if last_distance - distance > 0 then robo.move_forward duration
elsif last_distance - distance < 0 then robo.move_backward duration
end
end
sleep SLEEP_TIME_SEC
end while Time.now < next_fetch_time
last_distance = distance
end
robo.close

