「weblog」カテゴリーアーカイブ

openFrameworksでKinect v2

ちょっとサンプルと実際に使う感じで整理したクラスをアップした。プラグインって程でもなく、サクット使える感じで。Visual Studioの設定とかはこっちを参照

kinectv2sample

流れ的にはKinect v2用SDKの細かい処理はバックグラウンドスレッドで実行して、フロントではバックグラウンドスレッドで取得したデータ処理を行う感じ。色んな方のソースをつまみ食い参考にさせてもらって、マルチスレッド用のロックをちょこちょこ入れている。メモに近いコードだけど、まぁ普通に使ってこんな感じの電気ビリビリ&パーティクルパラパラとかもサクっと出来る感じ。

(続)8pinoを使ってみる

8pinoを使ってみるに続いて、8pinoを使ってArduinoっぽいことをしてみる。まず最初に…ブレッドボードに指せるように8pinoにピンヘッダを付ける。これはわりと決断が必要になる。いや、作業自体はサクッと出来るんだけど、AgICにくっ付けたみたいに、このめちゃ小さい&薄い8pinoにピンヘッダを付けて良いものかどうか…しかも1stの8個のうちの1個をゲットしたのに、ピンヘッダを付けて大きくする事はこの小ささに反する行為なのでは無いか…という決断力が必要になる。そう、自分の判断が正しいのかどうか?という心の葛藤が…

ブレッドボードに差したいという欲求は、直撃でハンダ付けするよりお手軽に試せるという所もあって…まぁ、あとでピンヘッダはハンダを取って外しちゃえば良いっか!!と思って、ピンヘッダを付けちゃうことに><

まずは、リセットボタンとユニバーサル基板になっている部分を切離して、

IMG_3770

まずはブレッドボードにピンヘッダを差しといて、この上に8pinoを置いてハンダ付けをする。

差しといたピンヘッダに8pinoを置いて…ちょちょっとハンダを付けて…

かんりょー!!8pinoが小さすぎて、iPhoneのカメラだとピンぼけしまくる素敵っぷりwww

続いて動作確認。USBを差してバッチリ動く。

んで、これから実際のセンサーを使ってみる。ここでは、目の前にあったGP2Y0A21YK(赤外線距離センサー)とLEDを使って、距離に応じてLEDの光をPWMで強弱を付ける感じの物を作ることに。
Arduino IDEでサクッと書けるから、ちょーーーー簡単!!!!以下な感じでバッチリ動く。

スケッチはめちゃシンプル。[len*2]ってしているのは、GP2Y0A21YKが距離が60-80cmくらいまでしか取れないから、2倍してPWM(0-255)に合わせて光の強さを変えている。

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, INPUT);
}

void loop() {
  int val = analogRead(1);
  int len = 18618/val;
  
  if (len * 2 <= 255)
    analogWrite(0, len * 2);
  delay(10);
}

8pinoを使ってみる

品モノラボに行ってきた。何気に自分、行くのが2回目という(いつも行こうと思ってはいるですが…)。いやー、刺激的っすねー。Web系でもあまり聞かないようなブッ飛び系のアイディアの話を聞いたりして、率直にモノ系以外の人でも参加してみたらメッチャ面白いと思う。

そして…8/8とくれば、8pinoにドキドキしていたら、田中さんよりジャンケン大会で限定8個の争奪戦と!!オイラ、ジャンケン大会とかめっちゃ弱いというか自信のひとかけらも無かったけど、勝っちゃいました。この場で勝負運を発動できたようで、ホントまぢで嬉しいぃぃぃ。

その場でまずは開封の儀を。まずは包装はこんな感じでカッコイイ。

中身をあけると…梱包物一覧は。

ちっちぇぇぇぇー!!早速、その場でマイクロUSBの端子をお借りしてチカチカーっと!!

この小ささに反比例して、むっちゃテンション上がりまくり。深爪な自分の指先ほどの大きさ。
Arduino IDEでの使い方は8pinoにアップされている通りで、自分はMacOS/Windows7のどちらでもArduino IDEからソースを焼け込めた。Windows7の方は追加でドライバを入れれば問題無し。MacはTrinketのIDEを入れて即使える。以下、Macでのやり方は…

