2009年12月12日土曜日

カメラを買ってみた


携帯のカメラが壊れたのでデジカメを買ってみました.
いろいろ設定を変えて撮ったり画像処理で調整したりして遊んでいますが,
同じ景色でも肉眼で見るのとは違う印象になっていて,おもしろいです.
意外と星が撮れることに特に驚いています.

2009年8月29日土曜日

Springer Exemplar

最近,英語で文章書くときに Springer Exemplar というサービスを使ってます.

このサービスは学術系の本でよく見る Springer 社の無料サービスで
指定した単語,または節が使われている例文を,同社が出版してる文献から検索して
列挙してくれるサービスです.

実は一時期似たようなのを自分で作って使っていたのですが,やっぱり大手が作ると
元のデータの量が多くて良いです.

気になった点は

  • 結果のソート順の基準がよくわからない.
  • 遅い

といったところですね.
あと,検索した後に左の方に分野・国ごとのヒット数がでているようですが,こちらも興味深いです.やっぱり日本人は良く "on the other hand" って使うんですね.

2009年8月24日月曜日

プレゼンテーション・ディレクターの設定

「プレゼンテーション・ディレクター」はThinkpad についているソフトで
プレゼンテーション用のディスプレイ設定(スクリーンセーバーオフとか通知機能オフとか)と
通常の設定をワンタッチで切り替えられる,そこそこ便利なソフトです.

ですが,このソフトには致命的な不具合があって僕が使ってるThinkpadの画面解像度1440x900をサポートしていません.
正直言って添付ソフトでこれはマズイような気もしますが,とりあえずの対処法を見つけたのでメモしておきます.

  1. 「メニューの設定」を開き,オプションボタンを押す
  2. 「スキームのエクスポート」で設定をエクスポートする
  3. テキストエディタでエクスポートしたファイルを開き,
    Width=1024
    Height=768
    の行を
    Width=1440
    Height=900
    とか書き換えて保存する
  4. 編集したファイルを「スキームのインポート」でインポートする

これで一通り使えるようになりますが,「通常のディスプレイ設定」の項目だけはこの方法を使っても修正できません.早いうちにアップデートで修正されるといいのですが・・・

2009年7月27日月曜日

論理インデックス

最近「論理インデックス(logical indexing)」というMATLABの便利機能に気づきました.
こんなふうに使います.

>> a=[1,2,3,4]
a =
    1 2 3 4
>> a(a>2)
ans =
    3 4
>>

配列のある条件を満たす部分だけ抽出する時に便利です.
通常のインデックス a(find(a>2))とかよりも高速に処理されるらしいです.

2009年6月21日日曜日

TeXclip を更新

この記事の情報は古いです
TeXclipで作成した数式の再編集については


を参照してください.

2009年5月30日土曜日

mov(H.264)形式の動画をPowerPointに挿入する方法

PowerPointでスライドに挿入できる(ことになっている)動画は,大雑把には
  • AVI
  • WMV
  • MPEG1/2
の3種類です.今実験機の撮影に使っているカメラで得られる動画はmov形式(QuickTime)なので,プレゼンで使うPowerPointに挿入するためには変換が必要になります.
簡単なことかと思いきや,意外と苦労しているのでメモを残しておきます.プレゼンでは自分のじゃないマシンで発表しないといけなくなったりすることも多いので,特殊なコーデックの追加とかは試していません.
ちなみに環境はWindows Vista / Powerpoint 2007. 動画はCasio EX-F1でSTD画質(640x480,30fps)で撮影したH.264 mov形式のファイルです.
QuickTime Pro 単体ではうまくいかなかった
一番素直な解はQuickTime Pro を購入して.movファイルを.aviに変換することだと思われるので,とりあえずやってみました.PowerPointに挿入するところまではうまくいったのですが,クリックすると動画が黒くなって再生されません.無圧縮のAVIでは再生まで可能ですが,ファイルサイズが大き過ぎる上に,再生時のディスクアクセスによるコマ落ちが激しく,実用には耐えません.
Windows Media エンコーダを併用すると一応OK
QuickTime Pro を使って一旦無圧縮のAVIを作成した後で,Windows Media エンコーダを併用すると,PowerPointに挿入可能な高画質なwmvファイルを作成できます.画質にこだわらなければ,aviからの変換にWindowsムービーメーカーを使うこともできます.この方法は作業が二段階になる上に有償のQuickTime Proが必要です.研究室の学生全員に使ってもらうにはちょっと面倒すぎる気がします.
Mp4cam2aviではH.264動画を無圧縮aviにすることはできない
mov形式のファイルを無圧縮aviにできそうなフリーソフトとしてMp4cam2aviがあげられますが,今のところH.264の動画のデコードには対応していないようです.
FFmpegでの結果
FFmpegを使うと動画の多彩な変換が可能ですが,PowerPointへの挿入はなかなかうまくいきません.結果を以下の表にまとめます.ちなみに,いずれの形式に変換したときもWindows Media Playerでの再生はできています.
コマンドライン
結果
$ ffmpeg -i test.mov \
  -vcodec wmv1 test.avi
プレビューは正常
再生で暗転

$ ffmpeg -i test.mov \
-vcodec wmv2 test.avi
プレビューは正常
再生で暗転

$ ffmpeg -i test.mov \
-vcodec msmpeg4 test.wmv
挿入時から黒いまま
$ ffmpeg -i test.mov \
-vcodec msmpeg4v2 test.wmv
挿入時から黒いまま
$ ffmpeg -i test.mov \
  -vcodec wmv1 test.wmv
