オブジェクトの活用

Rとtcltk

Rでは、require(tcltk)とすれば、tkが使えるようになる。しかし、tkのコマンドはあまり馴染みが無いので、なかなか使いにくい。これが多少は使いやすくなるように、ツールを作って、個人的に利用している。しかし、気に入らない点がある。それは、tkで入力した値を取り出すときの方法が統一的ではないということである。tclVarのときには、tclvalue()で値を呼び出す。一方、tklistboxは、tkcurselection()を使って選ばれているものを取り出す。本当はどれでも同じ関数で値を取り出したい。

そこで、tclvalueを調べてみると、UseMethod("tclvalue")となっている。つまり、オブジェクトの種類によって、実行されるメソッドが違うのだ。そこで、attr(,"class")をつかってクラス名を調べると、tclVarはそのままtclVarで、tklistboxはtkwinとなっている。他のtkのオブジェクトもtkwinであるようだが、値を呼び出す必要があるのは、listboxだけなので、次のように定義した。

tclvalue.tkwin <- function(x) as.integer(tkcurselection(x))

こうすると、tclvalue()でtklistboxを呼ぶと、tkcurselection()が呼ばれて、値が取得できるのだ。

これで、tclvalue()のみで値の取得ができるようになった。残る問題は値の代入だ。tclVarはtclvalue(x)<-1などで値を設定できるが、当然tklistboxではだめだ。値を代入できるような関数をどのように書くかが分からない。一つの解決策としては、全く別のメソッドをつくってしまって、例えば、my_set(x,1)とすると、値が代入されるようにして、my_set.tclVarとmy_set.tkwinを定義する方法がある。しかし、tclvalue(x)<-1という形でできるようにできないのかな。

Read more...

オブジェクト指向言語R(uby)

Rのオブジェクトプログラミング

Rはオブジェクト指向の言語らしい。しかし、どのように書くとオブジェクト指向っぽくなるのかよく分からない。The R language definitionを少し読んで、どのように使うのかを調べてみた。

まず、オブジェクトのクラスを指定するためには、"class"という属性に文字列で指定するだけでよい。したがって、どんな名前のクラスにもできる。

a<-2
attr(a,"class")<-"num"
b<-"2"
attr(b,"class")<-"str"

次に、オブジェクト毎に、異なった挙動をするメソッドを定義する必要がある。これは、UseMethodを使って、関数名とオブジェクト名をピリオドでつないだ関数を自動的に呼ぶようにすることで実現する。

dub<-function(x) UseMethod("dub")
dub.default<-function(x) x
dub.num<-function(x) 2*x
dub.str<-function(x) paste(x,x,sep="")

こうすると、dub(a)を呼び出すと4が、dub(b)を呼び出すと"22"となる。

しかし、rubyのように、インスタンス変数を定義して、それに値を代入したり、いろいろなデータ構造を持たせるにはどのようにすれば良いのかよく分からない。Rのオブジェクト指向を使った良い例が見つかると分かりやすいのだが、まだ見つけていない。

Read more...

Rのベクトル

Rのdeparse()の挙動
deparse()をつかってプログラムを書いていたら、なんだか思ったように動かない。原因を調べていたら、長いデータをdeparse()すると、ベクトルになって返ってくることが原因だった。Rでは、ベクトルの処理は独特である。例えば、c(1,2,3,4)+c(4,5)は、5 7 7 9となり、c(1,2,3,4)+c(4,5,4,5)と解釈される。このような挙動のために、変になっていた。paste(deparse(),collapse="\n")で、一つの文字列にすると、問題なく動いた。

Read more...

オブジェクトの保存

Rのdeparse
Rのオブジェクトをファイルに保存する方法を考えていたのだが、deparse()を使うと良いようだ。

d<-list(1, 2, c(1, 2, 3))
deparse(d)

とすると、そのまま"list(1, 2, c(1, 2, 3))“となる。つまり、この頭に"d<-“をつければ、そのオブジェクトを作るコードが保存できることになる。なるほど。

Read more...

Rのオブジェクト

ベクトルとスカラー、リストとデータフレームの違い
Rはグラフソフトとして使っていて、これまで言語としてとらえていなかった。また、一貫して勉強したことが無いので、その言語の特徴をいまいち理解していない。しかし、くせはあって組みにくいけど、なかなかおもしろい言語のように思えてきたので、少しずつ勉強していけたらと考えている。 Rには様々なオブジェクトがあるが、どれだけの種類があるのだろう。オブジェクトの種類は、typeof()で調べることができる。 Rのオブジェクトにベクトルがあるが、これにはさらに五つの型があって、異なる型のデータを入れることはできない。つまり、c(1,“2”)とはできない。実は、スカラーもベクトルと考えているようだ。‘1’[1]としたら"1"が返ってきたし、“1”==c(“1”)はTRUEとなる。 異なる型を配列にできるオブジェクトとしては、リストがある。また、それぞれの要素には成分名をつけることができるので、連想配列のように使うこともできる。例えば、d<-list(a=1,b=2)としておけば、d[[1]]でも良いが、d$aでもアクセスできる。ファイルからデータを読み込むときにつくるデータフレームにアクセスの仕方が似ていると思って、試しにデータフレームをtypeof()で調べてみたら、listとなった。つまり、データフレームはリストだったようだ。しかし、d<-list(a=c(1,2),b=3)とすると、d$bは当然3になるが、d<-data.frame(a=c(1,2),b=3)とすると、d$bはc(3,3)となる。厳密には多少違うようだ。 まだまだ勉強する必要がありそうだ。