Arduino IDEをサイトからダウンロードしたら書いてある通りに、まずはマイコンボードで「Trinket 8MHz」を選択。

次に「USBtinyISP」を選択

これで完了。ちなみに、Arduino IDEから書き込みの時、”Could not find USBtiny device (0x1781/0xc9f)”なんて書き込み失敗が出ると思うけど、8pinoとUSBの抜き差しがリセットという事は…そう、8pinoのUSBを抜き差しした10秒間が書き込みのとき。抜き差しした時にIDEから書き込みをポチっとすれば、すんなり書き込み完了する。

そして、8pinoをマイクロUSBにつけてLチカのコードをサクッと書き込んで終了!!LEDのピンを挟む感じで付けると特にハンダも使わないで動確できる。こんな感じでLEDのピンでキュッと挟んで。

チカチカー!!

そしてAgICとコラボってみる

薄っすーぃ!!ペラッペラで紙と一体化してるよw
サクッと折り紙にして仕込んじゃえるね。

AgICのは、最初の8個という事で、いつもの勢いでしょっぱなからハンダ付けするのは忍び無さ過ぎる…と思ってAgICを使って紙に書くことにした。ATTINY85と一緒な感じでPWMもバッチリー。ちょぴーっとだけ、ハンダ付けしちゃおっかなー。ピンヘッダを付けてブレットボードに刺せるのは合わせてみたらバッチリ出来るのを確認したし、あとはハンダ付けしちゃおーかしらーってオイラの心ひとつ。折角AgIC使って載せられたから、紙の上にセンサー載せちゃおーかしら。指先に8pinoを載せて、何かセンサー反応させて指先ピカピカー!!とか。

Arduino IDEでプログラムをサクッと書いて、この小ささに収めて動かせるというのは、かなり可能性を感じる。Makerやモノ寄りな人だけじゃなく、アートや音系、クリエイターの方でもArduinoを使った作品はよく見るし、この極小サイズは考えること&想像力(妄想力)が膨らみまくると思う。

追記) ピンヘッダの取り付けと、GP2Y0A21YK(赤外線センサ)を一緒に使ってみた内容はこちら。(続)8pinoを使ってみる

openFrameworks 0.8.3 and Kinect v2

環境は以下
– Windows 8.0
– VS 2012
– openFrameworks 0.8.3(x86)

まずMSのサイトからKinect SDKをダウンロードしてきてインストール。

1. Includeに$(KINECTSDK20_DIR)¥inc;を追加

2. Libに$(KINECTSDK20_DIR)¥lib¥x86;を追加

3. DependenciesにKinect20.libを追加

4. コードを書く
Kinect for Windows v2 Developer Preview入門 ― C++プログラマー向け連載をほぼコピってof向けに整形しただけですが…

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxOpenCv.h"
#include <kinect.h>
#include <Windows.h>

using namespace cv;

template
inline void SafeRelease( Interface *& pInterfaceToRelease )
{
	if( pInterfaceToRelease != NULL ){
		pInterfaceToRelease->Release();
		pInterfaceToRelease = NULL;
	}
}

class ofApp : public ofBaseApp{
	public:
		void setup();
		void update();
		void draw();

		bool initializeKinectv2();

		IKinectSensor* pSensor;
		IDepthFrameSource* pDepthSource;
		IColorFrameSource* pColorSource;
		IBodyFrameSource* pBodySource;

		IColorFrameReader* pColorReader;
		IBodyFrameReader* pBodyReader;
		IDepthFrameReader* pDepthReader;

		IFrameDescription* pDepthDescription;
		IFrameDescription* pColorDescription;

		ICoordinateMapper* pCoordinateMapper;


		// buffer
		ofxCvGrayscaleImage grayscaleImage;
		ofxCvColorImage colorscaleImage;

		// 
		int depthWidth, depthHeight;
		unsigned int depthBufferSize;

		int colorWidth, colorHeight;
		unsigned int colorBufferSize;

};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	ofSetVerticalSync(true);
	ofBackground(255, 255, 255);
	// ofSetFullscreen(true);
	ofEnableAlphaBlending();
	ofEnableSmoothing();
	ofSetBackgroundAuto(true);

	if (!this->initializeKinectv2())
		exit();
}