挿入時から黒いまま
$ ffmpeg -i test.mov \
  -vcodec wmv2 test.wmv
挿入時から黒いまま
$ ffmpeg -i test.mov test.mpeg
正常
$ ffmpeg -i test.mov test.m2v
正常(音声無し)
実質的にはmpegの一択ということになります.デフォルトではビットレートが低く(200kbps)画質が実用に耐えないので
$ ffmpeg –i test.mov –b 8192k test.mpeg
という感じでしょうか.
まとめ
色々やってみましたが,
  • ベストを尽くすなら
    1. QuickTime Pro で無圧縮AVIに変換
    (試してないですが,ffmpegでも同等の変換ができるはず?)
    2. Windows Media エンコーダでwmvに変換
    の2段階
  • そこそこでいいなら
    $ ffmpeg –i test.mov –b 8192k test.mpeg
という結論に達しました.あまり高画質な動画を作ってもプレゼンでの効果以上にマシンの要求スペックが上がりそうで怖いですし,ffmpegの変換サーバーを立てて,みんなで使うのが研究室レベルでは正解な気がします.
他にいい方法があればご教授いただければ幸いです.

2009年5月26日火曜日

Arduinoで簡易オシロスコープ

2013/4/22 ライセンスを修正BSDライセンスとしました
Arduinoで簡単に使える簡易オシロスコープもどきを作ってみました.ちょっとした実験にはなかなか便利なので公開しておきます.

スクリーンショット

全体図scr1
マウスで周波数などの読み取りも可能
scr2

操作法

  • [↑][↓] 時間軸の変更
  • [space] データ取得の停止/再開
  • [s] データをcsv形式で保存
  • [マウス操作] 値の読み取り・ドラッグで周波数読み取り

インストール

  • 下記のソースの末尾・Arduino用のプログラムの部分をArduinoに書き込んでおく.
  • 下記のソースをProcessingにコピーし,シリアルポートの設定とフォントの生成/設定を行う.
  • 実行してみる

ソース


// ArduinoScope v1.0.0
// 
// Note:
//  1. please confirm serial port setting
//  2. prepare font
//  3. Arduino code is attached at the end of this code

// Copyright (c) 2009-2013 I. Maruta <ichiro.maruta@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Neither the name of the author nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.

 

import processing.serial.*;

Serial ArduinoPort;  // Create object from Serial class

int NumOfScopes,NumOfInput=2;
int data_span=10000;
Strage dfs = new Strage();
Scope[] sp;

int fontsize=16;
PFont myFont;

void setup() 
{
  // Serial Port 
  println(Serial.list());
  String portName = Serial.list()[0]; // TODO: automatic detection?
  ArduinoPort = new Serial(this, portName, 38400);
  ArduinoPort.bufferUntil(10);

  // Screen
  size(800, 600);
  NumOfScopes=2;
  sp = new Scope[NumOfScopes];
  sp[0]= new Scope(0,50,10,width-100,height/2-35,512,-512,1000);
  sp[1]= new Scope(1,50,height/2+15,width-100,height/2-35,1024,0,1000);

  myFont = loadFont("Dotum-16.vlw");
  textFont(myFont,fontsize);
}

class Scope{
  int input_id;    // corresponding input
  int posx,posy;   // screen position of the scope
  int sizex,sizey; // pixel size of the scope
  float yu,yl;     // range of y is [yl,yu]
  int tspan;       //
  int ngx,ngy; // number of grids
  float maxposx,maxposy,minposx,minposy,maxx,minx,maxy,miny;

  Scope(int did,int px,int py,int sx,int sy,float syu,float syl,int ts){
    input_id=did;
    posx=px; 
    posy=py;
    sizex=sx; 
    sizey=sy;
    yu=syu; 
    yl=syl;
    tspan=ts;
    ngx=10; 
    ngy=4;
  }

  void grid(){
    pushStyle();
    fill(255,196);
    stroke(0,0,150);
    for(float gx=sizex; gx>=0; gx-= (float)sizex/ngx){
      line(posx+gx,posy,posx+gx,posy+sizey);
      textAlign(CENTER,TOP);
      text((int)map(gx,sizex,0,0,-tspan),posx+gx,posy+sizey+2);    
    }
    for(float gy=sizey; gy>=0; gy-= (float)sizey/ngy){
      line(posx,posy+gy,posx+sizex,posy+gy);
      textAlign(RIGHT,CENTER);
      text((int)map(gy,0,sizey,yu,yl),posx,posy+gy);    
    }
    popStyle(); 
  }

  int curx,cury;

