~ 芸術衛星特集 ~
今回は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