bool ofApp::initializeKinectv2() {
	HRESULT hResult = S_OK;

	// Open Kinect
	hResult = GetDefaultKinectSensor( &this->pSensor );
	if( FAILED( hResult ) ){
		std::cerr << "Error : GetDefaultKinectSensor" << std::endl;
 		return false;
 	}
 	hResult = this->pSensor->Open( );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IKinectSensor::Open()" << std::endl;
 		return false;
 	}

 	// Open Source
 	hResult = this->pSensor->get_ColorFrameSource( &this->pColorSource );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IKinectSensor::get_ColorFrameSource()" << std::endl;
 		return false;
 	}
 	hResult = this->pSensor->get_BodyFrameSource( &this->pBodySource );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IKinectSensor::get_BodyFrameSource()" << std::endl;
 		return false;
 	}
 	hResult = pSensor->get_DepthFrameSource( &this->pDepthSource );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IKinectSensor::get_DepthFrameSource()" << std::endl;
 		return false;
 	}
 	// Open Reader
 	hResult = this->pColorSource->OpenReader( &this->pColorReader );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IColorFrameSource::OpenReader()" << std::endl;
 		return false;
 	}
 	hResult = this->pBodySource->OpenReader( &this->pBodyReader );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IBodyFrameSource::OpenReader()" << std::endl;
 		return false;
 	}
 	hResult = this->pDepthSource->OpenReader( &this->pDepthReader );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IDepthFrameSource::OpenReader()" << std::endl;
 		return false;
 	}
 	// get descriptions
 	hResult = pDepthSource->get_FrameDescription( &this->pDepthDescription );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IDepthFrameSource::get_FrameDescription()" << std::endl;
 		return false;
 	}
 	hResult = pColorSource->get_FrameDescription( &this->pColorDescription );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IColorFrameSource::get_FrameDescription()" << std::endl;
 		return false;
 	}
 	// get coordinate mapper
 	hResult = this->pSensor->get_CoordinateMapper( &this->pCoordinateMapper );
	if( FAILED( hResult ) ){
		std::cerr << "Error : IKinectSensor::get_CoordinateMapper()" << std::endl;
 		return false;
 	}
 	this->pDepthDescription->get_Width( &depthWidth ); // 512
	this->pDepthDescription->get_Height( &depthHeight ); // 424
	this->depthBufferSize = depthWidth * depthHeight * sizeof( unsigned short );

	this->pColorDescription->get_Width( &colorWidth );
	this->pColorDescription->get_Height( &colorHeight );
	this->colorBufferSize = colorWidth * colorHeight * 4 * sizeof( unsigned char );

	this->grayscaleImage.allocate(depthHeight, depthWidth);
	this->colorscaleImage.allocate(colorHeight, colorWidth);

}