Read more...

R言語

Rの環境

Rでグラフを書きながら、測定の様子を観察していると、待っているときに、Rで楽にグラフが書けるようにRをいろいろといじってしまう。言語としてのRは、それなりに興味深い仕様になっている。

関数を定義すると、その中で定義された変数はローカルになる。しかし、外の変数を読むこともできるので、その変数がどの変数なのかが分からなくなってしまう。変数をすべてグローバルにしてしまえば、ややこしくはなくなるが、どうしても変数名が重複する可能性が出てくるので、変数はローカルであるべきだ。

次のような例を考えてみよう。

x<-1
test<-function(){
  cat(x)
  x<-2
  cat(x)
}
test()
cat(x)

この実行結果は121となる。testという関数が呼ばれて、最初にxを見ると、関数の外で定義されたxの値となり、関数の中で代入するとその値になる。そして関数の外で見ると、元の値になっている。つまり、関数の中の一個目と二個目のxは別のxになっているのである。

こうなってくると、関数から外の変数の値が見えるのが、便利なのか不便なのかが分からなくなってくる。

このような場合には、関数内だけの環境を作って、その環境を指定して変数に代入したり呼び出したりすればよい。長くなるけど、こんな感じになる。

x<-1
test<-function(){
  cat(x)
  testenv<-new.env()
  assign("x",2,env=testenv)
  cat(get("x",env=testenv))
}
test()
cat(x)
これで、xの意味合いがはっきりとする。しかもtempenvは関数の中のローカル変数なので、外からは見えない。でも、面倒だな。
Read more...

敗退か?

液晶ディスプレイの修理
本日、ある人から、液晶の割れたディスプレイを頂いた。これで、手元にある故障している液晶ディスプレイが三台となった。通常、壊れたものが三つあれば、うまく組み合わせれば、二つぐらいはうまく動くものが作れる。というわけで、部品を入れ替えて、ディスプレイの復活を試みた。 割れた液晶パネルを、別の液晶パネルと入れ替えれば、とりあえず一台は復活するはずである。しかし、そう単純では無かった。一台はbenq、一台はSharpで、もう一つはIODATAと、三つともかなり違うメーカーのものだった。液晶パネルの大きさが微妙に違うのである。どれも同じ19インチだったので、共通の規格だろうと思っていたら、縦横と厚さも違っていて、うまくいかない。それならばと、液晶パネルを分解して、最前面の液晶板だけを入れ替えようとしたが、これも厚さの違いによって挫折。最終的には液晶パネルと筐体の間にできた隙間にスペーサーをつめて、強引に組み立てた。なんとか一台は復活したが、納得がいかないやり方になってしまった。 最後の一台の部品も流用できないかも検討したのだが、これはまた規格が違っていた。通常は上部にあるコネクタが下部にあり、さらに陰極管のコネクタも他のものとは違っている。互換性という意味では、他のパネルとは入れ替えることができない。 三台から二台を復活させるつもりだったが、中途半端な一台だけしか復活させることができなかった。微妙に敗退感がある。

Read more...

Rのコマンド

Rでファイルの読み込み

グラフを書くときに使っているRだが、プログラム言語としてもそれなりに使える。統計的な計算を含んだ簡単なプログラムの場合には、別の言語でその統計処理のルーチンを書くよりも、Rに元からある関数を使う方が早い場合がある。

しかし、Rの目的は通常のプログラムを作ることではないので、他の言語では簡単にできることが、Rではどのようにしたら良いのか分からない場合もある。その一つがファイルからのデータの読み込みである。data frameにデータを取り込む場合には、read.tableを使ってやっているが、通常の文章などのファイルを読み込む方法がこれまで分からなかった。もしあるとすれば、readなんとかという関数だろうと思って、help.search("read")としてみると、readLinesというのがあって、ファイルの内容を行単位で読み取ることができる関数を見つけた。Rではもっといろいろなことができるのだろうが、良いリファレンスマニュアルは無いのかな。

Rubyではこのmethodを使えば良いということが分かっても、それと同じことをするRの関数が分からないとプログラムを書くのに四苦八苦してしまう。試しに、文字列操作の関数のRubyとRの対応表をつくってみよう。

