2014年4月29日火曜日

GWの工作2014 その3 ~操作インターフェースのwebアプリ化~ 

androidのバージョンがどうたらみたいな問題に悩まされたり、
PC上でちょっとした動作テストを行うために専用コードを書いたり(PCでのテスト用にGUIのインタフェースを作ろうとも考えた)、
もしかしたらiphoneでも使いたくなるかもしれないとか考えたときの解としてhtml(とjavascript)を選択。これは今回のラジコン製作の中でも最も成果が大きかった。ブラウザがあれば大体何でも使えるインターフェースが作れるのは多分後で効いてくる。はず

~今回のお話~
pythonのwebフレームワークを使ってPCをサーバー化、websocketを使ってリアルタイム性の高い通信を行ったときのメモ

環境
・python2.7 (eclipse4.3)
・c,c++のコンパイラはmingw32
・webフレームワークとしてgevent、geventwebsocket.handlerを使用
・htmlとjavascriptはBracketsとかいうフリーソフトを使用。ライブプレビュー機能が便利。

参考資料:
geventの導入関連(筆者環境では非常に重要だった。visualstudioを普段から使っている人は素通りできるかも)
・ http://stackoverflow.com/questions/2817869/error-unable-to-find-vcvarsall-bat
(概要、上記参考URLより引用) 
C:\Python27\Lib\distutils\distutils.cfg(←ファイルが無かったら新規作成)の中身を↓

[build]
compiler=mingw32

とする(内容を追記、変更する)。そのあとプロンプトを立ち上げてgeventをインストール(↓の問題が無ければ)

・http://stackoverflow.com/questions/13592192/compiling-pygraphviz-unrecognized-command-line-option-mno-cygwin
 (概要、上記参考URLより引用)
C:\Python27\Lib\distutils\cygwinccompiler.py  というファイル内の

    self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
                         compiler_so='gcc -mno-cygwin -mdll -O -Wall',
                         compiler_cxx='g++ -mno-cygwin -O -Wall',
                         linker_exe='gcc -mno-cygwin',
                         linker_so='%s -mno-cygwin %s %s'
                                    % (self.linker_dll, shared_option,
                                       entry_point))
 を
 
    self.set_executables(compiler='gcc "" -O -Wall',
                         compiler_so='gcc "" -mdll -O -Wall',
                         compiler_cxx='g++ "" -O -Wall',
                         linker_exe='gcc ""',
                         linker_so='%s "" %s %s'
                                    % (self.linker_dll, shared_option,
                                       entry_point))
 
に変更する(-mno-~というオプションを消す)
これでgeventに限らずコンパイルが必要なpythonのツールが
スムーズにインストールできるようになるはず。
 
Websocketの参考資料: 
geventを使ったwebsocketの実施例
 へきょのーと 様 記事URL http://d.hatena.ne.jp/hekyou/20120712/p1
 
上の記事を参考にしてwebsockサーバーを立て、↓のサイトで動作を確認
Echo Test  http://www.websocket.org/echo.html

htmlの参考資料:
stackoverflow http://stackoverflow.com/questions/5165579/onchange-event-for-html5-range
htmlのスライダーの値をリアルタイム変化させる為の質問。
Scott氏の回答が非常にスマート 
 
参考資料などを頼りになんとかインターフェースを構築 
メモ :
・javascriptのファイルとhtmlのファイルは別にすること
(htmlに直接スクリプトを書き込まないこと) これをやらないとIDEのエラーチェックがちゃんと機能しない

・python側、html側ともにPC(サーバー)のアドレスを127.0.0.1にしないこと。
別の機器からアクセスするとき面倒なことになるので192.168~のようにIPアドレスを記入すること

・IPカメラの映像を写すには以下のようにする。大きさはお好みで
(AI-ball(インフラストラクチャモード)の場合) 
<img src="http://(カメラのIPアドレス)/?action=stream.mjpeg" width="320" height="240"> 
(「IPwebcam」を使ったスマホの場合)
 <img src="(スマホのIPとポート)/videofeed" width="320" height="240">
 
 それぞれ上のタグを入れるだけで(大抵の)ブラウザ上に一発で動画が出る。
アンドロイドアプリで動画を出そうと苦しんでいたのは何だったのか。googleの人(?)を
問い詰めたくなるレベル。あとhtmlの仕様を策定している人たちは神
 
 肝心のインターフェースのほうは一応動かすのに必要な要素はあるが(その1の動画参照)