//--------------------------------------------------------------
void ofApp::update(){

	// get depth frame
	Mat bufferMat( depthHeight, depthWidth, CV_16SC1 );
	Mat depthMat(depthHeight, depthWidth, CV_8UC1 );

	cv::Mat colorBufferMat( colorHeight, colorWidth, CV_8UC4 );
	cv::Mat colorMat( colorHeight, colorWidth, CV_8UC4 );

	// Frame
	IDepthFrame* pDepthFrame = nullptr;
	HRESULT hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );

	if(SUCCEEDED( hResult )){
		hResult = pDepthFrame->AccessUnderlyingBuffer( &depthBufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );
		if( SUCCEEDED( hResult ) ){
			bufferMat.convertTo(depthMat, CV_8U, -255.0f / 4500.0f, 255.0f);
			grayscaleImage.setFromPixels(depthMat.data, depthWidth, depthHeight);
		}
	}
	SafeRelease( pDepthFrame );


	// get color frame
	cv::Vec3b color[6];
	color[0] = cv::Vec3b( 255,   0,   0 );
	color[1] = cv::Vec3b(   0, 255,   0 );
	color[2] = cv::Vec3b(   0,   0, 255 );
	color[3] = cv::Vec3b( 255, 255,   0 );
	color[4] = cv::Vec3b( 255,   0, 255 );
	color[5] = cv::Vec3b(   0, 255, 255 );

	IColorFrame* pColorFrame = nullptr;
	hResult = pColorReader->AcquireLatestFrame( &pColorFrame );
	if( SUCCEEDED( hResult ) ){
		hResult = pColorFrame->CopyConvertedFrameDataToArray( colorBufferSize, reinterpret_cast<BYTE*>( colorBufferMat.data ), ColorImageFormat_Bgra );
		/*
		if( SUCCEEDED( hResult ) ){
			cvtColor(colorBufferMat, colorMat, CV_BGR2RGB);
			colorscaleImage.setFromPixels(colorMat.data, colorWidth, colorHeight);
		}
		*/
	}
	SafeRelease( pColorFrame );

	// get body frame
	IBodyFrame* pBodyFrame = nullptr;
	hResult = pBodyReader->AcquireLatestFrame( &pBodyFrame );
	if( SUCCEEDED( hResult ) ){
		IBody* pBody[BODY_COUNT] = { 0 };
		hResult = pBodyFrame->GetAndRefreshBodyData( BODY_COUNT, pBody );
		if( SUCCEEDED( hResult ) ){
			for( int count = 0; count < BODY_COUNT; count++ ){
 				BOOLEAN bTracked = false;
 				hResult = pBody[count]->get_IsTracked( &bTracked );
				if( SUCCEEDED( hResult ) && bTracked ){
					Joint joint[JointType::JointType_Count];
					hResult = pBody[ count ]->GetJoints( JointType::JointType_Count, joint );
					if( SUCCEEDED( hResult ) ){
						// Left Hand State
						HandState leftHandState = HandState::HandState_Unknown;
						hResult = pBody[count]->get_HandLeftState( &leftHandState );
						if( SUCCEEDED( hResult ) ){
							ColorSpacePoint colorSpacePoint = { 0 };
							hResult = pCoordinateMapper->MapCameraPointToColorSpace( joint[JointType::JointType_HandLeft].Position, &colorSpacePoint );
							if( SUCCEEDED( hResult ) ){
								int x = static_cast( colorSpacePoint.X );
								int y = static_cast( colorSpacePoint.Y );
								if( ( x >= 0 ) && ( x < colorWidth ) && ( y >= 0 ) && ( y < colorHeight ) ){ 									if( leftHandState == HandState::HandState_Open ){ 										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 0, 128, 0 ), 5, CV_AA );
 									} else if( leftHandState == HandState::HandState_Closed ){
 										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 0, 0, 128 ), 5, CV_AA );
 									} else if( leftHandState == HandState::HandState_Lasso ) {
 										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 128, 128, 0 ), 5, CV_AA );
 									}
 							        }
 							}
 						}
 						// Right Hand State
 						HandState rightHandState = HandState::HandState_Unknown;
 						hResult = pBody[count]->get_HandRightState( &rightHandState );
						if( SUCCEEDED( hResult ) ){
							ColorSpacePoint colorSpacePoint = { 0 };
							hResult = pCoordinateMapper->MapCameraPointToColorSpace( joint[JointType::JointType_HandRight].Position, &colorSpacePoint );
							if( SUCCEEDED( hResult ) ){
								int x = static_cast( colorSpacePoint.X );
								int y = static_cast( colorSpacePoint.Y );
								if( ( x >= 0 ) && ( x < colorWidth ) && ( y >= 0 ) && ( y < colorHeight ) ){
									if( rightHandState == HandState::HandState_Open ){
										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 0, 128, 0 ), 5, CV_AA );
									}
									else if( rightHandState == HandState::HandState_Closed ){
										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 0, 0, 128 ), 5, CV_AA );
									}
									else if( rightHandState == HandState::HandState_Lasso ){
										cv::circle( colorBufferMat, cv::Point( x, y ), 75, cv::Scalar( 128, 128, 0 ), 5, CV_AA );
									}
								}
							}
						}

						// Joint
						for( int type = 0; type < JointType::JointType_Count; type++ ){
 							ColorSpacePoint colorSpacePoint = { 0 };
 							pCoordinateMapper->MapCameraPointToColorSpace( joint[type].Position, &colorSpacePoint );
							int x = static_cast( colorSpacePoint.X );
							int y = static_cast( colorSpacePoint.Y );
							if( ( x >= 0 ) && ( x < colorWidth ) && ( y >= 0 ) && ( y < colorHeight ) ){
								cv::circle( colorBufferMat, cv::Point( x, y ), 5, static_cast< cv::Scalar >( color[count] ), -1, CV_AA );
							}
						}
					}
				}
			}
			cvtColor(colorBufferMat, colorMat, CV_BGR2RGB);
			colorscaleImage.setFromPixels(colorMat.data, colorWidth, colorHeight);
		}
	}
	SafeRelease( pBodyFrame );

}

