種子島や内之浦でロケットの打ち上げを見るのであれば、撮影など気にせずに、自分の目で直接見た方が良い。せっかく現地にいるのに、ファインダー越しでは、テレビで見ているのと同じになってしまうからだ。これは何とももったいない。特に初めて見るような時には、ぜひ肉眼で見て欲しい。

……とは言え、毎回仕事で行っている筆者の場合、撮影をしないわけにもいかない。広角とズーム、動画と静止画と、いつも打ち上げ時には一人で3つも4つもカメラを使うことになるので、忙しすぎて打ち上げを楽しむ余裕などは全く無い。肉眼で見たのは、完全にプライベートで行ったH-IIAロケット初号機が最後である。

ロケットの打ち上げ。この眩しさは肉眼でないと経験できない

生で見たいが、撮影も必要。この超個人的な問題を解決すべく、筆者はロケットを自動追尾するシステムの開発を決意。このほど、H-IIAロケット29号機の打ち上げ(2015年11月24日)の際に、現地でテストを行った。本レポートはその顛末である。

システムの概要

まずは以下の動画を見て欲しい。

ロケットを追い越してしまった…

じつはこれは、2014年のH-IIAロケット26号機(小惑星探査機「はやぶさ2」を搭載)の打ち上げで、自動追尾カメラを初めて試したときのものだ。このとき、ハードウェアが完成したのは種子島へ出発する前夜。ソフトウェアは現地開発の予定だったのだが、当然ながら現地は現地で取材に忙しく、結局時間切れになってしまった。ダメ元で適当に上に動かすようにしたら、このような失敗になったというわけだ。

この時の模様。1分過ぎに謎の振動が起き、取材中の筆者の足を引っ張る始末。駄目すぎる

というわけで、今回はそのリベンジだ。

最初に、システムの構成から説明していこう。基本的な構成は、サーボモーターでパンチルト動作を可能にした雲台と、それを制御するPCの2つ。PCにはWEBカメラを接続して、画像認識によりロケットを検出、その方向にサーボを動かす。このサーボ雲台にビデオカメラを乗せておけば、追尾した動画が撮影できるというわけだ。

三脚に設置したサーボ雲台。最上部のビデオカメラで動画を撮影する

制御用のノートPC。風が強かったので、落ちないように床に置いた

サーボモーターとコントローラには、近藤科学製の「KRS-2552HV」と「KCB-5」の組み合わせを使用した。KRS-2552HVは2足歩行ロボット「KHR-3HV」で使われているサーボモーターだ。現在は後継製品「KRS-2552RHV」に切り替わっているのだが、KHR-3HVの予備パーツとして筆者の自宅に何個か転がっていたため、こちらを使用した。

サーボモーター「KRS-2552HV」。ロボット用なのでトルクは十分のはず

コントロールボード「KCB-5」。32ビットARMマイコンを搭載している

KCB-5はロボット用のマイコンボードで、C言語のプログラムからサーボモーターを制御することが可能。本来はこの基板に各種センサーを追加して、単独でロボットを制御できるのだが、今回は画像認識による制御をPC側で行っているため、KCB-5の役割は、シリアル通信でPCから送られてきたポジションデータをサーボモーター側に渡しているだけだ。

KCB-5の制御プログラムはこちら。

#include <stdlib.h>
#include <string.h>
#include "kcb5.h"
#include "uart.h"
#include "ics.h"

#define Y_MAX 10167 //ヨー上限(+90°)
#define Y_MIN 4833  //ヨー下限(-90°)
#define P_MAX 10611 //ピッチ上限(-15°)
#define P_MIN 7944  //ピッチ下限(+75°)

int main(void)
{
    unsigned char r_str[16], str1[16];
    int pos1, pos2;

    //通信ポートを初期化
    uart_init(UART_COM, UART, BR115200, 8, PARITY_NONE);

    //サーボ端子を初期化
    sio_init(UART_SIO1, BR115200);

    while(1){
        uart_rx(UART_COM, r_str, 10, 0);

        strncpy(str1, r_str, 5);
        pos1 = atoi(str1);
        pos2 = atoi(r_str+5);

        if (pos1>Y_MAX) pos1=Y_MAX;
        if (pos1<Y_MIN) pos1=Y_MIN;

        if (pos2>P_MAX) pos2=P_MAX;
        if (pos2<P_MIN) pos2=P_MIN;

        ics_set_pos(UART_SIO1, 1, pos1);
        ics_set_pos(UART_SIO1, 2, pos2);
    }

    return 0;
}