R Ruby
paste(x,y,sep="") x+y or a.join("")
substr(x,start,stop) x[start..stop]
sub(pattern,replacement,x) x.sub(pattern,replacement)
gsub(pattern,replacement,x) x.gsub(pattern,replacement)
strsplit(x,split) x.split(split)
ほんの一部のコマンドしか書いていないが、意外にrubyであるmethodに対応した関数はRにもかなりあるように思う。他のコマンドもhelp.search("string")などで探して使ってみようかな。

2010/8/31追記 rubyのa.join("")に対応するのは、Rのpaste(a,collapse="")かもしれない。

Read more...

ARM機

ちょいパソ
久しぶりにパソコン工房のhomepageを見ていたら、「ちょいパソ」というものを見つけた。ARM9を搭載して、600gで一万五千円程度である。ディスプレイは七インチで800*480とまあまあである。また、USBポートもある。非常に魅力的に感じたか、致命的なのがOSで、WindowsCEである。これをlinuxかBSDで動かすことができれば、買いなのだが、少し検索したところ、まだ情報はあまり無いようである。いずれはだれかがやってくれるだろうが、それまでは待ちかな。 以前、mobile gearIIにNetBSDを入れてしばらく使っていたが、emacsなどを立ち上げると、かなり遅く感じた。最近はめっきり使っていないが、まだ可愛いので捨てるのを躊躇している。sharpのNetWalkerZ1が出たときには、linuxだったので、良かったのだが、キーボードの評判が良く無かったので、見送った。しかし、次に出たT1では、キーボードが改良されるのではなく、無くなってしまったので、購入候補からは完全に外れてしまった。ちょいパソの今後に期待できると良いのだが。

Read more...

コンピュータ数値制御

AVRでCNC
必要な小型の部品が必要なときに、ちっちゃなNCフライスを使っている。最近は酷使しているので、いつか壊れないか心配している。しかし、市販のものはそれなりに高価である。しかし、ミニフライスにステッピングモーターを取り付けて、それをPCから制御するようなCNCフライスなら、結構安く手に入るらしい。 そこで、いろいろと調べてみたら、専用のソフトを使ってPCのパラレルポートでパルスを作り、それをモータのドライバーに入力している。パラレルポートは、今後姿を消す可能性が高いし、PCでパルスを作っていると、別のタスクが走ると、速度が変化する可能性がある。PCは1ms以下の時計を持っていないので、それ以下の時間制御は苦手で、おそらく空のループを回して時間を制御しているのだろう。そう考えると、PCから座標などのデータを送って、マイコンでパルスを作るようにした方が理想的である。というわけで、AVRでNCを制御する時の問題点を考えてみた。 まずx軸とy軸の同時移動である。直線的に動くためには、x軸とy軸にパルスをどのようなタイミングで送るかを決めなければならない。これは以下のようにすれば良い。それぞれの軸方向にdx,dyだけ動かすとして、dx>=dyとする。このとき、常にx軸にはパルスを送る。x軸にパルスを送るときに、変数にdyを加算し、もしそれがdxの値以上だったら同時にy軸にパルスを送り、dxを減算するということを繰り返す。すると、x軸にdx回パルスを送ったときに、y軸にdy回のパルスを送ることができる。 次に問題なのが、加速と減速時のパルス間隔をどのように決めるかである。加速度を指定したときには、どのようにパルス間隔を変化させれば良いかを、適当に数式をいじって導いた。加速度をa、一つのパルスで動く距離をdとすると、最初のパルス間隔をw0は、sqrt(d/q)となる。現在のパルス間隔w(i)に対して、w(i+1)/w(i)=w0**2/(w(i)2+w02)とすれば良いようだということが分かった。このパルス間隔の割合の数列をあらかじめAVRのFlashに記録しておき、それを用いてパルス間隔を変化させていけば良いだろう。 まだ検討中の課題としては、バックラッシュをどのように処理するかとか、円弧を描くときにはどうするか、などがある。 AVRとCNCで検索をかけると、AVR-CNCというのがすでにあるらしい。同じようなことを考える人はいるものだ。不完全な日本語のページもあったが、機械翻訳がひどかったので、日本語訳を投稿しておいた。いつか採用されるかな。AVR-CNCに関しては、いつかdownloadして、どうゆうものか調べてみよう。

2010/8/20追記 AVR-CNCを読んでみた。まず、PC側のソフトはWindows用だった。AVR側では、加速などは行わず、いきなり特定の速度で軸を動かすようになっていた。直線補間は、先に書いたようなことをx,y,zの三つの軸で行っている。さらに円弧補間もあったが、math.hを使っていたので、tinyでは難しいだろう。バックラッシュの処理はおそらくPC側で行っているのか、AVRのソースには見当たらなかった。

Read more...