//--------------------------------------------------------------
void ofApp::draw(){
	colorscaleImage.draw(0, 0);
	grayscaleImage.draw(0, 0);
}

5. 実行

脳波で迷路@ヤミ市

迷路いっぱい出来ました。

個々人の迷路は32×32マスで作成して、生成には約1分で完了ですね。そして79人分全員の脳波データを集めて1個の大きな迷路を作成しました。こちらは120×120マスで生成した結果はこちらです。

こちらは、誰かが(脳波で)作成した個人の迷路です。

同じサイズで見ると、密度が全然違います。32マスの方は生成される迷路の総数は約40億、120マスの方は115京個くらいです。どちらも膨大なパターンです。

他の個々人で作成した迷路も「入り口・出口」を用意すると解けます。変な所に用意すると閉路になっている所もあるので。最後は持って行った光沢紙が無くって終了でした。

WordPressの高速化

自分がマジメにやる時のWPの高速化方法について。一応、色々と設定とかをして、仮想(お名前.com KVM, MEM 2GB, CPU:3)サーバ1台で 10,000 access/sec くらいは普通に捌けてCPU負荷もほとんど上がらない感じには出来る。つかキャッシュだけどねw
以下、全部やっても1時間もかからずサクっと出来るはず。

– 構成
NginX + WordPress(FastCGI/Apacheどっちでも) + MySQL
まぁ、普通の3層構成っすね。

– 路線
簡単なチューニングとNginXのキャッシュを使う。

– 方法
1. APCを使う
これはオンにすれば即完了。迷う事無し。

2. ngx_pagespeedを入れてみる
多少は変わる。気休めだと思うけど。

3. NginXでgzipを有効にする。
いわゆるコンテンツの圧縮転送。高速化というか、クライアント側にも優しくなれる。

4. NginXのキャッシュを使う
これが本質。普通にNginXのキャッシュを使うと、WP側で記事の更新をしてもキャッシュがクリアされるまで記事が更新されないという残念な事になる。また、WordPressのSuperCacheなる物も結局はAP層(WP)までアクセスが来るので、出来るだけNginX側で全て完結させる。流れ的には以下。

4.1. nginx cache purgeモジュールをNginXに導入する
4.2. Word Press側にNginx Proxy Cache Purge WordPressをプラグインからインストール
4.3. NginX側のconfig, WP側の設定をして終わり。

実際の個別の方法とかはググれば出てくるからそれを参照に。あとwp-adminをキャッシュ対象から外すのも忘れずに。基本的に全部NginX側でキャッシュ、記事やコメントとか変更があったらそのページだけPurgeするという素敵な感じになる。他に色々とプラグインを入れて重いぜ…って事もあんまり関係無くなる。
WordPress側のキャッシュを使う例がよく散見するけど、NginXを使っているならそこで完結させた方が良い。あとどーしても、ApacheでWord Pressを動かしたいぜ!!という理由があれば、Varnishを使うとかってのもあるけど、余計なプロセスは出来れば動かしたく無いからね。