  // draw cursor
  void cur()
  {
    // return if mouse cursor is not in this scope
    if(constrain(mouseX,posx,posx+sizex)!=mouseX 
      || constrain(mouseY,posy,posy+sizey)!=mouseY) return;

    pushStyle();

    // draw cross cursor
    stroke(255,0,0,196);
    fill(255,0,0,196);
    line(mouseX,posy,mouseX,posy+sizey);
    line(posx,mouseY,posx+sizex,mouseY);

    // draw measure if mouse is dragged
    if(mousePressed){
      line(curx,posy,curx,posy+sizey);
      line(posx,cury,posx+sizex,cury);
      textAlign(RIGHT,BOTTOM);
      text((int)map(curx,posx,posx+sizex,-tspan,0)+"ms, "+(int)map(cury,posy,posy+sizey,yu,yl),curx,cury);
      textAlign(LEFT,TOP); 
      text("("+nfp((int)map(mouseX-curx,0,sizex,0,tspan),1)+"ms, "+nfp((int)map(mouseY-cury,0,sizey,0,-(yu-yl)),1)+")\n"+nf(1000/map(mouseX-curx,0,sizex,0,tspan),1,2)+"Hz\n"+nf(TWO_PI*1000/map(mouseX-curx,0,sizex,0,tspan),1,2)+"rad/sec",mouseX,mouseY+2);
    }
    else{
      curx=mouseX;
      cury=mouseY;
      textAlign(RIGHT,BOTTOM);
      text((int)map(curx,posx,posx+sizex,-tspan,0)+"ms, "+(int)map(cury,posy,posy+sizey,yu,yl),curx,cury);
    }
    popStyle();
  }

  // draw min&max tick
  void minmax(){
    pushStyle();
    fill(255,128);
    stroke(0,0,100);
    textAlign(RIGHT,CENTER);
    line(posx,maxposy,posx+sizex,maxposy);
    text((int)maxy,posx,maxposy); 
    line(posx,minposy,posx+sizex,minposy);
    text((int)miny,posx,minposy); 
    textAlign(LEFT,CENTER);
    textAlign(CENTER,TOP);
    text("max",maxposx,maxposy); 
    textAlign(CENTER,BOTTOM);
    text("min",minposx,minposy+20); 
    popStyle();
  }

  // draw scope
  void Plot(){
    float sx,sy,ex,ey;
    int nof=0;
    DataFrame df_last = dfs.get(0);

    maxy=-1e10; // -inf
    miny=1e10;  // +inf

    // draw background (for transparency)
    pushStyle();
    noStroke();
    fill(0,0,64,64);
    rect(posx,posy,sizex,sizey);
    popStyle();

    // draw data plot
    pushStyle();
    stroke(0,255,0);
    smooth();
    strokeWeight(1);
    for(int idx=0;(dfs.get(idx).t>max(df_last.t-tspan,0)) && -idx<data_span;idx--){
      DataFrame df_new=dfs.get(idx);
      DataFrame df_old=dfs.get(idx-1);
      sx=(float) map(df_new.t, df_last.t, df_last.t - tspan, posx+sizex,posx);
      ex=(float) map(df_old.t, df_last.t, df_last.t - tspan, posx+sizex,posx);
      sy=(float) map((float)df_new.v[input_id],(float) yu,(float) yl,(float) posy,(float) posy+sizey );
      ey=(float) map((float)df_old.v[input_id],(float) yu,(float) yl,(float) posy,(float) posy+sizey );
      if(ex<posx){
        ey+=(sy-ey)*(posx-ex)/(sx-ex);
        ex=posx;
      }
      line(sx,sy,ex,ey);
      maxy=max(maxy,df_new.v[input_id]);
      if(maxy==df_new.v[input_id]){
        maxposx=sx;
        maxposy=sy;
      }
      miny=min(miny,df_new.v[input_id]);
      if(miny==df_new.v[input_id]){
        minposx=sx;
        minposy=sy;
      }
      nof++;
    }
    popStyle();

    //    minmax();    

    // draw current value of input
    pushStyle();
    textAlign(LEFT,CENTER);
    stroke(0,0,64);
    fill(0,255,0,196);
    text(df_last.v[input_id],posx+sizex,map(df_last.v[input_id], yu, yl, posy, posy+sizey ));
    popStyle();   

    grid();
    cur();    
  }
}

void draw() 
{ 
  background(0);

  for(int i=0;i<NumOfScopes;i++){
    sp[i].Plot();
  }
}

// input data buffer class
// (now using ring buffer)
class Strage{
  int cur;
  DataFrame[] DataFrames;

  Strage(){
    cur=0;
    DataFrames=new DataFrame[data_span];
    for(int idx=0;idx<data_span;idx++){
      int ret_v[] = new int[NumOfInput];
      DataFrames[idx] = new DataFrame(0,ret_v);
    }
  }

  void push(DataFrame d){
    cur = ((cur+1) %data_span);
    DataFrames[cur]=d;
  }

  DataFrame get(int idx)
  {
    int num=(cur+idx);
    for(; num<0; num+= data_span);
    return((DataFrame) DataFrames[num]);
  }

  void save()
  {
    String savePath = selectOutput();  // Opens file chooser
    if (savePath == null) {
      // If a file was not selected
      println("No output file was selected...");
    }else{
      PrintWriter output;
      output = createWriter(savePath); 
      DataFrame df_last = this.get(0);
      for(int idx=0;-idx<data_span;idx--){
        if(this.get(idx).t==0) break;
        output.print(this.get(idx).t-df_last.t);
        for(int k=0;k<NumOfInput;k++){
          output.print(","+this.get(idx).v[k]);
        } 
        output.println("");
      }
      output.flush();
      output.close();
    }
  }
}

class DataFrame{
  int t;
  int[] v;
  DataFrame(int st, int[] sv){
    t=st;
    v=sv.clone();
  }
}

boolean isactive=true;