まだぜんぜんなのでまた今度

GWの工作2014 その2 ~VPN(SoftEther VPN)導入時に詰まった箇所のメモ~

~VPNの導入~ とか大げさなタイトルだが単純に自分が詰まったところのメモ

レジストリを変更する部分があるので自己責任で

設定時筆者環境
・win7 64bit
・NTTのフレッツ光 マンションタイプ 、プロバイダはyahooBB
・壁の電話線→NTTモデム→ルータ(BUFFALO WHR-300)→有線でPCと無線でタブレットなど
・スマホはDocomoのgalaxynote2。ドコモのケータイはVPN接続に癖があるらしいが以下のやり方(L2TP/IPsecを使用)では問題なし

導入メモ
・SoftEther VPN(https://ja.softether.org/) というVPNを導入。完全無料!筑波大学は神。オープンソースらしいので多分ずっと使えるだろう。

・基本的に上記HPのマニュアル通りに設定するだけでいける。
→チュートリアル「モバイルにおけるVPN」と「SoftEther VPN Server を使った L2TP/IPsec VPN の構成」 (一番下の方)を参照

・ マニュアルに書いてあったのだが見落としていて1日消費した箇所を以下にメモ
→見落としていたのはチュートリアル「VPN Server 側での L2TP/IPsec 機能の有効化方法 」の下の方の「VPN サーバー側に NAT がある場合」という項目の

・Windows 標準搭載の L2TP VPN クライアント機能を用いる場合で、接続先の VPN Server が NAT の背後に設置されている場合は、クライアント側のレジストリを以下のリンクの解説に従って編集する必要があります。

という文章とリンク(上の文言の下にリンクが張ってある。)。要は(ちゃんと理解してないが)外部のスマホとサーバー(今回は自宅PC)の間にNATデバイス(多分ルータのこと)がある場合はレジストリをいじる必要があるということ。リンク先を読めばわかるが筆者は値を1に変更

これをやらないとスマホでいくらがんばってもVPNが張られない(スマホからのデータがルータを通過できてもPCで弾かれる)

GWの工作2014 その1 ~スマホから動かせるラジコンの概要~

ここ最近作っていたラジコン(rev4?)のまとめ
細かいことは後の記事に個別でメモ

要約 : LANの届く範囲でなら動いたり色々入出力できる何か

主な機能 : 
1、スマホで外からでもコントロールできる。 (VPNで繋いでるだけ)。操作する人は電波さえあればどこにいてもいいがラジコンはLANの範囲(家の中)から出られない。

2、操作インターフェースはhtml+javascriptを採用。PCだろうがスマホ(androidでもiphoneでも)だろうがブラウザさえあれば関係なし。

3、前回は マルチタッチとかなんだかおしゃれなインターフェースを採用していたが、操作感が微妙だったので今回はとりあえずファミコン式(8方向のボタンで操作)

4、IP カメラで前方を見ながらのコントロールが可能。

5、arduinoとpythonの連携プラットフォームを使用しているのでいろいろ拡張可能。(そのうちちゃんとしたものができればGithubとかに上げたい)

6、無駄に駆動輪を独立駆動可能。ステアリングの操作と合わせて戦車的な挙動ができる(片方の駆動輪を中心にして回転とか)。

見た目:

上から : (前回のものと比べると)洗練された外観。まだ臓物載せただけ感は払拭できない
















 横から : 前回のラジコンはキャタピラだったが、やたら脱輪するのでタイヤに変更

















操作風景(動画)

 

ちなみにスマホのほうはWIFIではなくVPNを使って携帯の電波で動かしている。つまりスマホの電波さえ入っていれば家の中の映像を見ながらラジコンを操作できる!これで鍵の閉め忘れも確認できる(カメラの配置に課題)。
スマホ側の動画が若干カクカクしているがこれは電波が弱い為。外に出てLTEのアンテナが最大だともう少しましになった。

さっきその辺の公園から家にあるラジコンを動画のような感じで動かせることを確認(おもむろに公園のベンチに座りスマホでラジコンの動作確認をしてすぐ立ち去る様は若干不審人物だった気がする)。

材料 : 
(´д`;).oO(材料のリンクをアドセンスにすれば小遣い稼ぎができるのでは・・・ゴクリ。と思ったがそんなアクセス無かった。)
 気を取り直して材料リスト(以下に無いものも写真に写っているが今回は使ってないのでカット)

ヨドバシ.comで購入 (タミヤの部品はヨドバシが便利だった201404月現在)
・タミヤ TAMIYA 楽しい工作シリーズ ユニバーサルプレート(210×160mm)
・タミヤ TAMIYA 楽しい工作シリーズ ユニバーサルプレート(2枚セット)
・タミヤ TAMIYA 楽しい工作シリーズ ナロータイヤセット(58mm径)  ×2
・タミヤ TAMIYA 72007 4速パワーギヤボックスHE [テクニクラフトシリーズ] ×2
・タミヤ TAMIYA 楽しい工作シリーズ シャフトネジセット(直径3、直径4mm) [特殊ネジ] ×2くらい
・タミヤ TAMIYA 楽しい工作シリーズ ユニバーサルアームセット
スイッチサイエンスで購入 (同等品でも可。ただしArduino Leonardo系は何となくおすすめしない )
・デュアル・モータードライバTB6612FNG(連続最大1.2A)
・リチウムイオンポリマー電池×2
・Arduino Uno R3
・XBee ZB モジュール ×2
・XBeeエクスプローラUSBドングル
・XBee 5Vインターフェースアダプタ
・SparkFun製 プロトシールド・キット
・ジャンパワイヤ ×適量

アマゾンで購入。IPカメラなら何でもいい(余ったスマホに「IPwebcam」をインストールしたもので問題ない。というより重さ以外はコレがおすすめ)
・Trek 2000  Ai-Ball (写真ではなにやら回路がくっついているが(写真1枚目左側)、これは3.3V出すための電源回路。弄り倒して付属の電源アダプタをぶっ壊していなければ不要)

秋月電子で購入
・GWSサーボ PIC+F/BB/F(フタバ) (設定値、スペックなどは過去記事参照)




2014年2月23日日曜日

xbee wifiに関する走り書き

xbee wifiをソケット通信で普通に使うのに必要そうな情報

受信と送信のソケットを同時に開くことは(多分)できない。送信(または受信)が終わったらそのたびにソケットを閉じること

・基本だがsocket.accept()の直後に(ウェイトを入れずに) socket.recv() などでデータを取り出そうとしてもエラーになる。バッファがちゃんと溜まるまで(人間にとって)ちょっとでも待つべき。

・連続してデータの送受信を繰り返したいとき、デフォルトの設定だと受信(PC←xbee)で10秒、送信で多分60秒くらい待つようになっている。「Network」のTMとTSが受信と送信のタイムアウトになっているのでこれらを限界まで小さくすると待ち時間が減らせる(とりあえず0.5秒に1回程度の送受信ができる)

・「serial Interfacing」のROもタイムアウトになっている。小さくすると通信が多分速くなる。

・送受信のソケットを再生成するのにも時間が必要なので繰り返す場合は生成前にウェイトを入れること。

とりあえず上記で(電源系の問題を除けば)普通のxbeeと同じように使えるはず。詳細は来週

2013年12月23日月曜日

opencvで処理した画像(動画)をandroid端末に送信して表示するあたりのメモ

以前、SimpleMjpegViewというライブラリを利用してwebcamの映像をandroid上に表示したが、今回は別の手法で(もっと原始的な形で)端末上に動画を表示する。

前回:

 webcam → (mjpegストリーム) → android端末

今回:
 webcam → PC(c++(Opencv)) → (jpeg) → android端末

 今回の方でやれば重たい画像処理を母艦PCやraspiで行ってその処理結果をandroidに送信できる。

とりあえず結果↓

 いいwebカメラ(ロジクールの1万のやつ)なのに若干カクつく。サイズを小さくしたり、jpg品質落とすことでましにできると思われる



opencvを使ったりしているのでMITライセンスになります。
強制終了前提のコードなのであくまでご参考、自己責任でお願いします。

↓MITLicenceに基づく告知

Some codes in OpenCV are utilized.
Therefore, before downloading, you have to agree to the following license.
//////////////////////////////////////////////////////////////////////////////////
IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.

                    Intel License Agreement

            For Open Source Computer Vision Library
Copyright (C) 2000, Intel Corporation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
  • Redistribution's of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
  • Redistribution's in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
  • The name of Intel Corporation may not be used to endorse or promote products
    derived from this software without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall the Intel Corporation or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.

 ライセンス告知ここまで


まずC++側、環境はwin7 64bit Gcc(MINGW) opencvが必要(今回は2.4.7使用)


概要 : 
0、ソケット構築、android側からのアクセスを待ち受け

1、opencvで動画や画像フレームを取ってきて好きなように処理して最終的にjpgに圧縮 jpgのデータはvector<uchar>で保存される

2、jpgのデータサイズ(何バイトか)をバイナリ(intだと4byte)にする、地味なビット演算処理が必要(もっとスマートにできそうだが)。要は送信先でintとしてデータサイズを取れるようにする。これがわからないとあちらで正確なバッファが作れない

3、 jpgデータサイズとjpgデータをandroidに送る。
   vector<uchar>をソケットで送信できるconst char*に変換する部分の調査に時間がかかった(初見だとここで詰まる可能性あり)

4、おわり。上記処理をループさせている


(参考ソース)

#include <iostream>
#include <windows.h>
#include <winsock2.h>

#include "opencv2\highgui\highgui.hpp"
#include <vector>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <sstream>

using namespace cv;
using std::stringstream;
int main()
{
~~~~~~~~~~~~~



ここにソケットの初期化(bindまで)の処理が入るが諸事情(参考文献の丸写しのため)によりカット
参考文献 : http://blog.pusheax.com/2013/07/windows-api-winsock-create-your-first.html

windowsソケットプログラミング(C++)の基本説明



~~~~~~~~~~~~~



    //////////////// start(original from here)

    int lis=listen(u_sock,3);
    /////////////// waiting client data   
   
    //opencvによる動画の取得
    VideoCapture cap(0);
   
    //メインループ
    while(1){
        stringstream ss;
        //クライアントからの受信用バッファ、何らかのコマンド受け取りを想定
        int receive_buf_size = 20;
        char vect[receive_buf_size];

        std::cout <<"start waiting client command" <<std::endl;
        //client adress define
        struct sockaddr_in client;
        int len = sizeof(client);

        //client connect waiting・・・クライアント定義、待ちうけはループ外でもいいかもしれない
        SOCKET sockCli = accept(u_sock, (struct sockaddr *)&client, &len);   
        //クライアントから20byte何かしら受け取る、必要に応じてパース
        int get=recv(sockCli,vect,receive_buf_size,0);
        if(get==SOCKET_ERROR){
            std::cout<<"Error in Receiving: "<<WSAGetLastError()<<std::endl;
            continue;
        }

        // receivedta(command) process 受け取ったデータの処理、Stringstreamを使って文字列にして表示
        Sleep(10);//data receive waiting クライアントからのデータを待つ
        std::cout <<"end receive"<<std::endl;
        ss.clear();
        String res_string;
        ss << vect;
        ss >> res_string;

        if (get <0){
            std::cout <<"no receive data"<<std::endl;
            //    break;
        }else{
            std::cout <<"receive data : ";
            std::cout <<res_string<<std::endl;
        }

        ss.clear();

        /////////// image data send process 画像の取得と送信   
        Mat frame;

        cap >> frame;

        int framesize = 1000000; ///Max size

        //送信データ用のバッファ
        vector<uchar> bufv;
        //ちゃんと変換されたかの確認用
        bool imok;
        //jpg圧縮用のパラメータ設定
        vector<int> jpgparam;
        jpgparam.push_back(CV_IMWRITE_JPEG_QUALITY);
        jpgparam.push_back(20); /* jpeg quality */
        //ここまでパラメータ設定

        //圧縮した画像をバッファに入れる
        imok=imencode(".jpg",frame,bufv,jpgparam);
       
        //Mat sframe;

        std::cout<<bufv.size()<<std::endl;

        //Send some message to remote host

        ///////////// jpg data sending
        std::cout <<"start sending"<<std::endl;

        std::cout <<"send size"<<bufv.size() <<std::endl;
        std::cout <<"senddata "<<bufv.data()<<std::endl;
        std::cout <<"start sending"<<std::endl;

        // sizeof jpg send to java  画像サイズ(何バイトか)をクライアントに送信する
        // intの数値をバイナリ(4バイト)に変換する。泥臭い処理
        vector<uchar> jpgsize_send(4);
        int jpgsize=bufv.size();
       
        //int(4byte)のバイナリを1バイトずつ送信用の配列に入れる。エンディアン注意   
        for (int i=0;i<4;i++){
        jpgsize_send[3-i]=(jpgsize >>(i * 8) );
        }
        ////////// bynary genelator

        std::cout <<"data size : "<< jpgsize <<"type size"<<sizeof(jpgsize) <<std::endl;
        //std::string siz=std::to_string(jpgsize);
        std::cout <<"type size"<<sizeof(jpgsize_send) <<std::endl;
       
        /////////////////////// send data to android
        //vectorをcharに変換してクライアントに送信、
        //ロベール本によるとreinteroret_castの使用には注意が必要らしい

        //ヘッダ部(今回は画像データバイト数のみ)送信
        int smsg_header=send(sockCli,reinterpret_cast<const char*>(jpgsize_send
                    .data()),jpgsize_send.size(),0);
        //画像データ送信
        int smsg=send(sockCli,reinterpret_cast<const char*>(bufv.data()),bufv.size(),0);

        ///////////////////////


        if(smsg==SOCKET_ERROR){
            std::cout<<"Error: "<<WSAGetLastError()<<std::endl;
            WSACleanup();
        }

        /*
        //get=recv(u_sock,vect,512,0);
        if(get==SOCKET_ERROR){
        std::cout<<"Error in Receiving: "<<WSAGetLastError()<<std::endl;
        }
        //std::cout<<vect<<std::endl;
        */
    }
    closesocket(u_sock);

~~~~~ ここから終了処理を適当に

}

------------------------------------------  C++ここまで



Java(Android側)、eclipse4.3(Kepler Service Release 1) androidosは4.4が入ったnexsus7(2012)


概要:androidのプロジェクトで新しいクラスを作って以下のソースをコピペして、パラメータ(アドレス、ポートなど)設定してからonCreateに他のTextViewみたいに設定するだけで動作する(コピーした時点でレイアウトのxmlのカスタム&~のところに出てくるので普通にレイアウトできる)。はず。
インターネットの許可が必要(忘れてちょっと詰まった)


ゴミコードが混ざっているのはご愛嬌。あくまで個人的なメモなので。
自動生成とかどうでもいいところでないところは太字にしてある



基本的なsurfaceviewのクラスにネットから画像を取ってくるクラスを接続している。サーフェスの更新をマルチスレッドでずっと回してその中でさらにネットから画像を取ってくるスレッドを走らせる。
はっきり言ってバグの温床なのでいろいろ注意、ちなみに強制終了前提




コード

(Class Mysurfaceview.java)


package com.example.jpeg_binaly_client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ImageView;
import android.widget.TextView;

public class Mysurfaceview extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    //ビューの常時更新には普通のマルチスレッドを使う
    Thread thread;


    SurfaceHolder holder;

    //更新される画像
    public Bitmap tcpbmp;
    //ネットワークスレッドの更新可能シグナル
    public int imggetflag;

    public Mysurfaceview(Context context, AttributeSet attrs ) {//太字の部分がないとxml関連のエラーになる
        super(context,attrs);
        // TODO 自動生成されたコンストラクター・スタブ
        getHolder().addCallback(this);
        this.holder = getHolder();

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO 自動生成されたメソッド・スタブ

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO 自動生成されたメソッド・スタブ
        thread = new Thread(this);
        thread.start();


    }

    @Override
    public void run() {
        while(true){//無限ループ注意

            doDraw(getHolder());

            try {
                Thread.sleep(100);
//通信も絡むので若干待つ、が、ここで待たなくてもいいかも
             } catch (InterruptedException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
        }

    }


    //描画用関数
    public void doDraw(SurfaceHolder holder) {
       
        tcpbmp =null;
        //画像取得スレッドを走らせる
        tcp_getimage3 jpgg= new tcp_getimage3();
        jpgg.execute("nl");
//特にコマンドなんかが無ければ何でもいい

        int cnt=0;
        int timeout =10;
        int waiting=10;
   //画像取得が終わるまで待つ
        while (imggetflag ==0){
            System.out.println("waiting get...");

            //一定時間待つ
            try {
                Thread.sleep(waiting);
            } catch (InterruptedException e1) {
                // TODO 自動生成された catch ブロック
                e1.printStackTrace();
            }
            cnt += waiting;
            //一定時間待っても更新シグナルがこない場合はタイムアウトとする
            if(cnt>timeout){
                System.out.println("waiting get...timeout");
                break;}
        }

        //更新可能(フラグが出ており、bmpがカラでないとき)なら画像を更新
        if(imggetflag==1 && tcpbmp !=null){
             Canvas canvas = holder.lockCanvas();

             canvas.drawBitmap(tcpbmp, 0, 0, null);
          
            holder.unlockCanvasAndPost(canvas);

        }
        //フラグを0にする
        imggetflag=0;

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO 自動生成されたメソッド・スタブ

    }

    //ネットワークからの画像取得クラス
    public class tcp_getimage3 extends AsyncTask<String,Integer,byte[]>{


        public String ipaddr="(IPアドレス)"; 

        int port_bg = (ポート番号);
       
        Socket socket_bg = null;

        DataOutputStream out=null;
        BufferedReader inp=null;

        DataOutputStream out_bg=null;
        DataInputStream inp_bg=null;
       

        //エラー出力用のカラのバイト列
        public byte[] reterr =null;


        public int cnt =0;
        public int serverflag_bg=0;  //1だとサーバ無しとみなしている。

        public tcp_getimage3(){
            super();
        }



        @Override
        protected byte[] doInBackground(String... val) {
            // TODO 自動生成されたメソッド・スタブ
           
            if (serverflag_bg==0){

                try{

                    try{
                        InetSocketAddress addr = new InetSocketAddress(ipaddr, port_bg);
                        socket_bg =new Socket();
                        socket_bg.connect(addr,50);//タイムアウトの時間は重要、繋がらなかったらさっさと切り上げて再接続したほうが早いので、とりあえず短いほうがいい。でも短すぎると電波環境によっては通信できない可能性もある。

                    }catch(SocketException e){
                        e.printStackTrace();
                        Log.i("network", "socket not connect");
                        return reterr;  //タイムアウトしたらさっさとスレッドを閉じにいく

                    }catch(Exception e){  ///調べたがこの例外じゃないと死ぬ。重要
                        e.printStackTrace();
                        Log.i("network", "その他のネットワーク系エラー");

                        return reterr;

                    }


                    Log.i("network", "sendstart ");
         ///////////////////////////////////////ここからが実質的な処理
                    DataOutputStream out_bg = new DataOutputStream(socket_bg.getOutputStream());

                    ////// データの送信、コマンドなどが無いなら何でもいい
                    out_bg.writeBytes("jpgg");

                    byte[] buf =new byte[1000000]; //最大データサイズ(byte)c++と合わせる

                    int readflag;

                    //データ読み込み↓
                    InputStream is =socket_bg.getInputStream();
                    DataInputStream inp_bg = new DataInputStream(is);

                    Thread.sleep(50);//4バイト受信できるくらい待つ必要がある


                    int receive_size=inp_bg.readInt(); //C++からヘッダ(画像のバイト数)情報を受け取る

                    //画像容量分のバッファを定義する、ここら辺が正確じゃないとBMPがちゃんと生成されない

                    byte[] buffull =new byte[receive_size];

                    //画像データをすべて受信するまで待つ
                    if (inp_bg.available() != receive_size){

                        Thread.sleep(10);
                    }


                    //受信データをバッファに入れる、ループしなくていいかも
                    while(inp_bg.available()>=0){
                        System.out.print("datasize is ");
                        System.out.println(receive_size);

                        //受信データをバッファに入れる。何らかの方法で全部のバッファを受け取ったか確認する必要がある
                        inp_bg.read(buffull,0,receive_size);
                        if(inp_bg.available()==0){break;}

                    };
                   
                    out_bg.close();
                    inp_bg.close();
                    socket_bg.close();


                    //バイナリをビットマップに変換する。jpgも勝手に解析してBMPにしてくれる
                    Bitmap bmplocal=null;
                    bmplocal=BitmapFactory.decodeByteArray(buffull,0,buffull.length);
                    System.out.println(buffull.length);←データサイズと同じか一応比較

                    //グローバルのbmpに変換したBMPを入れる
                    tcpbmp = bmplocal;


                    ///////////////////////////////////////ここまでが実質的な処理
                    //バイナリを出力する。onPostExecuteでの処理はこっちに持ってきても問題ない
                    return buffull;

                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("io err"+e);

                    serverflag_bg=1;
                    return reterr;
                }catch (Exception e) {
                    e.printStackTrace();
                    Log.i("network", "Iilligal ");
                    System.out.println("io err"+e);

                    serverflag_bg=1;
                    return reterr;

                }

            }else{
                Log.v("tcp","noserver");
                return reterr;
            }
        }

        protected void onPostExecute(byte[] result) {

            //呼び出し元のスレッドに描画更新OKのシグナルを出す
            if (result !=null){
                imggetflag=1;}
            else{
                //何らかのエラーでバイナリが無い場合はシグナルを出さない
                imggetflag=0;
            }

            System.out.println("end tcp thread");


        }

    }
}











2013年12月7日土曜日

自分用Vim設定メモ

Vimの設定に関するメモ。主にc++(時々pythonも)でプログラム書くのをイメージ
GVimを(http://www.kaoriya.net/)入手

■ウィンドウズのキーバインドを変えてしまう
無変換キーとか変換キーなんて使わないのでそれぞれEscキーと半角/全角キーに割り振ってしまう。vimではEscキーを使いまくるのでこの変更は重要
↓これで簡単に変更できる(レジストリ変えるので再起動が必要)
http://www.forest.impress.co.jp/library/software/changekey/

■まず以下を vimrc(編集→起動時の設定 で開くファイル)にコピー

nnoremap - $
nnoremap <F11> :make run <Enter>
nnoremap <F5> :!python % <Enter>
set number
set incsearch
set autochdir
set wildmenu wildmode=list:full
copen

ここからメモ
・ノーマルモードで「-」を押すとカーソルが行末に行くこれで0が行頭 -が行末移動になる(隣り合っててわかりやすい)

・F11でメイク→実行 ちゃんとrunができるようにmakefileを書くこと
・ F5でpython実行

・左に行数を表示

・インクリメンタルサーチをオン(いい感じに検索できる)

・set autochdir : 開いているファイルのある場所にカレントディレクトリを移動する。基本的に必須

・ set wildmenu wildmode=list:full : コマンドモード(「:」入力以降)で補間する

・ copen デバッグウィンドウ的なものを開く。便利

■ctags(Exuberant ctags)を使う
主要参考ページ
http://nanasi.jp/articles/others/ctags.html

・ここ(http://hp.vector.co.jp/authors/VA025040/ctags/)でctagsをダウンロード
・exeを環境変数Pathにあるフォルダに入れる
・autochdir がオンになっていれば編集したいファイル開いてGvimのタグ作成ボタンなどでタグを作れる
・宣言と同時に値を入力している変数はタグをつけてもらえない模様

Taglistを入手(参考:http://nanasi.jp/articles/vim/taglist_vim.html)

(GVimフォルダ)\runtime\plugin の中に.vimを \runtime\doc の中に.docをコピーするだけ

・「:Taglist」で画面左もプロジェクトエクスプローラー的なものが出る(eclipseのほうが高性能だが)

2013年11月22日金曜日

windows-mingwでopencv環境構築 走り書き


基本部分参考
http://nenadbulatovic.blogspot.jp/2013/07/configuring-opencv-245-eclipse-cdt-juno.html

これの「mingw32-make」 を「mingw32-make install」にする。

「bin」フォルダにサンプル「c-example-contours.exe」などができていて動作することを確認すること。動作すればここまではOK


サンプル参考 : これが動作すれば環境構築完了
 http://stackoverflow.com/questions/10860352/getting-started-with-opencv-2-4-and-mingw-on-windows-7

上記binフォルダを環境変数 PATHにしておくこと

 -I オプションは "C:\(opencv)\build\include" opencv解凍したらbuildフォルダがある(mingwの場合使用しなさそうだから見逃した)。その中のincludeを-Iとすること他のincludeとかでは適切な階層にヘッダが無いことがある。

-Lは cmakeで生成されたopencvの「lib」フォルダ、-lオプションのバージョンもそのまま写さないように注意

これで最新バージョン(2.4.7)動作確認。細かい変更やらなにやら(解凍後の「build\x86」にmingw向けのbinが無いなど)で以前と勝手が異なっており1日つぶしたのでメモ