– その他(備忘)
カーネルチューニングとかってのもあるけど、あんまり劇的には変わらんでしょう。他にDBのバッファを増やすとかも、ただ、ふつーのVPSのメモリ(2G-4G)でそれをやった所であんまり何かパッとしないもんね。
他に自分がよくやったりする手法では、PHPのプロセス事前生成& Persistenceを有効にしたり、NginX/Apacheの基本的な設定の確認・見直しとか。PHPってマルチスレッドとかじゃなく、1アクセスに対してforkされた1個のPHPプロセスが対応して動作するから、仮に1アクセスに1秒かかるプログラムの場合、同時100アクセスが瞬間にきたら100個プロセスが無いとあとはキュー待ちというか、backlogに回って順番待ちになる。つまり、FastCGI/Apacheでのプロセス数とAPの秒間の性能、更にCPU数(LoadAvgのキュー)といった感じで可視化される訳で、結局PHPみたいな1リクエストに対して1プロセスで応答する物って、アクセス数を捌くためには最終的にはプロセス数・メモリ・CPU数・サーバ数とリクエスト数の関係がスケールする事になる。ThreadingしたところでCPUリソースは結局消費される訳だけどね。それを避けるために、キャッシュとかを使って軽くするって感じー。

DockerでElasticsearchとKuromoji

何となくelasticsearchをDockerで動かしたくなって探してみたら、

docker search elasticsearch

スゲーあるのね。ただKuromojiを使えそーな物がちょっとなくって、ググって調べてみたけど、ちょい前のだったり動かなかったりして…って事で、dockerfile/elasticsearch をforkしてサクっと作った。elasticsearchは1.3.0、kuomoji 2.3.0とHQが入る。今時点で、最新のelasticsearch(1.3.0)と対応するkuromojiで(elasticsearchのバージョンが変わると対応するkuromojiのバージョンも変わったりする)。こんな感じでめちゃ簡単。ポートの9200, 9300は通しておけば、以下コピペで完了。

# make elasticsearch container
git clone https://github.com/hirotakaster/elasticsearch
cd elasticsearch
docker  build -t hirotakaster/elasticsearch .
docker  run -d -p 9200:9200 -p 9300:9300 hirotakaster/elasticsearch

# search test
curl -XPUT 'http://localhost:9200/kuro_test/' -d'
  {
      "index":{
          "analysis":{
              "tokenizer" : {
                  "kuromoji" : {
                     "type" : "kuromoji_tokenizer"
                  }
              },
              "analyzer" : {
                  "analyzer" : {
                      "type" : "custom",
                      "tokenizer" : "kuromoji"
                  }
              }
          }
      }
  }'

# {"acknowledged":true}

curl -XPOST 'http://localhost:9200/kuro_test/_analyze?analyzer=analyzer&petty' -d '今日はラーメンだ'
{"tokens":[{"token":"今日","start_offset":0,"end_offset":2,"type":"word","position":1},{"token":"は","start_offset":2,"end_offset":3,"type":"word","position":2},{"token":"ラーメン","start_offset":3,"end_offset":7,"type":"word","position":3},{"token":"だ","start_offset":7,"end_offset":8,"type":"word","position":4}]}

おわり。HQへは、http://localhost:9200/_plugin/HQ/ でアクセス。

FlyngBallで遊んでみる

FlyngBallがどういう物かと言うと…

こんな感じで上下に飛ぶ物。羽が4枚ついていて、下部にある赤外線センサで地面(もしくは手とかかざして)が近づいたら、上がって行くシンプルなもの。上がるといっても3m位な感じ。普通にAmazonで買えます

白色LEDが内蔵されているから、こやつを大量に用意して夜にババーっと飛ばしたら、光りながら空中を動いて面白いかなと思った。たぶん綺麗な気はするけど、あきりたりな感じ&数を揃えただけーって感じもするし…まぁこの子で楽しんでみる事に。
中身は上図のように、リチウムポリマーとモーター、基板が付いている。

  

飛ばしている所を撮ってもらいました。中身をばらすとこんな感じ。

一番左が赤外線、左から2番目がON/OFFスイッチ、真ん中が充電用、一番右がリモコン受信部って感じ。まぁ普通に遊べるんだけど、ぶっちゃけすぐ何かがおかしくなります。自分が壊したパターンは…

 

・普通にまっすぐ上下に飛ぶ事は無いです。ちょっとバランスが崩れると、左右に暴れて飛んだり、墜落〜床に落ちて暴れまくります。自分は間違って踏んでしまい、あっさりシャフトが折れ曲がって修復不能になってしまった。