// buffering data from serial port
void serialEvent(Serial myPort)
{
  int[] vals=new int[NumOfInput];
  int timestamp;
  int[] splitdata;
  if( myPort.available() > 0) { 
    String datline=myPort.readString();
    splitdata=parseInt(datline.split(","));
    if((splitdata.length==NumOfInput+2)){
      timestamp=splitdata[0];
      for(int idx=0;idx<NumOfInput;idx++){
        vals[idx]=splitdata[idx+1];
      }
      if(isactive){
        if((timestamp-dfs.get(0).t)<0){
          dfs.cur--;
        }
        if((timestamp-dfs.get(0).t) > ((float)sp[0].tspan / sp[0].sizex/2.0) ){
          dfs.push( new DataFrame(timestamp,vals));
        }
      }
    }
  }
}

// keyboard user interface
void keyPressed(){
  switch(key){
    // activate/deactivate scope update
  case ' ':
    isactive=!isactive;
    break;
    // save record
  case 's':
    dfs.save();
    break;
  case CODED:
    switch(keyCode){
      // Increse time span
    case UP:
      for(int i=0;i<NumOfScopes;i++){
        sp[i].tspan*=2;
      }
      break;
      // Decrease time span
    case DOWN:
      for(int i=0;i<NumOfScopes;i++){
        sp[i].tspan/=2;
      }
      break;
    }
    break;
  }
}

/* Arduino code
void setup()
{
  Serial.begin(38400);  
}

void loop()
{
  Serial.print(millis());
  Serial.print(",");
  Serial.print(analogRead(0));
  Serial.print(",");
  Serial.print(analogRead(1));
  Serial.println(",");
}
*/

たぬき?

きょう宇治構内の水路にたぬきみたいな動物が出没しました.思わず写真を撮ってしまった・・・

たぬき正面

夜中には結構いるんですが,昼間に見るのは初めてです.よほど飢えていたのか・・・

水路内たぬき たぬき振り向き

たぬき手を洗ってる

たぬき隠れた

2009年5月22日金曜日

SyntaxHighlighter2でMATLABソースを表示 in Blogger

以前SyntaxHighlighterをMATLAB対応にしました.その後,ファイルを置いてあるサーバーの更新があったり,SyntaxHighlighterがバージョン2になったりで使えない状態で放置していたので,改めて作りなおしてみました.

BloggerでSyntaxHighlighter2を使う

まず最初にBloggerでSyntaxHighlighter2をつかうときの設定ですが,テンプレートに

<!--ここから -->
    <script src='http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shCore.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushPlain.js' type='text/javascript' />
    <script src='http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushXml.js' type='text/javascript' />
    <script src='http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushCss.js' type='text/javascript' />
    <script src='http://alexgorbatchev.com/pub/sh/2.0.278/scripts/shBrushJScript.js' type='text/javascript' />
    <script src='http://maru.bonyari.jp/storage/shBrushMatlab.js' type='text/javascript'/>
<!--ここまで -->
</head>
...
<!-- end outer-wrapper -->
<!--ここから -->
<script type='text/javascript'>
//<![CDATA[ 
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.all();
//]]>
</script>
<!--ここまで -->

のように追加するといいようです.config.bloggerModeの設定がないと改行の位置にBRタグの出来そこないが出現します.

MATLABのソースをSyntaxHighlighterで成形する

【使い方】

上記のファイルを通常の”shBrush*.js”と同じように読み込んで,class=”brush:matlab”で使えます.上のサーバーに置いてあるのを読み込んでも構いませんが,無保証自己責任でお願いします.ちなみにSyntaxHighlighter本体も本家でホスティングされているようですね.(リンク)
上の設定例はこのホストを使う設定にしてます.

2009年5月18日月曜日

MATLABで並列計算(PSO)

素のMATLABは並列計算に弱いようで,最近のデュアルコアのPCだと,プロセッサ使用量が50%で頭打ちします.

ただ,最近学校の MATLAB ライセンスに Parallel Computing Toolbox が加わって一部関数が置き換えられたためか,単にバージョンアップの恩恵なのかは知りませんが,一部の計算ルーチンがマルチコア用にコンパイルされているらしく,計算によっては50%を超えるプロセッサ使用率を見ることもできるようになりました.

でも依然として,大半の処理は片方のコアのみで処理されるようです.
本来は並列計算できる部分は処理系が自動的に判別して最適に処理してくれるのが理想なんですが,なかなか実現されないですね.また,最近はコア1つ当たりの性能向上は収束気味で,今後はコアの数が増える方向にPCは進化するようなので,今後MATLABでPCの進化の恩恵を享受するためには,並列計算のスキルを身につけておく必要がありそうです.

MATLAB で Parallel Computing Toolbox が使える場合,単一マシンで並列処理をするのはとても簡単で
matlabpool 2 %デュアルコアの場合
parfor idx=1:100
   % 並列化する処理
end
matlabpool close

とやれば並列に処理されます.matlabpool の後の数字は生成されるスレッド数です.

結構並列化のオーバーヘッドがあるようで,単位処理の計算量があまりに小さい場合,かえって遅くなることもあるようです.結果が芳しくないときはプロファイラでチェックしてみるべきですね.

Particle Swarm Optimization (PSO) なんかは並列計算の恩恵を最大限に受けられるアルゴリズムなので,目的関数の評価に時間がかかる問題であれば,処理速度がほぼコア数倍になります.(といってもまだデュアルコアでしか試してませんが・・・)

もうちょっと手間をかけると複数のマシンをつないでクラスタリングとかもできるようなので,人がいない夜中とかに実験室のマシンを束ねて試してみようかな〜

