2011/10/25

手作りレーザーレンジファインダー

レーザーレンジファインダーは、相手までの距離をレーザー光を使って計測する機器です。
工事現場などで使用されていたり、軍用で使用されていたりします。

また、ロボットカーなどに搭載して周りの障害物への距離を調べたりもします。

面白そうなセンサーなので、遊びで使ってみたいな〜とは思うのですが、いかんせんブツの値段が高い。数万円〜数百万円と、遊びで買うには無理な金額設定です(遊ぶためのものではないので当然ですが)

んで、そのレーザーレンジファインダーを手作りしてしまおう、というサイトがありました。

Webcam Based DIY Laser Rangefinder


レーザーを斜めに照射して、カメラのどの位置に来るかで距離を計算するという素晴らしいアイデア。
これならレーザーポインタかスポット照射できる光源があれば、個人でもレーザーレンジファインダーを作ることができそうです。



面白そうなので、「そのうち作りたいリスト」に追加することにしました。

Linuxネットワークプログラミング(TCPサーバー・pthread)

今日はLinuxのネットワークプログラミングについて調査、というか読書してました。
参考にしたのはTCP/IP Sockets in C という本です。
Kindle Storeで20ドルぐらいでした。紙の本で買うとすると、4週間ぐらい待たないとダメなようです。


ざ〜っと見た感じでは、Linuxのネットワークプログラミングも、Windowsのネットワークプログラミングとそんなに変わらないようなので安心。

ただ、スレッドの作り方がちょっとめんどそうな感じです。
スレッドの調査はまた後でするとして、まずは単純動作のサーバーアプリを作る(コピペする)ことにしました。

 
下記のサイトにあるサンプルコードを、まとめて1つのソースファイルにしています。
TCP/IP Sockets in C: Practical Guide for Programmers


/*
    TCPEchoServer
    Original:
    http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.html
*/


#include <pthread.h>
/*
スレッド使うときは、ライブラリにpthreadを追加しないと
undefined reference to `pthread_create
とビルドするときに怒られます。
*/
#include <stdio.h>      /* for printf() and fprintf() */

#include <sys/socket.h> /* for socket(), bind(), and connect() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */


void *ThreadMain(void *arg);            /* Main program of a thread */


/* Structure of arguments to pass to client thread */
struct ThreadArgs
{
    int clntSock;                      /* Socket descriptor for client */
};

//エラーメッセージ出して終了する関数
void DieWithError(char *errorMessage)
{
    perror(errorMessage);
    exit(1);
}


//バッファサイズ(byte)
#define RCVBUFSIZE 256   /* Size of receive buffer */


//TCPクライアントに対する応答
void HandleTCPClient(int clntSocket)
{
    char echoBuffer[RCVBUFSIZE];        /* Buffer for echo string */
    int recvMsgSize;                    /* Size of received message */

    //受け取った文字列をそのまま送り返して、こちらからソケットを閉じる。
    //クライアントが1回なにか送ってきたら、そこで通信は終わります。

    /* Receive message from client */
    if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
        DieWithError("recv() failed");

    /* Send received string and receive again until end of transmission */
    while (recvMsgSize > 0)      /* zero indicates end of transmission */
    {
        /* Echo message back to client */
        if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recvMsgSize)
            DieWithError("send() failed");

        /* See if there is more data to receive */
        if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
            DieWithError("recv() failed");
    }

    close(clntSocket);    /* Close client socket */
}


//待ち行列に待たせておく数
#define MAXPENDING 5    /* Maximum outstanding connection requests */


int CreateTCPServerSocket(unsigned short port)
{
    int sock;                        /* socket to create */
    struct sockaddr_in echoServAddr; /* Local address */

    /* Create socket for incoming connections */
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        DieWithError("socket() failed");
      
    /* Construct local address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));   /* Zero out structure */
    echoServAddr.sin_family = AF_INET;                /* Internet address family */
    echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    echoServAddr.sin_port = htons(port);              /* Local port */

    /* Bind to the local address */
    if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
        DieWithError("bind() failed");

    /* Mark the socket so it will listen for incoming connections */
    if (listen(sock, MAXPENDING) < 0)
        DieWithError("listen() failed");

    return sock;
}

//クライアントが接続してきた時の処理.
int AcceptTCPConnection(int servSock)
{
    int clntSock;                    /* Socket descriptor for client */
    struct sockaddr_in echoClntAddr; /* Client address */
    unsigned int clntLen;            /* Length of client address data structure */

    /* Set the size of the in-out parameter */
    clntLen = sizeof(echoClntAddr);
    
    /* Wait for a client to connect */
    if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, 
           &clntLen)) < 0)
        DieWithError("accept() failed");
    
    /* clntSock is connected to a client! */
    
    printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));

    return clntSock;
}