・天井が低いと、思いっきり天井にぶつかりまくります。ある程度高い天井でも、誤って手を赤外線センサの下にいれようものなら、勢い良く天井にぶつかって墜落します。墜落の衝撃で何かおかしくなってしまう。多分、この墜落パターンが一番多い気がする。

 

シャフトが折れて壊れるのは修復不能っす。床で暴れている時に間違って踏みつけorキックとかしないように…どうせ壊すと思って2個買ったけど、誤って踏みつけ&シャフトを曲げた時はさすが軽く涙目でした。んで、次の墜落パターンはかなり多い。もうボコボコ墜落しまくるwww
そして墜落しまくると、まず玉の内部の何かおかしい事になるか、壊れます。自分で玉を分解して治せないと「買って何度か飛ばしているうちに、動かなくなって終了」というパターンになると思われ。

このピンポン玉みたいな物を分解するには、超精密ドライバーが必要不可欠です。ダイソーで100円とかで売ってると思うので。この子ね。

墜落その1。ギアが外れる。

この上の方の羽を回しているシャフトは、下のシャフトの中を通している構造になっている。この上の羽につながっているシャフトのギアは、何かに衝突した衝撃でよく取れる。何度かぶつけるとすぐギアが上図のように外れてしまう。という事で、羽が動かなくなったら玉をばらしてギアを下のように取り付け直すと復活します。

墜落その2。ポキっと折れる。

そう、この左側(リポの方)のネジのソケットの所に本当は右部のように支えが入る。この部分が真ん中近くからポキっと折れる。これが折れると飛んでいる最中に中でバランスが取れなくなって、恐ろしい動きをする。例えば赤外線センサ部分が玉の中に入り込んで、延々と飛び続けたり、バランスがそもそも取れなくて床で暴れまくる。
ポキっと折れた部分は玉の中に入っていると思うので、折れた部分をつなぎ治せば修復完了。

何にしても…普通に飛ばして楽しもうとすると、すぐ何かおかしくなると思われです。すぐ動かなくなってコイツやべぇじゃん!!って訳でもなくって、大して複雑な感じでも無いし中を開けて見れば治せると思われ。

How to build PCL for Android memo

PCL(Point Cloud Library) can use on Android, but don’t supply Android binary. So let’s build PCL using Android NDK on MacOS 10.9.4!! verrrry easy to build.

wget http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2
tar -jxvf android-ndk-r8c-darwin-x86.tar.bz2
cd android-ndk-r8c
export ANDROID_NDK=$PWD
cd ~work
git clone https://github.com/hirotakaster/pcl-superbuild.git
cd pcl-superbuild
mkdir build
cd build
cmake ../
make -j4 # j4 is prallel build option

All build finish, you will find following include and library.
pcl-superbuild/build/CMakeExternals/Install/boost-android/
pcl-superbuild/build/CMakeExternals/Install/flann-android/
pcl-superbuild/build/CMakeExternals/Install/pcl-android/

Next build android application(like a Google Project tango) with PCL and NDK library.

VoIP Packet Capture

全てUDP(RTP)を利用している(LINEは暗号化されて不明だけど、過去記事からはRTPという事で…UDPしか流れてないし)、通話時のパケットのキャプチャ結果。
縦軸はパケット数、バイト数の2グラフ。クライアントはiPhone 5 LTEで、facetime/LINE/Skypeクライアントの所でキャプチャーをした結果。アプリは全て最新版。どう判断するかはあなた次第…ただ、自分的にはグリーンな所が良さげな気がする。

使われているコーデックは、
Facetime : AAC-ELD
LINE : AMR, G.723.1(どちらも、そうらしい位な感じ)
Skype : SiLK(Opus)
ちなみに、どれもメディア部分は暗号化(facetimeとskypeはAES 256、lineは不明)されている感じ。

■ facetime

packets per sec

bandwidth(bytes per sec)

■ LINE

packets per sec

bandwidth(bytes per sec)

■ Skype

packets per sec

bandwidth(bytes per sec)