・・・・と思ったらクラスタリングには MATLAB Distributed Computing Server っていう別製品が必要なようですね.
また,Parallel Computing Toolbox ではスレッドの数も4つまでに制限されてるようです.
つまり現状ではクアッドコアのXeon W3570以上のCPUを使っても性能向上は期待できないということかな?
値段を考えると2.66GHzのXeon W3520か,近々更新される見込みなCore i7あたりが計算用マシンのCPUとしてはベストになるのだろうか・・・

2009年4月15日水曜日

通販できる海外のホビーロボット用部品店

ネットを使うと海外からも簡単に部品が買えて良いですね.
最近目を付けてる海外サイトをメモしておきます.

  • Gravitech
    Arduino nanoを売ってます.僕が注文したときは12日で届きました.ちなみに送料は$5.85.スイッチサイエンスさんから買った方が速いし,値段もトータルでは同じくらいのはず.
  • Dimension Engineering
    モータードライバー,センサーなど.僕が購入したときはUSPS First Classで送料$2.5,一週間くらいで着きました.急ぐのならメカロボショップさんでも購入できます.
  • RobotShop
    ロボット材料,モジュールなどなど.ルンバをbluetooth接続するキットとかを売っているのが気になる.日本からも通販できるようだけど,重量物は送料が怖い・・・
  • Pololu Robotics and Electronics
    モータードライバ,センサー等々.試したことはないけど,日本からも購入可能なはずです.配送はUSPS First Classのようなので,一週間そこそこで着くはず.送料は基板程度なら$2.5だと思います.急ぐのならメカロボショップさんでも購入できます.
  • Endurance
    R/Cラジコンの部品.PCTx (パソコンをラジコンの送信機にするデバイス)が売ってるのでメモ.
  • The Robot Marketplace
    なんか凶悪そうなモーターが売ってるのでメモ.パワー系ロボコン用ですね
  • SuperDroid Robots
    ロボット関連いろいろ.オムニホイールを扱っているのでメモ.
  • SparkFun
    Arduino関連が超有名.大抵のものはスイッチサイエンスさんで扱っているので,そちらから購入した方が良いでしょう.最近は日本橋でもSparkFun製品を結構見かけますね.

2009年4月8日水曜日

Gainer mini でオシロスコープもどき

最近お手軽なマイコンが流行しているみたいで,僕も色々手を出しています.

Gainer はパソコンとUSBで接続できて,Processing等のお手軽な言語で
パソコン側から制御できるI/Oモジュールです.Gainer mini はその互換機で,より小型のモジュールになってます.
プログラムが簡単なので,芸術作品とかに良く使われてるみたいですね.

純粋な芸術作品にはあまり興味はないんですが,
融通の利く計測装置として便利そうなので,一つ購入してオシロスコープもどきを作ってみました.
パソコン側のスクリーンショットはこんな感じ


Sparkfunのジャイロセンサー(MLX90609・1軸)と秋月の加速度センサー(KXM52-1050・3軸)を接続して動かしている動画.



計測周期は4チャンネルで10msを若干切るくらいが限界のようですね.単チャンネルなら2ms前後までいけるかも知れません.
OSごとの時刻取得関数に依存してしまいますが,10ms程度の制御周期でよければ制御にも使えそうな感じもします.ただ,MacのProcessingの実装では時刻取得関数millis()の精度が良くないようで,厳しいかもしれません.

2009年3月24日火曜日

MATLABでフィードバック系のシミュレーション

たまにうっかり忘れるのでメモ.

MATLABでプラントPと制御器Kが構成するフィードバック系のシミュレーションをするとき,
>> s=tf('s');
>> P=1/s;
>> K=1/(1+s);
>> step(P*K/(1+P*K))
とかやるのはNG.正しくは
>> step(feedback(P*K,1))
とする.一見結果は同じなのだけど
>> P*K/(1+P*K)

Transfer function:
s^2 + s
-----------------------
s^4 + 2 s^3 + 2 s^2 + s

>> feedback(P*K,1)

Transfer function:
1
-----------
s^2 + s + 1

>>
という違いがあり,高次のシステムを使うときになって初めて問題が顕在化したりしてよろしくない.
システムの割り算はMATLABでは逆システムの計算と直列接続で計算されるので,この場合P*Kと1+P*Kが共通の極を持っているにも関わらず,これらが相殺されないことによって問題が起こる.
ちなみにseriesとparallelを*と+で書くのは,少なくともSISOの場合には問題ない(中でやってる処理は同じ).MIMOの場合は未確認.

MATLABに限らないけど,強力なツールを使うのは楽なようで難しい・・・
ソースを全部追うのは大変だし・・・

2009年3月22日日曜日

使えそうな部品探索@日本橋(モータードライバ編)

昔ほど頻繁に日本橋に行かなくなったので,どこの店にどの部品があるか把握できない・・・
というわけで,今後のためにまとめておきます.今回はモータードライバ関連です.

最初に店ごとにとってきたモータードライバ関連部品コーナーの写真,
続いてカテゴリーごとの部品まとめになっています.

あとトーカイとシリコンハウス共立は重要かと思いますが,見る時間がなかったので入ってません.