int main(int argc, char *argv[])
{
    int servSock;                    /* Socket descriptor for server */
    int clntSock;                    /* Socket descriptor for client */
    unsigned short echoServPort;     /* Server port */
    pthread_t threadID;              /* Thread ID from pthread_create() */
    struct ThreadArgs *threadArgs;   /* Pointer to argument structure for thread */

    if (argc != 2)     /* Test for correct number of arguments */
    {
        fprintf(stderr,"Usage:  %s <SERVER PORT>\n", argv[0]);
       echoServPort=80; 
        //exit(1);
    }
    else{

    echoServPort = atoi(argv[1]);  /* First arg:  local port */
}
    servSock = CreateTCPServerSocket(echoServPort);

    for (;;) /* run forever */
    {
    clntSock = AcceptTCPConnection(servSock);

        /* Create separate memory for client argument */
        if ((threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs))) 
               == NULL)
            DieWithError("malloc() failed");
        threadArgs -> clntSock = clntSock;

        /* Create client thread */
        if (pthread_create(&threadID, NULL, ThreadMain, (void *) threadArgs) != 0)
            DieWithError("pthread_create() failed");
        printf("with thread %ld\n", (long int) threadID);
    }
    /* NOT REACHED */
}

void *ThreadMain(void *threadArgs)
{
    int clntSock;                   /* Socket descriptor for client connection */

    /* Guarantees that thread resources are deallocated upon return */
     pthread_detach(pthread_self()); 

    /* Extract socket file descriptor from argument */
    clntSock = ((struct ThreadArgs *) threadArgs) -> clntSock;
    free(threadArgs);              /* Deallocate memory for argument */

    HandleTCPClient(clntSock);

    return (NULL);
}


これでechoサーバーを作ることができたので、あとはこのソース内のHandleTCPClient部分をいじれば、カメラの画像をクライアントに送りつけることもできるようになると思います。

ではまた。

2011/10/21

SSD化&メモリ増設

前からSSDが欲しくて買おう買おうと思っていたのですが、
最近SSDが安くなってきているようなのでとうとう買ってしまいました。

購入したのはIntelのSSD 320シリーズの80GBモデルです。
DDR3のメモリも8GBで4000円と安かったので2セット購入。


まずは現在の環境を保存するため、11.10についているバックアップで
home以下をハードディスクにバックアップしました。

SSDに交換したあとWindowsと同居させようと思い、HPのリカバリディスクで起動してみると
「出荷時のディスク容量よりも少ないため、続行できません」
と出てリカバリできず。無念。
最近のリカバリディスクはディスク容量もチェックするんですね。


というわけで大容量のSSDに換装するまでWindows7とお別れすることにしました。

気を取り直してUbuntu11.10 amd64版をCDからインストール。
インストールと初回アップデートは20分程度で完了。

システム情報を見たら、きちんと16GBのメモリを認識していました。64bit万歳。




バックアップを使用し、先ほど退避させておいたものから復元。
デスクトップとHomeフォルダは復元できたものの、メールの設定などは初期状態のままでした。
メールなどは個別でバックアップするもののようです。


アプリケーションもクリーンな状態になっているので、今まで使っていたものを再度インストールする必要はありますが、起動時間が15秒ぐらいになったので非常に快適になりました。

さてさて、開発環境の構築をし直しますかね。。
ではまた。

2011/10/18

Ubuntu11.10にアップグレード

1ヶ月ぶりの更新。

先月末からDARK SOULSをやっていたのでこっちは放置してましたが、
2週目に入って竜のボスが倒せなくなったので戻ってきました。

さて、以前やっていたArduinoタンクの続きでもやろうかと、Ubuntuを立ち上げたら

「新しいディストリビューションが利用できます」
と表示されるではありませんか。

早速アップグレードを開始。
何やらエラーが出てsambaのアップグレードが出来なかったようですが、
他は問題なくアップグレードできました。

再起動後、sambaを削除しました。(いまのところ必要ではないので)

ソフトウェアセンターが新しくなって、Android Market風になっていました。
他にもアイコンとかがかっこ良くなっている気がします。

Dashメニューもアプリの他に、最近使ったファイルや音楽も探せるようになっているので
結構便利です。


さて、Ubuntuはさておき、プロジェクトの続きを考えることに。
先月まではBeagleBoard-xmの電力測定や無線LAN化をしていたので、
次は取得した画像をネットワーク経由で送信する必要があります。


Arduinoタンクブロック図

既存のストリーミングソフトを使用すればカメラで取得した画像を簡単に送信することができますが、カメラの画像を加工することはできません。
OpenCVでカメラの画像を加工してから使用したいので、自分でネットワーク部分のプログラムを書く必要がありそうです。

というわけで、今後のタスクリストを作ってみました。
・ソケットプログラミングを調べる(まずはブロッキング接続で動かしてみる)
・OpenCVの画像情報をネットワーク経由で送れるか確認する
・ソケット通信でOpenCVで取得したカメラ画像を送受信する
・タンク操作用コマンドをソケット通信で送る
・受信したコマンドをArduinoにシリアル通信で送る

う〜ん。。通信系が結構ありますね。
とりあえず動くように頑張って調査&コーディングしてみたいと思います。

ではまた。