ではカテゴリーごとのまとめ編

  • モータードライバIC
    一番楽な選択肢で,基本的に一つの部品でモータードライバが構成できます.
    この手のICでよく使われているICにTA7291とかTA8440とかTA8429などがあります.これらのICは,東芝のカセットレコーダー用のICで入手が容易ですが,バイポーラトランジスタでできてるICなので電圧降下が激しく(1~3Vくらい),発熱が大きいことなどから,電池で動くタイプのマシンには使いたくありません.また,スイッチ速度も遅いのでPWMにもむかないです.
    ちなみにTB****という型番のモータードライバはFETベースなので電圧降下が小さく使いやすいです.ただし,こちらは滅多に見かけませんが・・・
    TA****については,どこでも手に入るし,個人的にあんまり使わないので,ここではバッサリ省略してます.
    DCモーター用
    TA****以外のICってやっぱりほとんど日本橋では出回ってないですねー.
    このジャンルに関しては通販で探した方がいいかも.
    1. μPD16805GS
      パーツランドの部品棚ではMPD16805になってます.これはこれで正しい気もしますが,uPDって書いてあることの方が多いかな?
      はんだ付けが少し困難であることを除けば,田宮の工作セット系のモーターFA130とかRA260の制御に申し分ない性能で使いやすいICです.
    ステッピングモーター用
    あんまり使わないけど,ついでにリストアップ.
    1. STK672-050
      ユニポーラ定電流チョッパ方式(他励PWM方式)ステッピングモータドライバ(正弦波駆動)出力電流3.0A
    2. LB1845
      PWM 電流制御式 ステッピングモータドライバ
    3. TB6615PG
      3相/4相ステッピングモータドライバ
    4. (PMM8713)
      製造中止のステッピングモーター用IC.直接ステッピングモーターを駆動するドライブ能力はないそうです.
      今後の入手性に難はありそうですが,デジットにはまだあるようですね.
    ブラシレスモーター用
    いつか使おうと思って全然使ったことがないブラシレスモーター・・・
    この機会に使ってみるか?
    1. ECN3022SP
      ECN3022はIGBTを6個内蔵したワンチップ三相ブリッジICです。
      特に三相DCブラシレスモータ制御用に最適です。
    RCサーボモーター用IC
    使ったことないですが,RCサーボで使われているICも売っています.何度か調べようと思って調べ損ねているのでついでにまとめ.自作の機械をラジコン化するときに便利かな?
    1. NJM2611D
    2. M64611FP
    3. M52461GP
    データシートを見た感じだと,安価なRCサーボのほとんどはデッドバンド付きのP制御のようですね.

  • ゲートドライバ&MOSFET
    適したモータードライバが見つからない場合,大抵はディスクリート部品でMOSFETを使ったモータードライバを組むことになります・・・が,MOSFETのゲートを駆動する回路は電源投入時や電圧低下時の安全性,ゲート電圧の確保などを考えると結構難しく,この部分の間違いでモータードライバが炎上する事故がよく起きます.
    というわけで,僕はゲートドライバは可能な限りIC使って設計を避けることにしてます(笑)
    昔はゲートドライバICとかあんまり売ってなかったのですが,最近は結構売っているようで,いい時代になったものです.
    ゲートドライバ
    マルツパーツ/千石電商の参入で入手できるものがだいぶ増えたようです.
    D級アンプとかが流行ってるのも要因のひとつか?
    1. HCPL-3180
      2 Amp Output Current, High Speed IGBT/ MOSFET Gate Drive Optocoupler
    2. HCNW3120-000E
      2.0 Amp Output Current IGBT Gate Drive Optocoupler
    3. HCPL-316J-000E
      2.0 Amp Gate Drive Optocoupler with Integrated Desaturation Detection and Fault Status Feedback
    4. HCPL-3150-000E
      0.5 Amp Output Current IGBT Gate Drive Optocoupler
    5. HCPL-314J
      HCPL-3140-000E
      HCPL-314-000E
      0.4 Amp Output Current IGBT Gate Drive Optocoupler
    6. IRS2011SPBF
      HIGH AND LOW SIDE DRIVER
    7. IRS2110PBF/IRS2110SPBF/IRS2113PBF/IRS2113SPBF
      HIGH AND LOW SIDE DRIVER
    8. IRS21271SPBF/IRS21281SPBF
      CURRENT SENSING SINGLE CHANNEL DRIVER
    9. IRS2092PBF/IRS2092SPBF
      PROTECTED DIGITAL AUDIO DRIVER
    10. IRS20955SPBF
      PROTECTED DIGITAL AUDIO DRIVER
    11. TLP250 / TLP251
      IGBT/MOSFET駆動用フォトカプラ
      昔結構探してみつからなかった思い出が・・・
    FETアレイ
    たぶん4AM12(廃品種)とかMP4212
    みたいなPch×2,Nch×2の構成のFETアレイがよくつかわれてるんですが,今回なぜか見つからなかった・・・また探しておきます.
    1. MP4208
      Pch×4 RDS:0.2Ω ID 5A(Peak 10A)
    2. MP4209
      Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
    3. MP4210
      Nch×4 RDS:0.12Ω ID 5A(Peak 20A)
    4. MP4211
      Pch×4 RDS:0.16Ω ID 5A(Peak 20A)
    5. MP4410
      Nch×4 RDS:0.12Ω ID 5A(Peak 20A)
    6. MP4411
      Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
    7. MP4412
      Nch×4 RDS:0.28Ω ID 3A(Peak 12A)
    8. MP6404
      Nch×3 Pch×3 RDS:0.12Ω(Nch) 0.16Ω(Pch) ID 5A(Peak 20A)



2009年2月22日日曜日

PowerPoint 2007 と TeXclip

この記事の情報は古いです
TeXclipで作成した数式の再編集については


を参照してください.

2009年2月19日木曜日

MATLABで可観測正準形/可制御正準形

制御の教科書では必ず出てくる可観測正準形/可制御正準形ですが,数値計算上は大変扱いづらく,実際に数値的にこの形式にあえて変換することなんて試験かレポート以外ではあまりないと思います.
そのあたりの事情を反映してかMATLABにはこれらの形式に変換する関数というのは存在していないようです.
ctrbf/obsvfという関数があります.

しかしまぁ研究の都合上これらの正準形を計算したい場合もあるわけで,そんな場合に使うルーチンを作りました.1入力1出力の場合にしか使えません.1入力1出力の場合だと伝達関数形式に変換した時点でこれらの形式は単純に決まるわけですが,復習をかねて教科書的な方法で計算しています.

可観測正準形
function [ csys ] = obsvcanon(sys)
%OBSVCANON Compute observability canonical form

[n,d]=tfdata(tf(sys),'v');
W=hankel(fliplr(d(1:numel(d)-1)));
G=ss(sys);
U0=obsv(G);
S=W*U0;
csys=ss(S*G.a*inv(S),S*G.b,G.c*inv(S),G.d);

end


可制御正準形
function [ csys ] = ctrbcanon(sys)
%CTRBCANON Compute controllability canonical form

[n,d]=tfdata(tf(sys),'v');
W=hankel(fliplr(d(1:numel(d)-1)));
G=ss(sys);
UC=ctrb(G);
S=UC*W;
csys=ss(inv(S)*G.a*S,inv(S)*G.b,G.c*S,G.d);

end

ダウンロード

2009年2月2日月曜日

IEEEのLaTeX投稿用テンプレで紹介されてるスタイルファイル

IEEEの投稿用のクラスファイルについているテンプレート(リンク)に,推奨スタイルファイルが結構詳しく紹介されているのでメモ.
  • \usepackage{ifpdf}
    Heiko Oberdiek 氏の ifpdf.sty は,出力の種類(pdfかdviか)に応じて条件コンパイルを行う時に便利です.
    使い方:
    \ifpdf
    % pdf code
    \else
    % dvi code
    \fi

    ifpdf.styの最新版は,
    http://www.ctan.org/tex-archive/macros/latex/contrib/oberdiek/
    から入手できます.
  • \usepackage{cite}
    文献の参照を改良するスタイルファイルです.たとえば,[1], [9], [2], [7], [5], [6] は自動的に [1], [2], [5]--[7], [9]とかになります.あと,参照の直前の余白は自動的に調節されるらしいです.
    IEEEのクラスファイルはこれを使うことが前提でnatbib.styとは基本的に共存できませんが(何かオプション付けたらできるはず),他のところではnatbib.sty使うことの方が多い気がします.最新版は
    http://www.ctan.org/tex-archive/macros/latex/contrib/cite/
    から入手できます.
  • \usepackage[pdftex]{graphicx}
    \usepackage[dvips]{graphicx}
    \graphicspath{{../eps/}}
    言わずと知れた図を挿入するためのスタイルファイルです.日本では日本語の問題からかあんまりメジャーじゃないですけど,海外ではpdftexって結構使われてるんですね.
    密かに\graphicspathでパスを指定できるのは知らなかった・・
  • \usepackage[cmex10]{amsmath}
    定番のAMSの数式環境.cmex10とオプションを付けると,ビットマップフォントが組み込まれるのを防げるらしい.
  • \usepackage{algorithmic}
    アルゴリズムを書くためのalgorithmic環境を提供.今の自分の専門分野ではアルゴリズムを書くことはあんまりないですが,一度使ってみたいなぁ〜
    algorithmic.styのドキュメントと最新版は
    http://www.ctan.org/tex-archive/macros/latex/contrib/algorithms/
    に,サポートサイトは
    http://algorithms.berlios.de/index.html
    です.あと,より新しくてカスタムが可能なalgorithmicx.sty
    http://www.ctan.org/tex-archive/macros/latex/contrib/algorithmicx/
    もあるそうです.
  • \usepackage{array}
    LaTeX2eの標準的なarrayとtabular環境を改善して,よりよい見た目と出力の制御を実現するものらしいです.「標準での表の出力はひどいから,とりあえず入れとけ.」という感じで紹介されています.次から使おう・・・
    大抵のシステムにデフォルトでインストールされていますが,最新版は
    http://www.ctan.org/tex-archive/macros/latex/required/tools/
    で入手できます.
  • \usepackage{mdwmath}
    \usepackage{mdwtab}

    これらは Mark Wooding さんによるMDW tools の一部です.
    他にも色々なツールを提案されているようです.
    http://www.ctan.org/tex-archive/help/Catalogue/entries/mdwtools.html
    ざっと見た中ではsyntax.styのgrammer環境が目を引きます.

    (↑の図はドキュメントから抜粋したものです)
    こんな感じのコンピュータ言語の文法を記述できるようです.
    いつかは自分言語の文法を書くようなことをしてみたい・・・
  • \usepackage{eqparbox}
    自動的に同じ幅に調整されるボックスを実現するパッケージです.TeXで同じ幅の表を作ったりする作業は地味にめんどうですが,これを使えばスマート(?)に実現できます.
    他にも通常は揃えにくい場所の位置や長さを揃えることができそうです.単純な原理でありながら応用範囲の広い秀逸なパッケージですね.
    入手先はhttp://www.ctan.org/tex-archive/macros/latex/contrib/eqparbox/です.
  • \usepackage[caption=false]{caption}
    \usepackage[font=footnotesize]{subfig}
    subfig.styはsubfigure.styをより現代的にしたものらしいです.今までずっとsubfigure.styだったので次から使ってみます.もともとsubfigureを使いこなせてないので差はよくわかりませんが,従来の\subfigureに代えて\subfloatコマンドが提供されています.これは図だけでなく表にも適用できて,Figure 7(a)みたいにsubfigure を直接参照したり,図目次に subfigure の Caption を入れられたり, Caption の見た目を色々制御したりできるみたいです.
    ちなみにsubfig.styはcaption.styに依存していて自動で読み込みます.そのため IEEEtran.clsのcaption周りと衝突するらしく,IEEE用の原稿では上のような並びで使います.ダウンロードは
    http://www.ctan.org/tex-archive/macros/latex/contrib/subfig/
    から.
    ※ 日本語を使っているとき,タイトル等の書式設定がおかしくなる問題が発生する事があるようですが, caption.sty を最新版に置き換えることで解決するようです,
  • \usepackage{fixltx2e}
    LaTeX2e の問題点を修正するパッケージです.例えば,2つのカラムに及ぶ図と1カラムの図が混在したときに,それらの順序が入れ替わることがある問題とかが修正されるます.次から使ってみます・・・.最新版とドキュメントは
    http://www.ctan.org/tex-archive/macros/latex/base/
    から.
  • \usepackage{stfloats}
    二段組みの文書で二段使う図を,ページ下に配置することができるようになったりするパッケージです.float周りをごっそり書き換えるので他のパッケージと共存できないことが多いらしい・・・あんまり使う機会はないかも??
    ドキュメントと最新版は
    http://www.ctan.org/tex-archive/macros/latex/contrib/sttools/
    から.
  • \usepackage{endfloat}
    IEEEtran.cls を captionoff オプションで使うタイプの文書で便利らしい.今のところそういう流儀の雑誌と縁遠いかなぁ・・・必要な時が来たら調べます.最新版とドキュメントは
    http://www.ctan.org/tex-archive/macros/latex/contrib/endfloat/
    から.
  • \usepackage{url}
    URL をかしこく扱うためのスタイルファイルです.改行する場所とかも改善するらしい.これは結構使いますね.ほとんどの場合デフォルトで入ってますが,最新版は
    http://www.ctan.org/tex-archive/macros/latex/contrib/misc/
    から.
実は今までTeXファイルの受け渡し時のトラブルもあって,スタイルファイルを使うのを敬遠していたのですが,標準的に入っているのも多いみたいだし,今後はちょくちょく使うことにします.

2009年1月16日金曜日

MATLABのグラフに目盛りを追加

MATLABでグラフを作るとき,自動でつく目盛り以外に特定の値の目盛りがほしい場合があります.真値のところに目盛りがほしいとか収束先のところに目盛りがほしいとかそんなときです.

じつはこれをプログラムからやるのは結構面倒だったりします.
なので専用の関数を作ってみました.

こんなグラフに
>> addxtick(2/pi)
とすると

こんな風に目盛りがつきます.
ラベルもいじりたいときは
>> addxtick(pi/2,'pi/2')
と入れれば

となります.便利ですよ.
短いプログラムなのでコピーしてaddxtick.mという名前で保存して使ってください.

function [] = addxtick( tk, tklbl )
%ADDXTICK --- Add new tick to x-axis
%   Ex.    addxtick(3.14)
%   Ex2.  addxtick(3.14, 'Pi')

if nargin==1
    set(gca,'XTick',unique(sort([get(gca,'XTick'), tk ] )));
else
    temp = cellstr(get(gca,'XTickLabel'));
    temp = {temp{:},tklbl};
    [temp2,idx] = sort([get(gca,'XTick'),tk]);
    [temp2,idx2]=unique(temp2);
    idx=idx(idx2);
    set(gca,'XTick',temp2);
    set(gca,'XTickLabel',temp(idx));   
end

end
あと,ほとんど同じですがaddytick.mも置いておきます.
function [] = addytick( tk, tklbl )
%ADDYTICK --- Add new tick to y-axis
%   Ex.    addytick(3.14)
%   Ex2.  addytick(3.14, 'Pi')

if nargin==1
    set(gca,'YTick',unique(sort([get(gca,'YTick'), tk ] )));
else
    temp = cellstr(get(gca,'YTickLabel'));
    temp = {temp{:},tklbl};
    [temp2,idx] = sort([get(gca,'YTick'),tk]);
    [temp2,idx2]=unique(temp2);
    idx=idx(idx2);
    set(gca,'YTick',temp2);
    set(gca,'YTickLabel',temp(idx));   
end

end

2009年1月15日木曜日

三叉ヘビ型ロボットの製作

三叉ヘビ型ロボットというおもしろい構造のロボットが
杉江研の石川先生たちによって研究されています。
僕は研究に深く関わっているわけではありませんが、とてもいい動きをするロボットなので一度作ってみたいと思っていました。研究室には一応理論を検証するための機械がありますが、データを取ったり精度を確保するためにそれなりに大がかりな装置になっています。

今回は、より単純に三叉の動きを楽しむために、小型で小回りの良いロボットを製作してみました。
以下製作記録です。
デモ用のプログラムを書き込んで動作

いつもより多めにまわってます。
学部生の勧誘で本部に出張する時とかに役立てる予定。