(EusLisp 9.29)  通商産業省 工業技術院 電子技術総合研究所 知能システム部 松井 俊浩, 原 功, 中垣 博文(九州電力) matsui@etl.go.jp, hara@etl.go.jp, nakagaki@etl.go.jp〒305 茨城県つくば市梅園1-1-4 .. toctree::

jintro :maxdepth: 2 :caption: EusLisp 基本

jgenerals

jcontrols

jobjects

jarith

jsymbols

jsequences

jio

jevaluation

システム関数

メモリ管理

メモリ管理の設計は、オブジェクト指向言語の柔軟性と効率性にたいへん 影響を及ぼす。 Euslispは、フィボナッチバディ法を基本に統一した方法で オブジェクトをメモリに割り当てる。 この方法は、chunkと呼ばれる大きなメモリのプールを小さなセルに分割する。 それぞれのセルは、サイズが等しくなく、フィボナッチ数がそれぞれ割り当てられる。 chunkメモリは、symbol, cons, string, float-vectorなどのような 様々な型のオブジェクトのための同次なデータ容器である。 それらのサイズはchunkと一致する長さである。 chunkは、固定、動的、再配置可能、交替可能などのような どんな特別な属性も持っていない。 EusLispのヒープメモリは、chunkの集合である。そして、 ヒープはUNIXより新しいchunkを得ることにより動的に拡張することができる。 拡張は、動作中に自動的に発生するかあるいはユーザーがsystem:alloc関数を 呼び出すことにより発生する。 自動的に処理されるとき、使用可能なメモリサイズは合計のヒープサイズの 約25%に保つ。この比率は、sys:*gc-margin*パラメータに0.1から0.9までの値を設定 することにより変更することができる。

すべてのヒープメモリを使いきったとき、mark-and-sweep型のガーベージコレクション(GC) を始める。 ルート(パッケージ,クラスやスタック)からアクセス可能なセルは, 同じアドレスのままである。 他のアクセス不可能なセルは、矯正されfree-listsにリンクされる。 GCの間にコピーやコンパクト化は発生しない。 ガーベージされるセルが矯正されるとき、その隣接セルがfreeかどうかチェックされる。 そして、できるだけ大きなセルを構成するようにマージされる。 しかしながら、このマージは、ときどき意味の無いものになる。 なぜなら、もっとも頻繁に呼び出されるメモリアロケータであるconsが、 そのマージされたセルを最も小さなセルに分割することを要求するからである。 したがって、Euslispはconsの高速化のためにマージされないある特定の量の ヒープを残すことを許可している。 この比率は、sys:*gc-merge*パラメータによって決定される。その値のデフォルトは 0.3である。 sys:*gc-merge*に大きな値を設定することにより、マージされないヒープを多く残す。 これは、consが要求されるとき、buddy-cellの分割が滅多に起こらないので、consの性能を改善する。 これは、また3次元ベクトルのような相対的に小さなセルのアロケーションについて すべて成り立つ。

sys:gcは、明示的にガーベージコレクターを呼び出す。 そして、ヒープに配置された空いているワード数と全体のワード数(バイト数ではない)を示す2つの整数の リストを返す。

もし、実行中に“fatal error: stack overflow”が報告され、 そのエラーが無限ループあるいは再帰処理によるものでないと確信するならば、 sys:newstackでLispのスタックの大きさを拡張すれば回避できる。 sys:newstackを設定する前には、resetを実行しなければならない。 なぜなら、 スペシャルバインドとunwind-protectの整理用の書式が 現在のスタックの中からすべて捨てられるためである。

新しいスタックが配置された後、オープニングメッセージを表示するところから 実行を始める。 デフォルトのスタックサイズは、16Kwordである。 Lispのスタックは、システムのスタックと別物である。 前者は、ヒープ上に配置され、後者は、オペレーティングシステムによって スタックセグメント内に配置される。 もし、“segmentation fault”エラーが発生したならば、システムのスタックが小さいことに より発生したことが考えられる。 cshのコマンドlimitで、システムのスタックサイズを増加することにより、 解決できる可能性がある。

sys:reclaimsys:reclaim-tree関数は、オブジェクトにより占有されているセルを メモリマネージャーに戻す。そのため、ガーベージコレクションを呼び出すことなしに その後も再使用をすることができる。 しかし、それらのセルが他のセルから参照されていないことが確実でなければならない。

memory-reportroom関数は、メモリの使用に関する統計を セルのサイズやクラスによりソートして表示する。

addressは、オブジェクトのバイト換算したアドレスを返す。 このアドレスはプロセスに独自のものであるから、 この関数はハッシュテーブルが使用するハッシュ関数に有用である。

peekpokeは、メモリから直接データを読み書きできる関数である。 アクセスする型は、:char, :byte, :short, :long, :integer, :float, :double のどれかにすべきである。 例えば、(SYS:PEEK (+ 2 (SYS:ADDRESS ’(a b))) :short)は、 consセルのクラスID(ふつう1である)を返す。

list-all-’を名前の前に付けている幾つかの関数がある。 これらの関数は、システムのリソースあるいは環境のリストを返し、 動的なデバッグに有用である。

sys:gc **

ガーベージコレクションを実行する。割り当てられている中で空いているワード数および全体のワード数 のリストを返す。

sys:*gc-hook* **

ガーベージコレクションを実行する時に呼ばれる関数を定義する。

sys:gctime **

3つの整数のリストを返す。1つは、GCを呼び出した回数。 2つは、セルをマーキングするために使用した時間(1ユニットに1/60秒)。 3つが、矯正(マーキングを外し、マージする)のために使用した時間。

sys:alloc size

ヒープに少なくともsizeワードのメモリを配置し、 実際に配置されたワード数を返す。

sys:newstack size

現在のスタックを廃棄し、sizeワードの新しいスタックを配置する。

sys:*gc-merge* **

メモリ管理用のパラメータ。 gc-merge*は、GCによりマージされずに残すヒープメモリの比率を示す。 このマージされない領域は、すぐにconsのような小さなセルに満たされる。 デフォルトの値は、0.3である。 この値を0.4のように大きくすると、マージされない空きヒープが40%であることを 示し、consのためには役立つが、実数ベクトルやエッジや面などのような大きなセル の確保には、害を及ぼす。

sys:*gc-margin* **

メモリ管理用のパラメータ。 gc-margin*は、全体のヒープに対する空きヒープの比率を決定する。 メモリは、UNIXから獲得したものであるため、空き空間はこの比率より 小さくならない。 デフォルトは、0.25であり、GCの際に25%以上の 空き空間が維持されることを意味する。

sys:reclaim object

ごみとしてobjectを廃棄する。 そのオブジェクトは、他のどのオブジェクトからも絶対に参照されないことが 保証されなければならない。

sys:reclaim-tree object

から通過できるsymbolを除いてすべてのオブジェクトを矯正する。

sys::bktrace num

Lispのスタックのnum番目の深さの情報をトレースして表示する。

sys:memory-report &optional strm

セルのサイズでソートしたメモリ使用のテーブルをstrmストリームに出力する。

sys:room output-stream

クラスで整列したメモリ配置の情報を出力する。

sys:address object

プロセスのメモリ空間内にあるobjectのアドレスを返す。

sys:peek [vector] address type

で指定されたメモリ位置のデータを読みだし、 それを整数として返す。 typeは、:char, :byte, :short, :long, :float, :doubleの内の1つである。 もし、vectorが与えられなかったなら、 そのアドレスは、UNIXの処理空間として扱われる。 例えば、Sunにおいてa.outのヘッダーは#x2000に置かれるため、 (sys:peek #x2000 :short)はmagic number(ふつうは#o403)を返す。 Solaris2は、ELFヘッダーを#10000に置くため、 (sys:peek #x10000 :long)が“ELF”を表現する文字列である #xff454c46を返す。 もし、vectorが与えられたならば、それはforeign-stringであり、 アドレスはvectorの起点からのオフセットとして認識される。 (sys:peek “123456” 2 :short)は、“34”を表現する short wordを返す。(#x3334(13108)である)

アドレス位置については十分注意すること。 short, integer, long. float, double wordを奇数アドレスから読み出すと、 “bus error”になる。

sys:poke value [vector] address value-type

addressで指定された位置に書き込む。 プロセスのメモリ空間内のどこでも書き込むことができるため、 特に注意をしなければならない。 プロセスの空間の外へ書き込んだなら、 確実に“segmentation fault”が発生する。 short, integer, long. float, double wordを奇数アドレスに書き込んだ 場合、“bus error”が発生する。

sys:list-all-chunks **

配置されたすべてのヒープのchunkをリストアップする。 他に有用な実行関数はない。

sys:object-size obj

からアクセス可能なセルとワードの数を計算する。 objから参照可能なすべてのオブジェクトが探索される。 そして、3つの数のリストが返される。 1つ目は、セルの数。2つ目は、これらのオブジェクトに論理的に配置されたワード数( すなわち、ユーザーからアクセスできるワード数)。 3つ目は、物理的に配置されたワード数。 これは、ヘッダーとメモリ管理のための特別なスロットを含む。 探索は、symbolで停止する。すなわち、property-listあるいはprint-name stringのような symbolから参照されるオブジェクトは、カウントされない。

UNIXシステムコール

EusLispは、UNIXオペレーティングシステムのシステムコールとライブラリ関数とに 直接関連する関数を取りそろえている。 これらの関数の詳細については、UNIX system interface (2)を調べること。 unix-package*に定義されているこれらの低レベル関数の使用は、 ときどき危険をはらむ。 できるだけ他のパッケージに定義されている高レベル関数を使用すること。 例えば、unix:socket, unix:bind, unix:connectなどの代わりに[IPC]節に 記述されているIPC機能を使用すること。

時間

unix:ptimes **

経過時間、システム時間、ユーザー時間、サブプロセスのシステム時間とサブプロセスのユーザー時間 の5つの要素を持つリストを返す。 この関数は旧いので、unix:getrusageの使用を推奨する。

unix:runtime **

プロセスのシステムとユーザー時間の合計を返す。 単位は、1/60秒である。

unix:localtime **

現在の時間と月日を整数ベクトルで返す。 要素は、秒、分、時、日、月(0から始まることに注意)、年(1900からの経過年数)、曜日(0が日曜日、6が土曜日)、年内の通し日数(0から始まる)、夏時間がセットされているか、サポートされている時間帯である。

ex.) unix:localtime => #(10 27 12 8 10 116 2 312 nil (“JST” “JST”))

unix:asctime tm_intvector

整数ベクトルで表現されるローカル時間を文字列表現に変換する。 (unix:asctime (unix:localtime))は、現在の実際の時間の文字列 表現を返す。

プロセス

unix:getpid **

このプロセスのプロセスID(16ビット整数)を返す。

unix:getppid **

親プロセスのプロセスIDを返す。

unix:getpgrp **

このプロセスのグループIDを返す。

unix:setpgrp **

新しいプロセスのグループIDを設定する。

unix:getuid **

このプロセスのユーザーIDを返す。

unix:geteuid **

このプロセスの使用可能なユーザーIDを返す。

unix:getgid **

このプロセスのユーザーグループIDを返す。

unix:getegid **

このプロセスの使用可能なユーザーグループIDを返す。

unix:setuid integer

このプロセスの使用可能なユーザーIDを設定する。

unix:setgid integer

このプロセスの使用可能なユーザーグループIDを設定する。

unix:fork **

他のEuslispを作成する。サブプロセスに0が返され、 親プロセスにforkされたプロセスのpidが返される。 パイプで接続されたプロセスを作成するためには、[UnixProcess]節に書かれている system:piped-forkを使用すること。

unix:vfork **

他のEuslispをforkし、その新しいEuslispのプロセスが終了するまで親プロセスの実行を 一時停止する。

unix:exec path

Euslispから他のプログラムへ実行を移す。

unix:wait **

サブプロセスの中の1つのプロセスの終了を待つ。

unix::exit code

実行を終了し、codeを終了状態として返す。 ゼロは通常の終了を意味する。

sys:*exit-hook* **

プロセスが終了する直前に呼ばれる関数を定義する。

unix:getpriority which who

このプロセスが持つ最大の優先順位を返す。 whichは、0(プロセス)、1(プロセスグループ)、2(ユーザー)のうちの 1つである。

unix:setpriority which who priority

whoで決定されるリソースの優先順位をpriorityに設定する。 whichは、0,1,2の内の1つである。 whoは、whichから相対的に解釈される (\(which=0\)ならプロセスを示し、\(which=1\)ならプロセスグループを示し、 \(which=2\)ならユーザーのIDを示す)。 whoがゼロのとき、現在のプロセス、プロセスグループ、ユーザーを示す。 Euslispプロセスに低い優先順位を指定することは、大きい値を設定することであり、 これはプロセスを不利にする。 (unix:setpriority 0 0 10)は、優先順位を10に設定する。

unix:getrusage who

プロセスについてのシステムリソースの使用情報のリストを返す。 要素は、以下のような順番になっている。 もっと多くの情報が、lisp:rusageより得られる。

float ru_utime (sec.) /* user time used */
float ru_stime (sec.) /* system time used */
int  ru_maxrss;       /* maximum resident set size */
int  ru_ixrss;        /* currently 0 */
int  ru_idrss;        /* integral resident set size */
int  ru_isrss;        /* currently 0 */
int  ru_minflt;       /* page faults without physical I/O */
int  ru_majflt;       /* page faults with physical I/O */
int  ru_nswap;        /* number of swaps */
int  ru_inblock;      /* block input operations */
int  ru_oublock;      /* block output operations */
int  ru_msgsnd;       /* messages sent */
int  ru_msgrcv;       /* messages received */
int  ru_nsignals;     /* signals received */
int  ru_nvcsw;        /* voluntary context switches */
int  ru_nivcsw;       /* involuntary context switches */

unix:system &optional command

サブシェルでcommandを実行する。 commandは、Bourn-shellで認識されるものでなければならない。

unix:getenv env-var

の環境変数の値を返す。

unix:putenv env

プロセスの環境変数リストにenvを追加する。 envは、“VARIABLE=value”のように変数と値の等価を表す文字列である。

unix:sleep time

秒間このプロセスの実行を一時停止する。

unix:usleep time

マイクロ秒間このプロセスを一時停止する。 (uは、マイクロを表現する。) usleepは、Solaris2あるいは他のSystem5系のシステムには実現されていない。

ファイルシステムと入出力

unix:uread stream &optional buffer size

からsizeバイト読み込む。 streamは、ストリームオブジェクトあるいはファイルディスクリプタ(fd)を 表現する整数である。 もし、bufferが与えられるとき、入力はそこに蓄積される。 そうでないならば、入力はstreamのバッファに蓄積される。 したがって、もしstreamがfdなら、bufferは与えられなければならない。 unix:ureadは、新しい文字列バッファを配置しない。 unix:ureadは、実際に読み込まれたバイト数を返す。

unix:write stream string &optional size

stringsizeバイトを書き込む。 もし、sizeが省略されたならば、stringの全部の長さが出力される。

unix:fcntl stream command argument

unix:ioctl stream command buffer

unix:ioctl_ stream command1 command2

unix:ioctl_R stream command1 command2 buffer &optional size

unix:ioctl_W stream command1 command2 buffer &optional size

unix:ioctl_WR stream command1 command2 buffer &optional size

unix:uclose fd

で指定されるファイルをクローズする。

unix:dup fd

で指定されるファイルディスクリプタを2重化して返す。

unix:pipe **

パイプを作成する。このパイプの入出力ストリームを返す。

unix:lseek stream position &optional (whence 0)

のファイルポインタをwhenceからpositionの 位置に設定する。

unix:link path1 path2

hardリンクを作る。

unix:unlink path

で指定されたファイルのhardリンクを取り去る。 もし、ファイルに参照が残っていないなら、削除される。

unix:mknod path mode

ファイルシステムにinodeを作る。 pathは、pathnameオブジェクトでなく文字列でなければならない。

unix:mkdir path mode

ファイルシステムにディレクトリを作る。 pathは、pathnameオブジェクトでなく文字列でなければならない。

unix:access path mode

へのアクセス権利をチェックする。

unix:stat path

のinode情報を得て、以下に示す整数のリストを返す。

st_ctime  ; file last status change time
st_mtime  ; file last modify time
st_atime  ; file last access time
st_size   ; total size of file, in bytes
st_gid    ; group ID of owne
st_uid    ; user ID of owner
st_nlink  ; number of hard links to the file
st_rdev   ; the device identifier (special files only)
st_dev    ; device file resides on
st_ino    ; the file serial number
st_mode   ; file mode

unix:chdir path

現在のディレクトリをpathに変更する。

unix:getwd **

現在のディレクトリを返す。

unix:chmod path integer

のアクセスモード(permission)を変更する。

unix:chown path integer

ファイルのオーナーを変更する。

unix:isatty stream-or-fd

もし、stream-or-fdがTTY型のデバイス(シリアルポートあるいは仮想TTY)に接続されているなら Tを返す。

unix:msgget key mode

によってアドレスされるメッセージキューを作成し、配置する。

unix:msgsnd qid buf &optional msize mtype flag

unix:msgrcv qid buf &optional mtype flag

unix:socket domain type &optional proto

に定義されている名前を持ちtypeを抽象型とするソケットを作成する。 typeは、1 (SOCK_STREAM), 2 (SOCK_DGRAM), 3 (SOCK_RAW), 4 (SOCK_RDM), 5 (SOCK_SEQPACKET)の内の1つである。

unix:bind socket name

socketを関連付ける。 もし、ソケットがUNIX領域内で定義されているならば、nameは、UNIXのパス名でなければならない。

unix:connect socket addr

addrで指定される他のソケットを接続する。

unix:listen socket &optional backlog

から接続要求を受け始める。 backlogは、接続の確定を待つためのキューの長さを指定する。

unix:accept socket

から接続要求を受け、両方向にメッセージを交換できるファイルディスクリプタ を返す。

unix:recvfrom socket &optional mesg from flag

からデータを書いたメッセージを受ける。 そのソケットは、unix:bindにより名前を割り当てられなければならない。 mesgは、入ってきたメッセージが蓄積されるための文字列である。 もし、mesgが与えられたならば、unix:recvfromは受け取ったバイト数を返す。 もし省略されたなら、メッセージを蓄積するための新しい文字列を作成し、 その文字列を返す。

unix:sendto socket addr mesg &optional len flag

によって指定される他のソケットへデータの書かれたメッセージを送る。 socketは、名前が割り当てられてないデータ書き込み型のソケットでなければならない。 mesgは、送るための文字列であり、lenは文字列の最初から 数えたメッセージの長さである。 もし、省略されたなら、すべての文字列を送る。

unix:getservbyname servicename

あるいはNISデータベースに記録されているservicename のサービス番号を返す。

unix:gethostbyname hostname

のipアドレスとアドレス型のリストを返す。 (一般にいつも AF_INET==2).

unix:syserrlist errno

のエラーコードに対するエラー情報が記述された文字列を返す。

シグナル

unix:signal signal func &optional option

に対してシグナルハンドラーfuncをインストールする。 BSD4.2システムにおいて、システムコール処理の間に捕まえたシグナルは、 システムコールのリトライに起因する。 これは、もしその処理がシステムコールの呼び出しを発行するならば、 シグナルを無視することを意味する。 もし、option=2が指定されたならば、シグナルはsystem-5の手法で 処理される。そのシグナルは、システムコールの失敗に起因する。

unix:kill pid signal

で名前付けされるプロセスにsignalを送る。

unix:pause **

シグナルが到着するまでこのプロセスの実行を一時停止する。

unix:alarm time

秒後にアラーム時計シグナル(SIGALRM 14)を送る。 time=0でunix:alarmを呼び出すと、アラーム時計をリセットする。

unix:ualarm time

がマイクロ秒単位であることを除いてunix:alarmと同じである。 ualarmは、Solaris2あるいはSystem5系のシステムに実現されていない。

unix:getitimer timer

は、0 (ITIMER_REAL), 1 (ITIMER_VIRTUAL), 2(ITIMER_PROF)の内の1つである。 秒単位の時間(timer)と間隔(interval)の2つの要素を持つリストを返す。

unix:setitimer timer value interval

valueintervalを設定する。 timerは、0 (ITIMER_REAL), 1 (ITIMER_VIRTUAL), 2(ITIMER_PROF)の内の1つである。 ITIMER_REALは、valueが終了したとき、SIGALRMを発行する。 ITIMER_VIRTUALは、SIGVTALRMを発行し、 ITIMER_PROFは、SIGPROFを発行する。

unix:select inlist outlist exceptlist timeout

exceptlistは、ファイルディスクリプタ を示すビットベクトルである。そのファイルディスクリプタの入出力イベント は、テストされなければならない。 例えば、もしinlist=#b0110でoutlist=#b100で exceptlist=NILであるなら、 fd=1あるいはfd=2で読み込み可能かあるいはfd=2で書き込み可能であるかどうかをテストする。 timeoutは、unix:selectが待つために許される秒数を指定する。 inlistで指定されているポートの1つに入力データが現れるかあるいは outlistに指定されるポートの1つに書き込み可能となるかあるいは exceptlistで指定されるポートの1つに例外条件が起こるとすぐに unix:selectは、inlist, outlist, exceptlistのそれぞれにおいて アクセス可能なポートとして設定されたポートの中で、入力処理可能なポート番号を返す。

unix:select-read-fd read-fdset timeout

入出力の選択は、ふつう入力処理のときのみ意味がある。 unix:select-read-fdは、 select fdset nil nil timeoutの速記法である。 read-fdsetは、ビットベクトルでなく、設定された読み込みfdを指定する整数である。

マルチスレッド

スレッド内でシグナルを生成することはできない。 したがって、1つのシグナルスタックと1つのタイマーがEuslispのプロセスの 中で実現されている。 Solaris2の上では、メインの最上位レベルが分割されたスレッド内で実行する。

unix:thr-self **

現在実行されているスレッドのID(整数)を返す。

unix:thr-getprio id

で指定されたスレッドの実行優先順位を返す。

unix:thr-setprio id newprio

で指定されたスレッドの実行優先順位にnewprioを設定する。 newprioが小さい数値の場合、優先順位が高いことを意味する。 言い替えれば、 newprioよりも大きな数値を持つスレッドは、CPUにアクセスされることが 少なくなる。 ユーザーは、実行優先順位をプロセスの値(普通はゼロ)よりも高く することはできない。

unix:thr-getconcurrency **

並列に実行できるスレッドの数で表現される 並列度(整数)を返す。

unix:thr-setconcurrency concurrency

の値は、プロセス内のLWPの数である。 もし、concurrensyがデフォルトの1ならば、 生成されたたくさんのスレッドがすべて実行可能であったとしても 順番に1つのLWPに割り当てられる。 もし、プログラムがマルチプロセッサマシン上で実行され、 同時に複数のCPUを利用したいならば、 concurrencyに1より大きい値を設定しなければならない。 concurrencyに大きな値を設定すると、オペレーティングシステムの リソースをたくさん消費する。普通、concurrencyはプロセッサの数 と同じかあるいは小さくすべきである。

unix:thr-create func arg-list &optional (size 64*1024)

ワードのlispスタックを持ち、sizeバイトのCスタック持つ 新しいスレッドを作成し、そのスレッド内でarg-listfuncを適用する。 スレッドは、どんな結果も呼びだし側に返すことができない。 この関数の使用は避けること。

低レベルメモリ管理

unix:malloc integer

Euslispのメモリ空間の外にメモリを配置する。

unix:free integer

で配置されたメモリブロックを開放する。

unix:valloc integer

unix:mmap address length protection share stream offset

unix:munmap address length

unix:vadvise integer

IOCTL

Unixはターミナルデバイスをioctlの2番目の引数に命令を設定することにより 制御することができるが、Euslispはインクルードファイルの参照や命令コードとしての 引数の論理和を省略するために、関数で備えている。 詳しい内容は、Unixのtermioのマニュアルを参照すること。

ターミナルの入出力制御には、TIOC*とTC*という2つの命令系がある。 自分のオペレーティングシステムにこれらの関数が実現されているがどうか について気を付けなさい。 基本的に、BSD系はTIOC*の入出力をサポートし、System5系がTC*を サポートしている。

SunOS 4.1 TIOC*とTC*の両方サポート

Solaris2 TC*のみサポート

mips, ultrix? TIOC*のみサポート

unix:tiocgetp stream &optional sgttybuf

パラメータを得る。

unix:tiocsetp stream sgttybuf

パラメータを設定する。

unix:tiocsetn stream &optional sgttybuf

unix:tiocgetd stream &optional sgttybuf

unix:tiocflush stream

バッファをすべて出力する。

unix:tiocgpgrp stream integer

プロセスのグループIDを得る。

unix:tiocspgrp stream integer

プロセスのグループIDを設定する。

unix:tiocoutq stream integer

unix:fionread stream integer

unix:tiocsetc stream buf

unix:tioclbis stream buf

unix:tioclbic stream buf

unix:tioclset stream buf

unix:tioclget stream buf

unix:tcseta stream buffer

ターミナルパラメータをすぐに設定する。

unix:tcsets stream buffer

ターミナルパラメータを設定する。

unix:tcsetsw stream buffer

出力として列をなす全ての文字を転送した後、ターミナルパラメータを設定する。

unix:tcsetsf stream buffer

出力として列をなす全ての文字を転送し、 入力として列をなす全ての文字列を廃棄した 後、ターミナルパラメータを設定する。

unix:tiocsetc stream buffer

unix:tcsetaf stream buffer

unix:tcsetaw stream buffer

unix:tcgeta stream buffer

unix:tcgets stream buffer

unix:tcgetattr stream buffer

unix:tcsetattr stream buffer

キーインデックスファイル

近年UNIXは、キーインデックスファイルの管理のためにdbmあるいはndbm ライブラリを提供する。このライブラリを使用することにより、 キーとデータの組みで構成されるデータベースを構築することができる。 以下に示す関数は、clib/ndbm.cに定義されている。 Sunにおいて、そのファイルは、cc -c -Dsun4 -Bstaticでコンパイルし、 (load “clib/ndbm” :ld-option “-lc”)でEuslispにロードすること。

dbm-open dbname mode flag

は、データベースファイルを作るときと、そのデータベースに読み込み/書き込み をするとき、最初に呼び出されなければならない。 dbnameは、データベースの名前である。 実際に、ndbm managerは“.pag”と“.dir”の拡張子を持つ 2つのファイルを作成する。 modeは、ファイルのオープンモードを指定する。0は読み込み専用、1は書き込み専用、 2は読み書き用を示す。また、最初にファイルを作成するときは、#x200を論理和すべきである。 flagは、chmodで変更されるアクセス許可を与える。 #o666あるいは#o664が、flagに適している。 dbm-openは、そのデータベースを確認するための整数を返す。 この値は、他のdbm関数によってデータベースを確認するために使用される。 言い換えれば、同時に幾つかのデータベースをオープンすることができる。

dbm-store db key datum mode

datumの組み合わせをdbに蓄積する。 dbは、データベースを確認するための整数である。 keydatumは文字列である。 modeは0(挿入)あるいは1(置き換え)のどちらかである。

dbm-fetch db key

の中のkeyに関連付けられているデータを呼び出す。

UNIXプロセス

EuslispからUNIX命令を実行ためにunix:system関数を使用すること。 piped-forkは、標準出力を標準入力がパイプを通してEuslispの双方向ストリームに 接続されるサブプロセスを作成する。 piped-forkはストリームを返す。 以下に示す関数は、“wc”を使用することにより、ファイルに含まれる行の数を 数えるものである。

(defun count-lines (file) (read (piped-fork "wc" file)))

次の例は、他のワークステーション“etlic0”の上にeusプロセスを作成し、 分散計算をするためのポートを提供する。

(setq ic0eus (piped-fork "rsh" "etlic0" "eus"))
(format ic0eus "(list 1 2 3)~%")
(read ic0eus) --> (1 2 3)

ソースコードを修正するために、Euslispからezを呼び出すことができる。 スクリーンエディターezは、メッセージキューを通してEuslispと接続する。 もし、既にezプロセスをEuslispと並列に実行しているならば、 ezはezプロセスを再スタートし、ターミナル制御を得る。 ezの中でesc-Pあるいはesc-M命令を発行することにより、 テキストは戻され、Euslispで評価される。 ファイルに少しの変更を加えたとき、全部のファイルをロードする必要がないので、 デバッグするのにこれは便利である。 emacsの上でもM-X run-lisp命令でおなじことが可能である。

cd &optional (dir (unix:getenv “HOME”))

現在のディレクトリを変更する。

ez &optional key

ezエディターの画面に入る。それからLisp書式を読み込み、 評価する。

piped-fork &optional (exec) &rest args

プロセスをforkし、両方向ストリームをEuslispとサブプロセスの間に作る。

rusage **

このプロセスのリソースの使用状況を表示する。

Cで書かれたLisp関数の追加

ファイルに含まれるCを重く参照したり、行列にしばしばアクセスするような プログラムにおいては、Euslispで記述するよりはむしろCあるいは他の言語で 記述した方が効率が良く、記述もわかり易い。 EusLispは、Cで書かれたプログラムをリンクする方法を備えている。

もしCで書かれたEuslispの関数を定義したいならば、 Euslispで呼び出しできるCの関数はそれぞれ、3つの引き数を受けるように書かれなければ ならない。環境へのポインタと受け取る引き数の数とlispの引数領域を示す ポインタの3つである。 これらの引数は、c/eus.hの中のマクロによって参照されるため、 ctx, n, argvと名付けられねばならない。 Cのプログラムは、eusdir*/c/eus.hをincludeしなければならない。 プログラマーは、そこに書かれた型やマクロに精通していなければならない。 エントリ関数名には、ソースファイルのbasenameを付けなければならない。

任意の数の実数の算術平均を計算するCの関数AVERAGEのサンプルコードは、 以下に示す通りである。 この例において、引数から実数値を得る方法、実数のポインタを作る方法、 特殊変数AVERAGEにポインタを設定する方法やエントリ関数aveに 関数やsymbolを定義する方法を知ることができる。 ’cc -c -Dsun4 -DSolaris2 -K pic’でこのプログラムをコンパイルする。 c/eus.h内の正しい定義を選択するために、-Dsun4や-DSolaris2 が必要である。 -K picは、ロード可能な共有オブジェクトのために、位置に依存するコードを Cコンパイラで生成させるために必要である。 その後、コンパイルの結果である’.o’ファイルがEuslispにロードすることができる。 もっと完全な例はeusdir*/clib/*.cに置かれている。 これらの例は、ここで書かれた方法で定義され、ロードされる。

/* ave.c */
/* (average &rest numbers) */
#include "/usr/local/eus/c/eus.h"
static pointer AVESYM;
pointer AVERAGE(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ register int i;
  float sum=0.0, a, av;
  pointer result;
  numunion nu;
  for (i=0; i<n; i++) {
    a=ckfltval(argv[i]);
    sum += a;} /*get floating value from args*/
  av=sum/n;
  result=makeflt(av);
  AVESYM->c.sym.speval=result;  /*kindly set the result in symbol*/
  return(result);}

ave(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ char *p;
  p="AVERAGE";
  defun(ctx,p,argv[0],AVERAGE);
  AVESYM=intern(ctx,p,strlen(p),userpkg); /* make a new symbol*/
  }

他言語インターフェース

Euslispとのリンクを考慮していないCの関数もEuslispにロードすることができる。 これらの関数は、他言語関数と呼ばれる。 そのようなプログラムはload-foreignマクロによりロードされる。 そのマクロは、foreign-moduleのインスタンスを返す。 オブジェクトファイルの中の外部symbol定義は、モジュールオブジェクトの中に 登録されている。 defforeignは、Euslispから呼び出すための C関数に対するエントリーを作るために使用される。 defun-c-callableは、Cから呼び出し可能なlisp関数を定義する。 呼び出し可能なCの関数は、パラメータを変換し関連するEuslispの関数へ制御を移すために pod-codeと呼ばれる特別なコードを持つ。 pod-addressは、この特別なコードのアドレスを返す。 そのアドレスはCの関数に通知されるべきである。

これは、CのプログラムのサンプルとEuslispへの関数インターフェースである。

/* C program named cfunc.c*/

static int (*g)();  /* variable to store Lisp function entry */

double sync(x)
double x;
{ extern double sin();
  return(sin(x)/x);}

char *upperstring(s)
char *s;
{ char *ss=s;
  while (*s) { if (islower(*s)) *s=toupper(*s); s++;}
  return(ss);}

int setlfunc(f)      /* remember the argument in g just to see */
int (*f)();          /* how Lisp function can be called from C */
{ g=f;}

int callfunc(x)      /* apply the Lisp function saved in g to the arg.*/
int x;
{ return((*g)(x));}

;;;; Example program for EusLisp's foreign language interface
;;;; make foreign-module
(setq m (load-foreign "cfunc.o"))

;; define foreign functions so that they can be callable from lisp
(defforeign sync m "sync" (:float) :float)
(defforeign toupper m "upperstring" (:string) :string)
(defforeign setlfunc m "setlfunc" (:integer) :integer)
(defforeign callfunc m "callfunc" (:integer) :integer)

;; call them
(sync 1.0)  --> 0.841471
(print (toupper "abc123"))  --> "ABC123"

;; define a test function which is callable from C.
(defun-c-callable TEST ((a :integer)) :integer
      (format t "TEST is called, arg=~s~%" a)
      (* a a))    ;; return the square of the arg
;;  call it from C
;;setlfunc remembers the entry address of Lisp TEST function.
(setlfunc (pod-address (intern "TEST")))
(callfunc 12)  --> TEST is called, arg=12  144

Euslispのデータ表現は、以下に示す方法でCのデータ表現に変換される。 EusLispの30ビット整数(文字列を含む)は、符号拡張され、スタックを通してCの関数に渡される。 30ビット実数は、倍精度実数(double)に拡張され、スタックを通して渡される。 文字列と整数ベクトルと実数ベクトルについては、その最初の要素のアドレスのみが スタックに渡され、行列自体はコピーされない。 Euslispには、2次元以上の配列を渡す方法がない。 2次元以上の配列はすべての要素を線形に保持する1次元ベクトルを持つ。 このベクトルは、array-entityマクロにより得られる。 もし、2次元行列をFORTRANのサブルーチンに送る場合、FORTRANにおいて列と行が反対となっているため その行列を転置しなければならないことに注意すること。

実数のEuslisp表現は、いつも単精度であるので、倍精度の実数のベクトルに渡すとき変換を要する。 変換関数、double2floatfloat2doubleは、この目的でclib/double.cの中に定義されている。 例えば、もし3x3の実数行列があり、CFのいう名のCの関数にそれを倍精度実数の行列として渡したいなら、 以下のように使用すればよい。

(setq mat (make-matrix 3 3))
(CF (float2double (array-entity mat)))

Cの構造体は、defstructマクロにより定義することができる。 defstructは、次のようなフィールド定義書式によりstruct-nameを受け取る。

(defcstruct <struct-name>
   {(<field> <type> [*] [size])}*)

たとえば、以下に示す構造体の定義は、つぎのdefstructによって表現される。

/* C definition */
struct example {
   char  a[2];
   short b;
   long  *c;
   float *d[2];};

/* equivalent EusLisp definition */
(defcstruct example
   (a :char 2)
   (b :short)
   (c :long *)
   (d :float * 2))

load-foreign objfile &key symbol-input symbol-output (symbol-file objfile) ld-option)

Euslisp以外の言語で書かれたオブジェクトモジュールをロードする。 Solaris2において、load-foreign:entryパラメータにnull文字列を 与えたloadを呼び出す。 コンパイルされたコードのオブジェクトが返される。 この結果は、後にdefforeignを呼び出すことによって モジュールの中の関数のエントリーを作ることが 必要である。 ライブラリーはld-optionに指定することができる。 しかしながら、ライブラリの中に定義されたsymbolはデフォルトのsymbol-outputファイルで 獲得することができない。 ライブラリで定義された関数の呼び出しをEuslispに許可するために、 symbol-outputsymbol-fileが明示的に与えられなければならない。 (もし、objfileからのみそれらを参照するならば、これらの引き数は必要ない。) load-foreignは、指定されたライブラリとグローバル変数と一緒にobjfileをEuslispのコアにリンクし、 リンクされたオブジェクトをsymbol-outputに書き込む。 それから、symbol-fileの中のsymbolは、検索され、他言語モジュールの中にリストアップされる。 symbol-fileのデフォルトがobjfileであるので、もしsymbol-fileが与えられないなら、 objfileに定義されているsymbolのみ認識される。 objfileとライブラリの両方のグローバルエントリーをすべて見るために、 load-foreignの最初のプロセスリンクの結果であるリンクされた(マージされた)symbolテーブル は確かめられなければならない。このような理由で、symbol-outputsymbol-fileの両方に 同一のファイル名を与えなければならない。

以下に示されるように、中間のsymbolファイルはunix:unlinkによって 削除することができる。 しかしながら、もし同じライブラリを参照する2つ以上の他言語モジュールをロードするとき、 ライブラリの2重化を避けたいなら、symbol-output引き数を使用しなければならない。 上記の例として、“linpack.a”のすべての関数をロードしており、 次に“linpack.a”の関数を呼び出している他のファイル“linapp.o”を呼びだそうとしていると仮定する。 次のload-foreign呼び出しは、“euslinpack”をunlinkする前に発行しなければならない (load-foreign “linapp.o” :symbol-input “euslinpack”)。 load-foreigndefforeignのもっと完全な例は、eusdir*/llib/linpack.lで 見ることができる。

(setq linpack-module
    (load-foreign "/usr/local/eus/clib/linpackref.o"
        :ld-option  "-L/usr/local/lib -llinpack -lF77 -lm -lc"
        :symbol-output "euslinpack"
        :symbol-file "euslinpack"
        ))
(unix:unlink "euslinpack")

defforeign funcname module cname paramspec resulttype

他言語モジュールの中の関数エントリーを作る。 funcnameは、Euslispに作られるsymbolである。 moduleは、load-foreignによって返されるコンパイルされたコードのオブジェクトである。 cnameは、他言語プログラムの中で定義されているCの関数の名前である。 その名前は“_myfunc”のような文字列である。 paramspecは、パラメータの型指定のリストである。 それは、EuslispからCの関数に引き数を渡すときに、データの型変換と強制(coercion)を行うために使用される。 データ変換がなかったり、あるいは型チェックが必要ないとき、paramspecはNILで構わない。 :integer, :float, :string, (:string n)の内の1つがresulttypeに与えられなければならない。 :integerは、Cの関数がchar,short,int(long)のいずれかを返すことを意味する。 :floatは、返す値がfloatあるいはdoubleのときに指定する。 :stringは、C関数がstringへのポインターを返すことを意味し、 EuslispはEuslispの文字列に変更するためにstringにlong-wordのヘッダーを追加する。 文字列の長さはstrlenによって見つけられる。 stringの直前に書き込まれるヘッダーは、悲惨な結果を引き起こすことがあることに注意。 もう一方で、(:string n)は、安全だが遅い。なぜなら、 nの長さを持つEuslispの文字列が新しく作成され、Cの文字列の内容が そこにコピーされるからである。 (:string 4)は、整数へのポインターを返すCの関数に使用できる。 FORTRANユーザーは、FORTRANの関数あるいはサブルーチンのあらゆる引き数は、 call-by-refferenceによって渡されることに注意すべきである。 したがって、1つの整数あるいは実数型の引き数でさえFORTRANへ 渡される前に整数ベクトルあるいは実数ベクトルに 置かれなければならない。

defun-c-callable funcname paramspec resulttype &rest body

他言語のコードから呼び出すことができるEuslispの関数を定義する。 funcnameは、Euslispの関数として定義されているsymbolである。 paramspecは、defforeignの中の型指定のリストである。 defforeignのparamspecと違い、defun-c-callableのparamspecは、 関数が引き数を全く受け取らない場合以外、省略することができない。 :integerは、int,char,shortのすべての型に使用すべきである。 :floatは、floatとdoubleに使用する。 resulttypeは、Lisp関数の型である。 resulttypeは、型のチェックあるいは整数から実数に型の強制を 必要とする場合を除いて、省略することができる。 bodyは、この関数がCから呼び出されるとき、実行されるlisp表現である。 defun-c-callableで定義されている関数は、Lisp表現からでも 呼び出すことができる。 defun-c-callablefuncnameを返す。 その返り値は、symbolのようであるが、そうではなく、symbolのサブクラスである foreign-podのインスタンスである。

pod-address funcname

で定義されたCで呼び出し可能なLisp関数funcnameにおける 他言語とEuslispとのインターフェースコードのアドレスを返す。 これは、他言語プログラムにLisp関数の位置を知らせるために使用される。

array-entity array-of-more-than-one-dimension

多次元配列の要素を保持する1次元ベクトルを返す。 これは、多次元あるいは一般の配列を他言語に渡すために必要である。 しかし、1次元のベクトルは直接渡すことができる。

float2double float-vector &optional doublevector

を倍精度実数の表現に変換する。 その結果は、float-vectorであるが、最初の引き数の長さの2倍になっている。

double2float doublevector &optional float-vector

倍精度実数表現が単精度のfloat-vectorに変換される。

VxWorks

ホストとVxWorksとの通信機能が“vxworks/vxweus.l”ファイルで提供されている。 VxWorks上にvxwservサーバを常駐させることにより、 ホスト上のEusLispからvxwservに コネクションを張り、vxwsプロトコルに従った コマンドを送ることにより、VxWorksの関数を起動し、引数を送り、 結果を受け取ることができる。

VxWorksのソフトはSunのcコンパイラによって開発することができる上、 データ表現がsun3, sun4, VME147の間で共通であることを利用して、 vxwsプロトコルは、バイナリモードで動作することができる。

VxWorks側の起動

VxWorksにログインし、“*eusdir*/vxworks/vxwserv.o”をロードする。 その後、vxwservタスクをspawnする。 vxwservはVxWorks上の2200番ポートをlistenする。 2200が塞がっている場合、2201, 2202, ...を試す。 正しくbindされたポート番号が表示される。

% rlogin asvx0  (あるいはetlic2上であれば、% tip asvx[01] も可能)
-> cd "atom:/usr/share/src/eus/vxworks"
-> ld <vxwserv.o
-> sp vxwserv
port 2200 is bound.

VxWorksのiコマンドで、vxwservタスクが常駐したことを確かめる。 同じ要領で、eusから呼び出したいVxWorksのプログラムをVxWorks上にロードする。 その後、EuslispとVxWorksとの コネクションが張られると、vxwservを走らせたTTYに、次のようなメッセージが 出力される。

CLIENT accepted: sock=9 port = 1129: family = 2: addr = c01fcc10:
VxWserv started with 16394 byte buffer

ホスト側の起動

任意のマシンの上でeusを起動し、“vxworks/vxweus”をロードする。 connect-vxw関数を用いてvxwservに接続する。 接続後、ソケットストリームがvxw-stream*にバインドされる。 以下に、コネクトの例を示す。この例では、VxWorks上のsin, vadd関数を euslispの関数VSIN,VADとして定義している。

(load "vxworks/vxweus")
(setq s (connect-vxw :host "asvx0" :port 2200 :buffer-size 1024))
(defvxw VSIN "_sin" (theta) :float)
(defvxw VAD "_vadd" (v1 v2) (float-vector 3))

VxWorks上に作成される関数が、vxwsを通じて呼び出されるためには、 次の条件を満たさなければならない。

  1. 引数は、32個以内であること、引数に受け取るベクタの容量の合計が connect-vxwの:buffer-sizeで指定した値を越えないこと
  2. structを引数にしないこと、必ずstructへのポインタを引数にすること
  3. 結果は、int, float, doubleまたは、それらの配列のアドレスであること
  4. 配列のアドレスを結果とする場合、その配列の実体は、 関数の外部に取られていること
connect-vxw = `[関数]
&key = (host “asvx0”) (port 2200) (buffer-size 16384) (priority 1280) (option #x1c)

:hostに対してvxwsプロトコルによる通信のためのソケットストリームを作成し、そのストリームを返す。 :hostには、ネットワークにおけるVxWorksのアクセス番号あるいはアクセス名を指定する。 :portには、VxWorks上のvxwservがバインドしたポートを捜すための最初のポート番号を指定する。 このポート番号から、増加方向に接続を試行する。 :optionのコードについては、VxWorksの、spawn関数を参照のこと。 コネクションは、同時に複数張ってよい。

vxw vxw-stream entry result-type args

は、vxw-streamに接続されているVxWorksの関数entryを呼び出し、 その関数に引き数argsを与えてresult-typeで指定された結果を得る。 vxw-streamには、connect-vxwで作成したソケットストリームを与える。 entryには、VxWorksの関数名をストリングで指定するか、あるいは関数の アドレスを整数で指定する。 関数のアドレスを知るには、VxWorksのfindsymbolを呼び出す。 知りたいシンボルは、通常、“_”で始まることに注意。 entryがストリングの場合、VxWorks上でシンボルテーブルの逐次探索が行われる。 result-typeには、結果のデータ型(:integerまたは:float)、 あるいはデータを受け取るベクタ型を指定する。 ベクタは、float-vector, integer-vector, stringのインスタンスである。 general vector(lispの任意のオブジェクトを要素とするベクタ)は指定できない。 結果型は、必ず、実際のVxWorks関数の結果型と一致しなければならない。 argsには、entryに与える引き数を指定する。 引数に許されるEusLispデータは、integer, float, string, integer-vector, float-vector, integer-matrix, float-matrixである。 ポインタを含んだ一般のオブジェクト、一般のベクトルは送れない。 また、送られたベクトルデータは、一旦vxwservが獲得したバッファの中に蓄積される。 例えば、VxWorksに定義された関数“sin”を呼び出すためには、次のように実行すればよい。 (vxw *vxw-stream* “sin” :float 1.0)

defvxw eus-func-name entry args &optional (result-type :integer)

は、findsymbolを用いてvxwを呼び出して、VxWorksの関数の高速な呼び出しを 実現するためのマクロである。 VxWorksの関数entryを呼び出すためのEuslispの関数eus-func-nameを定義する。 このマクロを実行後は、eus-func-nameを呼び出すことにより、VxWorksの関数を呼び出すことができる。 このとき、呼び出しに使用されるソケットストリームはvxw-stream*に固定されている。 ただし、VxWorks側で、関数をコンパイルし直して再ロードした場合、 新しい関数定義が呼ばれるようにするためには、eus側で、defvxwをもう一度 実行し直して、最新のエントリアドレスが指定されるようにする必要がある。

マルチスレッド

マルチスレッドは、Solarisオペレーティングシステム上の 並列プログラミングや非同期プログラミングの機能である。 非同期プログラミングは、プログラムの状態と無関係に発生する 様々なセンサを経由した外部イベントに応答するためのプログラムに要求される。 並列プログラミングは、画像処理や経路計画の干渉チェックのような プロセス向きの計算の効率を改善する場合に効果的である。

マルチスレッドEuslispの設計

Solaris 2 オペレーティングシステムのマルチスレッド

マルチスレッドEuslisp(MT-Eus)は、複数のプロセッサを持ったSolaris 2 オペレーティングシステム上で動作する。 Solarisのスレッドは、 共有メモリと異なった環境を持つような従来の UNIXプロセスをCPUに配置するためのユニットである。Solaris OSによって提供されるスレッドのライブラリは、 それぞれのスレッドを単一のLWP(light weight process)に配置する。 このプロセスがカーネルのリソースである。 UNIXのカーネルは、それぞれのスレッドに割り当てられたスレッドの優先権に 基づいて複数の物理CPUにLWPの配置を計画する。 図[threadmodel]は、スレッドとLWPとCPUの関係を表わしたものである。 Euslispの環境およびメモリ管理の設計について、 マルチスレッドの能力を引き出すために2つの大きな変更がされた。

Context Separation

MT-Eusは、それぞれのスレッドに対し個別にスタックと環境を配置する。 そのため、他のスレッドと独立に実行することができる。 symbolやconsのようなオブジェクトは、これまでのEuslispのように 共有ヒープメモリ上に配置される。 したがって、block labelやcatch tagやローカル変数のような スレッドの個別データは、他のスレッドから保護される。 ところが、グローバル変数によって示される値(オブジェクト)は、 情報の変更が許可されているすべてのスレッドから見ることができる。

Solarisオペレーティングシステムのスレッドモデル

Solarisオペレーティングシステムのスレッドモデル

環境はC-stackとbinding-stackおよびlambda, block, catch, let, flet などのローカルブロックに繋がるフレームポインタにより構成されており、 新しいスレッドが作成されたときに設置される。 複数の環境が本当のマルチプロセッサマシンの上で同時に 動作できるので、グローバル変数の中の現在の環境に対して単一なポインタ を持つことができない。 むしろ、環境のポインタを最上位の評価から低レベルのメモリ管理に変換するために、 すべての内部関数にもう一つ引き数を付け加えなければならない。

メモリ管理

EusLispは、すべての型のオブジェクトに対して単一のヒープの中で フィボナッチバディを用いたメモリ管理方法を採用している。 異なったメモリ要求を持つプログラムを実行した後、 フィボナッチバディが様々な大きさのオブジェクトを等しく高速に配置することができ、コピーなしに素早くガーベージコレクトができ、 かつ、高いメモリ利用率(内部損失が10〜15%で外部損失は無視できる) を示すことを確信した。 マルチスレッドのためには、2つ目のポイントすなわちコピーなしの ガーベージコレクトが重要である。 もし、オブジェクトのアドレスがガーベージコレクトのコピーにより 変化したならば、すべてのスレッド環境のスタックおよびCPUのレジスタ 内のポインタを新しいアドレスに書き換えなければならない。 しかし、この書き換えは不可能かあるいは大変困難である。

すべてのメモリ配置要求は、低レベルのalloc関数によって処理される。 allocは、mutex-lockingをする。なぜなら、大きさを持たないリストの グローバルデータベースを扱うからである。 ガーベージコレクトの始まる時期およびどのスレッドによってガーベージコレクトが 生じるのかを予言できないので、 すべてのスレッドは突発的に起こるガーベージコレクトのために 準備をしておかなければならない。 生きているオブジェクトへのすべてのポインタは、ゴミとして掃除されない ように保護するためいつでもガーベージコレクトからアクセスできるよう 調整されなければならない。 これは、スタックの上に保存されていることを信用する代わりに、 それぞれの環境の固定されたスロットの中に極最近に配置されたオブジェクトに 対するポインタを蓄積することによって達成される。

図 [parathreads]は、スレッドのメモリ要求とforkされたガーベージコレクト 内部でのmarkingおよびsweepingを並列に行っている流れ図を示したものである。 メモリ要求およびポインタの処理を行わないスレッドはガーベージコレクトと並列に 実行することができ、信号処理や画像獲得のような低レベルのタスクの 実時間応答を改善することに注意すること。

並列スレッドのメモリ要求とガーベージコレクトに並列実行

並列スレッドのメモリ要求とガーベージコレクトに並列実行

非同期プログラミングと並列プログラミングの構築

スレッド作成とスレッドプール

Solarisにおいて複数のプロセッサ上で並列にプログラムを実行するためには、 そのプログラムは関数の集まりとして書かれる必要がある。 その関数はそれぞれプロセスの中で動的に作成されるスレッドによって 実行される。 スレッドを作成するために要求される時間は、プロセスを作成するよりも 速くなければならないが、スタックを配置しスタックのオーバーフローを 発見するためのページ属性を設定した後にスレッドが動き始めるまでに Euslispにおいて数ミリ秒かかる。 この遅れは関数実施と比較して我慢できないため、 評価時間におけるシステムコールに対する所要時間を排除する目的で、 あらかじめmake-thread関数により十分な数のスレッドが作られ、 システムのスレッドプールに置かれる。 スレッドプールの中のそれぞれのスレッドは、図[threadobj]で示されるように スレッドIDと同期のためのセマフォと引き数や評価結果を転送するためのスロット から構成されるスレッドオブジェクトにより表現される。

スレッド間で制御やデータを受け渡すためのスレッドオブジェクト(左)とスレッドプール内に置かれたスレッドの集まり(右) スレッド間で制御やデータを受け渡すためのスレッドオブジェクト(左)とスレッドプール内に置かれたスレッドの集まり(右)

スレッドの並列実行

スレッドによる並列実行の配置のために、スレッド関数が使用される。 スレッドは、スレッドプールから1つの空きスレッドを取り、 共有メモリを経由して引き数を渡し、図[threadobj]に示されるような セマフォ信号によりスレッドを立ち上げ、 停止することなしに呼出側へスレッドオブジェクトを返す。 立ち上げられたスレッドは、呼び出したスレッドと並列に実行され、 引き数を評価し始める。 呼出側は、forkされたスレッドから評価結果を受けとるためにwait-threadを 使用する。 plistマクロは、引き数の並列評価を記述するために大変便利な書式である。 plistは、それぞれの引き数を評価するためにスレッドを割り当て、 すべてのスレッドが評価し終わるのを待って結果をリストアップする。

同期の手法

MT-Eusは、mutex lock, condition variable, セマフォと呼ばれる 3種類の同期手法を持っている。 mutex lockは、スレッド間の共有変数の連続アクセスのために使用される。 condition variableは、ロックの仮開放あるいは再獲得によってmutex-lockされた 部分の条件がtrueになることを待つことをスレッドに許可する。 セマフォは、イベントの発生を通知するためあるいはリソースの分割を制御するために 使用される。 Solarisのカーネルが時間分割スケージューリングを基本として何気なしにタスク 切り替えを発生するのと異なり、 これらの同期手法は、任意の環境切り替えを引き起こす。

同期障壁と同期メモリポート

同期障壁と同期メモリポート

同期障壁

barrier-synchは、複数のスレッドを同時に同期させるための機構である (図 [synchports])。 この目的において、barrierクラスのインスタンスが作成され、 同期に関係するスレッドがオブジェクトに登録される。 その後、それぞれのスレッドはbarrierオブジェクトに:waitメッセージを 送り、そのスレッドは停止する。 オブジェクトに登録された最後のスレッドが:waitメッセージを送ったとき、 待ちが解除され、すべての待ちスレッドがTの返り値を得る。 barrier-syncは、マルチロボットシミュレーションのグローバルタイムという 重要な役割を演じている。

同期メモリポート

同期メモリポート(synch-memory-port)は、 スレッド間でデータを交換するための1種のストリーム である(図 [synchports])。 プロセス内のすべてのスレッドはヒープメモリを共有しているので、 もし1つのスレッドがグローバル変数にオブジェクトを割り当てた場合、 直ちに他のスレッドから見れるようになる。 しかしながら、共有メモリはグローバルデータが更新されたという イベントを送るための能力が不足している。 同期メモリポートは、共有オブジェクトをアクセスするための この同期機能を保証する。 同期メモリポートオブジェクトは、1つのバッファスロットと同期読み書きの ために使用される2つのセマフォによって構成されている。

タイマー

実時間プログラムは、予定された時間に実行される関数や、 特定の間隔で繰り返される関数をしばしば要求する。 これまでのEusLispは、Unixのインターバルタイマーによって 定期的に生成される信号によって発生するユーザー関数を 実行することができた。 MT-Eusにおいて、この実行はデッドロックを引き起こす。 なぜなら、割り込みがmutex-lockされたブロック内から発生する可能性がある。 したがって、制御はevalの最初のように安全な場所で渡されなければ ならない。 上記の同期によって引き起こされる遅れを避けるために、 MT-Eusはセマフォを経由して信号通知(signal-notification)も 提供する。 言い換えれば、信号関数は呼び出されるかあるいは信号の到着を知らせる 関数あるいはセマフォのどちらかをとる。 セマフォは、低レベルで告示されるので、 同期により隠れているところは最小である。

以下に示すものは、マルチスレッド機能を用いた画像処理のプログラム例である。 画像入力スレッドとフィルタースレッドが生成される。 samp-imageは、33msec毎に通知されるsamp-semを待つことにより、 定期的に画像データをとる。 2つのスレッドはthread-portの読み書きを通じて同期する。 filter-imageは、フィルターの並列計算のために複数のスレッドを使用している。

(make-threads 8)
(defun samp-image (p)
   (let ((samp-sem (make-semaphore)))
        (periodic-sema-post 0.03 samp-sem)
        (loop (sema-wait samp-sem)
              (send p :write (read-image))))
(defun filter-image (p)
  (let (img)
       (loop (setf img (send p :read))
             (plist (filter-up-half img)
                    (filter-low-half img)))))
(setf port (make-thread-port))
(setf sampler (thread #'samp-image port))
(setf filter (thread #'filter-image port))

並列度の計測

表 [paragain]は、32CPUで構成されるCray Superserverの上で測定 した並列実行効率を示したものである。 コンパイルされたフィボナッチ関数において線形な並列度が得られた。 なぜなら、共有メモリへのアクセスがなく、それぞれのプロセッサのキャッシュ メモリに十分ロードできるほどちいさなプログラムであったためである。 それに反して、同じプログラムをインタープリターで実行したとき、 キャッシュメモリを使い果たしたため、 線形な高効率を達成することができなかった。 さらにまた、頻繁に共有メモリを参照するようなプログラムや メモリ配置を要求するようなプログラムは1個のプロセッサで実行した ときよりも良い性能を得ることができなかった。 これは、頻繁なキャッシュメモリの入れ替えが原因と考えられる。

processors 1 2 4 8 GC (ratio)
  1. compiled Fibonacci
1.0 2.0 4.0 7.8 0
  1. interpreted Fibonacci
1.0 1.7 2.7 4.4 0
  1. copy-seq
1.0 1.3 0.76 0.71 0.15
  1. make-cube
1.0 0.91 0.40 0.39 0.15
  1. interference-check
1.0 0.88 0.55 0.34 0.21

Table: マルチプロセッサ上で実行されたプログラムの並列度


スレッド生成

スレッドは、計算を割り当てる単位であり、普通lisp書式を評価する ための単位である。 Euslispのスレッドは、threadクラスのインスタンスによって 表現される。 このオブジェクトは、内容を表現するスレッド全体というよりはむしろ、 実際に引き数と結果を渡すためのスレッドの 制御ポートであり、評価を始めるものである。

sys:make-thread num &optional (lsize 32*1024) (csize lsize)

ワードのlispスタックとcsizeワードのC-スタックを持つ スレッドをnum個だけ生成し、システムのスレッドプールに 置く。 スレッドプール内のすべてのスレッドは、sys:*threads*に束ねてあり、 make-threadが呼び出されたときに拡張される。 thread関数によって、計算はスレッドプールの中で空いたスレッドの 1つに割り当てられる。 したがって、指定された計算がどのスレッドに割り当てられるか 制御できないため、スレッドのスタックサイズを変更する方法が無い。

sys:*threads* **

によって作成されたすべてのスレッドのリストを持つ。

sys::free-threads **

スレッドプール内の空いたスレッドのリストを返す。 もし、結果がNILならば、スレッドへのタスクの新しい付託は現在実行されている スレッドのどれかの評価が終了するかあるいは make-threadによってスレッドプールに新しいスレッドを生成するまで 停止される。

sys:thread func &rest args

スレッドプールから空いたスレッドを1つ取り出し、 (func . args)の評価のためにそれを割り当てる。 sys:threadは、argsを展開したリストにfuncを適用 するが、関数の適用結果を受け取らないため、 非同期のfuncallとみなすことができる。 むしろ、sys:threadはfuncallに割り当てられたスレッド オブジェクトを返すので、実際の結果はsys:wait-threadによって 後から得ることができる。

(defun compute-pi (digits) ...)
(setq trd (sys:thread \#'compute-pi 1000)) ;assign compute-pi to a thread
...  ;; other computation
(sys:wait-thread trd) ;get the result of (compute-pi 1000)

sys:thread-no-wait func &rest args

空いたスレッドの1つに計算を割り当てる。 スレッドは、wait-threadされることなしに、 評価が終了したとき、スレッドプールに戻される。

sys:wait-thread thread

sys:thread関数によって与えられたfuncallの評価が 終了するのを待ち、その結果を受け取り、返す。 もし、スレッドにsys:threadによって評価が割り当てられたならば、 sys:wait-threadは、必須である。 なぜなら、スレッドは結果を転送し終わるまでスレッドプールに戻らない ためである。

sys:plist &rest forms

異なったスレッドにより並列にformsを評価し、 すべての評価が終了するのを待ち、 結果のリストを返す。 sys:plistは、リスト化されたそれぞれのformが関数呼び出しされる ことを除いて、parallel-listとしてみなされるだろう。

同期

Solarisオペレーティングシステム内には、マルチスレッドプログラムのために 4つの同期手法がある。 Euslispは、mutex-lockとcondition variableとセマフォを提供している。 reader-writer lockは実現されてない。 これらの手法に基づいて、同期メモリポートや同期障壁のような 高レベルの同期機構が実現されている。

sys:make-mutex-lock **

mutex-lockを作り、返す。 mutex-lockは、6つの要素を持つ整数ベクトルで表現されている。

sys:mutex-lock mlock

mutex-lockのmlockをロックする。 もし、mlockが既に他のスレッドからロックされているなら、 mutex-lockはロックが外されるまで待つ。

sys:mutex-unlock mlock

を解除し、このロックを待っている他のスレッドの内の1つが再び実行され始める。

sys:mutex mlock &rest forms

mutex-lockとmutex-unlockは、組みで使用されなければならない。 mutexは、重要な部分をひとまとまりにしたマクロである。 mlockは、評価するformsが評価される前にロックされる。 そして、評価が終了したときに、ロックが解除される。 このマクロは、以下のprogn formに展開される。 unwind-protectは、formsの評価中にエラーが発生したとき でさえ、ロックの解除を保証するために使用されることに注意すること。

(progn
    (sys:mutex-lock mlock)
    (unwind-protect
        (progn . forms)
        (sys:mutex-unlock mlock)))

sys:make-cond **

4つの要素を持つ整数ベクトルであるcondition variableオブジェクトを 作る。condition variableの返り値としては、ロックされてない状態でである。

sys:cond-wait condvar mlock

に信号が出されるまで待つ。 もし、condvarが他のスレッドによってすでに獲得されていたならば、 mlockを解除し、condvarに信号が出されるまで待つ。

sys:cond-signal condvar

で示されるcondition variableに信号を出す。

sys:make-semaphore **

20の要素を持つ整数ベクトルによって表現されるセマフォオブジェクトを作る。

sys:sema-post sem

に信号を出す。

sys:sema-wait sem

に信号が来るまで待つ。

sys:barrier-synch

:super = ** propertied-object**
:slots threads n-threads count barrier-cond threads-lock count-lock

同期障壁のための構造を表現する。 同期を待っているスレッドは、thread-lockによって 相互に排除されるthreadに置かれる。 barrier-synchオブジェクトが生成されたとき、 countは、ゼロに初期化される。 同期しているスレッドは、:addメッセージを送ることによって、 threadsリストに置かれる。 このbarrier-synchオブジェクトに:waitを送ることは、 countを増加させることの原因となり、 送られたスレッドは待ち状態になる。 threadsの中のすべてのスレッドに:waitメッセージが送られたとき、 待ちが解除され、すべてのスレッドの実行が再び始まる。 同期は、count-lockのmutex-lockとbarrier-condのcondition-variable の組み合わせによって実行される。

:init **

このbarrier-synchオブジェクトを初期化する。 2つのmutex-lockと1つのcondition-variableが生成される。

:add thr

リストの中にthrスレッドが追加される。

:remove thr

リストの中からthrスレッドを削除する。

:wait **

リストの中のすべてのスレッドに:waitが配布されるのを待つ。

sys:synch-memory-port

:super = ** propertied-object**
:slots sema-in sema-out buf empty lock

1方向の同期されたメモリポートを実現する。 このオブジェクトを通じてデータを転送するために、2つのスレッドを同期させる。 転送制御は、セマフォを用いて実現されている。

:read **

このsynch-memory-portにバッファされているデータを読む。 もし、まだ書かれていなかったならば、:readは停止する。

:write datum

バッファにdatumを書き込む。 1ワードのバッファのみ存在するので、 もし他のデータが既に書かれておりまだ読まれていなかったならば、 :writeは:readによってそのデータが読み込まれるまで待つ。

:init **

このsync-memory-portを初期化する。 これには2つのセマフォが生成され、:write動作が可能な状態になっている。

幾何学関数

実数ベクトル(float-vector)

float-vectorは、要素が実数である1次元ベクトルである。 float-vectorは、どんなサイズでも良い。 resultが引き数リストで指定されているとき、 そのresultはfloat-vectorであるべきである。

float-vector &rest numbers

を要素とするfloat-vectorを新しく作る。 (float-vector 1 2 3)と#F(1 2 3)の違いに注意すること。 前者は、呼ばれたときはいつでもベクトルが生成されるが、 後者は読み込まれたときのみ生成される。

float-vector-p obj

がfloat-vectorであるならば、Tを返す。

v+ fltvec1 fltvec2 &optional result

2つのfloat-vectorを加える。

v- fltvec1 &optional fltvec2 result

2つのfloat-vectorを差し引く。もし、fltvec2が省略されているならば、 fltvec1の符号が反転される。

v. fltvec1 fltvec2

2つのfloat-vectorの内積を計算する。

v* fltvec1 fltvec2 &optional result

2つのfloat-vectorの外積を計算する。

v.* fltvec1 fltvec2 fltvec3

スカラー3重積を計算する。(v.* A B C)=(V. A (V* B C))=(V. (V* A B) C)

v:math:`=` fltvec1 fltvec2

もし、fltvec1の要素がfltvec2の対応する要素とすべて等しいとき、 Tを返す。

v:math:`<` fltvec1 fltvec2

もし、fltvec1の要素がfltvec2の対応する要素よりすべて小さいとき、 Tを返す。

v:math:`>` fltvec1 fltvec2

もし、fltvec1の要素がfltvec2の対応する要素よりすべて大きいとき、 Tを返す。

vmin &rest fltvec

の中のそれぞれの次元における最小値を捜し、 その値でfloat-vectorを新しく作る。vminvmaxは、 頂点の座標から最小のminimal-boxを見つけるために使用される。

vmax &rest fltvec

の中のそれぞれの次元における最大値を捜し、 その値でfloat-vectorを新しく作る。

minimal-box v-list minvec maxvec &optional err

与えられたv-listに対してminimal bounding boxを計算し、 その結果をminvecmaxvecに蓄積する。 もし、実数errが指定されているならば、minimal boxはその比率によって 成長する。すなわち、もしerrが0.01のとき、minvecのそれぞれの 要素はminvecmaxvecとの距離の1%減少する。 そして、maxvecのそれぞれの要素は1%増加する。 minimal-boxは、minvecmaxvecとの距離を返す。

scale number fltvec &optional result

のすべての要素をスカラーnumber倍する。

norm fltvec

のノルムを求める。\(\Vert fltvec\Vert\)

norm2 fltvec

のノルムの2乗を求める。 \(\Vert fltvec\Vert^2\)=(v. fltvec fltvec)

normalize-vector fltvec &optional result

のノルムが1.0となるように正規化する。

distance fltvec1 fltvec2

2つのfloat-vectorの距離を返す。\(|fltvec-fltvec2|\)

distance2 fltvec1 fltvec2

2つのfloat-vectorの距離の2乗を返す。\(|fltvec-fltvec2|^2\)

homo2normal homovec &optional normalvec

同次ベクトルhomovecを正規表現に変換する。

homogenize normalvec &optional homovec

正規ベクトルnormalvecを同次表現に変換する。

midpoint p p1 p2 &optional result

は実数で、p1,p2は同次元のfloat-vectorである。 p1:math:`-`p2\(p:(1-p)\)の比率で等分した点\((1-p)\cdot p1 + p\cdot p2\) を返す。

rotate-vector fltvec theta axis &optional result

2次元あるいは3次元のfltvecaxis回りにthetaラジアン 回転する。 axisは、:x, :y, :z, 0, 1, 2, または NILの内の一つである。 axisがNILのとき、fltvecは2次元として扱われる。 3次元空間の任意の軸の回りにベクトルを回転するためには、 rotation-matrixで回転行列を作り、そのベクトルにかければよい。

行列と変換

行列は、要素がすべて実数の2次元の配列である。 ほとんどの関数において行列はどんなサイズでもよいが、 v*, v.*, euler-angle, rpy-angle関数では3次元の行列のみ 扱うことができる。 transform, m*transposeは、行列を正方行列に限定せず、 一般のn*m行列に対して処理を行う。

resultパラメータを受けた関数は、計算結果をそこに置く。 そのため、ヒープは使用しない。 すべての行列関数は、正規座標系における変換を考慮しており、 同次座標系は考慮していない。

rpy-angle関数は、回転行列をワールド座標系におけるz,y,x軸回りの 3つの回転角に分解する。 euler-angle関数はrpy-angleと同様に分解するが、 回転軸がローカル座標系のz,y,z軸となっている。 角度が反対方向にも得られるため、これらの関数は2つの解を返す。

; Mat is a 3X3 rotation matrix.
(setq rots (rpy-angle mat))
(setq r (unit-matrix 3))
(rotate-matrix r (car rots) :x t r)
(rotate-matrix r (cadr rots) :y t r)
(rotate-matrix r (caddr rots) :z t r)
;--> resulted r is equivalent to mat

3次元空間の位置と方向の組みを保つために、[Coordinates]節に記載されている coordinatescascaded-coordsクラスを使用すること。

matrix &rest elements

から行列を新しく作る。 Row x Col = (elementsの数) x (最初のelementの長さ) elementsは、どの型の列((list 1 2 3)や(vector 1 2 3)や (float-vector 1 2 3))でもよい。 それぞれの列は行列の行ベクトルとしてならべられる。

make-matrix rowsize columnsize &optional init

\(rowsize \times columnsize\)の大きさの行列を作る。

matrixp obj

もし、objが行列のとき、すなわち、objが2次元の配列で その要素が実数であるとき、Tを返す。

matrix-row mat row-index

行列matからrow-indexで示される行ベクトルを抽出する。 matrix-rowは、setfを使用することにより 行列の特定の行にベクトルを設定することにも使用される。

matrix-column mat column-index

行列matからcoloumn-indexで示される列ベクトルを抽出する。 matrix-columnは、setfを使用することにより 行列の特定の列にベクトルを設定することにも使用される。

m* matrix1 matrix2 &optional result

matrix2の積を返す。

transpose matrix &optional result

の転置行列を返す。すなわち、matrixの列と行を入れ替える。

unit-matrix dim

\(\times\) dimの単位行列を作る。

replace-matrix dest src

行列destのすべての要素を同一な行列srcで置き換える。

scale-matrix scalar mat

のすべての要素にscalerを掛ける。

copy-matrix matrix

のコピーを作る。

transform matrix fltvector &optional result

行列matrixをベクトルfltvectorの左から掛ける。

transform fltvector matrix &optional result

行列matrixをベクトルfltvectorの右から掛ける。

rotate-matrix matrix theta axis &optional world-p result

で行列matrixを回転させるとき、 回転軸(:x, :y, :zまたは0,1,2)はワールド座標系あるいは ローカル座標系のどちらかを与えられる。 もし、world-pにNILが指定されているとき、 ローカル座標系の軸に沿った回転を意味し、回転行列を左から掛ける。 もし、world-pがnon-NILのとき、 ワールド座標系に対する回転行列を作り、回転行列を右から掛ける。 もし、axisにNILが与えられたとき、行列matrixは2次元と仮定され、 world-pの如何にかかわらず2次元空間の回転が与えられる。

rotation-matrix theta axis &optional result

軸回りの2次元あるいは3次元の回転行列を作る。 軸は:x,:y,:z,0,1,2,3次元ベクトルあるいはNILのどれかである。 2次元回転行列を作るとき、axisはNILでなければならない。

rotation-angle rotation-matrix

から等価な回転軸と角度を抽出し、 実数とfloat-vectorのリストを返す。 rotation-matrixが単位行列のとき、NILが返される。 また、回転角が小さいとき、結果がエラーとなる。 rotation-matrixが2次元のとき、1つの角度値が返される。

rpy-matrix ang-z ang-y ang-x

ロール、ピッチ、ヨー角で定義される回転行列を作る。 最初に、単位行列をx軸回りにang-xラジアン回転させる。 次に、y軸回りにang-yラジアン、最後にz軸回りにang-z ラジアン回転させる。 すべての回転軸はワールド座標系で与えられる。

rpy-angle matrix

の2組のロール、ピッチ、ヨー角を抽出する。

Euler-matrix ang-z ang-y ang2-z

3つのオイラー角で定義される回転行列を作る。 最初に単位行列をz軸回りにang-z回転させ、次にy軸回りにang-y 回転させ、最後にz軸回りにang2-z回転させる。 すべての回転軸はローカル座標系で与えられる。

Euler-angle matrix

から2組のオイラー角を抽出する。

LU分解

lu-decomposelu-solveは、線形の連立方程式を 解くために用意されている。 最初に、lu-decomposeは行列を下三角行列を上三角行列に分解する。 もし、行列が特異値なら、lu-decomposeはNILを返す。 そうでなければ、lu-solveに与えるべき順列ベクトルを返す。 lu-solveは、与えられた定数ベクトルの解をLU行列で計算する。 この手法は、同じ係数行列と異なった定数ベクトルのたくさんの組に対して 解を求めたいときに効果的である。 simultaneous-equationは、1つの解だけを求めたいときにもっとも 手軽な関数である。 lu-determinantは、LU分解された行列の行列式を計算する。 inverse-matrix関数は、lu-decomposeを1回とlu-solveをn回 使って逆行列を求める。 3*3行列での計算時間は約4msである。

lu-decompose matrix &optional result

にLU分解を実行する。

lu-solve lu-mat perm-vector bvector &optional result

LU分解された1次連立方程式を解く。 perm-vectorは、lu-decomposeで返された結果でなければならない。

lu-determinant lu-mat perm-vector

LU分解された行列の行列式を求める。

simultaneous-equation mat vec

係数がmatで、定数がvecで記述される1次連立方程式を解く。

inverse-matrix mat

正方行列matの逆行列を求める。

pseudo-inverse mat

特異値分解を用いて擬似逆行列を求める。

座標系

座標系と座標変換は、coordinatesクラスで表現される。 4*4の同次行列表現の代わりに、 Euslisp内で座標系は、高速性と一般性のために 3*3の回転行列と3次元位置ベクトルの組で表現される。

coordinates

:super = ** propertied-object**
:slots (pos :type float-vector
rot :type array)

位置ベクトルと3x3の回転行列の組みで座標系を定義する。

coordinates-p obj

coordinatesクラスかまたはそのサブクラスのインスタンス のとき、Tを返す。

:rot **

この座標系の3x3回転行列を返す。

:pos **

この座標系の3次元位置ベクトルを返す。

:newcoords newrot &optional newpos

newposでこの座標系を更新する。 newposが省略された時はnewrotにはcoordinatesのインスタンスを 与える。 この座標系の状態が変化するときはいつでも、このメソッドを用いて新しい 回転行列と位置ベクトルに更新するべきである。 このメッセージはイベントを伝えて他の:updateメソッドを呼び出す。

:replace-coords newrot &optional newpos

メソッドを呼び出さずにrotとposスロットを変更する。 newposが省略された時はnewrotにはcoordinatesのインスタンスを与える。

:coords **

:copy-coords &optional dest

もしdestが与えられなかったとき、:copy-coordsは同じrotとpos スロットを持つ座標系オブジェクトを作る。 もし、destが与えられたとき、dest座標系にこの座標系のrotとposを コピーする。

:reset-coords **

この座標系の回転行列を単位行列にし、位置ベクトルをすべてゼロにする。

:worldpos **

:worldrot **

:worldcoords **

このオブジェクトのワールド座標系における位置ベクトル・回転行列・座標系 を計算する。 その座標系は、いつもワールド座標系で表現されていると仮定され、 これらのメソッドは簡単にposとrotとselfを返すことができる。 これらのメソッドはcascaded-coordsクラスと互換性がとられている。 cascaded-coordsではワールド座標系での表現と仮定していない。

:copy-worldcoords &optional dest

最初に、ワールド座標系が計算され、destにコピーされる。 もし、destが指定されてないとき、新たにcoordinates オブジェクトを作る。

:rotate-vector vec

この座標系の回転行列によってvecを回転させる。すなわち、 この座標系で表現される方向ベクトルをワールド座標系における表現 に変換する。 この座標系の位置は、回転に影響を与えない。

:transform-vector vec

この座標系で表現されるvecをワールド座標系の表現に変換する。

:inverse-transform-vector vec

ワールド座標系におけるvecをローカル座標系の表現に逆変換する。

:transform trans &optional (wrt :local)

座標系で表現されるtransによってこの座標系を変換する。 transは座標系の型でなければならないし、wrtは :local, :parent, :worldのキーワードあるいはcoordinatesの インスタンスでなければならない。 もしwrtが:localのとき、transをこの座標系の右 から適用する。もしwrtが:world, :parentのとき、 transを左から掛ける。 もしwrtcoordinatesの型であるとき、wrt座標系で表現される transは最初にワールド座標系の表現に変換され、左から掛ける。

:move-to trans &optional (wrt :local)

で表現されるtransでこの座標系のrotとpos を置き換える。

:translate p &optional (wrt :local)

このオブジェクトの位置をwrt座標系で相対的に変更する。

:locate p &optional (wrt :local)

この座標系の位置をwrt座標系で絶対的に変更する。 もし、wrtが:localのとき、:translateと同一な 効果を生む。

:rotate theta axis &optional (wrt :local)

軸回りにthetaラジアンだけ相対的にこの座標系を回転させる。 axisは、軸キーワード(:x, :y, :z)あるいは任意のfloat-vector である。 axiswrt座標系で表現されていると考える。 よって、もしwrtが:localでaxisが:zであるとき、 座標系はローカル座標系のz軸回りに回転される。 もしwrtが:world, :parentであるとき、ワールド座標系のz軸回りに 回転される。 言い換えると、もしwrtが:localのとき、 回転行列はこの座標系の右から掛けられる。 そして、もしwrtが:worldあるいは:parentのとき、 回転行列は左から掛けられる。 wrtが:worldあるいは:parentでさえ、 この座標系のposベクトルは変化しない。 本当にワールド座標系の軸回りに回転するためには、 回転を表現するcoordinatesクラスのインスタンスを :transformメソッドに与えなければならない。

:orient theta axis &optional (wrt :local)

を強制的に変更する。:rotateメソッドの絶対値版である。

:inverse-transformation **

この座標系の逆変換を持つ座標系を新しく作る。

:transformation coords (wrt :local)

この座標系と引き数で与えられるcoordsとの間の変換を作る。 もし、wrtが:localであるとき、ローカル座標系で表現される。 すなわち、もしこの:transformationの結果を:transformの引き数として wrt=:localと一緒に 与えたとき、この座標系はcoordsと同一な座標系に変換される。

:Euler az1 ay az2

オイラー角(az1, ay, az2)で表現される回転行列をrotに 設定する。

:roll-pitch-yaw roll pitch yaw

ロール・ピッチ・ヨー角で表現される回転行列をrotに設定する。

:4x4 &optional mat44

もし、mat44として4x4行列が与えられるとき、3x3回転行列と3次元位置ベクトル の座標表現に変換される。 もし、mat44が与えられないとき、この座標系の表現を 4x4の同次行列表現に変換して返す。

:init = `[メソッド]
&key = (pos #f(0 0 0)) = (rot #2f((1 0 0) (0 1 0) (0 0 1))) rpy euler axis angle 4X4 coords properties name

このcoordinatesオブジェクトを初期化し、rotとposを設定する。 それぞれのキーワードの意味は、以下に示す通りである。

:dimension
2あるいは3 (デフォルトは 3)
:pos
位置ベクトルを指定する (デフォルトは #f(0 0 0))
:rot
回転行列を指定する (デフォルトは単位行列)
:euler
オイラー角として3つの要素の列を与える
:rpy
ロール・ピッチ・ヨー角として3つの要素の列を与える
:axis
回転軸 (:x,:y,:z あるいは任意のfloat-vector)
:angle
回転角 (:axisと一緒に使用)
:wrt
回転軸を示す座標系 (デフォルトは :local)
:4X4
4X4 行列(posとrotを同時に指定)
:coords
coordsからrotとposをコピーする
:name
:name値を設定する。

:angle:axisと組みで唯一使用することができる。 その軸は:wrt座標系で決定される。 :wrtと関係なしに:Eulerはローカル座標系で定義されるオイラー角 (az1, ayaz2)をいつも指定する。 また、:rpyはワールド座標系のz, yx軸回りの角度 を指定する。 :rot, :Euler, :rpy, :axis, :4X4の中から2つ以上を連続で指定することは できない。しかしながら、指定してもエラーは返さない。 axis:angleパラメータには列を指定することができる。 その意味は、与えられた軸回りの回転を連続的に処理する。 属性とその値の組みのリストを:propertiesの引き数として 与えることができる。これらの組みは、この座標系のplistにコピーされる。

連結座標系

cascaded-coords

:super = ** coordinates**
:slots (parent descendants worldcoords manager changed)

連結された座標系を定義する。cascaded-coordsは、 しばしばcascoordsと略す。

:inheritance **

このcascaded-coordsの子孫をすべて記述した継承treeリストを返す。 もし、aとbがこの座標系の直下の子孫でcがaの 子孫であるとき、((a (c)) (b))を返す。

:assoc childcoords &optional relative-coords

は、この座標系の子孫として関係している。 もし、childcoordsが既に他のcascaded-coordsassocされて いるとき、childcoordsはそれぞれのcascaded-coordsが1つの親しか 持っていないならdissocされる。 ワールド座標系におけるchildcoordsの方向あるいは位置は変更されない。

:dissoc childcoords

この座標系の子孫リストからchildcoordsを外す。 ワールド座標系におけるchildcoordsの方向あるいは位置は変更されない。

:changed **

この座標系の親座標系が変更されていることを通知する。 また、もっとあとでワールド座標系が要求されたとき、ワールド座標系を再計算する 必要がある。

:update **

現在のワールド座標系を再計算するために:worldcoordsメソッド を呼び出す。

:worldcoords **

ルートの座標系からこの座標系までの全ての座標系を連結させることにより、 この座標系をワールド座標系で表現したcoordinatesオブジェクトで返す。 その結果は、このオブジェクトが持ち、後に再利用される。 よって、この結果の座標系を変更すべきでない。

:worldpos **

ワールド座標系で表現したこの座標系のrotを返す。

:worldrot **

ワールド座標系で表現したこの座標系のposを返す。

:transform-vector vec

をこのローカル座標系での表現とみなして、ワールド座標系での 表現に変換する。

:inverse-transform-vector vec

ワールド座標系で表現されるvecをこのローカル座標系の表現に逆変換する。

:inverse-transformation **

この座標系の逆変換を表現するcoordinatesのインスタンスを作る。

:transform trans &optional (wrt :local)

:translate fltvec &optional (wrt :local)

:locate fltvec &optional (wrt :local)

:rotate theta axis &optional (wrt :local)

:orient theta axis &optional (wrt :local)

クラスの記述を参照すること。

make-coords &key pos rot rpy Euler angle axis 4X4 coords name

make-cascoords &key pos rot rpy Euler angle axis 4X4 coords name

coords &key pos rot rpy Euler angle axis 4X4 coords name

cascoords &key pos rot rpy Euler angle axis 4X4 coords name

これらの関数は、すべてcoordinatesあるいはcascaded-coordsを 新しく作る。 キーワードパラメータについては、coordinatesクラスの:initメソッドを 見ること。

transform-coords coords1 coords2 &optional (coords3 (coords))

coords2に左から適用(乗算)される。 その積はcoords3に蓄積される。

transform-coords* &rest coords

にリスト表現されている変換を連結させる。 連結された変換で表現されるcoordinatesのインスタンスを返す。

wrt coords vec

coordsにおける表現に変換する。 その結果は(send coords :transform-vector vec)と同一である。

変換行列とcoordinates classとの関係

変換行列Tを\(4\times4\)の同次行列表現として以下のように表したした時の、 coordinatesとの関係を説明する。

\[\begin{split}T = \begin{pmatrix} \mathbf{R}_T & \mathbf{p}_T \\ \mathbf{0} & 1 \end{pmatrix}\end{split}\]

\(\mathbf{R}_T\)\(3\times3\)行列、\(\mathbf{p}_T\)\(3\times1\)行列(eus内部処理 では要素数3のfloat-vector)であって、 EusLispにおけるcoordinatesクラスは\(\mathbf{R}\)\(3\times3\) の回転行列と 3 次元位置ベクトルの組で表現されており、 スロット変数のrotとposは、それぞれ、\(\mathbf{R}_T\)\(\mathbf{p}_T\)に対応する。

回転行列と3次元位置の取り出し

coordinates classのメソッドを用いて、以下のように\(\mathbf{R}\)\(\mathbf{p}\)を取り出せる。

以下、Tはcoordinateクラスのインスタンスである。

(send T :rot)

\(\Rightarrow\) \(\mathbf{R}_T\)

(send T :pos)

\(\Rightarrow\) \(\mathbf{p}_T\)

ベクトルを変換するメソッド

以下、\(\mathbf{v}\)は3次元ベクトルである。

(send T :rotate-vector :math:`mathbf{v}`)

\(\Rightarrow\) \(\mathbf{R}_T \mathbf{v}\)

(send T :inverse-rotate-vector :math:`mathbf{v}`)

\(\Rightarrow\) \(\mathbf{v}^T \mathbf{R}_T\)

(send T :transform-vector :math:`mathbf{v}`)

\(\Rightarrow\) \(\mathbf{R}_T\mathbf{v} + \mathbf{p}_T\)

ローカル座標系Tで表されたベクトルをワールド座標系で表されたベクトルに変換する

(send T :inverse-transform-vector :math:`mathbf{v}`)

\(\Rightarrow\) \(\mathbf{R}_T^{-1}\left( \mathbf{v} - \mathbf{p}_T \right)\)

ワールド座標系で表されたベクトルをローカル座標系Tで表されたベクトルに変換する

座標系を返すメソッド (座標系を変更しない)

(send T :inverse-transformation)

\(\Rightarrow\) \(T^{-1}\)

逆行列を返す。

\[\begin{split}T^{-1} = \begin{pmatrix} \mathbf{R}_T^{-1} & -\mathbf{R}_T^{-1}\mathbf{p}_T \\ \mathbf{0} & 1 \end{pmatrix}\end{split}\]

(send T :transformation A (&optional (wrt :local)))

wrt == :local のとき、\(T^{-1}A\) を返す

wrt == :world のとき、\(AT^{-1}\) を返す

wrt == W (coordinates class) のとき、\(W^{-1}AT^{-1}W\) を返す

座標系を変更するメソッド

以下、A は coordinatesクラスのインスタンスである。

\(\Leftrightarrow\) はスロット変数と与えられたインスタンス(行列またはベクトル)が同一になることを表す。 一方の変更が、他方の変更に反映されるため、注意して使用すること。

\(\leftarrow\) は代入を表す。

(send T :newcoords A)

\(\mathbf{R}_T \Leftrightarrow \mathbf{R}_A\)

\(\mathbf{p}_T \Leftrightarrow \mathbf{p}_A\)

(send T :newcoords :math:`mathbf{R}` :math:`mathbf{p}`)

\(\mathbf{R}_T \Leftrightarrow \mathbf{R}\)

\(\mathbf{p}_T \Leftrightarrow \mathbf{p}\)

(send T :move-to A (&optional (wrt :local)))

wrt == :local のとき、\(T \leftarrow TA\)

wrt == :world のとき、\(T \Leftrightarrow A\)

wrt == W (coordinates class) のとき、\(T \leftarrow WA\)

(send T :translate :math:`mathbf{v}` (&optional (wrt :local)))

wrt == :local のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{p}_{T} + \mathbf{R}_{T}\mathbf{v}\)

wrt == :world のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{p}_{T} + \mathbf{v}\)

wrt == W (coordinates class) のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{p}_{T} + \mathbf{R}_{W}\mathbf{v}\)

(send T :locate :math:`mathbf{v}` (&optional (wrt :local)))

wrt == :local のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{p}_{T} + \mathbf{R}_{T} \mathbf{v}\)

wrt == :world のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{v}\)

wrt == W (coordinates class) のとき、 \(\mathbf{p}_{T} \leftarrow \mathbf{p}_{W} + \mathbf{R}_{W}\mathbf{v}\)

(send T :transform A (&optional (wrt :local)))

wrt == :local のとき、 \(T \leftarrow TA\)

wrt == :world のとき、 \(T \leftarrow AT\)

wrt == W (coordinates class) のとき、\(T \leftarrow\) \(\left( WAW \right)^{-1} T\)

幾何学モデリング

Euslispは、3次元の幾何学モデルの内部表現として(境界表現)を採用している。 Brep内の要素はedge, plane, polygon, face, hole,bodyクラスによって 表現される。 基本bodyの作成関数とbodyの合成関数は、これらのクラスの新しい インスタンスを作る。 もっと属性を持った独自の幾何学クラスを使用するためには、 edge-class*, *face-class*body-class*の特殊変数に 独自のクラスオブジェクトを設定すること。

頂点とエッジと面の分類

頂点とエッジと面の分類

種々の幾何学関数

vplus vector-list

のすべての要素の合計を実数ベクトルとして 新しく作り、返す。 v+との違いは、vplusが2つ以上の引数について合計を計算し、 結果のベクトルが指定できない点である。

vector-mean vector-list

の平均ベクトルを返す。

triangle a b c &optional (normal #f(0 0 1))

は、2次元または3次元の実数ベクトルである。 normalは、a,b,cが置かれる平面の正規ベクトルである。 trianglea,b,cで形作られる三角形の領域の2倍の大きさを返す。 normalと同じ方向から見たときにa,b,cが時計方向に回転する ならば、triangleは正である。 言い換えると、もしtriangleが正ならば、 ca-bの線分の左手側に位置し、 ba-cの右手側に位置している。

triangle-normal a b c

で定義される三角形に対して垂直方向の正規ベクトルを見つける。

vector-angle v1 v2 &optional (normal (v* v1 v2))

2つのベクトルの角度を計算する。 これは次の式であらわされるatan(normal\(\cdot\)(v1:math:timesv2), v1\(\cdot\)v2)。 v1,v2normalは正規ベクトルでなければならない。 normalが与えられないとき、v1,v2の共通垂線の正規ベクトルが 使用される。この場合、結果は\(0\)から\(\pi\)までの範囲の正の角度になる。 符号付きの角度を得るためには、normalを指定しなければならない。

face-normal-vector vertices

同じ平面の上にあるベクトルのリストから面の正規化ベクトルを計算する。

farthest p points

3次元ベクトルのリストpointsの中からpより最も遠い点を捜す。

farthest-pair points

3次元ベクトルのリストpointsからもっとも遠い点の組を 捜す。

maxindex 3D-floatvec

の3つの要素の中で絶対値が最大の要素の位置を捜す。

random-vector &optional (range 1.0)

3次元デカルト空間の中で同次的に分散されるランダムベクトルを発生する。

random-normalized-vector &optional (range 1.0)

3次元の正規化ランダムベクトルを返す。

random-vectors count range

の大きさのランダムベクトルをcount個つくり、そのリストを返す。

line-intersection p1 p2 p3 p4

は、すべて2次元以上の実数ベクトルである。 p1-p2p3-p4が平面上の2つの線分として定義される。 line-intersectionは、これらの2つの線分の交差する点のパラメータ(線分に置ける 交点の位置の比率)を2要素のリストで返す。3次元で使用するとき、 p1, p2, p3, p4は共通平面内になければならない。

collinear-p p1 p2 p3 &optional tolerance

は、すべて3次元の実数ベクトルで3つの点を表現している。 collinear-pは、もし\(\Vert\)((p2:math:-p1)\(\times\)(p3:math:-p1))\(\Vert\)が coplanar-threshold*より小さければ、p1-p3の線分の上に p2を投影したときのパラメータを返す。そうでなければ、NILを返す。

find-coplanar-vertices p1 p2 p3 vlist

は、3次元の実数ベクトルで、この3つのベクトルから平面を表現している。 find-coplanar-verticesは、その平面内にある点を vlistの中から捜す。

find-connecting-edge vertex edgelist

に接続されたedgelistの中からエッジを捜す。

make-vertex-edge-htab bodfacs

は、bodyあるいはfaceのリストである。 make-vertex-edge-htabは、bodfacsの中の頂点を抽出し、それに接続されるエッジの検索ができる ハッシュテーブルを作る。

left-points points p1 p2 normal

は、正規化ベクトルnormalで表現される 平面内にあるものと仮定する。 left-pointsは、p1, p2間の線分の左側に置かれている点を pointsの中から捜し、集める。

right-points points p1 p2 normal

は、正規化ベクトルnormalで表現される 平面内にあるものと仮定する。 right-pointsは、p1, p2間の線分の右側に置かれている点を pointsの中から捜し、集める。

left-most-point points p1 p2 normal

は、正規化ベクトルnormalで表現される 平面内にあるものと仮定する。 left-most-pointsは、p1, p2で決定される線分の左側に置かれている点を pointsの中から捜し、その中でもっとも遠い点を返す。

right-most-point points p1 p2 normal

は、正規化ベクトルnormalで表現される 平面内にあるものと仮定する。 right-most-pointsは、p1, p2で決定される線分の右側に置かれている点を pointsの中から捜し、その中でもっとも遠い点を返す。

eps= num1 num2 &optional (tolerance *epsilon*)

2つの実数num1num2を比較して、torelanceの誤差範囲内で 等しいかどうかを返す。

eps:math:`<` num1 num2 &optional (tolerance *epsilon*)

が明らかにnum2よりも小さいときTを返す。すなわち、 num1\(<\)num2-toleranceである。

eps:math:`<=` num1 num2 &optional (tolerance *epsilon*)

が多分num2よりも小さいときあるいは等しいときTを返す。すなわち、 num1\(<\)num2+toleranceである。

eps:math:`>` num1 num2 &optional (tolerance *epsilon*)

が明らかにnum2よりも大きいときTを返す。すなわち、 num1\(>\)num2+toleranceである。

eps:math:`>=` num1 num2 &optional (tolerance *epsilon*)

が多分num2よりも大きいときあるいは等しいときTを返す。すなわち、 num1\(>\)num2-toleranceである。

bounding-box

:super = ** object**
:slots (minpoint maxpoint)

xy-,yz-やzx-平面に平行な面を境界とする最小の四角柱を定義する。 bounding-boxは、初期に与えられるベクトルの次元によって、 どんな次元でも使用することができる。 bounding-boxは、surrounding-boxの名前で定義されていた。

:box **

このbounding-boxのオブジェクト自身を返す。

:volume **

このbounding-boxの体積を返す。

:grow rate

このbounding-boxのサイズをrate率で増加または減少させる。 rateが0.01のとき、1%拡大される。

:inner point

がこのbounding-box内にあればTを返し、 そうでないときはNILを返す。

:intersection box2 &optional tolerance

このbounding-boxbox2との共通bounding-boxを返す。 もし、torelanceが与えられたならば、このboxはその誤差で拡大される。 もし、共通部分がなければ、NILを返す。

:union box2

このbounding-boxbox2を結合したbounding-boxを返す。

:intersectionp box2

このbounding-boxbox2との間に共通領域があればTを返し、 そうでなければNILを返す。 このメソッドは、:intersectionよりも速い。なぜなら、新しい bounding-boxのインスタンスを作らないためである。

:extreme-point direction

このbounding-boxの8つの頂点の中で、directionとの内積が最大のものを 返す。

:corners **

このbounding-boxのすべての頂点のリストを返す。 もし、このboxが2次元であれば、4点が返される。 同様に3次元の場合、8点が返される。

:below box2 &optional (direction #(0 0 1)

このbounding-boxbox2に対してdirectionの示すベクトル の下の方向にあればTを返す。 このboundign-boxdirectionの方向に動かされるとき、 2つのboxに共通部分でできるかどうかをチェックするために使用される。

:body **

このbounding-boxによって内包される立方体を表現する bodyを返す。

:init vlist &optional tolerance

とmaxpointスロットをvlistから設定する。 もし、torelanceが指定されたなら、このbounding-boxは その量で増大される。

make-bounding-box points &optional tolerance

のリストの中から最小と最大の座標値を見つけ、 bounding-boxのインスタンスを作る。

bounding-box-union boxes &optional (tolerance *contact-threshold*)

の結合で表現されるbounding-boxのインスタンスを作る。 その結果は、toleranceによって拡張される。

bounding-box-intersection boxes &optional (tolerance *contact-threshold*)

の共通領域を表現するbounding-boxのインスタンスを作る。 その結果は、toleranceによって拡張される。

線とエッジ

頂点の順番やエッジの順番の向きは、bodyを外から見たときに反時計方向 に整列するように定義される。 pvertexやnvertexやpfaceやnfaceは、 pfaceが外から見たときエッジの左側に位置しているとき、 pvertexからnvertexに向かう方向にエッジを定義する。

line

:super = ** propertied-object**
:slots ((pvert :type float-vector) (nvert :type float-vector))

pvertとnvertの上を通る線分を定義する。 線分は、pvertからnvertに向かう方向を持つ。 t \(\cdot\) pvert +(1-t)nvert

:vertices **

とnvertのリストを返す。

:point p

この線分の上でpパラメータで示される位置の3次元のベクトルを返す。 p \(\cdot\) pvert + (1-p)nvert

:parameter point

この線分の上のpointに対するパラメータを計算する。 これは、:pointメソッドの逆メソッドである。

:direction **

からnvertへ向かう正規化ベクトルを返す。

:end-point v

この線分の他の端点を返す。すなわち、 もしvがpvertに等しいとき、nvertを返す。 もしvがnvertに等しいとき、pvertを返す。 それ以外のとき、NILを返す。

:box **

この線分のbounding-boxを作成し、返す。

:boxtest box

とこの線分のbounding-boxの共通部分をチェックする。

:length **

この線分の長さを返す。

:distance point-or-line

この線分とpoint-or-lineの間の距離を返す。 もし点からこの線分におろした垂線の足が pvertとnvertの間になければ、 最も近い端点までの距離を返す。 このメソッドを使うことにより、2つの線分の間の距離を計算することができるため、 2つの円柱の間の干渉をテストすることができる。

:foot point

からこの線分へおろした垂線の足である点を示すパラメータ を見つける。

:common-perpendicular l

この線分とlとに垂直な線分を見つけ、2つの3次元ベクトルのリスト として返す。 2つの線分が平行で共通な垂線が一意に決定できないとき、:parallelを返す。

:project plane

にpvertとnvertを投影した2つの点のリストを返す。

:collinear-point point &optional (tolerance *coplanar-threshold*)

を用いてtorelanceの誤差範囲内でpointがこの線分と 一直線上にあるかどうかをチェックする。 もし、pointがこの線分と一直線上にあるとき、その線分のその点に 対するパラメータを返す。そうでなければ、NILを返す。

:on-line-point point &optional (tolerance *coplanar-threshold*)

がこの線分と一直線上にあり、pvertとnvertとの間に あるかどうかをチェックする。

:collinear-line ln &optional (tolerance *coplanar-threshold*)

がこの線分と共通線上にあるとき、すなわちlnの両端がこの線分上に あるときTを返し、そうでないときNILを返す。

:coplanar ln &optional (tolerance *coplanar-threshold*)

とこの線分が共通平面上にあるかどうかをチェックする。 この線分の両端とlnの1つの端点で平面が定義される。 もし、lnの他の端点がその平面上にあるとき、Tを返す。 そうでなければ、NILを返す。

:intersection ln

は、この線分と共通平面上にあるとする。 :intersectionは、これら2つの線分の交点に対する2つのパラメータの リストを返す。 パラメータは0から1までの実数である。これは、両端で区切られた 線分の内分点を示す。2つの線が平行であるときNILを返す。

:intersect-line ln

は、この線分と共通平面上にあるとする。 交点のパラメータが:parallel, :collinearや:intersectのような シンボル情報と共に返される。

edge

:super = ** line**
:slots (pface nface
(angle :type float)
(flags :type integer))

2つの面の間の交差線分として定義されるエッジを表現する。 pfaceとnfaceがスロットの中に定義されているが、 それらの解釈はこのエッジの方向によって相対的に決まる。 例えば、このエッジがpvertからnvertに向かっていると 考えたとき、pfaceが正しいpfaceを表現している。 そのため、:pface:nfaceメソッドで適当な面を選択するためには、 pvertとnvertの解釈を与えなければならない。

make-line point1 point2

をpvertとし、point2をnvertとする lineのインスタンスを作る。

:pvertex pf

をこのエッジのpfaceとみなしたpvertexを返す。

:nvertex face

をこのエッジのpfaceとみなしたnvertexを返す。

:body **

このエッジを定義するbodyオブジェクトを返す。

:pface pv nv

仮想的にpvnvをこのエッジの pvertとnvertに解釈したときのpfaceを返す。

:nface pv nv

仮想的にpvnvをこのエッジの pvertとnvertに解釈したときのnfaceを返す。

:binormal aface

このエッジとafaceの正規化ベクトルに垂直な方向ベクトルを見つける。

:angle **

このエッジでつながった2つの面の間の角度を返す。

:set-angle **

このエッジでつながった2つの面の間の角度を計算し、 それをangleスロットに置く。

:invert **

:set-face pv nv f

をpfaceとし、pvをpvertexとし、nvを nvertexとして設定する。 このメソッドは、このエッジのpfaceあるいはnfaceを変更することに 注意すること。

:contourp viewpoint

もし、このエッジが輪郭エッジであれば、すなわち、このエッジのpface あるいはnfaceのどちらかがviewpointから見え、もう一方が 見えないならTを返す。

:approximated-p **

このエッジが円柱の側面のような曲面を表現するための近似エッジであるならば、 Tを返す。 近似エッジは部分直線で曲線を表現するのに必要である。

:set-approximated-flag &optional (threshold 0.7)

Euslispでは、どんな曲面もたくさんの平面で近似される。 flagsのLSBは、このエッジの両側の面が曲面であるかどうかを 示すために使用される。

もし、2つの面の間の角度がthresholdより大きいなら、 :set-approximated-flagは、このフラグをTに設定する。

:init &key pface nface pvertex nvertex

平面と面

planeオブジェクトは、その平面の正規化ベクトルと座標原点から平面までの 距離で表現される。 2対の正規化ベクトルと距離がplaneオブジェクトに記録される。 1つは、変換後の現状を表現し、もう1つが平面を定義したときの 正規化ベクトルと距離を表現する。

plane

:super = ** propertied-object**
:slots ((normal :type float-vector)
(distance :float))

平面方程式を定義する。平面は境界がなく、無限に広がっているものとする。

:normal **

この平面の正規化ベクトルを返す。

:distance point

この平面とpointとの間の距離を計算する。

:coplanar-point point

もし、pointがこの平面の上に置かれているならTを返す。

:coplanar-line line

もし、lineがこの平面の上に置かれているなら、Tを返す。

:intersection point1 point2

point2を端点とする線分とこの平面との交点 を計算する。その線分の上の交点に対するパラメータを返す。 もし、線分とこの平面が平行であるなら、:parallelを返す。

:intersection-edge edge

この平面とpoint1point2で表現される線分あるいはエッジとの 交点のパラメータを返す。

:foot point

この平面上にpointを直角に投影した位置の3次元ベクトルを返す。

:init normal point

を通りnormalを面の正規化ベクトルとする平面を定義する。 normalは、正規化されていなければならない。\(|normal|=1\)

polygon

:super = ** plane**
:slots (convexp edges vertices
(model-normal float-vector)
(model-distance :float))

polygonは、平面の上の輪で表現される。 convexpは、その輪が凸面であるかどうかを示す論理フラグである。 edgesは、この輪の輪郭や頂点のリストであるverticesで 形成されるエッジのリストである。

:box &optional tolerance

この多角形のためのbounding-boxを返す。

:boxtest box2 &optional tolerance

この多角形のためのbounding-boxを作成し, そのboundign-boxbox2との共通領域を返す。 もし,共通領域がなかった場合,NILを返す。

:edges **

この多角形のエッジのリストを返す。 そのリストは,この平面の正規化ベクトルに沿ってその多角形を見たとき, 時計方向の順番になっている。 もし,正規化ベクトルをねじと考えると,そのエッジは ねじを入れる方向に回転させる向きの順番になっている。 多角形または面が立体オブジェクトの面を表現するために使用されているとき, その正規化ベクトルはその立体の外側に向かっている。 多角形をそのオブジェクトの外側から見たとき,エッジは 反時計方向の順番になっている。

:edge n

エッジのn番目の要素を返す。

:vertices **

この多角形の頂点をエッジと同じ順番にならべたものを返す。 最初の頂点は,そのリストの最後に重複してコピーされているため, そのリストは実際の頂点の数より1だけ長くなっていることに注意すること。 これは,頂点のリストを用いてエッジへの変換を簡単にするためである。

:vertex n

頂点のn番目の要素を返す。

:insidep point &optional (tolerance *epsilon*)

この領域に対して相対的に置かれたpointの位置にしたがって :inside,:outsideあるいは:borderを返す。

:intersect-point-vector point vnorm

と正規化方向ベクトルvnormによって定義される 擬似線分との交点を計算する。

:intersect-line p1 p2

p2で指定される線分との交点を計算する。 その結果は、交点がなければNILを返し,交点があればその交点の位置の パラメータのリストを返す。

:intersect-edge edge

で指定される線分との交点を計算する。 その結果は,交点がなければNILを返し、交点があれば 交点の位置のパラメータのリストを返す。

:intersect-face aregion

もし,この領域がaregionと交差しているなら,Tを返す。

:transform-normal **

:reset-normal **

この多角形の現在のverticesリストから面の正規化ベクトルを再計算する。

:invert **

:area **

この領域の面積を返す。

:init &key vertices edges normal distance

face

:super = ** polygon**
:slots (holes mbody primitive-face id)

穴を持った面を定義する。 mbodytypeは、基本bodyとbody内の面の属性(:top, :bottom, :side) を表現する。

:all-edges **

:all-vertices **

この面および内部ループ(穴)の輪郭のエッジあるいは頂点をすべて返す。 :edges:verticiesメソッドは, 輪郭を構成するエッジと頂点のみを返す。

:insidep point

がこの面の内部にあるかどうかを決定する。 もしpointがこの面の外側の輪郭の中にあり,どれかの穴の 範囲内にあるならば,外側として分類される。

:area **

この面の面積を返す。 これは,外側のエッジで囲まれる面積から穴の面積を引いたものである。

:centroid &optional point

この面の重心を表現する実数と実数ベクトルのリストを返す。 もし,pointが与えられないならば,最初の数はこの多角形の 面積を表わし,2番目のベクトルがこの多角形の重心の位置を示す。 もし,pointが与えられたならば,この多角形を底面としその点を頂点 とするような多角錐を考え,その体積と重心のベクトルを返す。

:invert **

この面の向きをひっくり返す。 正規化ベクトルが逆方向とされ,エッジループの順番も反転される。

:enter-hole hole

この面に穴holeを加える。

:primitive-body **

この面を定義する基本bodyを返す。

:id **

や(:side seq-no.)の中の1つを返す。

:face-id **

基本bodyの型とこの面の型をリストで返す。 例えば,円柱の側面は ((:cylinder radius height segments) :side id)を返す。

:body-type **

この面を定義する基本bodyを返す。

:init &key normal distance edges vertices holes

hole

:super = ** polygon**
:slots (myface)

穴は,面の内部ループを表現する多角形である。faceのオブジェクトは、 自分のholesスロット の中にholeのリストを持っている。

:face **

このholeを含む面を返す。

:enter-face face

このholeを囲んでいる面faceへリンクを作る。 このメソッドは、faceクラスの:enter-holeメソッドと共に 使用されるものである。

:init &key normal distance edges vertices face

立体(body)

body

:super = ** cascaded-coords**
:slots (faces edges vertices model-vertices box convexp evertedp csg)

3次元形状を定義する。

:magnify rate

このbodyのサイズをrateで変更する。拡大は,csgリストの中に 記録される。

:translate-vertices vector

モデルの頂点を相対移動する。vectorはローカル座標系で与えられなければならない。 変換はcsgリストに記録される。

:rotate-vertices angle axis

モデルの頂点をaxis軸回りにangleラジアン回転させる。 回転はcsgリストに記録される。

:reset-model-vertices **

:newcoords rot &optional pos

座標系をrotposを用いて変更する。 posが省略された時はnewrotにはcoordinatesのインスタンスを与える。

:vertices **

このbodyのすべての頂点のリストを返す。

:edges **

このbodyのすべてのエッジのリストを返す。

:faces **

このbodyを構成するすべての面のリストを返す。

:box **

このbodybounding-boxを返す。

:Euler **

このbodyのオイラー数を計算する。これは, faces+vertices\(-\)edges\(-\)2\(-\)holesである。 これは,\(-\)2ringsと等しくなるべきである。

:perimeter **

すべてのエッジの長さの合計を返す。

:volume &optional (reference-point #f(0 0 0))

このbodyの体積を返す。

:centroid &optional (point #f(0 0 0)

このbodyが均質な立体と仮定し,重心の位置を返す。

:possibly-interfering-faces box

:common-box body

このbodyと他のbodyの共通な最小のboxを返す。 もし,2つのbodyが干渉しているならば,その交差部分は この共通boxの中に存在するはずである。

:insidep point

もし,pointがこのbodyに属するなら,:insideを返す。 もし,pointがこのbodyの表面上にある場合,:borderを返す。 そうでなければ,:outsideを返す。

:intersect-face face

もし,このbodyの面とfaceの間に干渉がある場合,Tを返す。

:intersectp body

このbodyと他のbodyとの間の交差部分を返す。

:evert **

すべての面とエッジの方向を反転させる。 そのため,このbodyの内部は外部になる。

:faces-intersect-with-point-vector point direction

からdirectionの方向に伸びるベクトルと交差する面をすべて集める。

:distance target

は,実数ベクトルあるいは平面オブジェクトである。 :distanceメソッドは,targetから最も近い面を見つけ, その面と距離のリストを返す。

:csg **

が構築された履歴であるcsgスロットを返す。

:primitive-body **

このbodyを構築する基本bodyのリストを返す。

:primitive-body-p **

もし,このbodyが[primitive-body-creation] 節で示される関数の内の1つから作られた基本bodyであるなら,Tを返す。

:creation-form **

このbodyを作るためのLisp表現を返す。

:body-type **

もし,このbodyが基本bodyあるいはこのbodyの表現が複雑(に構成された) bodyなら,作成パラメータのリストを返す。

:primitive-groups **

2つの要素をもつリストを返す。 最初の要素は,このbodyを構成するために追加(body+)された基本body のリストである。次の要素は,差し引かれた基本bodyのリストである。

:get-face &optional body face id

は,このbodyを構成しているbodyのインスタンスであり, 基本body型の1つである。例えば,:cube, :prism, :cone, :solid-of-resolutionなどか あるいはNILである。 もし,faceidも与えられないならば,bodyに一致する面をすべて返す。 もし,faceが与えられたなら,その上にフィルターが実行される。 faceは,:top,:bottomと:sideの内の1つでなければならない。 (send abody :get-face :cylinder :top)は,abodyを構成する円柱の上面すべてを返す。 もし,faceが:sideなら,idで番号付けされた面を取り出すことができる。 (send abody nil :side 2)は,idが0から始まるため,abodyを構成する bodyの側面から3番目の面をすべて返す。

:init &key faces edges vertices

よりこのbodyを初期化する。 :facesは,必要な引き数である。 :faces,:edges:verticesは完全な立体モデルを定義するために 矛盾のない関係を持っていなければならないので,矛盾した引き数でこのメソッドを 呼び出すことは,意味の無いことである。 bodyを作るために,[primitive-body-creation]節で書いている基本bodyの作成関数と [BodyComposition]節の**body**合成関数を使用する。

:constraint b

このbodybに接触しているとき, このbodyの拘束を返す。このメソッドの詳細な説明は[Contact]節を参照すること。

基本bodyの作成関数

make-plane &key normal point distance

を通り,normalの方向を向いたplaneオブジェクトを作る。 pointを与える代わりdistanceを指定することもできる。

*xy-plane* **

*yz-plane* **

*zx-plane* **

基本body

基本body

make-cube xsize ysize zsize &key name color

x,y,z軸の方向に大きさがxsize,ysize,zsizeである,直方体を作る。 この直方体の原点はbodyの中心に置かれる。

make-prism bottom-points sweep-vector &key name color

に沿ったbottom-pointsにより定義される 形状を積み上げることにより角柱を作る。 もし、sweep-vectorが実数ベクトルでなく数字であれば、\(z\)方向の 角柱の高さとして扱われる。 bottom-pointsは,このbodyの底面を定義する順番になっていなければならない。 例えば, (make-prism ’(#f(1 1 0) #f(1 -1 0) #f(-1 -1 0) #f(-1 1 0)) 2.0) は,高さ2.0の直方体を作る。

make-cylinder radius height &key (segments 12) name color

半径radiusと高さheightで指定される円柱を作る。 底面は,xy-平面に定義され,座標系の原点は底面の中心に置かれる。

make-cone top bottom &key (segments 16) color name

頂点がtopで底面がbottomである角錐を作る。 topは,3次元ベクトルである。 bottomは,底面の頂点のリストあるいは半径である。 もし,頂点のリストなら,順番を慎重にしなさい。 `` (make-cone #f(0 0 10) (list #f(10 0 0) #f(0 10 0) #f(-10 0 0) #f(0 -10 0)))`` は,正方形の底面を持つ四角錐を作る。

make-solid-of-revolution points &key (segments 16) name color

は,z軸まわりの時計方向に回転される。 もし、pointsのリストの2つの端点がz軸上に置かれてないならば, 曲面を作る。したがって, (make-solid-of-revolution ’(#f(0 0 1) #f(1 0 0))) は、円錐を作り、 (make-solid-of-revolution ’(#f(1 0 1) #f(1 0 0))) は、円柱を作る。 pointsは、順番が重要であり、\(z\)軸の高い方から低い方へ 整列しておくことが望まれる。

make-torus points &key (segments 16) name color

ドーナッツのようなtorus形状を作る。 pointsは,断面上の頂点のリストである。

make-icosahedron &optional (radius 1.0)

正20面体を作る。それぞれの面は正三角形である。

make-dodecahedron &optional (radius 1.0)

正12面体を作る。それぞれの面は,正五角形である。

make-gdome abody

の三角面を4つの面に小分けすることにより 測地ドームを新しく作る。 abodyは,最初正20面体とすべきである。 それから,make-gdomeの結果を再帰的にmake-gdomeに与えることができる。 それぞれの呼び出しで,測地ドームの面の数は,4倍に増加する。すなわち, 20, 80, 320, 1280, 5120などになる。

(setq g0 (make-icosahedron 1.0))        ; 20 facets
(setq g1 (make-gdome g0))               ; 80 facets
(setq g2 (make-gdome g1))               ; 320 facets
...

grahamhull vertices &optional (normal #f(0 0 1))

Grahamのアルゴリズムを用いて,2次元上で凸状の覆いを計算する。 quickhullよりも遅い。

quickhull vertices &optional (normal #f(0 0 1))

2分探索法を用いて2次元上で凸状の覆いを計算する。

convex-hull-3d vertices

gift-wrapping法を用いて3次元上で凸面の覆いを計算する。

make-body-from-vertices vertices-list

矛盾しない順番になっている面のループを定義する頂点のリストからbodyを返す。

bodyの合成関数

face+ face1 face2

face* face1 face2

face2は,3次元上で共通平面上にある。 face+は,これらの面の結合を構築し,面のオブジェクトとして返す。 もし,交差領域がないなら,元の2つの面が返される。 face*は,これらの面の交差領域を返す。もし,交差領域がなければ,NILを返す。

cut-body body cutting-plane

cutting-planeで切断し,その切断面に作られる面のリストを返す。

body+ body1 body2 &rest more-bodies

body- body1 body2

body* body1 body2

2つあるいはそれ以上のbodyの和,差あるいは積を計算する。 それぞれのbodyは,body+, body-, body*の処理を行う前に コピーされ,元のbodyは変更されない。 その結果のbodyの新しい座標系の位置・姿勢は,ワールド座標系のものと一致している。 もし,しきい値パラメータcoplanar-threshold*,contact-threshold*,parallel-threshold* を正確に設定するなら,2つのbodyが面同士で接触している場合でも これらの関数は正しく働くであろう。 しかしながら,もしbodyの頂点が他のbodyの頂点あるいは面に接触している場合, どの処理も失敗する。

body/ body plane

で作られたplaneクラスのインスタンスであるplanebodyを切断する。新しく作られたbodyが返される。

body-interference &rest bodies

の中で1対1の組み合わせにおける干渉をチェックし, 交差している2つのbodyのリストを返す。

座標軸

coordinates-axesクラスは,画面上に表示可能な3次元座標軸を定義する。 それぞれの軸とz軸の頂点の矢印は,lineオブジェクトで定義される。 このクラスは,cascaded-coordsを継承しているので, このクラスのオブジェクトは,bodyのような他のcascaded-coordsを元とする オブジェクトに付けることができる。 このオブジェクトは,bodyの座標軸あるいは他の座標の相対座標系を見るために 使用される。

coordinates-axes

:super = ** cascaded-coords**
:slots (size model-points points lines)

表示可能な3次元座標軸を定義する。

立体の接触状態解析

この節のメソッドおよび関数は、次のファイルに記述されている。 contact/model2const.l, contact/inequalities.l, contact/drawconst.l

constrained-motion c

拘束cを満たしている 動作のリストを返す。

constrained-force m

拘束されているbodyから 拘束しているbodyに加わる力を返す。mは、constrained-motion から返される動作のリストである。

draw-constraint c

拘束cを描く。

draw-motion m a b

bに接触しているときに 取り得る動作を描く。リターンキーを押すことにより描画を始める。

Example
;;
;;      peg in a hole with 6 contact points
;;
(in-package "GEOMETRY")
(load "view")
(load "../model2const.l" :package "GEOMETRY")
(load "../inequalities.l" :package "GEOMETRY")
(load "../drawconst.l" :package "GEOMETRY")

(setq x (make-prism '(#f(50 50 0) #f(50 -50 0) #f(-50 -50 0) #f(-50 50 0))
                    #f(0 0 200)))
(setq x1 (copy-object x))
(send x1 :translate #f(0 0 -100))
(send x1 :worldcoords)
(setq a1 (make-prism '(#f(100 100 -150) #f(100 -100 -150)
                       #f(-100 -100 -150) #f(-100 100 -150))
                     #f(0 0 150)))
(setq ana (body- a1 x1))
(send x :translate #f(0 -18.30127 -18.30127))
(send x :rotate -0.523599 :x)
(send x :worldcoords)

(setq c (list (send x :constraint ana)))
(setq m (constrained-motion c))
(setq f (constrained-force m))

(hidd x ana)
(draw-constraint c)
(draw-motion m)
拘束の例を次の図で示す。図の小さな矢印は,ペグに対する拘束を示す。
Constraints for a peg in a hole. Constraints for a peg in a hole.
Constraints for a peg in a hole. Constraints for a peg in a hole.

ペグを穴に入れる作業において取り得る動作の例を次の図で示す。 この例は,上記のプログラムと一致している。

Possible motions of a peg in a hole Possible motions of a peg in a hole
Possible motions of a peg in a hole Possible motions of a peg in a hole

多角形のVoronoi Diagram

このプログラムは,Common Lispで書かれている。 “A sweepline algorithm for Voronoi diagrams”, Proceedings of the 2nd Annual ACM symposium on computational geometry, 1986, 313-322.を 手法として用い、 多角形の場合への応用を行った。これは,サンプルプログラム付きの簡単な説明である。 このプログラムは,ETLのEuslisp環境で書かれているため, 画像への出力もサポートしている。 どのCommon Lisp上でも使用することはできるが, utilities.lで与えられている画像への関数を自分のディスプレイ環境へ 合うように書き換える必要がある。この節の最後にその関数を示す。

目的:
多角形の集合のvoronoi diagramの計算を行う。 語彙を理解するために上記の文献を読んで、使用してください。 ここでは、このプログラムに対する説明をしません。
入力:

多角形のリストと囲むための枠は,次のように定義する。

DATA= (
       (x11 y11 x12 y12 x13 y13 ...) first polygon,
                                     counterclocwise enumeration of vertices
       (x21 y21 x22 y22 x23 y23 ...) second polygon
               ...
       (xn1 yn1 xn2 yn2 xn3 yn3 ...) nth polygon

       (xf1 yf1 xf2 yf2 xf3 yf3 xf4 yf4) enclosing frame
      )

囲む枠は,DATA内のどの位置にも配置することができる。また, 内部と外部が矛盾しないように時計方向の順番でなければならない。 多角形は交差の無い簡単な図形でなければならない。 一直線あるいは平坦なエッジは受け付けない。 独立した点あるいは線分も受け付けない。

出力:

diagram*:2重に接続されたエッジリストのリスト (utilities.lファイルを参照)を返す。それぞれのエッジは,symbolであり,次に示す ようなfieldを含むproperty-listを持っている。

(start <pointer to a vertex>)
       (end <pointer to a vertex>)
       (pred <pointer to an edge>)
       (succ <pointer to an edge>)
       (left <pointer to a site>)
       (right <pointer to a site>)
       (type <:endpoint or :point-point or :segment-segment or :point-segment>)
       (outflag <t or nil>)

vertexは,symbolで“pos”fieldを含むproperty-listを持つ。 このfieldは,cons(x,y)を含み,vertexの平面座標を示す。 predsuccのfieldは,decl形式にしたがって反時計方向の 前者と後者を与える(ShamosとPreparataの, Computational Geometry: An introduction, 1985, pp 15-17を参照)。 siteもsymbolであり,関連した情報を含むproperty-listを持つ。 siteは,元の入力データを記述しており,多角形の頂点であるpoint あるいは多角形のエッジであるsegmentを持つ。

typeは,2等分線の中点であり,それを分割するsiteの型より 決定される。 規約により,外側はstart-endエッジの右側である。 voronoi diagramは,2等分線の内部と同様に外側を計算する。 必要とするoutflagを保つためにoutflagをソートする。

サンプル:

サンプルプログラムを実行するためには,以下のようなステップを実施してください。

  1. 自分の環境に以下のプログラムをコピーする。
    utilities.l 幾何学ユーティリティ関数とeusxの画像出力関数
    polygonalvoronoi.l プログラム本体
    testdata.l 上記の書式によるデモデータ
  2. もし,Euslispを使用しないなら,命令にしたがってutilities.lを書き換え, “compatibility package”を修正する。。

  3. 以下の3つのファイルをコンパイルしてロードするか、あるいはそのままロードする。
    utilities.l  
    polygonalvoronoi.l  
    testdata.l 上記の書式によるデモデータを含んでいる。
  4. (pv demoworld)でデモデータ上でプログラムが実行される。 グローバル変数diagram*には,voronoi diagramの2等分線が含まれている。

eusx(Xwindowインターフェースを持つEuslisp)のもとでは,以下の命令でdiagramの結果を画面上に表示することができる。

(make-display)          ;;Initializes the *display* window object
(dps demoworld *thick*) ;; Shows original data in thick lines
(dbs *diagram*)         ;; Shows the result

pv data

上記の書式で書かれたdataから多角形のvoronoi diagramを計算する。

視界とグラフィックス

視界(viewing)

viewingオブジェクトは、viewing座標系を処理する。 この座標系の原点は仮想カメラの位置に置かれる。 -z軸方向がオブジェクトの視線方向で、xy平面が投影画面である。 viewingcascaded-coordsクラスを継承するので、 :translate:rotate:transformのような 座標変換メッセージを受け付ける。 また、cascaded-coordsから得られる他のオブジェクトを張り付けることができる。 したがって、移動物体上のカメラシステムのシミュレーションができる。 viewingの主な目的は、ワールド座標系で表現されるベクトルを カメラ座標系に変換することである。 変換は、一般の座標変換に対して逆方向で与えられる。 このローカル座標系内のベクトルはワールド座標系における表現に変換される。 したがって、viewingはviewcoordsスロットに逆変換された左手系変換を持つ。 このスロットは、viewing座標系として普通参照される。

viewing座標系と投影画面

viewing座標系と投影画面

viewing

:super = ** cascaded-coords**
:slots (viewcoords)

viewing変換を定義する。

:viewpoint **

このviewingの原点のベクトル位置を返す。

:view-direction **

の原点から画面の中心までのベクトルを返す。 これは、viewing座標系のz軸方向である。

:view-up **

ワールド座標系におけるこのviewingのy軸ベクトルを返す。 y軸は、viewportの上方である。

:view-right **

ワールド座標系におけるこのviewingのx軸ベクトルを返す。 x軸は、viewportの水平右方向である。

:look from &optional (to #f(0 0 0))

は、その目がfromに位置されており、toの位置を 見ているとしてviewing座標系を設定する。

:init = `[メソッド]
&key = (target #f(0 0 0)) (view-direction nil) (view-up #f(0.0 0.0 1.0)) (view-right nil) &allow-other-keys

viewingは、cascaded-coordsを継承するので、:pos:rot:euler:rpyなどの:initのパラメータはすべてviewing座標系の位置や姿勢を 指定することに使用できる。 しかしながら、viewingの:initは回転を決定する簡単な方法を持っている。 もし、:targetだけが与えられたとき、視線方向は視点からtarget位置 の方向に決定され、:view-rightベクトルはワールド座標系のxy平面に平行な x軸に決定される。 :view-direction:targetの代わりに指定しても同じ様な 効果を得られる。 もし、:view-upまたは:view-rightパラメータを:targetあるいは :view-directionに加えて指定するならば、3つの回転パラメータをすべて 自分自身で決定することができる。

投影

parallel-projectionperspective-projectionクラスは、 投影変換を処理する。この変換は4X4の行列で表現される。すなわち、変換は 3次元の同次座標系で与えられる。 projectionクラスは、両方のクラスの抽象クラスである。 これらの投影クラスは、viewingクラスを継承しているので、 2つの座標変換(ワールド座標からviewing座標系への変換と投影変換)を 同時に実行することができる。 3Dベクトルと:project3メッセージを投影オブジェクトに送ることにより、 4要素の実数ベクトル返す。 homo2normal関数は、この同次ベクトルを標準のベクトル表現に変換 するために使用される。 その結果は、標準デバイス座標系(NDC)と呼ばれる座標系上に表現される ベクトルである。 その中で、見えるベクトルはそれぞれのx,y,z次元において-1から1までの 範囲で表される。 ロボット世界の本当のカメラをシミュレートするために、 perspective-projectionparallel-projectionよりも多く使用される。 perspective-projectionは、定義されているパラメータが少し多い。 screenxとscreenyは、見える物体が投影されるviewing平面の上のwindowの大きさで、 大きな画面と広い空間が投影される。 viewdistanceは、視点とview平面との距離を定義しているが、 視角にも関係する。 viewdistanceを大きくすると、view平面のwindowに狭い範囲が投影される。 hitherとyonパラメータは、クリップする平面の前面と後面の距離を 定義する。 これら2つの平面の外側に位置するオブジェクトは、クリップから除外される。 実際に、このクリップ処理はviewportオブジェクトによって実現されている。

projection

:super = ** viewing**
:slots (screenx screeny hither yon projection-matrix)

4x4行列であらわされる投影変換を定義する。

:projection &optional pmat

もし、pmatが与えられたならば、 projection-matrixのスロットに設定する。 :projectionは、現在の4x4投影行列を返す。

:project vec

は、4要素を持つ3次元同次ベクトルである。 vecは、投影行列により変換される。 そして、変換された結果である同次表現が返される。

:project3 vec

は、標準の3Dベクトル。 vecは、投影行列により同次化され変換される。 そして、変換された結果である同次表現が返される。

:view vec

にviewing変換と投影変換を連続的に適用する。 そして、変換された結果である同次表現が返される。

:screen xsize (&optional (ysize xsize))

viewing画面の大きさを変える。 大きくすると、広いviewが得られる。

:hither depth-to-front-clip-plane

視点からクリップ前面までの距離を決定する。 このクリップ前面よりも前にあるオブジェクトはクリップから除外される。

:yon depth-to-back-clip-plane

視点からクリップ後面までの距離を変える。 このクリップ後面よりも後ろにあるオブジェクトはクリップから除外される。

:aspect &optional ratio

アスペクト比は、screen-yとscreen-xとの比である。 もし、ratioが与えられたならば、 アスペクト比は変えられ、screen-yはscreen-x * ratioに設定される。 :aspectは、現在のアスペクト比を返す。

:init = `[メソッド]
&key = (hither 100.0) (yon 1000.0) (aspect 1.0) (screen 100.0) (screen-x screen) (screen-y (* screen-x aspect)) &allow-other-keys

viewingprojectionを初期化する。

parallel-viewing

:super = ** projection**
:slots

平行投影を定義する。 hid(陰線消去関数)は平行投影では扱うことが出来ない。

:make-projection **

perspective-viewing

:super = ** projection**
:slots (viewdistance)

透視投影変換を定義する。

:make-projection **

:ray u v

視点から正規化画面の上にある(u,v)への単位方向ベクトルを返す。

:viewdistance &optional vd

は、視点から画面迄の距離である。 もし、vdが与えられたならば、viewdistanceに設定される。 viewdistanceは、カメラの焦点距離と一致する。 vdを大きくすれば、ズームアップされたviewを得ることができる。 :viewdistanceは、現在のviewdistanceを返す。

:view-angle &optional ang

画面の対角線を見込む角度がangラジアンであるように画面の大きさを設定する。 20度(約0.4ラジアン)から50度(約0.9ラジアン)までの角度が自然な透視view を生成することができる。 角度を大きくすると歪んだviewを生成する。 そして、狭くすると直角(平行)viewingのような平坦なviewが生成される。 :view-angleは、現在の視角あるいは新しい視角をラジアンで返す。

:zoom &optional scale

もし、scaleが与えられたならば、画面はscaleによって 現在の大きさを相対的に変化させる(viewdistanceは変化しない)。 もし、scaleに0.5を与えるならば、以前のviewより2倍広いviewを得られる。 :zoomは、新しい視角をラジアンで返す。

:lookaround alfa beta

視点を移動し回転させる。 回転中心は、視線の上でhither平面とyon平面の中間点 に与えられる。 viewing座標系は、ワールド座標系のz軸回りにalfaラジアン回転し、 ローカル座標系のx軸回りにbetaラジアン回転される。 :lookaroundは、viewingの中心にあるオブジェクト回りに視線を 動かすことができる。

:look-body bodies

視線、画面の大きさおよびhither/yonをすべてのbodiesに適合するviewport となるよう変える。視点は変化しない。 視線は、すべてのbodiesのbounding boxの中心を通る視線から選択される。

:init &key (viewdistance 100.0) &allow-other-keys

Viewport

viewportクラスは、正規デバイス座標系(NDC)の中の3次元viewportのクリップ を実行する。そして、デバイスに依存する座標系に結果を作る。 viewportは、画面上の見える四角領域の境界表現である。 viewportの物理的な大きさ(x軸とy軸方向のドット数)は、 :initメッセージの中の:width:heightとの引き数 で与えられなければならない。 :xcenter:ycenter引き数は、viewportの物理的な位置を決定する。 画面の原点からのそれぞれの次元が絶対的に与えられているテクトロニクス4014 のような基本的なディスプレイデバイスを使っているとき、これら2つのパラメータは、実際に画面の上にオブジェクトを描く位置を決定する。 もし、位置が親windowから相対的に決まるXwindowのような精巧なディスプレイ デバイスを使っているなら、 viewportを動かすためにviewportのパラメータを変える必要はない。 なぜなら、これらのパラメータは、実際のディスプレイ位置に依存しないからである。。

viewportクラスは、四角領域の左下をviewportの原点と仮定している。 そして、y軸は上方向に伸びているとする。 しかし、多くのwindowシステムやディスプレイデバイスでは原点を左上とし、 y軸が下方向に伸びているとしている。 この問題を回避するために、:heightパラメータに負の値を与えればよい。

homo-viewport-clip v1 v2

v2は、4要素を持つ同次ベクトルであって、 3次元空間の線分として表現される。 その線分は、\(x=-1, x=1, y=-1, y=1, z=0, z=1\)の境界でクリップされる。 そして、2つのベクトルのリストを返す。 もし、その線分がviewportの外側に完全に置かれているならば、 NILを返す。

viewport

:super = ** coordinates**
:slots

viewport変換は、デバイスで指定される座標系にNDC(正規化デバイス座標系)を作る。 coordinatesクラスを継承しているため、viewportはサイズと投影画面の 相対位置を定義している。

:xcenter &optional xcenter

このviewportのx軸の中心を返す。 もし、xcenterが与えられていれば、設定を行う。

:ycenter &optional ycenter

このviewportのy軸の中心を返す。

:size &optional size

このviewportのx軸とy軸方向の大きさのリストを返す。

:width &optional width

このviewportの幅をwidthに設定する。

:height &optional height

このviewportの高さをheightに設定する。

:screen-point-to-ndc p

は、物理的画面の中の位置を表現する実数ベクトルである。 pは、正規化デバイス座標系(NDC)の中での表現に変換される。

:ndc-point-to-screen p

このviewportのNDC表現であるpを画面の物理的位置に変換する。

:ndc-line-to-screen p1 p2 &optional (do-clip t)

2つの3次元ベクトルp1p2は、NDCの中の線分を定義する。 これらの2つの端点は、画面空間の表現に変換される。 もし、do-clipがnon-NILなら、その線分はクリップされる。

:init &key (xcenter 100) (ycenter 100) (size 100) (width 100) (height 100)

新しいviewportオブジェクトを作る。

Viewer

画面の上に描画するためには、4つのオブジェクトが必要である。 1つは描かれたオブジェクト、2つはviewing座標系と投影で定義されるviewing、 3つはNDCの中でのクリップ処理のためのviewportとNDCから物理的画面座標系への 変換、4つは 物理的ディスプレイデバイスの上に描画関数を実行するviewsurfaceviewerオブジェクトは、viewingviewportviewsurface オブジェクトを持ち、 座標系変換を連続的に制御する。 [Drawings]節に記述される**draw**とhid関数はviewerの インスタンスを使用する。

viewer

:super = ** object**
:slots (eye :type viewint)
(port :type viewport)
(surface :type viewsurface)

viewingからviewportを経由してviewsurfaceへ移るCascaded Coordinatesの変換を定義する。

:viewing &rest msg

もし、msgが与えられたならば、msgviewing(eye)オブジェクト に送られる。そうでなければ、viewing(eye)オブジェクトが返される。

:viewport &rest msg

もし、msgが与えられたならば、msgviewport(port)オブジェクト に送られる。そうでなければ、viewport(port)オブジェクトが返される。

:viewsurface &rest msg

もし、msgが与えられたならば、msgviewsurface(surface)オブジェクト に送られる。そうでなければ、viewsurface(surface)オブジェクトが返される。

:adjust-viewport **

の大きさが変えられたとき、:adjust-viewportは portに固有のメッセージを送ることによりviewportの変換を変える。

:resize width height

に:resizeメッセージを送り、viewportに:sizeメッセージを送る ことによりviewsurfaceの大きさを変える。

:draw-line-ndc p1 p2 &optional (do-clip t)

NDCの中に定義される2つの端点p1,p2を結ぶ線を描く。

:draw-polyline-ndc polylines &optional color

NDCの中に定義される端点を結ぶ多角形を描く。

:draw-star-ndc center &optional (size 0.01) color

NDCの中に十字マークを描く。

:draw-box-ndc low-left up-right &optional color

NDCの中に四角形を描く。

:draw-arc-ndc point width height angle1 angle2 &optional color

NDCの中に円弧を描く。 このviewerに結び付くviewsurfaceオブジェクトは、:arcメッセージを 受けなければならない。

:draw-fill-arc-ndc point width height angle1 angle2 &optional color

NDCの中に塗り潰し円弧を描く。

:draw-string-ndc position string &optional color

NDCの中に定義されるpositionstringを描く。

:draw-image-string-ndc position string &optional color

:draw-rectangle-ndc position width height &optional color

:draw-fill-rectangle-ndc point width height &optional color

:draw-line p1 p2 &optional (do-clip t)

ワールド座標系に定義される2つの端点p1,p2を結ぶ線を描く。

:draw-star position &optional (size 0.01) color

ワールド座標系のposition位置に十字マークを描く。

:draw-polyline vlist &optional color

ワールド座標系のvlist端点を結ぶ多角形を描く。

:draw-box center &optional (size 0.01)

ワールド座標系のcenterに四角形を描く。

:draw-arrow p1 p2

からp2へ向けての矢印を描く。

:draw-edge edge

:draw-edge-image edge-image

:draw-faces face-list &optional (normal-clip nil)

:draw-body body &optional (normal-clip nil)

:draw-axis coordinates &optional size

で定義される軸をsizeの長さで描く。

:draw &rest things

3次元の幾何学オブジェクトを描く。 もし、オブジェクトが3次元ベクトルならば、その位置に小さな十字マークを描く。 もし、3次元ベクトルのリストであれば、多角形を描く。 もし、thingが:drawメッセージを受けたならば、 このviewerを引き数としてそのメソッドが呼び出される。 もし、オブジェクトが:drawnersメソッドを定義しているならば、 :drawメッセージは:drawnersの結果に送られる。 line, edge, polygon, faceおよびbodyオブジェクトは、 viewerに定義されている:draw-xxx(xxxにそのオブジェクトのクラス名が入る) メソッドによって描かれる。

:erase &rest things

背景色でthingsを描く。

:init &key viewing viewport viewsurface

およびviewsurfaceをこのviewerのスロット eye, portとsurfaceに設定する。

view = `[関数]
&key = (size 500) (width size) (height size) (x 100) (y 100) (title “eusx”) (border-width 3) (background 0) (viewpoint #f(300 200 100)) (target #f(0 0 0)) (viewdistance 5.0) (hither 100.0) (yon 10000.0) (screen 1.0) (screen-x screen) (screen-y screen) (xcenter 500) (ycenter 400)

新しいviewerを作り、viewer*リストに置く。

描画

draw &optional viewer &rest thing

thingを描く。 thingは、座標系、立体、面、エッジ、ベクトル、2つのベクトルのリストのどれでも可能である。 (progn (view) (draw (make-cube 10 20 30))) は、xwindowに立方体を描く。

draw-axis &optional viewer size &rest thing

の中にthingの座標系の軸をsizeの長さで描く。 thingは、座標系から得られるどのオブジェクトでも可能である。

draw-arrow p1 p2

p1からp2に向かう矢印を描く。

hid &optional viewer &rest thing

に陰線処理された画像を描く。 thingは、faceまたはbodyが可能である。

hidd &optional viewer &rest thing

陰線を点線で描くことを除いて、hidと同じである。

hid2 body-list viewing

edge-imageオブジェクトで表現される陰線処理画像を生成する。 その結果はhid*に置かれる。

render &key bodies faces (viewer *viewer*) (lights *light-sources*) (colormap *render-colormap*) (y 1.0)

facesにレイトレーシングを行い、陰面消去した画像を生成する。 viewing, viewportおよびviewsurfaceはviewerから得られる。 lightsは、light-source(光源)オブジェクトのリストである。 colormapは、Xwindowのcolormapオブジェクトである。 それぞれのbodiesfacesは、割り当てられるカラー属性を 持たなければならない。 colormapに定義されているカラーLUTの名前を:colorメッセージで 送ることによりカラー属性を設定できる。 一般にこの関数は、Xlib環境下でのみ働く。 demo/renderdemo.lのサンプルプログラムを見ること。

make-light-source pos &optional (intensity 1.0)

の位置に光源オブジェクトを作る。 intensityは、デフォルトの光の強さを増す拡大比である。 もっと正確に強さを決定するためには、光源の:intensityメソッドを 使用する。

tektro file &rest forms

ストリームのためにfileをオープンし、 formsを評価する。 これは、tektro描画の出力を直接fileに書き込むために使用される。

kdraw file &rest forms

は、kdrawまたはidrawで読み込めるポストスクリプトファイルを 生成するためのマクロ命令である。 kdrawは、:outputモードでfileをオープンし、 viewer*を置き換えるためのkdraw-viewsurfaceとviewportを 作り、formsを評価する。 それぞれのformsは、drawやhidのような描画関数の どれかを呼び出す。 これらのformsからの描画メッセージは、kdraw-viewsurfaceに 直接出力される。この出力はidrawやkdrawで認識できる ポストスクリプト表現にメッセージを変換する。 そして、fileに蓄積する。 idrawまたはkdrawが呼び出されfileがオープンされたとき、 EusViewer windowに書いたものと同一の図形を見ることができる。 その図形は、idrawの機能で変更することができる。 そして、最終描画はepsfile環境を用いることによりLaTeXドキュメント に組み込むことができる。 この機能は、“llib/kdraw.l”のファイルに記述されている。

pictdraw file &rest forms

は、MacintoshのPICTフォーマットで画像ファイルを 生成するためのマクロである。 pictdrawは、fileを:outputモードでオープンし、 pictdraw-viewsurfaceを作り、viewer*のviewportに置き換え、 formsを評価する。 formsは、それぞれdrawあるいはhidのような描画関数のどれかを 呼び出すものである。 これらの書式からの描画メッセージは、kdraw-viewsurfaceに 直接出力された後、PICTフォーマットへのメッセージに変換され, fileへ蓄積される。 このPICTフォーマットは、Macintoshのmacdrawやteachtextで 認識することができる。

hls2rgb hue lightness saturation &optional (range 255)

HLS(Hue, Lightness, Saturation)で表現される色を、RGB表現に変換する。 HLSは、しばしばHSLとして参照される。 hueは、rainbow circle(0から360)の色で表現される。 0が赤で45が黄で120が緑で240が青で270が紫そして360が再び赤となる。 lightnessは、0.0から0.1の値を持ち、黒から白までの明るさを表現する。 lightnessが0のときは、huesaturationにかかわらず 黒となる。そして、lightnessが1のときは、白となる。 saturationは、0.0から1.0までの値を持ち、色の強さを表現する。 saturationの値が大きいと鮮明な色調を生成し、小さい値は弱く濁った色調 を生成する。 rangeは、RGB値の限界を示す。 もし、それぞれの色に8ビットの値が割り当てられているカラーディスプレイ を使っているならば、rangeは255とすべきである。 もし、RGBに16ビットの整数が仮想的に割り当てられているXwindowを使って いるならば、rangeは65536とすべきである。 HSVとHLSとの違いに注意すること。 HLSでは、鮮明な(rainbow)色はlightness=0.5で定義されている。

rgb2hls red green blue &optional (range 255)

RGBの色表現を、HLS表現に変換する。

アニメーション

EusLispのアニメーションは、グラフィックアクセラレータを持たない 普通のワークステーション上での擬似リアルタイムグラフィックス機能を備えている。 その基本的な考え方は、長い時間かかって生成された1連の画像を高速に 再表示することである。 画像は2つの方法で保存される。 1つは、完全なピクセル画像を持つたくさんのXwindow pixmapを保存する。 もう1つは、陰線処理で得られる線分データを保存する。 前者は、高速で陰面処理された画像を表示するための方法であるが、 長いアニメーションではたくさんのメモリーをX serverに要求するため 適さない。 後者は、メモリーが少なくて済み、データをディスクに蓄積するのに適する。 しかし、線分の数が増加したならば、性能を悪化させる。

他の方法として、描かれるオブジェクトの構成を得て、 viewer*に描画を生成する関数をユーザーが作ることもできる。 pixmap-animationは、count引数で指定された数と同じ回数この関数を呼び出す。 それぞれの呼び出し後、Xwindowと仮定されるviewsurfaceの内容は、 新しく作られたXwindow pixmapにコピーされる。 これらのpixmapは、playback-pixmapで再表示される。 同様に、hid-lines-animationhidの結果から見える線分を抜き出し、 リストに蓄積する。 そのリストは、playback-hid-linesによって再表示される。

以下に示す関数は、“llib/animation.l”に定義されており、 “llib/animdemo.l”の中にはETA3 マニピュレータのモデルに関して hid-lines-animationを用いたアニメーションの サンプルプログラムを含んでいる。

pixmap-animation count &rest forms

は、count回評価される。 それぞれの評価後、viewsurface*の内容は新しいpixmapにコピーされる。 count枚のpixmapのリストが、返される。

playback-pixmaps pixmaps &optional (surf *viewsurface*)

リストのなかのpixmapはそれぞれ、 surfに連続的にコピーされる。

hid-lines-animation count &rest forms

への呼び出しを含むformscount回評価される。 それぞれの評価後、hid*が持つhidの結果は検索され、 見える線分は2点一組のリストの形で集められる。 count長さのリストが返される。

playback-hid-lines lines &optional (view *viewer*)

は、2点一組のリストである。 viewの上に線分を連続的に描く。 他のpixmapを割り当てるときにフリッカーフリーアニメーションを生成するために 2重バッファ技法が使用される。

list-visible-segments hid-result

のedge画像のリストから見える線分を集める。

Xwindow インターフェース

Euslisp上のXwindowインターフェースは、’eusx’という 名前でEuslispが呼び出されたとき、実行可能となる。 [1] eusxは、起動時に環境変数“DISPLAY”を参照してXserverに接続を試みるため、 自分のXseverに環境変数“DISPLAY”が正しく設定されていなければならない。

Euslispには、次の3つのレベルのXwindowインターフェースが定義されている。 (1) Xlib関数, (2) Xlibクラスと(3) XToolKitクラスである。 この節と次のXToolKitの節に記述されている 全てのXwindow関数は、“X”パッケージの中に含まれている。 それらの関数名は、元のXlib関数名から最初の“X”を省いき、全ての文字を大文字に 変更したものとなっている。 例えばXdefaultGCはX:DEFAULTGCと名付けられていて、 X:XDEFAULTGCではない。

Xlib関数は、Xwindowシステムへの低レベルインターフェースで、 foreign関数として定義されている。 これらのXlib関数は、パラメータの型チェックあるいは パラメータの数のチェックを実行していないため、 十分注意して使用しなければならない。 例えば、すべてのXlibの呼び出しにおいてXserverとの接続を確認するために x:*display*を引き数として要求する。もし、指定し忘れたならば、Xlibは エラーを通知し、そのプロセスは死ぬ。 このような不便を避け、オブジェクト指向のインターフェースを作るために、 2番めのレベルのインターフェースであるXlibクラスが備わっている。 この節では、この2番めのレベルのインターフェースに焦点を当てる。 XToolKitと呼ばれるもっと高レベルのXwindowライブラリは、次節で 説明されている。

この節に記述されているクラスは、以下の継承の階層を持っている。

propertied-object
   viewsurface
      x:xobject
         x:gcontext
         x:xdrawable
             x:xpixmap
             x:xwindow
   colormap

Xlibのグローバル変数とその他関数

x:*display* **

Xのdisplay ID(整数)。

x:*root* **

デフォルトのroot windowオブジェクト。

x:*screen* **

デフォルトのscreen ID(整数)。

x:*visual* **

デフォルトのvisual ID(整数)。

x:*blackpixel* **

黒色のpixel値 = 1

x:*whitepixel* **

白色のpixel値 = 0

x:*fg-pixel* **

window作成時に参照されるデフォルトの文字色のpixel値、ふつうblackpixel*。

x:*bg-pixel* **

window作成時に参照される背景色のpixel値、ふつうwhitepixel。

x:*color-map* **

システムのデフォルトカラーマップ。

x:*defaultGC* **

pixmap生成時に参照されるデフォルトgcontext。

x:*whitegc* **

文字色が白色のgcontext。

x:*blackgc* **

文字色が黒色のgcontext。

*gray-pixmap* **

の結果。

*gray25-pixmap* **

1/4のピクセルがfg-pixel*であり、3/4がbg-pixel*である16x16のpixmap。

*gray50-pixmap* **

1/2のピクセルがfg-pixel*である16x16のpixmap。

*gray75-pixmap* **

3/4のピクセルが黒色である16x16のpixmap。

*gray25-gc* **

から作る25%のグレーGC。

*gray50-gc* **

から作る50%のグレーGC。

*gray75-gc* **

から作る75%のグレーGC。

*gray* **

*bisque1* **

*bisque2* **

*bisque3* **

*lightblue2* **

*lightpink1* **

*maroon* **

*max-intensity* **

65535

font-cour8 **

font-cour10 **

font-cour12 **

font-cour14 **

font-cour18 **

font-courb12 **

font-courb14 **

font-courb18 **

font-helvetica-12 **

font-lucidasans-bold-12 **

font-lucidasans-bold-14 **

font-helvetica-bold-12 **

font-a14 **

x:*xwindows* **

Euslispによる子windowを含んだ全てのwindowのリストを保持する。

x:*xwindow-hash-tab* **

drawable IDからxwindowオブジェクトを探すためのハッシュテーブル。 x:nexteventで得られるイベント構造はwindow IDであるため、 x:window-main-loopはこのテーブルを使用して一致するxwindowオブジェクト を知るためにx:event-windowを呼び出す。

xflush **

Xlibのコマンドバッファに保有するコマンドをすべてXserverに送る。 XlibバッファがXserverに出力するため、 Xserverに発行されたコマンドは、すぐに実行されない。 これは、ネットワークの渋滞およびプロセスの切替え頻度を減少させるために 必要である。 コマンドの効果を見るためにコマンドバッファを掃き出す方法として、 xflushを使用するかあるいは:flushメッセージをxwindowオブジェクトに 送る。

find-xwindow subname

*xwindows*の中から、名前にsubnameを含むもののリストを還す。

Xwindow

Xobject

:super = ** geometry:viewsurface**
:slots

すべてのXwindowに関連するクラスの共通のスーパークラスである。 現在、スロットもメソッドも定義されていない。

Xdrawable

:super = ** Xobject**
:slots (drawable = ; drawable ID
gcon ; this drawable’s default graphic context object
bg-color ; background color
width height ; horizontal and vertical dimensions in dots

Xdrawableは、線分や文字列のようなグラフィックオブジェクト を描くための四角領域を定義する。 Xdrawableは、xwindowやxpixmapのための共通メソッド を定義するための抽象クラスであり、 このクラスのインスタンスは何の効果も持っていない。

:init id

は、このdrawableのIDとしてdrawableスロットに設定される。 新しいGC(graphic context)が生成され、このdrawableオブジェクトの デフォルトGCとしてgconに設定される。

:drawable **

drawable IDを返す。

:flush **

Xlibのバッファに保有されるコマンドを掃き出す。

:geometry **

7つの幾何学属性のリストを返す。 そのリストは、root-window-id, x座標, y座標, 幅, 高さ, 枠線の幅, visualの深さである。

:height **

このXdrawableの高さ(y軸方向のドット数)を返す。

:width **

このXdrawableの幅(x軸方向のドット数)を返す。

:gc &rest newgc

もし、newgcが与えられない場合、現在のGCオブジェクトを返す。 もし、newgcgcontextのインスタンスなら、 このXdrawableのgcに設定する。 そうでなければ、newgcはメッセージとみなされ、 現在のgcに送られる。

:pos **

このXdrawableの位置を示す整数ベクトルを返す。 位置は親windowの相対位置としていつも定義され、 windowマネージャの仲介のもとにルートwindowの直接の子windowとして 生成されたwindowは、ルートwindowの本当の位置に関わらず、環境の タイトルwindowの固定座標を返す。

:x **

このXdrawableの親windowとの相対的な現在のx座標を返す。

:y **

このXdrawableの親windowとの相対的な現在のy座標を返す。

:copy-from drw

は、他のdrawableオブジェクト(Xwindowまたはpixmap)である。 drwの内容がこのXdrawableにコピーされる。

描画の基本

描画の基本

:point x y &optional (gc gccon)

\((x, y)\)の位置にオプションのgcで点を描く。

:line x1 y1 x2 y2 &optional (gc gcon)

から(x2,y2)へオプションのgcを用いて 線分を描く。x1, y1, x2, y2は整数でなければならない。

:rectangle x y width height &optional (gc gcon)

を中心としてwidthの幅とheightの高さを持つ 四角形を描く。

:arc x y width height angle1 angle2 &optional (gc gcon)

を中心としてwidthの幅とheightの高さを持つ 四角形に内接する楕円の円弧を描く。angle1が始まりの角度を示し、 angle2が終わりの角度を示す。これらの角度の単位はラジアンである。

:fill-rectangle x y width height &optional (gc gcon)

四角領域を埋める。

:fill-arc x y width height angle1 angle2 &optional (gc gcon)

円弧の中を埋める。

:string x y str &optional (gc gcon)

の位置から文字列strを表示する。背景は、書かない。

:image-string x y str &optional (gc gcon)

文字列strを表示する。文字列は、背景色で満たされる。

:getimage &key x y width height (mask #ffffffff) (format 2)

serverからximageを取り、ピクセルデータを文字列として返す。 serverから送られるピクセルデータは、一端 Xlibのximage構造に蓄積される。 その後、行毎に文字列にコピーされる。 ximage構造は、自動的に破壊される。 :getimageにより得られた画像文字列は、pixel-imageを作るために 使用できる。また、[PBMfile]節に書かれているようにpbmフォーマットのファイルに 書き込むことができる。

:putimage image &key src-x src-y dst-x dst-y width height (gc gcon)

このXdrawableの指定された位置にimageを表示する。 imageは、文字列あるいはximage構造へのアドレスポインターである。

:draw-line from to

メソッドと同じである。 他のviewsurfaceクラスとの互換性を提供できる。

:line-width &optional dots

このXdrawableのデフォルトGCの線の幅を設定する。 :gc :line-widthメッセージの使用を推薦する。

:line-style &optional dash

このXdrawableのデフォルトGCの線スタイルを設定する。 :gc :line-styleの使用が好まれる。

:color &optional c

このXdrawableの色を設定する。

:clear **

全画面を消去する。この関数は、:clear-areaを呼び出す。

:clear-area &key x y width height gc

メソッドを用いて四角領域を消去する。

Xpixmap

:super = ** Xdrawable**
:slots

pixmapは、画像バッファあるいは背景のパターンとしてしばしば用いられる drawableである。xwindowと異なり、xwindowにコピーされるまで pixmap自身を見ることはできないし、pixmapはどんなイベントも発生しない。

:init id

このpixmapを初期化する。

:create &key (width 500) (height 500) (depth 1) (gc *defaultgc*)

デフォルトGCとして:gcを持つ、width\(\times\)heightのpixmapを作成する。

:create-from-bitmap-file fname

で指定されるbitmapファイルからpixmapを作る。

:write-to-bitmap-file fname

このpixmapの内容をfnameで指定されるbitmapファイルに書き込む。 このファイルは、:create-from-bitmap-fileメソッドで pixmapを作り、読み戻すことができる。

:destroy **

このpixmapを破壊し、X resourceを開放する。

Xwindow

:super = ** Xdrawable**
:slots (parent subwindows backing-pixmap event-forward)

Xwindowは、画面の見える四角領域を定義する。 これは、text-windowやグラフィックオブジェクトを描くためのcanvas だけでなく、windowというよりはむしろグラフィックオブジェクトのような たくさんのpanel-itemscroll-barsからも継承される。

:create = `[メソッド]
&key = (parent *root*) (x 0) (y 0) (size 256) (width size) (height size) (border-width 2) (save-under nil) (backing-store :always) (backing-pixmap nil) (border *fg-pixel*) (background *bg-pixel*) (map T) (gravity :northwest) (title “WINDOW”) (name title) (font) event-mask (:key :button :enterLeave :configure :motion)
xwindow生成し、初期化する。 :parentが与えられたとき、このwindowは:parentの子windowとして 生成され、:parentのsubwindowsリストに蓄積される。 :x, :y, :size, :width, :height:border-widthは、このwindow の位置と寸法を決定する。 :save-under:backing-storeは、windowが再マップされたときに 生じるXserverの行動を制御する。 :backing-storeは:notUseful, :WhenMapped, :Alwaysのどれかであるが、 :save-underはTあるいはNILである。 :backing-pixmapがTのとき、このwindowと同じサイズのpixmapがEuslispにより 生成され、もしXserverがbacking-storeの容量を持っていない場合は、 backing-storeとして蓄積される。 :border:backgroundは、border_pixelと background_pixel属性をそれぞれ指定する。 もし、panelの中のpanel-buttonとしてたくさんの小さなwindowを 作成するような場合で、このwindowが生成後にすぐ表示されるべきでないならば、 :mapはNILにセットされなければならない。 :titleは、windowのタイトルバーに現れるwindowのタイトルである。 :nameは、このwindowのplistに蓄積されるwindowの名前であり、 プリンタにより表示される名前である。 このwindowへのXのイベントは、:event-maskによって決定される。 それはビットで構成されるevent-maskの整数表現あるいは次のsymbolのリスト である。 :key, :button, :enterLeave, :motionと:configure。 もし、もっと正確な制御が必要ならば、次のsymbolをそれぞれのイベントに 指定することができる。:keyPress, :keyRelease, :ButtonPress, :ButtonRelease, :EnterWindow, :LeaveWindow, :PointerMotion, :PointerMotionHint, :ButtonMotion, :KeyMapState, :Exposure, :VisibilityChange, :StructureNotify, :ResezeRedirect, :SubstructureNotify, :SubstructureRedirect, :FocusChange, :PropertyChange, :ColormapChangeと
:OwnerGrabButton。 :keyは、:keyPressと:KeyReleaseの両方が指定でき、 :buttonは、:ButtonPressと:ButtonReleaseの両方が指定できる。 サーバからイベントが送られてきたとき、window-main-loopは、 そのイベント構造を解析し、:KeyPress, :KeyRelease, :buttonPress, :ButtonRelease, :EnterNotify, :LeaveNotify, :MotionNotify, :ConfigureNotify メッセージをそのイベントが発生したwindowに送る。

:map **

このXwindowとその子windowを全て表示する。

:unmap **

このXwindowをとその子windowを全て非表示にする。

:selectinput event-mask

は、整数かあるいはイベントマスクsymbolのリストである。 ビットが1となっているかあるいはevent-maskリスト に列挙されているイベントは、それぞれこのwindowに通知される。

:destroy **

このXwindowを破壊し、X resourceを開放する。 windowオブジェクトは、ガーベージコレクトされないため、 xwindow*やxwindow-hash-tab*の中の一致するエントリも削除される。 全ての子windowも:destroyを送ることにより削除する。 このwindowは、親windowの子windowのリストから削除される。 drawableIDは、NILに設定される。

:parent **

親windowオブジェクトを返す。

:subwindows **

全ての子windowのリストを返す。 子windowは、もっとも最近作られたものがリストの最初である。 このwindowの直接の子windowだけがリストされ、子windowの子windowは リストされない。

:associate child

このwindowの子windowとしてchild windowを登録する。

:dissociate child

子windowのリストからchild windowを削除する。

:title title

このwindowのタイトル名を変更する。そのタイトル名はXserverに送られるため、 一旦蓄積され、window managerによって表示される。

:attributes **

このwindowの属性を表現する整数ベクトルを返す。

:visual **

このXwindowのvisual resource IDを返す。

:screen **

このXwindowのscreen resource IDを返す。

:root **

root window IDを返す。

:location **

このwindowのxとy座標を記述する2次元の整数ベクトルを返す。

:depth **

このwindowの深さ(カラープレーンの数)を返す。

:size **

このwindowのサイズ(高さと幅)を返す。

:colormap **

このwindowのcolormap resource IDを返す。

:move newx newy

このwindowの位置を(newx,newy)に変更する。 位置は、親windowの相対位置で与えられる。

:resize width height

このwindowのサイズを変更する。 たぶん、大きさのパラメータがクライアント側のXlibに中にキャッシュされるため、 :resizeの直後に:geometryメッセージを 送ると誤った(古い)結果を返す。

:raise **

このwindowを前面に持ってくる。

:lower **

このwindowを後ろに置く。

:background pixel

背景のピクセル値(カラーマップのインデックス)をpixelに変更する。 pixel値は、bg-colorスロットにも保存される。 :clear処理は、現在の背景を指定されたpixelで埋める。

:background-pixmap pixmap

背景のpixmap値をpixmapに変更する。

:border pixel

このwindowの枠線の色をpixelに設定する。

:set-colormap cmap

colormapを設定する。

:clear **

このXwindow内を全て消去する。

:clear-area &key x y width height

このXwindowの指定された四角領域を消去する。

make-xwindow &rest args

引き数argsで示されるXwindowを作る。

init-xwindow &optional (display (getenv “DISPLAY”))

eusxが起動するときに最初に呼び出される関数である。 init-xwindowは、displayで指定されるXserverに接続し、 [xvariables]節に記述されているデフォルト変数を初期化する。 init-xwindowは、デフォルトフォントをロードし、 グローバル変数に設定する。例えば、font-courb12, lucidasans-bold-12など。 このフォントロードは、起動時に時間遅れを引き起こす。 フォントロードの数を減らしたり、ワイルドカード文字“*”を使用せずに 正確なフォント名を指定することにより、その遅れを短くできる。

Graphic Context

gcontext

:super = ** Xobject**
:slots (gcid GCValues)

graphic context(GC)を定義する。 Euslispの中で、全てのwindowはデフォルトGCを持っている。

:create = `[メソッド]
&key = (drawable defaultRootWindow) (foreground *fg-pixel*) (background *bg-pixel*) function plane-mask line-width line-style cap-style join-style font dash

与えられた属性でGCを作成する。 drawableは、画面と画面の深さを知るためにXserverにより使用される。 結果のGCは、同じ画面上で作成される限り、 どのdrawableでも使用できる。

:gc **

XのGC IDを返す。

:free **

このGCを開放する。

:copy **

このGCのコピーを作る。

:foreground &optional color

もし、colorが与えられたならば、 文字色にcolorを設定する。colorはピクセル値である。

:background &optional color

もし、colorが与えられたならば、 背景色にcolorを設定する。colorはピクセル値である。

:foreback fore back

一度に文字色と背景色を設定する。

:planemask &optional plane-mask

plane-maskを設定する。

:function x

描画機能を設定する。 xは、以下に示す数字かキーワードの内の1つである。 0=Clear, 1=And, 2=AndReverse, 3=Copy, 4=AndInverted, 5=NoOp, 6=Xor, 7=Or, 8=Nor, 9=Equiv, 10=Invert, 11=XorReverse, 12=CopyInverted, 13=OrInverted, 14=Nand, 15=Set, :clear, :and, :andReverse, :copy, :andInverted, :NoOp, :Xor, :Or, :Nor, :Equiv, :Invert, :XorReverse, :CopyInverted, :OrInverted, :Nand, :Set

:font x

このGCのフォント属性を設定する。 xは、フォント名あるいはフォントIDである。 もし、xがフォント名(文字列)であったならば、:fontは フォントIDを決めるためにx:LoadQueryFontを呼び出す。 もし、見つからなかった場合、“no such font ...”が警告される。 もし、xがNIL(与えられなかった)ならば、このGCの現在の フォントIDが返される。

:line-width x

線幅をピクセル数xで設定する。

:line-style x

線スタイル(実線、点線など)を設定する。

:dash &rest x

のそれぞれの要素は、整数である。 :dashは、線スタイルの点線パターンを設定する。

:tile pixmap

をこのGCのタイルパターンに設定する。

:stipple pixmap

をこのGCの点画に設定する。

:get-attribute attr

属性値を得る。 attrは、:function, :plane-mask, :foreground, :background, :line-width, :line-style, :cap-style, :join-style, :fill-style, :fill-rule, :fontの内の1つである。 属性値を表す整数が返される。

:change-attributes = `[メソッド]
&key = function plane-mask foreground background line-width line-style cap-style join-style font dash

属性値を変更する。 同時に複数の属性値を変更できる。

font-id fontname

もし、fontnameが整数であるなら、フォントIDとみなしてその値を返す。 もし、fontnameが文字列であるなら、x:LoadQueryFontを使用して フォント構造を得て、そのフォントIDを返す。 fontnameは、正確な名前の略語でも良い。例えば、 24ポイントのクーリエフォントとして“*-courier-24-*”を指定できる。 もし、フォントが見つからなければ、can’t load fontの警告を 出力する。

textdots str font-id

文字列のascent descent widthをドット単位に示す3つの整数のリストを 返す。

色とカラーマップ

colormap

:super = ** object**
:slots (cmapid planes pixels LUT-list)

Xwindowのカラーマップおよびアプリケーション指向のカラールックアップテーブル を定義する。 カラーはRGB値で表現され、その範囲は0〜65535である。 カラーマップのカラーセルは、8ビットの擬似カラーディスプレイの上の 0〜255の範囲の値に設定される。

ここで、8ビットの擬似カラーディスプレイの機能があり、 256色を選択することができると仮定する。 基本的にカラーマップを使用する2つの方法がある。 1つは、システムデフォルトのカラーマップを共有する方法で、 もう1つはプロセスに独自のカラーマップを作成する方法である。 もし、システムのデフォルトカラーマップを使用する場合、 マップのすべてのカラーセルを使いきらないように注意しなければならない。 なぜなら、マップは多くののプロセスから共有されているからである。 もし、独自のカラーマップを使用する場合、 他のプロセスを気にすることなく256色すべてを使用することができる。 しかし、そのマップは明確に独自のwindowに設定しなければならない。 マウスのポインターがwindow内のどこかに動かされたとき、 カラーマップはwindow managerにより活性化される。

システムデフォルトのカラーマップは eusxが実行される最初にx:colormapのクラスのインスタンスとして、 x:*color-map*に設定されている。 もし、独自のカラーマップを使用するとき、x:colormapのインスタンスを 作る。 これらのインスタンスは、x serverで定義されたcolormapオブジェクトと 一致しており、それぞれのインスタンスのcmapidに示されている。

システムデフォルトのカラーマップを使用するとき、 他のプロセスと共有するカラーを読み込み専用(read-only)に、 Euslispの独自カラーを読み書き可能(read-write)に定義することができる。 “読み込み専用”は、カラーセルに割り当てられる 任意のカラーに定義することができる。 しかし、割り当てた後変更することができない。 もう一方で、“読み書き可能”カラーは定義した後でさえ、変更することができる。 共有カラーは、他のプロセスが変更を予期していないため“読み込み専用”である。 この“読み込み専用”と“読み書き可能”の属性は、それぞれのカラーに付けられる。 (しばしば、カラーセルとして参照される)

colormapオブジェクトは、color IDからRGBの物理的な表現への変換を 定義する。 しかしながら、これらの論理的なcolor IDは、任意に選択することができない。 特に、システムのデフォルトのカラーマップを使用しているとき、使用できない。 color ID(しばしば’pixel’として参照される)は、カラーマップの特別な色 のインデックスである。 Xlibは、割り当ての要求があると、共有カラーのために空いたインデックスの 1つを選択する。 したがって、たくさんのグレー階調のカラーを連続的に割り当てることを 保証することあるいは最初(0番目)のインデックスから始めることはできない。

アプリケーションの観点から、もっと論理的なカラー名が必要とされる。 例えば、グレー階調の数は明るさをインデックスとして参照すべきである。 レイトレーシングプログラムは、 HLSで定義される違った明るさのカラーのグループのために 連続的なインデックスの割り当てを要求する。

この問題に対処するために、Euslispのカラーマップはルックアップテーブル(LUT) と呼ばれる別の変換テーブルを提供している。 論理的なカラーグループのために、LUTを定義でき、symbol名を付けることができる。 1つ以上のLUTをカラーマップとして定義できる。 LUTは、Xserverが認識できるように、アプリケーションが指定した論理カラーの インデックスを物理ピクセル値に変換するために整数ベクトルである。

:id **

を返す。

:query pix

指定されたピクセル数のRGB値を返す。

:alloc r g b

このメソッドは、:store nil r g bと同一である。 新しいカラーセルがこのカラーマップに配置され、指定されたRGB値に割り当てられる。

:store pix r g b

番目のカラーセルのRGB値を設定する。

:store pix color-name

は、カラーマップに色を設定する低レベルメソッドである。 1つの書式として、RGB値を0〜65535で指定する方法である。 他の書式として、“red” や“navy-blue”のようなカラー名で指定する。 もし、color-nameがなければ、NILを返す。 ピクセルはカラーマップのインデックスあるいはNILである。 もし整数なら、カラーセルは読み書き可能でなければならない。 もしNILなら、共有の読み込み専用カラーセルが割り当てられている。 :storeは、カラーマップ内のカラーセルのインデックスを返す。

:store-hls pix hue lightness saturation

HLS(Hue, Lightness and Saturation)で 指定される色をカラーマップのpix番目に蓄積する。 もし、pixがNILなら、共有の読み込み専用のカラーセルが割り当てられる。 :store-hlsは、カラーセルに割り当てられるインデックスを返す。

:destroy **

このcolormapを破壊し、リソースを空にする。

:pixel LUT-name id

の中からid番目を調べて、ピクセル値を返す。 LUT-nameは、:define-LUTで定義されたルックアップテーブルの名前である。

:allocate-private-colors num

独自のカラーマップにnum個のカラーセルを割り当てる。

:allocate-colors rgb-list &optional private

のそれぞれの要素は、red,green,blueのリストである。 カラーセルは、それぞれのRGB値が割り当てられ、ピクセル値を要素とする 整数ベクトルを返す。

:define-LUT LUT-name rgb-list &optional private

に記述されたカラーが割り当てられ、 LUTがLUT-nameのシンボリック名で登録される。 独自のカラーセルを定義するためには、privateをTに設定すること。

:define-gray-scale-LUT LUT-name levels &optional private

線形のグレースケールカラーで表現されるlevels階調の カラーセルを割り当て、LUTを返す。 例えば、(send x:*color-map* :define-gray-scale-LUT ’gray8 8) は、システムのデフォルトカラーマップの中に8つのグレーカラーを配置し、 #i(29 30 31 48 49 50 51 0)のような整数ベクトルを返す。 物理ピクセル値は、:pixelメッセージを送ることにより得られる。 例えば、(send x:*color-map* :pixel ’gray8 2)は、31を返す。

:define-rgb-LUT LUT-name red green blue &optional private

RGB表現を縮小したLUTを定義する。 例えば、もし、red=green=blue=2なら、カラーセルには\(2^{2+2+2}=2^6=64\) が割り当てられる。

:define-hls-LUT LUT-name count hue low-brightness high-brightness saturation &optional private

HLSで使用するcount数のカラーを配置する。 hue (0..360),*saturation* (0..1),*low-brightness* とhigh-brightnessの明るさの差をカラーマップに蓄積される。 LUT-nameで名付けられるLUTも作られる。

:define-rainbow-LUT LUT-name &optional (count 32) (hue-start 0) (hue-end 360) (brightness 0.5) (saturation 1.0) private

HLSモデルを用いてcountの色を配置する。 brightness (0..1)と saturation (0..1)と, hue-starthue-end間の異なったhueを持つ色を カラーマップに蓄積する。 LUT-nameを名付けられたLUTも生成される。

:LUT-list **

このカラーマップに定義されている全てのLUTのリストを返す。 リストのそれぞれのエントリは、LUT名と整数ベクトルの組である。

:LUT-names **

このカラーマップの全てのLUTの名前のリストを返す。

:LUT name

で指定される整数ベクトル(LUT)を返す。

:size LUT

の長さを返す。

:planes **

このカラーマップのプレーンを返す。

:set-window xwin

このカラーマップをxwinのwindowと関連付ける。 このカラーマップは、xwinにカーソルが入ったとき活性化される。

:free pixel-or-LUT

の場所にあるカラーセルを開放するか あるいはLUTのすべてを開放する。

:init &optional cmapid

このカラーマップをcmapidで初期化する。 登録されたLUTはすべて捨てられる。

:create &key (planes 0) (colors 1) (visual *visual*) contiguous

新しいカラーマップを作成する。

XColor

:super = ** cstruct**
:slots ((pixel :integer)
(red :short)
(green :short)
(blue :short)
(flags :byte)
(pad :byte))

RGBモデルのカラーを定義する。 それぞれのスロットに値を割り当てるには、setfを用いる。 RGB値は、符合拡張され、最大値は\(-1\)と表現される。

:red **

このXColorの赤色の値を返す。

:blue **

このXColorの青色の値を返す。

:green **

このXColorの緑色の値を返す。

:rgb **

このXColorのRGB値のリストを返す。

:init pix R G B &optional (f 7)

を初期化する。

find-visual type depth &optional (screen 0)

depthで指定されるvisual-IDを見つける。 typeは、:StaticGray, :GrayScale, :StaticColor, :pseudoColor, :TrueColorあるいは:DirectColorのどれかである。 ふつう、depthは1, 8 または 24である。

[1]eusxは、eusへのシンボリックリンクである。

XToolKit

XToolKitは、 ボタン、プルダウンメニュ、テキストwindowなどのGUI要素を使用して GUI (Graphical User Interface)を作成するのを容易にするための 高レベルXwindowインターフェースである。 Xlibクラスとの大きな違いは、XToolKitがXserverから送られる Xeventと一致するユーザーが定義した対話ルーチンを呼び出し、 それらの対話指向windowパーツと一致した外観を提供することである。 XToolKitに含まれるクラスは、以下の継承構造を持っている。

xwindow
     panel
          menubar-panel
          menu-panel
          filepanel
          textviewpanel
          confirmpanel
     panel-item
          button-item
               menu-button-item
               bitmap-button-item
               menu-item
          text-item
          slider-item
          choice-item
          joystick-item
     canvas
     textwindow
          buffertextwindow
               scrolltextwindow
          textedit
     scroll-bar
          horizontal-scroll-bar

以下に示すxwindowクラスはXToolKitの5つの基本クラスである。 panel, panel-item, canvas, textWindowとscroll-bar。 menubar-panelとmenu-panelは、panelの下に定義される。 新しいアプリケーションwindowを作り、イベントの上でそれを実行させるための 基本的な方策は、以下の通りである。

  1. アプリケーションクラスの定義 アプリケーションクラスwindowは、 XToolKitの要素を置く能力を持つpanelのサブクラスとして 定義されなければならない。
  2. イベントハンドラの定義 アプリケーションクラスにおいて、 ボタンが押されたり、メニューアイテムが選択されたりしたときに 呼び出されるイベントハンドラを定義する。 イベントハンドラは、panel-itemの指定された引数を持つメソッドとして 定義すべきである。
  3. サブパネルの定義 もし、menubar-panelを使用するなら、 アプリケーションwindowの一番上におかれる。 したがって、:create-menubarによって最初に作成されなければ ならない。 同様に、menu-panelは、そのmenu-panelと関連する menu-button-itemより前に定義する必要がある。
  4. パネルアイテムの作成 button-item, text-item, slider-itemなどのようなパネルアイテムは、 (send-super :create-item class label object method)によって 作成することができる。 上記で定義されたイベントハンドラは、それぞれのパネルアイテムと 接続される。 これらの初期化手続きは、アプリケーションwindowクラスの :createメソッドの中で定義すべきである。 必要なときはいつでもイベント送信を停止するためのquitボタンを 定義することを忘れないこと。 どんなtextWindowとcanvasも、:locate-itemメソッドを経由して アプリケーションwindowの中に置くことができる。
  5. window全体の作成 :createメッセージをアプリケーション クラスに送ることで、windowにXToolKitの要素を正しく置いたアプリケーション windowを作成する。
  6. イベント送信の実行 Xserverからイベントを受け、一致する windowに配るためには、window-main-loopを実行すること。 Solaris2上では、イベントを配るための異なったスレッドである window-main-threadで実行する。 window-main-threadでは、最上位レベルの対話が活きている。 window-main-threadを2回以上実行してはならない。

Xイベント

現在の実行において、 イベント構造は固定イベントバッファ(25要素の整数ベクトル)から受け、 同じバッファが全てのイベントに関して再使用される。 イベント構造は、同時に2つ以上のイベントを参照する必要があるとき、 コピーされなければならない。

window-main-loopは、Xserverから送られる全てのイベントを 捕獲し、イベントが発生したwindowに配るための関数である。

event **

もっとも最近のイベント構造を持つ25要素の整数ベクトル

next-event **

の中にイベント構造を蓄積し、 もし1つでも未決定のイベントがあればそれを返し、 なければNILを返す。

event-type event

のイベント型を表現するキーワードsymbol返す。 イベント型キーワードは、 :KeyPress (2), :KeyRelease (3), :ButtonPress (4), :ButtonRelease (5), :MotionNotify (6), :EnterNotify (7), :LeaveNotify (8), :FocusIn (9), :FocusOut (0), :KeymapNotify (1), :Expose (12), :GraphicsExpose (13), :NoExpose (14), :VisibilityNotify (15), :CreateNotify (16), :DestroyNotify (17),
:UnmapNotify (18), :MapNotify (19), :MapRequest (20), :ConfigureNotify (22), :ConfigureRequest (23), :GravityNotify (24), :ResizeRequest (25), :CirculateNotify (26), :CirculateRequest (27), :PropertyNotify (28), :SelectionClear (29), :SelectionRequest (30), :SelectionNotify (31), :ColormapNotify (32), :ClientMessage (33), :MappingNotify (34), :LASTEvent (35)である。

event-window event

が発生したwindowオブジェクトを返す。

event-x event

からそのイベントが発生したx座標を抜き出す。 (すなわち、window内におけるマウスポインタの横方向の相対的な位置)

event-y event

からそのイベントが発生したy座標を抜き出す。 (すなわち、window内におけるマウスポインタの縦方向の相対的な位置)

event-width event

イベントに幅パラメータを表現する eventの8つの要素を返す。

event-height event

イベントに高さパラメータを表現する eventの8つの要素を返す。

event-state event

キーの状態で変更されたマウスボタンを表現するキーワードのリストを返す。 キーワードは、:shift, :control, :meta, :left, :middleと:rightである。 例えば、もしシフトキーが押されている状態で左のボタンが押されたならば、 (:shift :left)が返される。

display-events **

によって捕獲された全てのxwindowイベントを表示する。 Control-Cは、この関数を停止させる唯一の方法である。

window-main-loop &rest forms

Xeventを受け、イベントが発生したwindowオブジェクトにそれを 配る。 イベントの型に沿って、 :KeyPress, :KeyRelease, :ButtonPress, :ButtonRelease, :MotionNotify, :EnterNotify, :LeaveNotify
や :ConfigureNotifyと名付けられた windowクラスのメソッドがeventを引数として 呼び出される。 もし、formsが与えられたならば、 到着したイベントがチェックされるとき毎にそれらを評価する。

window-main-thread **

スレッドであることを除いてwindow-main-loopと同じことをする。 window-main-threadは、Solaris2でのみ実現されている。 window-main-threadは、read-eval-printが入力されない エラーハンドラをインストールしている。 エラー情報を表示した後、そのイベントは処理を続ける。

パネル

panel

:super = ** xwindow**
:slots (pos items fontid
rows columns ;total number of rows and columns
next-x next-y
item-width item-height)

panelは、パネルアイテムや他のpanelを含んだどんなxwindowも置くこと ができるxwindowである。 panelオブジェクトは、panelの中で生成されたパネルアイテムへの デフォルトフォントを供給する。 アプリケーションwindowは、panelのサブクラスとして定義 去れなければならない。

:create = `[メソッド]
&rest args = &key = (item-height 30) (item-width 50) (font font-lucidasans-bold-12) ((:background color) *bisque1*) &allow-other-keys

panelを生成し、初期化する。 スーパークラスの:createが呼び出されるため、 xwindowに対する全ての生成用パラメータ(:width, :height, :border-widthなど)が許される。 :item-height:item-widthは、最小の高さと幅をそれぞれのパネルアイテムに 与える。

:items **

関連するアイテムを全てリストで返す。

:locate-item item &optional x y

は、xwindowオブジェクト(ふつうはパネルアイテム)である。 もしxyが与えられたならば、アイテムはそこに置かれる。 そうでなければ、itemは、もっとも最近に置かれたアイテムに 隣接するように置かれる。 アイテムは、 図 [panellayout]のように 上から下に向かって、また左から右に向かって置かれていく。 :locate-itemは、またitemsやsubwindowsリストに itemを追加し、:mapを送ることにより見えるようにする。

panelのアイテムレイアウト

panelのアイテムレイアウト

:create-item = `[メソッド]
klass label receiver method = &rest args &key (font fontid) &allow-other-keys

klassで指定されるパネルアイテムのクラス (すなわち、button-item, menu-button-item, slider-item, joystick-itemなど), のインスタンスを作り、:locate-itemを用いてpanelにアイテムを置く。 argsは、klassの:createメソッドに送られる。 labelは、パネルアイテムの中に書かれる識別文字列である。 receivermethodは、一致するイベントを呼び出すイベントハンドラを 指定する。

:delete-items **

パネルアイテムを全て削除する。

:create-menubar = `[メソッド]
= &rest args &key (font fontid) &allow-other-keys

menubar-panelを作成し、panelの最上部に置く。

以下に示すメソッドは、イベントがイベントハンドラのないpanelに送られたとき、 “subclass’s responsibility”警告メッセージを避けるために提供されている。 ユーザーのアプリケーションでは、これらのメソッドを上書きしなければならない。

:quit &rest a

に:quitメッセージを送り、 イベント処理を停止する。

:KeyPress event

NILを返す。

:KeyRelease event

NILを返す。

:ButtonPress event

NILを返す。

:ButtonRelease event

NILを返す。

:MotionNotify event

NILを返す。

:EnterNotify event

NILを返す。

:LeaveNotify event

NILを返す。

サブパネル(メニューとメニューバー)

menu-panel

:super = ** panel**
:slots (items item-dots item-height
charwidth charheight
height-offset
highlight-item
color-pixels
active-color)

menu-panelは、panel-buttonとmenu-itemのみを 含むことができるパネルの一種である。 panelと異なり、menu-panelはふつう見えないし、 menu-panelと関連したbutton-itemが押された時に 表示される。 もし、menu-panelがいつも見えるように作られたならば、 ピンを刺したメニューとなる。 マウスイベントに対するmenu-itemの応答は、アイテムの外のどこかで 押されたマウスボタンのようにふつうのmenu-buttonと 全く異なっている。 menu-panelを使用するためには、最初に作成し、 その中にbutton-itemを置く。 それから、menu-button-itemがpanelの中あるいはmenubarの中に :menuの引数としてmenu-panelと一緒に作成される。

:create = `[メソッド]
&rest args = &key= items (border-width 0) (font font-courb12) (width 100) (height-offset 15) (color *bisque1*) (active *bisque2*) &allow-other-keys

menu-panel windowを作成する。 そのwindowの大きさは、新しいmenu-itemが追加される時に 拡張される。

:add-item label name &optional (receiver self) &rest mesg

このmenu-panel windowの中にmenuアイテムを追加し、 対応する行動を張り付ける。 マウスボタンがアイテムの上で外されたとき、 receiverオブジェクトはmesgを受け取る。

menubar-panel

:super = ** panel**
:slots

menubar-panelは、親panelの最上部にいつも置かれるサブパネルである。 メニューバーに置かれるパネルアイテムは、menu-button-itemで なければならない。 menubar-panelは、panelの:create-menubarメソッドにより 生成される。

ファイルパネル

FilePanelは、ファイルやディレクトリを対話的に処理する アプリケーションwindowである。 cdやgo-upボタンを使用することにより、 どんなディレクトリも見に行くことができるし、 以下のScrollTextWindowの中にディレクトリ内に含まれるファイルを 表示する。 テキストファイルは、異なったwindow(TextViewPanel)の中に 表示することができる。 ファイルは、また印刷することができ、削除することができ、 ボタンをクリックすることにより簡単にコンパイルすることができる。 ファイルを印刷するとき、a2ps file | lprコマンドがforkされたプロセスとして実行される。

ファイルパネルwindow

ファイルパネルwindow

テキスト表示パネル

TextViewPanelは、テキストファイルを表示するための アプリケーションwindowクラスである (図 [textviewpanel])。 プログラムテキストは、もっとも簡単なアプリケーションwindowの1つが どのように記述されているかを見れる。 :createメソッドにおいて、quitボタンとfindボタンと ファイルの中を捜すための文字列を供給するためのtext-itemを 作成する。 view-windowは、縦と横にスクロールバーを持ちファイルを表示するための ScrollTextWindowである。 TextViewPanelは、windowマネージャーにより一番外側のタイトルwindowの 大きさを変えたときview-windowの大きさを変えるために :ConfigureNotifyイベントを捕獲する。

テキスト表示パネルwindow

テキスト表示パネルwindow

(defclass TextViewPanel :super panel
        :slots (quit-button find-button find-text view-window))

(defmethod TextViewPanel
 (:create (file &rest args &key (width 400) &allow-other-keys)
    (send-super* :create :width width args)
    (setq quit-button
          (send self :create-item panel-button "quit" self :quit))
    (setq find-button
          (send self :create-item panel-button "find" self :find))
    (setq find-text
          (send self :create-item text-item "find: " self :find))
    (setq view-window
            (send self :locate-item
                (instance ScrollTextWindow :create
                   :width (setq width (- (send self :width) 10))
                   :height (- (setq height (send self :height)) 38)
                   :scroll-bar t :horizontal-scroll-bar t
                   :map nil      :parent self)))
    (send view-window :read-file file))
 (:quit (event)  (send self :destroy))
 (:find (event)
    (let ((findstr (send find-text :value)) (found)
          (nlines (send view-window :nlines)))
        (do ((i 0 (1+ i)))
            ((or (>= i nlines) found))
           (if (substringp findstr (send view-window :line i)) (setq found i)))
        (when found
           (send view-window :display-selection found)
           (send view-window :locate found))))
 (:resize (w h)
    (setq width w height h)
    (send view-window :resize (- w 10) (- h 38)))
 (:configureNotify (event)
   (let ((newwidth (send self :width))
         (newheight (send self :height)))
        (when (or (/= newwidth width) (/= newheight height))
          (send self :resize newwidth newheight)))  ) )

パネルアイテム

panel-item

:super = ** xwindow**
:slots (pos notify-object notify-method fontid label labeldots)

panel-itemは、パネルアイテムwindowのすべての種類において、 アイテムが指定するイベントが発生したとき notify-objectのnotify-methodを呼び出すための 抽象クラスである。

:notify &rest args

のnotify-methodを呼び出す。 イベント応答やnotify-methodへ送るための引き数が アイテムにより区別される。

button-item
ボタンは、同じbutton-itemの押し、外し時に応答。 引き数はbutton-itemオブジェクトである。
menu-button-item
メニューアイテムの選択時に応答。 引き数は、menu-button-itemオブジェクトである。
choice-item
新しい選択ボタンの選択時に応答。 引き数は、choice-itemオブジェクトとその選択番号である。
text-item
改行あるいはリターンの入力時に応答。 引き数は、text-itemオブジェクトと入力行(文字列)である。
slider-item
スライダーノブは、つかみと移動時に応答。 引き数は、slider-itemオブジェクトと新たな値である。
joystick-item
ジョイスティックは、つかみと移動時に応答。 引き数はslider-itemオブジェクトと新しいxとyの値である。
:create = `[メソッド]
name reciever method = &rest args &key (width 100) (height 100) (font font-courb12) &allow-other-keys

パネルアイテムを作成する。 パネルアイテムは、抽象クラスである。 このメソッドは、サブクラスによってsend-superを通してのみ 呼び出すべきである。

button-item

:super = ** panel-item**
:slots

button-itemは、簡単なパネルアイテムである。 button-itemは、四角ボックスとその中のラベル文字列を持っている。 クリックされたとき、button-itemはpanel-itemオブジェクトを唯一の引き数として notify-objectのnotify-method を呼び出す。

:draw-label &optional (state :top) (color bg-color) (border 2) offset

のラベルを書く。

:create = `[メソッド]
label revciever method = &rest args &key= width height (font (send parent :gc :font)) (background (send parent :gc :background)) (border-width 0) (state :top) &allow-other-keys

button-itemを作成する。 もし、ボタンの幅と高さが与えられないなら、サイズは 与えられたフォントを用いて書かれた ラベル文字列に合わせて自動的に設定される。 :border-widthはデフォルトで0であるが、 擬似3次元表現でボタンを浮き出しにする。 背景やフォントは親window(すなわち、panel)で定義されているものを デフォルトとする。

:ButtonPress event

もし、ボタンであれば、背景色をグレーにする。

:ButtonRelease event

の背景色を標準に変更する。

menu-button-item

:super = ** button-item**
:slots (= items item-dots item-labels
charwidth charheight
menu-window window-pos high-light)

プルダウンメニューを定義する。 menu-button-itemは、button-itemのようであるが、 menu-button-itemは、ボタンの下の関連するmenu-panelが 押されたとき、 notify-objectにすぐにメッセージを送る代わりに、 活性化させる。 メニューアイテムの1つの上でマウスボタンが外されたときに、本当のメッセージが 送られる。

:create = `[メソッド]
= label reciever method &rest args &key menu items (state :flat) &allow-other-keys

プルダウンメニューを作成する。 receivermethod引き数は、影響を与えない。

:ButtonPress event

プルダウンメニューのボタンを反転させ、 ボタンの下に関連するmenu-panelをさらす。

:ButtonRelease event

このボタンの下のmenu-panelを消し、 このボタンを元に戻す。

bitmap-button-item

:super = ** button-item**
:slots (pixmap-id bitmap-width bitmap-height)

bitmap-button-itemの関数は、button-itemに似ているが、 表現が異なっている。 button-itemの場合にボタンの上に簡単なラベル文字列を描く代わりに、 bitmap-button-itemでは、ボタンが作られたときにbitmapファイルから ロードされるpixmapを描く。

:create = `[メソッド]
bitmap-file reciever method = &rest args &key width height &allow-other-keys)

bitmap-button-itemを作成する。 最初の引き数bitmap-fileは、button-itemのlabel引き数 を置き換えたものである。

:draw-label &optional (state :flat) (color bg-color) (border 2)

ボタンの上にbitmapかpixmapを描く。

:create-bitmap-from-file fname

という名のbitmapファイルからpixmapを作り、 pixmap-idにそのIDを入れる。

choice-item

:super = ** button-item**
:slots (choice-list active-choice transient-choice
choice-dots choice-pos button-size)

choice-itemは、丸い選択ボタンの集合である。 1つの選択はいつも活性化しており、同時に1つの選択だけが 活性化することができる。 choice-itemは、ラジオボタンと同様な機能を提供する。

:create = `[メソッド]
label reciever method = &rest args &key = (choices ’(“0” “1”)) (initial-choice 0) (font (send parent :gc :font)) (button-size 13) (border-width 0)

choice-item-buttonを作成する。 それぞれの選択ボタンは:button-sizeの半径を持つ円である。 新しい選択ボタンが選択されたとき、 notify-objectのnotify-methodが choice-itemオブジェクトと選択された選択ボタンの番号と一緒に呼び出される。

:value &optional new-choice invocation

もし、new-choiceが与えられたならば、現在の活性化選択ボタンとして 設定し、対応する円が黒色になる。 もしinvocationも指定されているなら、notify-objectの notify-methodが呼び出される。 :valueは、現在の(あるいは新しい)選択ボタンの番号を返す。

:draw-active-button &optional (old-choice active-choice) (new-choice active-choice)

ボタンを活性化として書く。

:ButtonPress event

もし、選択ボタンのどこかでマウスボタンが押されているなら、 その番号がtransient-choiceに記録される。 マウスボタンが外されるまでそれ以上の行動は、起こさない。

:ButtonRelease event

もし、既に押されていたところと同じボタンの上でマウスボタンが外されたなら、 active-choiceが更新され、 notify-objectのnotify-methodが呼び出される。

slider-item

:super = ** panel-item**
:slots (min-value max-value value
minlabel maxlabel valueformat
bar-x bar-y bar-width bar-height valuedots label-base
nob-x nob-moving
charwidth)

choice-itemが離散的な値の選択に使用されるのに対し、 slider-itemはmin-valueとmax-valueの間の範囲の 連続的な値に対して使用される。 それぞれ値が変化した瞬間、slider-itemオブジェクトと新しい値が引き数として 一緒にnotify-objectのnotify-methodが呼び出される。

:create = `[メソッド]
label reciever method = &rest args &key (min 0.0) (max 1.0) parent (min-label “”) (max-label “”) (value-format “ 4,2f”) (font font-courb12) (span 100) (border-width 0) (initial-value min)

slider-itemを作成する。 スライドのノブは、バーの上に小さな黒の四角として表示される。 左端が:min値を表現し、右端が:max値を表現する。 バーの長さは、:spanドットに引き伸ばす。 現在の値は、:value-formatでslider-itemの右に表示する。

:value &optional newval invocation

もし、newvalが与えられたなら、現在の値として設定され、 ノブは対応する位置にスライドする。 もし、invocationもnon NILに指定されていたなら、 notify-objectのnotify-methodが呼び出される。 :valueは、現在の(新しい)値を返す。

joystick-item

:super = ** panel-item**
:slots (stick-size min-x min-y max-x max-y
center-x center-y stick-x stick-y
value-x value-y
stick-return stick-grabbed
fraction-x fraction-y)

joystick-itemは、2次元のslider-itemとしてみなすことができる。 2つの連続値はクモの巣のような同心円図の上を動く黒い円によって 指定することができる(図 [panelitem])。

:create = `[メソッド]
name reciever method = &rest args &key = (stick-size 5) return (min-x -1.0) (max-x 1.0) (min-y -1.0) (max-y 1.0) &allow-other-keys

:stick-sizeは、スティックの黒い円の半径である。 同心円図の円の大きさは、joystick-item windowの幅と高さ に合うように決定される。 もし、:returnがnon NILであるなら、 ジョイスティックは、マウスボタンが外された時の原点に帰る。 そうでないなら、ジョイスティックは、外された位置に残る。

:value &optional newx newy invocation

もし、newxnewyが与えられたなら、 現在の位置として設定され、ジョイスティックは同心円図の 対応する位置に移動する。 もし、invocationもnon NILに指定されたなら、 notify-objectのnotify-methodが、 joystick-itemオブジェクトとx,y値を引き数として一緒に呼び出される。 :valueは、現在の(新しい)値のリストを返す。

以下に上に記述されているpanel-itemを使った短いプログラムを示し、 図 [panelitem]がパネルの中にどのように表示されるかを示したものである。

(in-package "X")
(defclass testPanel :super panel
        :slots (quit joy choi sli))
(defmethod testPanel
 (:create (&rest args)
    (send-super* :create :width 210 :height 180
                 :font font-courb12 args)
    (send-super :create-item button-item "quit" self :quit :font font-courb14)
    (send-super :create-item choice-item "choice" self :choice
                :choices '(" A " " B " " C ")
                :font font-courb12)
    (send-super :create-item slider-item "slider" self :slider
                :span 90)
    (send-super :create-item joystick-item "joy" self :joy)
    self)
 (:choice (obj c) (format t "choice: ~S ~d~%" obj c))
 (:slider (obj val) (format t "slider: ~S ~s~%" obj val))
 (:joy (obj x y) (format t "joy: ~S ~s ~s~%" obj x y)) )
(instance testPanel :create)
(window-main-thread)
panelの中に作成されたpanel-item

panelの中に作成されたpanel-item

text-item

:super = ** panel-item**
:slots (textwin)

text-itemは、ファイル名のような短いテキストを表示したり入力したり するために使用する。 text-itemは、ラベル文字列とその右側に小さなテキストwindowを持っている。 テキストwindow内にポインタが置かれたとき、キー入力が可能となり、 入力された文字がバッファに入れられる。 テキストwindow内の行修正が可能である。 control-Fとcontrol-Bは前後に1文字動かし、 delはカーソルの左の1文字を削除し、 control-Dはカーソル位置の文字を削除し、 カーソル位置にはどんなグラフィック文字も挿入できる。 マウスボタンをクリックすれば、クリックされた文字にカーソルを 移動させる。 enter(改行)キーを打つことにより、バッファされたテキストが notify-objectのnotify-methodに送られる。

:create = `[メソッド]
label revciever method = &rest args &key (font font-courb12) (columns 20) initial-value (border-width 0) &allow-other-keys

text-itemを作成する。 テキストwindowの行バッファには、長さの制限が無いけれども、 見える部分はcolumns文字に制限されている。

:getstring **

キーバッファ内の文字列を返す。

キャンバス

canvas

:super = ** xwindow**
:slots (topleft bottomright)

canvasは、図や画像を入れるためのXwindowである。 現在、領域選択機能のみ実現されている。 ButtonPressイベントにより、canvasは押された位置を左上の端とし、 現在の位置を右下の端とする四角を描き始める。 ButtonReleaseにより、notify-objectのnotify-methodが 送られる。 canvas内に図や画像を描くためにはXdrawableのメソッドが使用される。

テキストwindow

TextWindowとBufferTextWidnowとScrollTextWindowの 3つのテキストwindowがある。

textWindow

:super = ** xwindow**
:slots (fontid
charwidth charheight charascent dots
win-row-max win-col-max
win-row win-col = ;physical current position in window
x y
charbuf ; for charcode conversion
keybuf keycount ;for key input
echo
show-cursor cursor-on ;boolean
kill delete ;control character
notify-object notify-method
)

メッセージを表示するために使用可能な仮想端末を実現する。 表示される内容は、バッファされないし、TextWindowに既に表示された 文字や行を引き出す方法はない。 基本的に、TextWindowは カーソル移動、行削除、領域削除、表示テキストのスクロール、文字列挿入 などを持つダンプ端末と似た能力を持っている。 また、テキストカーソルはマウスポインタで指示された位置に 移動することができる。

:init id

番目のテキストwindowを初期化する。

:create = `[メソッド]
&rest args &key = width height (font font-courb14) rows columns show-cursor notify-object notify-method &allow-other-keys

text-windowを作成する。 windowの大きさは、:width:heightかあるいは:rows:columnsで指定されたものとなる。 :notify-object:notify-methodは、改行文字が入力された ときに呼び出される。

:cursor flag

は、:on, :off, :toggleのどれかが可能である。 テキストカーソルは、win-rowとwin-colの位置である。 もし、flagが:onであれば、テキストカーソルは表示され、 flagが:offならば、消される。 また、flagがtoggleならば、反対になる。 このメソッドは、カーソルの位置の文字を更新するときはいつでも、 呼び出されなければならない。

:clear **

テキストwindow内を消去する。

:clear-eol &optional (r win-row) (c win-col) (csr :on)

cで指定される位置の文字以降の残りの行を 消去する。カーソル位置の文字も含む。

:clear-lines lines &optional (r win-row)

番目の行以降の複数行を消去する。

:clear-eos &optional (r win-row) (c win-col)

cで指定される位置から画面の最後までの領域を消去する。

:win-row-max **

このwindowに表示可能な最大行数を返す。

:win-col-max **

このwindowに表示可能な最大列数を返す。

:xy &optional (r win-row) (c win-col)

cで指定される位置の文字のピクセル座標を計算する。

:goto r c &optional (cursor :on)

番目の行のc番目の列にカーソルを移動する。

:goback &optional (csr :on)

カーソルを1文字戻す。

:advance &optional (n 1)

文字だけカーソルを進める。

:scroll &optional (n 1)

行だけ縦方向にテキストwindowをスクロールする。

:horizontal-scroll &optional (n 1)

列だけ横方向にテキストをスクロールする。

:newline **

次の行の最初にカーソルを移動する。

:putch ch

カーソル位置に文字chを挿入する。 行の残りは、1文字前方に進められる。

:putstring str &optional (e (length str))

カーソル位置にstrを置く。

:event-row event

:event-col event

における、テキストカーソルの位置をを返す。

:KeyPress event

カーソル位置に入力された文字を挿入する。 もし、文字が改行であったなら、notify-objectに通知する。

textWindowStream

:super = ** stream**
:slots (textwin)

TextWindowStreamは、TextWdinowに接続された出力ストリームである。 print, format, write-byteなどによってこのストリームに出力 される文字や文字列がTextWdindowに表示される。 通常のファイルストリームとしては、 出力データはバッファされる。

:flush **

バッファされたテキスト文字列を掃き出し、TextWindowに送る。 finish-outputやこのストリームへの改行文字の書き込みは、 このメソッドを自動的に呼び出す。

make-text-window-stream xwin

を作り、そのストリームオブジェクトを返す。

BufferTextWindow

:super = ** TextWindow**
:slots (linebuf expbuf max-line-length row col)

TextWindowの内容を表現する行バッファを保持する。 linebufは、行のベクトルである。exbufは、 タブ拡張されたテキストを持つ。 windowに表示可能な行のみが保持される。 BufferTextWindowは、数行のテキストを持つ 簡単なテキストエディタとして使用することができる。 text-itemは、表示可能な行バッファとしてBufferTextWindowを 使う。

:line n

番目の行の内容を文字列として返す。

:nlines **

の行数を返す。

:all-lines **

文字列のベクトルであるlinebufを返す。

:refresh-line &optional (r win-row) (c win-col)

番目の行のc番目の列以降を再書き込みする。

:refresh &optional (start 0)

番目の行以降の行を再書き込みする。

:insert-string string

カーソル位置にstringを挿入する。

:insert ch

カーソル位置に文字を挿入する。

:delete n

カーソル以降のn文字を削除する。

expand-tab src &optional (offset 0)

は、タブを含んだ可能性のある文字列である。 これらのタブは、タブの停止位置が8の倍数であると仮定して空白文字に 置き換えられる。

ScrollTextWindow

:super = ** BufferTextWindow**
:slots (top-row top-col = ;display-starting position
scroll-bar-window
horizontal-scroll-bar-window
selected-line)

ScrollTextWindowは、行数制限がなく、縦と横にスクロールバーを持った BufferTextWindowを定義する。 ScrollTextWindowは、スクロールバーを伴ってwindowの大きさを変更するため、 あるいはテキストを再表示するために:configureNotifyイベントを 扱うことができる。 クリックすることによって、行を選択することができる。

:create &rest args &key scroll-bar horizontal-scroll-bar &allow-other-keys

スクロールバーが必要なとき、それぞれのキーワードの引き数にTを指定する。

:locate n

windowの上部からn番目の行にバッファされたテキストを表示する。

:display-selection selection

は、選択された行の位置を表現する。 選択された行がすべて高輝度で表示される。

:selection **

選択された行(文字列)を返す。

:read-file fname

で指定されるテキストファイルをlinebufに読み込み、 タブを拡張し、windowに表示する。 カーソルは、画面の最初に置かれる。

:display-string strings

は、行(文字列)の列である。 stringsは、linebufにコピーされ、windowに表示される。

:scroll n

行、縦にスクロールする。

:horizontal-scroll n

列、横にスクロールする。

:buttonRelease event

マウスポインタが置かれている行が選択される。 もし、windowが作成されたときにnotificationが指定されている ならば、notify-objectのnotify-methodが呼び出される。

:resize w h

windowの大きさを変更し、新しいサイズに合うように 内容を再表示する。 もし、スクロールバーがあれば、同じメッセージが送られる。

ロボットモデリング

ロボットのデータ構造とモデリング

ロボットのデータ構造と順運動学

ロボットの構造はリンクと関節から構成されていると考えることが出来るが, ロボットを関節とリンクに分割する方法として

  • (a)切り離されるリンクの側に関節を含める
  • (b)胴体,あるいは胴体に近いほうに関節を含める

が考えられる.コンピュータのデータ構造を考慮し, (a)が利用されている.その理由は胴体以外のすべてのリンクにおいて, 必ず関節を一つ含んだ構造となり,すべてのリンクを同一のアルゴリズムで扱う ことが出きるためである.

この様に分割されたリンクを計算機上で表現するためにはツリー構造を利用する ことが出来る.一般的にはツリー構造を作るときに二分木にすることでデータ構 造を簡略化することが多い.

ロボットのリンクにおける同次変換行列の求め方としては,関節回転座標系上に 原点をもつ\(\Sigma_j\)を設定し,親リンク座標系からみた回転軸ベクトルが \(a_j\), \(\Sigma_j\)の原点が\(b_j\)であり,回転の関節角度を\(q_j\)とする.

このとき\(\Sigma_j\)の親リンク相対の同次変換行列は

\[ \begin{align}\begin{aligned}\begin{split} {}^iT_j = \left[ \begin{array}{cc} e^{\hat{a}_jq_j} & b_j \\ 0~0~0 & 1 \end{array} \right]\end{split}\\と書くことが出来る.\end{aligned}\end{align} \]

ここで,\(e^{\hat{a}_jq_j}\)は,一定速度の角速度ベクトルによって生ずる回 転行列を与える以下のRodriguesの式を用いている.これを回転軸\(a\)周りに \(wt[rad]\)だけ回転する回転行列を与えるものとして利用している.

\[e^{\hat{\omega}t} = E + \hat{a} sin (wt) + \hat{a}^2 (1 - cos(wt))\]

親リンクの位置姿勢\(p_i, R_i\)が既知だとすると,\(\Sigma_i\)の同次変換行列を

\[ \begin{align}\begin{aligned}\begin{split} T_i = \left[ \begin{array}{cc} R_i & p_i \\ 0~0~0 & 1 \end{array} \right]\end{split}\\と作ることができ,ここから\end{aligned}\end{align} \]
\[T_j = T_i ~ {}^iT_j\]

として計算できる.これをロボットのルートリンクから初めてすべてのリンクに 順次適用することでロボットの全身の関節角度情報から姿勢情報を算出すること ができ,これを順運動学と呼ぶ.

EusLispによる幾何情報のモデリング

Euslispの幾何モデリングでは,基本モデル(body)の生成,bodyの合成関数,複 合モデル(bodyset)の生成と3つの段階がある.

これまでに以下のような基本モデルの生成,合成が可能な事を見てきている.

(setq c1 (make-cube 100 100 100))
(send c1 :locate #f(0 0 50))
(send c1 :rotate (deg2rad 30) :x)
(send c1 :set-color :yellow)
(objects (list c1))

(setq c2 (make-cylinder 50 100))
(send c2 :move-to
      (make-coords
       :pos #f(20 30 40)
       :rpy (float-vector 0 0 (deg2rad 90)))
      :world)
(send c2 :set-color :green)
(objects (list c1 c2))

(setq c3 (body+ c1 c2))
(setq c4 (body- c1 c2))
(setq c5 (body* c1 c2))

bodysetはirteusで導入された複合モデルであり,bodyで扱えない複数の物体や 複数の色を扱うためのものである.

(setq c1 (make-cube 100 100 100))
(send c1 :set-color :red)
(setq c2 (make-cylinder 30 100))
(send c2 :set-color :green)
(send c1 :assoc c2)           ;;; これを忘れいように
(setq b1 (instance bodyset :init
                   (make-cascoords)
                   :bodies (list c1 c2)))
(objects (list b1))

幾何情報の親子関係を利用したサンプルプログラム

(setq c1 (make-cube 100 100 100))
(setq c2 (make-cube 50 50 50))
(send c1 :set-color :red)
(send c2 :set-color :blue)
(send c2 :locate #f(300 0 0))
(send c1 :assoc c2)
(objects (list c1 c2))
(do-until-key
 (send c1 :rotate (deg2rad 5) :z)
 (send *irtviewer* :draw-objects)
 (x::window-main-one) ;; process window event
 )

bodyset-linkとjointを用いたロボット(多リンク系)のモデリング

irteusではロボットリンクを記述するクラスとしてbodyset-link(irtmodel.l) というクラスが用意されている.これは機構情報と幾何情報をもち,一般的な木 構造でロボットの構造が表現されている.また,jointクラスを用いて関節情報 を扱っている.

(defclass bodyset-link
  :super bodyset
  :slots (joint parent-link child-links analysis-level default-coords
                weight acentroid inertia-tensor
                angular-velocity angular-acceleration
                spacial-velocity spacial-acceleration
                momentum-velocity angular-momentum-velocity
                momentum angular-momentum
                force moment ext-force ext-moment))

ジョイント(関節)のモデリングはjointクラス(irtmodel.l)を用いる.jointクラスは基底ク ラスであり,実際にはrotational-joint, linear-joint等を利用する. jointの子クラスで作られた関節は,:joint-angleメソッドで関節角度を指定す ることが出来る.

(defclass joint
  :super propertied-object
  :slots (parent-link child-link joint-angle min-angle max-angle
    default-coords))
(defmethod joint
  (:init (&key name
               ((:child-link clink)) ((:parent-link plink))
               (min -90) (max 90) &allow-other-keys)
         (send self :name name)
         (setq parent-link plink child-link clink
               min-angle min max-angle max)
         self))

(defclass rotational-joint
  :super joint
  :slots (axis))
(defmethod rotational-joint
  (:init (&rest args &key ((:axis ax) :z) &allow-other-keys)
         (setq axis ax joint-angle 0.0)
         (send-super* :init args)
         self)
  (:joint-angle
   (&optional v)
   (when v
        (setq relang (- v joint-angle) joint-angle v)
        (send child-link :rotate (deg2rad relang) axis)))
     joint-angle))

ここでは,joint, parent-link, child-links, defualt-coordsを利用する.

簡単な1関節ロボットの例としてサーボモジュールを作ってみると

(defun make-servo nil
  (let (b1 b2)
    (setq b1 (make-cube 35 20 46))
    (send b1 :locate #f(9.5 0 0))
    (setq b2 (make-cylinder 3 60))
    (send b2 :locate #f(0 0 -30))
    (setq b1 (body+ b1 b2))
    (send b1 :set-color :gray20)
    b1))

(defun make-hinji nil
  (let ((b2 (make-cube 22 16 58))
        (b1 (make-cube 26 20 54)))
    (send b2 :locate #f(-4 0 0))
    (setq b2 (body- b2 b1))
    (send b1 :set-color :gray80)
    b2))

(setq h1 (instance bodyset-link :init (make-cascoords) :bodies (list (make-hinji))))
(setq s1 (instance bodyset-link :init (make-cascoords) :bodies (list (make-servo))))
(setq j1 (instance rotational-joint :init :parent-link h1 :child-link s1 :axis :z))
;; instance cascaded coords
(setq r (instance cascaded-link :init))
(send r :assoc h1)
(send h1 :assoc s1)
(setq (r . links) (list h1 s1))
(setq (r . joint-list) (list j1))
(send r :init-ending)

となる.

ここでは,h1s1というbodyset-linkと, j1というrotational-jointを作成し,ここから cascaded-linkという,連結リンクからなるモデルを生成している. cascaded-linkcascaded-coordsの子クラスであるため, r (cascaded-link)h1s1の座標系の親子関係を :assocを利用して設定している.

(r . links)という記法はrというオブジェクトのスロット変数 (メンバ変数)であるlinksにアクセスしている.ここでは, linksおよびjoint-listに適切な値をセットし, (send r :init-ending)として必要な初期設定を行っている.

これでrという2つのリンクと1つの関節情報 を含んだ1つのオブジェクトを生成できる.これで例えば (objects (list h1 s1))ではなく, (objects (list r))としてロボットをビューワに表示できる. また,(send r :locate #f(100 0 0))などの利用も可能になっている.

cascaded-linkクラスのメソッドの利用例としては以下ある. :joint-list:linksといった関節リストやリンクリストへの アクセサに加え,関節角度ベクトルへのアクセスを提供する :angle-vectorメソッドが重要である.これを引数なしで呼び出せば現 在の関節角度が得られ,これに関節角度ベクトルを引数に与えて呼び出せば,その引 数が示す関節角度ベクトルをロボットモデルに反映させることができる.

$ (objects (list r))
(#<servo-model #X628abb0  0.0 0.0 0.0 / 0.0 0.0 0.0>)
;; useful cascaded-link methods
$ (send r :joint-list)
(#<rotational-joint #X6062990 :joint101067152>)
$ (send r :links)
(#<bodyset-link #X62ccb10 :bodyset103598864  0.0 0.0 0.0 / 0.0 0.0 0.0>
 #<bodyset-link #X6305830 :bodyset103831600  0.0 0.0 0.0 / 0.524 0.0 0.0>)
$ (send r :angle-vector)
#f(0.0)
$ (send r :angle-vector (float-vector 30))
#f(30.0)

EusLispにおける順運動学計算

順運動学計算を行うには,cascaded-corods, bodyset, bodyset-link 各クラ スに定義された :worldcoords メソッドを用いる. :worldcoords メソッドは,ルートリンクが見つかる(親リンクがなくなる) か, スロット変数 changed が nil であるリンク (一度順運動学計算を行ったことがある)が見つかるまで さかのぼって親リンクの :worldcoords メソッドを呼び出すことで 順運動学計算を行う. その際,スロット変数 changed を nil で上書く. したがって,二度目の :worldcoords メソッドの呼び出しでは,一度計算され たリンクの順運動学計算は行われず,即座にリンクの位置姿勢情報を取り出す ことができる.

また,bodyset-link クラスの :worldcoords メソッドは, level 引数を取る ことができ,それが :coords である場合には,リンクのもつ bodies スロット変数 の順運動学計算は行われない. bodies にリンクの頂点を構成する faceset が含まれている場合には,これら についての順運動学計算を省略することで大幅な高速化が期待できるだろう. なお, level 引数の初期値には,リンクのもつ analysis-level スロット変数 が用いられるため,常に bodies の順運動学計算を行わない場合は, リンクのインスタンス l について (send l :analysis-level :coords) とすればよい.

(defmethod bodyset-link
  (:worldcoords
   (&optional (level analysis-level))
   (case
    level
    (:coords (send-message self cascaded-coords :worldcoords))
    (t       (send-super :worldcoords)))
   ))

(defmethod bodyset
  (:worldcoords
   ()
   (when changed
     (send-super :worldcoords)
     (dolist (b bodies) (send b :worldcoords)))
   worldcoords))

(defmethod cascaded-coords
 (:worldcoords  ()      ;calculate rot and pos in the world
   (when changed
      (if parent
          (transform-coords (send parent :worldcoords) self
worldcoords)
          (send worldcoords :replace-coords self))
      (send self :update)
      (setf changed nil))
   worldcoords))

ロボットの動作生成

逆運動学

逆運動学においては, エンドエフェクタの位置・姿勢\(^0_n\bm{H}\)から マニピュレータの関節角度ベクトル \(\bm{\theta}=(\theta_1, \theta_2, ..., \theta_n)^T\) を求める.

ここで, エンドエフェクタの位置・姿勢\(\bm{r}\) は関節角度ベクトルを用いて

\[ \begin{align}\begin{aligned} \begin{aligned} \bm{r} = \bm{f}(\bm{\theta}) \eqlabel{forward-kinematics-functional}\end{aligned}\\とかける. は のように記述し,関節角度ベクトルを求める.\end{aligned}\end{align} \]
\[\begin{aligned} \bm{\theta} = \bm{f}^{-1}(\bm{r}) \eqlabel{inverse-kinematics-func}\end{aligned}\]

における\(f^{-1}\)は一般に非線形な関数となる. そこでを時刻tに関して微分することで, 線形な式

\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} \dot{\bm{r}} &=& \frac{\partial \bm{f}}{\partial \bm{\theta}} (\bm{\theta})\dot{\bm{\theta}} \\ &=& \bm{J}(\bm{\theta})\dot{\bm{\theta}} \eqlabel{inverse-kinematics-base}\end{aligned}\end{split}\\を得る. ここで,\end{aligned}\end{align} \]

\(\bm{J}(\bm{\theta})\)\(m \times n\)のヤコビ行列である. \(m\)はベクトル\(\bm{r}\)の次元, \(n\)はベクトル\(\bm{\theta}\)の次元である. \(\bm{\dot{r}}\)は速度・角速度ベクトルである.

ヤコビ行列が正則であるとき逆行列\(\bm{J}(\bm{\theta})^{-1}\)を用いて 以下のようにしてこの線型方程式の解を得ることができる.

\[\begin{aligned} \dot{\bm{\theta}} = \bm{J}(\bm{\theta})^{-1}\dot{\bm{r}} \eqlabel{inverse-kinematics}\end{aligned}\]

しかし, 一般にヤコビ行列は正則でないので, ヤコビ行列の疑似逆行列\(\bm{J}^{\#}(\bm{\theta})\) が用いられる().

\[\begin{split}\begin{aligned} \bm{A}^{\#} = \left\{ \begin{array}{l l} & \bm{A}^{-1} \ ( m = n = rank \bm{A}) \\ & \bm{A}^T \ (\bm{A}\bm{A}^T)^{-1} ( n > m = rank \bm{A}) \\ & (\bm{A}^T\bm{A})^{-1}\bm{A}^T \ ( m > n = rank \bm{A}) \end{array} \right. \eqlabel{psuedo-inverse-matrix}\end{aligned}\end{split}\]

は, \(m>n\)のときはを, \(n>=m\)のときはを, 最小化する最小二乗解を求める問題と捉え,解を得る.

\[\begin{aligned} \min_{\dot{\bm{\theta}}} \left(\dot{\bm{r}} - \bm{J}(\bm{\theta})\dot{\bm{\theta}}\right)^{T} \left(\dot{\bm{r}} - \bm{J}(\bm{\theta})\dot{\bm{\theta}}\right) \eqlabel{inverse-kinematics-error-func}\end{aligned}\]
\[\begin{split}\begin{aligned} \min_{\dot{\bm{\theta}}} & \dot{\bm{\theta}}^{T}\dot{\bm{\theta}}\\ \nonumber s.t. & \dot{\bm{r}} = \bm{J}(\bm{\theta})\dot{\bm{\theta}} \eqlabel{inverse-kinematics-min-func}\end{aligned}\end{split}\]

関節角速度は次のように求まる.

\[\begin{aligned} \dot{\bm{\theta}} = \bm{J}^{\#}(\bm{\theta})\dot{\bm{r}} + \left(\bm{E}_n - \bm{J}^{\#}(\bm{\theta})\bm{J}(\bm{\theta})\right)\bm{z} \eqlabel{inverse-kinematics-lagrangian-formula}\end{aligned}\]

しかしながら, に従って解を 求めると, ヤコビ行列\(\bm{J}(\bm{\theta})\)がフルランクでなくなる特異点に近づく と, \(\left|\dot{\bm{\theta}}\right|\)が大きくなり不安定な振舞いが生じる. そこで, Nakamura et al.のSR-Inverse [1] を用いること で, この特異点を回避する.

本研究では ヤコビ行列の疑似逆行列\(\bm{J}^{\#}(\bm{\theta})\)の代わりに, に示す\(\bm{J}^{*}(\bm{\theta})\) を用いる.

\[\begin{aligned} \bm{J}^{*}(\bm{\theta}) = \bm{J}^T\left(\bm{J}\bm{J}^T + \epsilon \bm{E}_m\right)^{-1} \eqlabel{SR-inverse-jacobian}\end{aligned}\]

これは, の代わりに, を最小化する最適化問題を 解くことにより得られたものである.

\[\begin{aligned} \min_{\dot{\bm{\theta}}} \{ \dot{\bm{\theta}}^T \dot{\bm{\theta}} + \epsilon \left(\dot{\bm{r}} - \bm{J}(\bm{\theta})\dot{\bm{\theta}}\right)^T \left(\dot{\bm{r}} - \bm{J}(\bm{\theta})\dot{\bm{\theta}}\right) \} \eqlabel{SR-inverse-error-func}\end{aligned}\]

ヤコビ行列\(\bm{J}(\bm{\theta})\)が特異点に近づいているかの指標には 可操作度\(\kappa(\bm{\theta})\) [2] が用いられる().

\[\begin{aligned} \kappa(\bm{\theta}) = \sqrt{\bm{J}(\bm{\theta}) \bm{J}^{T}(\bm{\theta})} \eqlabel{manipulability}\end{aligned}\]

微分運動学方程式における タスク空間次元の選択行列 [3] は見通しの良い定式化のために省略するが, 以降で導出する全ての式において 適用可能であることをあらかじめことわっておく.

基礎ヤコビ行列

一次元対偶を関節に持つマニピュレータのヤコビアンは 基礎ヤコビ行列 [4] により 計算することが可能である. 基礎ヤコビ行列の第\(j\)関節に対応するヤコビアンの列ベクトル\(\bm{J}_j\)

\[\begin{split}\bm{J}_j= \begin{cases} \left[ \begin{array}{ccc} \bm{a}_j\\ \bm{0} \end{array} \right] & \text{if linear joint} \\ \left[ \begin{array}{ccc} \bm{a}_j \times (\bm{p}_{end} - \bm{p}_j)\\ \bm{a}_j \end{array} \right] & \text{if rotational joint} \end{cases}\end{split}\]

と表される. \(\bm{a}_j\)\(\bm{p}_j\)はそれぞれ第\(j\)関節の関節軸単位ベクトル・位置ベクトルであり, \(\bm{p}_{end}\)はヤコビアンで運動を制御するエンドエフェクタの位置ベクトルである. 上記では1自由度対偶の 回転関節・直動関節について導出したが, その他の関節でもこれらの列ベクトルを 連結した行列としてヤコビアンを定義可能である. 非全方位台車の運動を表す2自由度関節は 前後退の直動関節と 旋回のための回転関節から構成できる. 全方位台車の運動を表す3自由度関節は 並進2自由度の直動関節と 旋回のための回転関節から構成できる. 球関節は姿勢を姿勢行列で, 姿勢変化を等価角軸変換によるものとすると, 3つの回転関節をつなぎ合わせたものとみなせる.

関節角度限界回避を含む逆運動学

ロボットマニピュレータの軌道生成において, 関節角度限界を考慮することはロボットによる実機実験の際に重要となる. 本節では,文献 [5] [6] の式および文章を引用しつつ, 関節角度限界の回避を 含む逆運動学について説明する.

重み付きノルムを以下のように定義する.

\[\begin{aligned} \left|\bm{\dot{\theta}}\right|_{\bm{W}} = \sqrt{\bm{\dot{\theta}}^T\bm{W}\bm{\dot{\theta}}} \eqlabel{weighted-norm}\end{aligned}\]

ここで, \(\bm{W}\)\(\bm{W} \in \bm{R}^{n \times n}\)であり, 対象で全ての要 素が正である重み係数行列である. この\(\bm{W}\)を用いて, \(\bm{J}_{\bm{W}}, \bm{\dot{\theta}}_{\bm{W}}\)を以下のよう に定義する.

\[\begin{aligned} \bm{J}_{\bm{W}} = \bm{J}\bm{W}^{-\frac{1}{2}}, \bm{\dot{\theta}}_{\bm{W}} = \bm{W}^{\frac{1}{2}}\bm{\dot{\theta}}\end{aligned}\]

この\(\bm{J}_{\bm{W}}, \bm{\dot{\theta}}_{\bm{W}}\)を用いて, 以下の式を得 る.

\[\begin{split}\begin{aligned} \dot{\bm{r}} & = & \bm{J}_{\bm{W}}\bm{\dot{\theta}}_{\bm{W}} \\ \left|\dot{\bm{\theta}}\right|_{\bm{W}} & = & \sqrt{\bm{\dot{\theta}}_{\bm{W}}^T\bm{\dot{\theta}}_{\bm{W}}}\end{aligned}\end{split}\]

これによって線型方程式の解はから 以下のように記述できる.

\[\begin{aligned} \bm{\dot{\theta}}_{\bm{W}} = \bm{W}^{-1}\bm{J}^T \left(\bm{J}\bm{W}^{-1}\bm{J}^T\right)^{-1}\dot{\bm{r}}\end{aligned}\]

また、現在の関節角度\(\theta\)が関節角度限界\(\theta_{i,\max}, \theta_{i, \min}\)に対してどの程度余裕があるかを評価する ための関数\(H(\bm{\theta})\)は以下のようになる [7]).

\[\begin{aligned} H(\bm{\theta}) = \sum_{i = 1}^n\frac{1}{4} \frac{(\theta_{i,\max} - \theta_{i,\min})^2} {(\theta_{i,\max} - \theta_i)(\theta_i - \theta_{i,\min})} \eqlabel{joint-performance-func}\end{aligned}\]

次にに示すような\(n \times n\)の重み係数行列 \(\bm{W}\)を考える.

\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} \bm{W} = \left[ \begin{array}{ccccc} w_1 & 0 & 0 & \cdots & 0 \\ 0 & w_2 & 0 & \cdots & 0 \\ \cdots & \cdots & \cdots & \ddots & \cdots \\ 0 & 0 & 0 & \cdots & w_n \\ \end{array} \right] \eqlabel{joint-weight-matrix}\end{aligned}\end{split}\\ここで\ :math:`w_i`\ は\end{aligned}\end{align} \]
\[ \begin{align}\begin{aligned} \begin{aligned} w_i = 1 + \left|\frac{\partial \bm{H}(\bm{\theta})}{\partial \theta_i}\right|\end{aligned}\\である.\end{aligned}\end{align} \]

さらにから次の式を得る.

\[\begin{aligned} \frac{\partial H(\bm{\theta})}{\partial \theta_i} = \frac{(\theta_{i,\max} - \theta_{i,\min})^2(2\theta_i - \theta_{i,\max} - \theta_{i,\min})} {4(\theta_{i,\max} - \theta_i)^2(\theta_i - \theta_{i,\min})^2}\end{aligned}\]

関節角度限界から遠ざかる向きに関節角度が動いている場合には重み係数行列を 変化させる必要はないので,\(w_i\)を以下のように定義しなおす.

\[\begin{split}\begin{aligned} w_i = \left\{ \begin{array}{l l} 1 + \left|\frac{\partial \bm{H}(\bm{\theta})}{\partial \theta_i}\right| & if \;\Delta\left|\frac{\partial \bm{H}(\bm{\theta})}{\partial \theta_i}\right| \geq 0 \\ 1 & if \;\Delta\left|\frac{\partial \bm{H}(\bm{\theta})}{\partial \theta_i}\right| < 0 \end{array} \right.\end{aligned}\end{split}\]

この\(w_i\)および\(\bm{W}\)を用いることで関節角度限界回避を含む逆運動学を解くこ とができる.

衝突回避を含む逆運動学

ロボットの動作中での自己衝突や環境モデルとの衝突は 幾何形状モデルが存在すれば計算することが可能である. ここではSugiura et al. により提案されている効率的な衝突回避計算 [8] [9] を応用した動作生成法を示す. 実際の実装はSugiura et al. の手法に加え, タスク作業空間のNullSpaceの利用を係数により制御できるようにした点や 擬似逆行列ではなくSR-Inverseを用いて特異点に ロバストにしている点などが追加されている.

衝突回避のための関節角速度計算法

逆運動学計算における目標タスクと衝突回避の統合は リンク間最短距離を用いたblending係数により行われる. これにより,衝突回避の必要のないときは目標タスクを厳密に満し 衝突回避の必要性があらわれたときに目標タスクを あきらめて衝突回避の行われる関節角速度計算を行うことが可能になる. 最終的な関節角速度の関係式はで得られる. 以下では\(ca\)の添字は衝突回避計算のための成分を表し, \(task\)の部分は衝突回避計算以外のタスク目標を表すことにする.

\[\labeq{collision-avoidance-all} \bm{\dot{\theta}} = f(d)\bm{\dot{\theta}}_{ca} + \left(1-f(d)\right)\bm{\dot{\theta}}_{task}\]

blending係数\(f(d)\)は, リンク間距離\(d\)と閾値\(d_a\)\(d_b\)の関数として計算される ().

\[\begin{split}\begin{aligned} \labeq{collision-avoidance-blending-coefficient} f(d) = \left\{ \begin{array}{l l} (d-d_a)/(d_b-d_a) & if d<d_a\\ 0 & otherwise \end{array} \right.\end{aligned}\end{split}\]

\(d_a\)は衝突回避計算を行い始める値 (yellow zone)であり, \(d_b\)は目標タスクを阻害しても衝突回避を行う閾値 (orange zone)である.

衝突計算をする2リンク間の最短距離・最近傍点が計算できた場合の 衝突を回避するための動作戦略は 2リンク間に作用する仮想的な反力ポテンシャルから導出される.

2リンク間の最近傍点同士をつなぐベクトル\(\bm{p}\)を用いた 2リンク間反力から導出される速度計算を に記す.

\[\begin{split}\begin{aligned} \labeq{collision-avoidance-distance-force} \bm{\delta x} = \left\{ \begin{array}{l l} 0 & if \left|\bm{p}\right|>d_{a}\\ (d_{a}/\left|\bm{p}\right|-1)\bm{p} & else \end{array} \right.\end{aligned}\end{split}\]

これを用いた関節角速度計算は となる.

\[\labeq{collision-avoidance-joint-speed} \dot{\bm{\theta}}_{ca} = \bm{J}_{ca}^{T} k_{joint} \bm{\delta x} + (\bm{E}_n - \bm{J}_{task}^{*}\bm{J}_{task}) \bm{J}_{ca}^{T} k_{null} \bm{\delta x}\]

\(k_{joint}\)\(k_{null}\)はそれぞれ反力ポテンシャルを 目標タスクのNullSpaceに分配するかそうでないかを制御する係数である.

衝突回避計算例

以下ではロボットモデル・環境モデルを用いた衝突回避例を示す. 本研究では, ロボットのリンク同士,またはリンクと物体の衝突判定には,衝突判定ライブラリ PQP(A Proximity Query Package) [10]_を用いた.

では \(d_a = 200[mm]\),\(d_b = 0.1 * d_a = 20[mm]\), \(k_{joint} = k_{null} = 1.0\)と設定した.

この衝突判定計算では,衝突判定をリンクの設定を

  1. リンクのリスト\(n_{ca}\)を登録
  2. 登録されたリンクのリストから全リンクのペア\(_{n_{ca}}C_2\)を計算
  3. 隣接するリンクのペア,常に交わりを持つリンクのペアなどを除外

のように行うという工夫を行っている.

例では衝突判定をするリンクを 「前腕リンク」「上腕リンク」「体幹リンク」「ベースリンク」 の4つとして登録した. この場合, \(_4C_2\)通りのリンクのペア数から 隣接するリンクが除外され,全リンクペアは 「前腕リンク-体幹リンク」 「前腕リンク-ベースリンク」 「上腕リンク-ベースリンク」 の3通りとなる.

の3本の線(赤1本,緑2本)が 衝突形状モデル間での最近傍点同士をつないだ 最短距離ベクトルである. 全リンクペアのうち赤い線が最も距離が近いペアであり, このリンクペアより衝突回避のための 逆運動学計算を行っている.

Example of Collision Avoidance

Example of Collision Avoidance

非ブロック対角ヤコビアンによる全身協調動作生成

ヒューマノイドは枝分かれのある複雑な構造を持ち, 複数のマニピュレータで協調して動作を行う必要がある ().

Duplicate Link Sequence Duplicate Link Sequence

複数マニピュレータの動作例として,

  • リンク間に重複がない場合
    それぞれのマニピュレータについて 式を用いて関節角速度を求める. もしくは,複数の式を連立した方程式(ヤコビアンはブロック対角行列となる) を用いて関節角速度を求めても良い.
  • リンク間に重複がある場合
    リンク間に重複がある場合は, リンク間の重複を考慮したヤコビアンを考える必要がある. 例えば,双腕動作を行う場合,左腕のマニピュレータのリンク系列と 右腕のマニピュレータのリンク系列とで,体幹部リンク系列が重複し, その部位は左右で協調して関節角速度を求める必要がある.

次節ではリンク間に重複がある場合の 非ブロック対角なヤコビアンの計算法 および それを用いた関節角速度計算法を述べる (前者の重複がない場合も以下の計算方法により後者の一部として計算可能で ある).

リンク間重複があるヤコビアン計算と関節角度計算

微分運動学方程式を求める際の条件を以下に示す.

  • マニピュレータの本数 \(L\)

  • 全関節数 \(N\)

  • マニピュレータの先端速度・角速度ベクトル \([\bm{\xi}_0^T,...,\bm{\xi}_{L-1}^T]^T\)

  • 各関節角速度ベクトル \([\bm{\dot{\theta}_0}^T,...,\bm{\dot{\theta}_{L-1}}^T]^T\)

  • 関節の添字和集合 \(S = \{0,\hdots,N-1\}\)
    ただし,マニピュレータ\(i\)の添字集合\(S_i\)を用いて\(S\)\(S = S_0 \cup \hdots \cup S_{L-1}\)と表せる.
  • \(S\)に基づく関節速度ベクトル \([\dot{\theta}_0, ..., \dot{\theta}_{N-1}]^T\)

とする.

運動学関係式はのようになる.

\[\begin{split}\begin{aligned} \left[ \begin{array}{c} \bm{\xi}_0 \\ \vdots\\ \bm{\xi}_{L-1} \end{array} \right] = \left[ \begin{array}{ccc} \bm{J}_{0,0} & \hdots & \bm{J}_{0, N-1}\\ \vdots & \bm{J}_{i,j} & \vdots\\ \bm{J}_{L-1,0} & \hdots & \bm{J}_{L-1, N-1} \end{array} \right] \left[ \begin{array}{c} \dot{\theta}_0\\ \vdots\\ \dot{\theta}_{N-1} \end{array} \right] \labeq{multi-manipulator-jacobi-eq}\end{aligned}\end{split}\]

小行列\(\bm{J}_{i,j}\)は以下のように求まる.

_i,j= _j & if \(j\)-th joint \(\in\) \(i\)-th link array
& otherwise

ここで,\(\bm{J}_j\)はのもの.

を単一のマニピュレータの 逆運動学解法と同様にSR-Inverseを用いて関節角速度を 求めることができる.

ここでの非ブロック対角ヤコビアンの計算法は, アーム・多指ハンドの動作生成
[11]_に おいて登場する運動学関係式から求まるヤコビアンを

導出することが可能である.

ベースリンク仮想ジョイントを用いた全身逆運動学法

一般に関節数が\(N\)であるのロボットの運動を表現するためには ベースリンクの位置姿勢と関節角自由度を合わせた\(N+6\)個の変数が必要であ る. ベースリンクとなる位置姿勢の変数を用いたロボットの運動の定式化は 宇宙ロボット [12]_だけでなく, 環境に固定されないヒューマノイドロボット

[13]_の場合にも重要である.

ここでは 腕・脚といったマニピュレータに ベースリンクに3自由度の直動関節と 3自由度の回転関節が仮想的に付随したマニピュレータ構成を考える (). 上記の仮想的な6自由度関節を 本研究ではベースリンク仮想ジョイントと名づける. ベースリンク仮想ジョイントを用いることにより ヒューマノイドの腰が動き全身関節が駆動され, 運動学,ひいては動力学的な解空間が拡充されることが期待できる.

|Concept of the Virtual Joint of the Base Link (Left figure) Overview of the Robot Model (Right figure) Skeleton Figure of Robot Model with the Virtual Joint | |Concept of the Virtual Joint of the Base Link (Left figure) Overview of the Robot Model (Right figure) Skeleton Figure of Robot Model with the Virtual Joint |

ベースリンク仮想ジョイントヤコビアン

ベースリンク仮想ジョイントのヤコビアンは 基礎ヤコビ行列の計算() を利用し, 絶対座標系\(x\)\(y\)\(z\)軸の直動関節と 絶対座標系\(x\)\(y\)\(z\)軸回りの回転関節を それぞれ連結した\(6\times6\)行列である. ちなみに,並進・回転成分のルートリンク仮想ジョイントのヤコビアンは 以下のように書き下すこともできる.

\[\begin{split}\begin{aligned} \labeq{virtual-joint-jacobian} \bm{J}_{B,l} = \left[ \begin{array}{cc} \bm{E}_3 & -\hat{\bm{p}}_{B\to l}\\ \bm{0} & \bm{E}_3 \end{array} \right]\end{aligned}\end{split}\]

\(\bm{p}_{B\to l}\)はベースリンク位置から添字\(l\)で表現する位置までの 差分ベクトルである.

マスプロパティ計算

複数の質量・重心・慣性行列を統合し 単一の質量・重心・慣性行列の組 \([m_{new}, \bm{c}_{new}, \bm{I}_{new}]\) を計算する演算関数を次のように定義する.

\[ \begin{align}\begin{aligned} [m_{new}, \bm{c}_{new}, \bm{I}_{new}] = AddMassProperty( [m_{1}, \bm{c}_{1}, \bm{I}_{1}] ,\hdots, [m_{K}, \bm{c}_{K}, \bm{I}_{K}] )\\これは次のような演算である.\end{aligned}\end{align} \]
\[m_{new} = \sum_{j=1}^{K}m_{j}\]
\[\bm{c}_{new} = \frac{1}{m_{new}}\sum_{j=1}^{K} m_j \bm{c}_j\]
\[ \begin{align}\begin{aligned} \bm{I}_{new} = \sum_{j=1}^{K} \left( \bm{I}_j + m_j \bm{D}(\bm{c}_{j} - \bm{c}_{new}) \right)\\ここで,\ :math:`\bm{D}(\bm{r})=\hat{\bm{r}}^T\hat{\bm{r}}`\ とする.\end{aligned}\end{align} \]

運動量・角運動量ヤコビアン

シリアルリンクマニピュレータを対象とし, 運動量・角運動量ヤコビアンを導出する. 運動量・原点まわりの角運動量を各関節変数で表現し, その偏微分でヤコビアンの行を計算する.

\(j\)関節の運動変数を\(\theta_j\)とする. まず,回転・並進の1自由度関節を考える.

_j =

cl _j _j (_j - _j) _j &
_j _j _j &

_j =

cl _j _j + _j _j _j &
&

ここで, \([\tilde{m}_j, \tilde{\bm{c}}_j, \tilde{\bm{I}}_j]\)は AddMassProperty関数に第\(j\)関節の子リンクより 末端側のリンクのマスプロパティを与えたものであり, 実際には再帰計算により計算する [14]. これらを\(\dot{\theta}_j\)で割ることにより ヤコビアンの各列ベクトルを得る.

_j =

cl _j (_j - _j) _j &
_j _j &

_j =

cl _j _j + _j _j &
&

これより慣性行列は次のように計算できる.

\[\bm{M}_{\dot{\bm{\theta}}} = [\bm{m}_1, \hdots, \bm{m}_{N}]\]
\[ \begin{align}\begin{aligned} \bm{H}_{\dot{\bm{\theta}}} = [\bm{h}_1, \hdots, \bm{h}_{N}] - \hat{\bm{p}}_{G} \bm{M}_{\dot{\bm{\theta}}}\\ここでは,全関節数を\ :math:`N`\ とした. また,ベースリンクは\end{aligned}\end{align} \]

直動関節\(x\)\(y\)\(z\)軸, 回転関節\(x\)\(y\)\(z\)軸を もつと考え整理し,次のようになる.

\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} \left[ \begin{array}{c} \bm{M}_{B}\\ \bm{H}_{B} \end{array} \right] = \left[ \begin{array}{cc} M_{r} \bm{E}_3 & - M_{r} \hat{\bm{p}}_{B\to G}\\ \bm{0} & \tilde{\bm{I}} \end{array} \right]\end{aligned}\end{split}\\これを用いて重心まわりの角運動量・運動量は次のようになる.\end{aligned}\end{align} \]
\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} \left[ \begin{array}{c} \bm{P}\\ \bm{L} \end{array} \right] = \left[ \begin{array}{cc} \bm{M}_{B} & \bm{M}_{\dot{\bm{\theta}}}\\ \bm{H}_{B} & \bm{H}_{\dot{\bm{\theta}}} \end{array} \right] \left[ \begin{array}{c} \bm{\xi}_{B}\\ \dot{\bm{\theta}} \end{array} \right]\end{aligned}\end{split}\\ここで ヒューマノイドの全質量\ :math:`M_{r}`\ ,\end{aligned}\end{align} \]

重心位置\(\bm{p}_{G}\), 慣性テンソル\(\tilde{\bm{I}}\)は次のように 全リンクのマスプロパティ演算より求める.

\[[M_{r}, \bm{p}_{G}, \tilde{\bm{I}}] = AddMassProperty( [m_{1}, \bm{c}_{1}, \bm{I}_{1}] ,\hdots, [m_{N}, \bm{c}_{N}, \bm{I}_{N}] )\]

重心ヤコビアン

重心ヤコビアンは 重心速度と関節角速度の間のヤコビアンである. 本論文ではベースリンク仮想ジョイントを用いるため, ベースリンクに6自由度関節がついたと考え ベースリンク速度角速度・関節角速度の 重心速度に対するヤコビアンを重心ヤコビアンとして用いる. 具体的には, ベースリンク成分\(\bm{M}_{B}\)と 使用関節について抜き出した成分\(\bm{M}_{\dot{\bm{\theta}}}^{\prime}\) による運動量ヤコビアンを 全質量で割ることで重心ヤコビアンを計算する.

\[\bm{J}_{G} = \frac{1}{M_{r}} \left[ \begin{array}{cc} \bm{M}_{B} & \bm{M}_{\dot{\bm{\theta}}}^{\prime} \end{array} \right]\]

ロボットの動作生成プログラミング

三軸関節ロボットを使ったヤコビアン,逆運動学の例

3軸関節をもつロボットを定義し, 逆運動学やヤコビアンの計算例を紹介する.

ロボットの定義は以下の用になる.

(defclass 3dof-robot
  :super cascaded-link
  :slots (end-coords l1 l2 l3 l4 j1 j2 j3))
(defmethod 3dof-robot
  (:init ()
   (let (b)
     (send-super :init)

     (setq b (make-cube 10 10 20))
     (send b :locate #f(0 0 10))
     (send b :set-color :red)
     (setq l4 (instance bodyset-link :init (make-cascoords) :bodies (list b) :name 'l4))
     (setq end-coords (make-cascoords :pos #f(0 0 20)))
     (send l4 :assoc end-coords)
     (send l4 :locate #f(0 0 100))
     ;;
     (setq b (make-cube 10 10 100))
     (send b :locate #f(0 0 50))
     (send b :set-color :green)
     (setq l3 (instance bodyset-link :init (make-cascoords) :bodies (list b) :name 'l3))
     (send l3 :assoc l4)
     (send l3 :locate #f(0 0 100))
     ;;
     (setq b (make-cube 10 10 100))
     (send b :locate #f(0 0 50))
     (send b :set-color :blue)
     (setq l2 (instance bodyset-link :init (make-cascoords) :bodies (list b) :name 'l2))
     (send l2 :assoc l3)
     (send l2 :locate #f(0 0 20))
     ;;
     (setq b (body+ (make-cube 10 10 20 :pos #f(0 0 10)) (make-cube 300 300 2)))
     (send b :set-color :white)
     (setq l1 (instance bodyset-link :init (make-cascoords) :bodies (list b) :name 'l1))
     (send l1 :assoc l2)
     ;;
     (setq j1 (instance rotational-joint :init :name 'j1
                 :parent-link l1 :child-link l2 :axis :y :min -100 :max 100)
           j2 (instance rotational-joint :init  :name 'j2
                 :parent-link l2 :child-link l3 :axis :y :min -100 :max 100)
           j3 (instance rotational-joint :init  :name 'j3
                 :parent-link l3 :child-link l4 :axis :y :min -100 :max 100))
     ;;
     (setq links (list l1 l2 l3 l4))
     (setq joint-list (list j1 j2 j3))
     ;;
     (send self :init-ending)
     self))
  (:end-coords (&rest args) (forward-message-to end-coords args))
  )

ここではロボットの手先の座標をend-coordsというスロット変数に格 納し,さらにこれにアクセスするためのメソッドを用意してある.

これまでと同様,

(setq r (instance 3dof-robot :init))
(objects (list r))
(send r :angle-vector #f(30 30 30))

としてロボットモデルの生成,表示,関節角度の指定が可能である. さらに,

(send (send r :end-coords) :draw-on :flush t)

とすると,ロボットのend-coords(端点座標系)の表示が可能であるが, マウスイベントが発生すると消えてしまう.恒久的に表示するためには

(objects (list r (send r :end-coords)))

とするとよい.

次に,ヤコビアン,逆運動学の例を示す.まず基本になるのが,

(send r :link-list (send r :end-coords :parent))

として得られるリンクのリストである.これはロボットのルート(胴体)から 引数となるリンクまでのたどれるリンクを返す.

:calc-jacobian-from-link-listメソッドはリンクのリストを引数にと り,この各リンクに存在するジョイント(関節)に 対応するヤコビアンを計算することができる. また,:move-targetキーワード引数でエンドエフェクタの座標系を 指定してる.その他のキーワード引数については後述する.

(dotimes (i 100)
  (setq j (send r :calc-jacobian-from-link-list
                (send r :link-list (send r :end-coords :parent))
                :move-target (send r :end-coords)
                :rotation-axis t
                :translation-axis t))
  (setq j# (sr-inverse j))
  (setq da (transform j# #f(1 0 0 0 0 0)))
  ;;(setq da (transform j# #f(0 0 0 0 -1 0)))
  (send r :angle-vector (v+ (send r :angle-vector) da))
  (send *irtviewer* :draw-objects)
  )

ここではリンクの長さ(ジョイントの数)は3個なので6行3列のヤコビアン(j)が 計算される.これの逆行列(j#)を作り,位置姿勢の6自由度の目標速度・角速度 (#f(1 0 0 0 0 0))を与えると,それに対応する関節速度(da) が計算でき,これを現在の関節角度に足している ((v+ (send r :angle-vector) da)).

次に,ロボットの端点作業の位置は合わせるが姿勢は拘束せず任意のままでよい,とい う場合の例を示す.ここでは,:calc-jacobian-from-link-listのオプ ショナル引数として:rotation-axis, :translation-axis があり,それぞれ位置,姿勢での拘束条件を示す. tは三軸拘束,nilは拘束なし,その他に:x, :y, :zを指定することができる.

(setq translation-axis t)
(setq rotation-axis nil)
(dotimes (i 2000)
  (setq j (send r :calc-jacobian-from-link-list
                (send r :link-list (send r :end-coords :parent))
                :move-target (send r :end-coords)
                :rotation-axis rotation-axis
                :translation-axis translation-axis))
  (setq j# (sr-inverse j))
  (setq c (make-cascoords :pos (float-vector (* 100 (sin (/ i 500.0))) 0 200)))
  (setq dif-pos (send (send r :end-coords) :difference-position c))
  (setq da (transform j# dif-pos))
  (send r :angle-vector (v+ (send r :angle-vector) da))
  (send *irtviewer* :draw-objects :flush nil)
  (send c :draw-on :flush t)
  )

ここでは位置の三軸のみを拘束した3行3列のヤコビアンを計算し,これの 逆行列からロボットの関節に速度を与えている.さらに,ここでは

(send *irtviewer* :draw-objects :flush nil)

として*irtviewer*に画面を描画しているが,実際に ディスプレイに表示するフラッシュ処理は行わず,その次の行の

(send c :draw-on :flush t)

で目標座標は表示し,かつフラッシュ処理を行っている.

上記の計算をまとめた逆運動学メソッドが:inverse-kinematicsである. 第一引数に目標座標系を指定し,ヤコビアン計算のときと同様にキーワード 引数で :move-target, :translation-axis, :rotation-axis を指定する. また,:debug-viewキーワード引数にtを与えると計算中の様 子をテキスト並びに視覚的に提示してくれる.

(setq c (make-cascoords :pos #f(100 0 0) :rpy (float-vector 0 pi 0)))
(send r :inverse-kinematics  c
      :link-list (send r :link-list (send r :end-coords :parent))
      :move-target (send r :end-coords)
      :translation-axis t
      :rotation-axis t
      :debug-view t)

逆運運動学が失敗する場合のサンプルとして以下のプログラムを見てみよう.

(dotimes (i 400)
  (setq c (make-cascoords
             :pos (float-vector (+ 100 (* 80 (sin (/ i 100.0)))) 0 0)
             :rpy (float-vector 0 pi 0)))
  (send r :inverse-kinematics  c
        :link-list (send r :link-list (send r :end-coords :parent))
        :move-target (send r :end-coords) :translation-axis t  :rotation-axis t)
  (x::window-main-one)
  (send *irtviewer* :draw-objects :flush nil)
  (send c :draw-on :flush t)
  )

このプログラムを実行すると以下のようなエラーが出てくる.

;; inverse-kinematics failed.
;; dif-pos : #f(11.7826 0.0 0.008449)/(11.7826/1)
;; dif-rot : #f(0.0 2.686130e-05 0.0)/(2.686130e-05/0.017453)
;;  coords : #<coordinates #X4bcccb0  0.0 0.0 0.0 / 0.0 0.0 0.0>
;;  angles : (14.9993 150 15.0006)
;;    args : ((#<cascaded-coords #X4b668a0  39.982 0.0 0.0 / 3.142 1.225e-16 3.14
2>) :link-list (#<bodyset-link #X4cf8e60 l2  0.0 0.0 20.0 / 0.0 0.262 0.0> #<body
set-link #X4cc8008 l3  25.866 0.0 116.597 / 3.142 0.262 3.142> #<bodyset-link #X4
c7a0d0 l4  51.764 0.0 20.009 / 3.142 2.686e-05 3.142>) :move-target;; #<cascaded-
coords #X4c93640  51.764 0.0 0.009 / 3.142 2.686e-05 3.142> :translation-axis t :
rotation-axis t)

これは,関節の駆動範囲の制限から目標位置に手先が届かない状況である. このような場面では,例えば,手先の位置さえ目標位置に届けばよく姿勢を 無視してよい場合:rotation-axis nilと指定することができる.

また,:thre:rthreを使うことで逆運動学計算の終了条件で ある位置姿勢の誤差を指定することができる.正確な計算が求められていない 状況ではこの値をデフォルトの1, (deg2rad 1)より大きい値を 利用するのもよい.

また,逆運動学の計算に失敗した場合,デフォルトでは逆運動学計算を始める 前の姿勢まで戻るが,:revert-if-failというキーワード引数をnilと指定 すると,指定されたの回数の計算を繰り替えしたあと,その姿勢のまま関数か ら抜けてくる.指定の回数もまた,:stopというキーワード引数で指 定することができる.

(setq c (make-cascoords :pos #f(300 0 0) :rpy (float-vector 0 pi 0)))
(send r :inverse-kinematics  c
      :link-list (send r :link-list (send r :end-coords :parent))
      :move-target (send r :end-coords)
      :translation-axis t
      :rotation-axis nil
      :revert-if-fail nil)

irteusのサンプルプログラムにおける例

cascaded-coordsクラスでは

  • (:link-list (to &optional form))
  • (:calc-jacobian-from-link-list (link-list &key move-target (rotation-axis nil)))

というメソッドが用意されている.

前者はリンクを引数として,ルートリンクからこのリンクまでの経路を計算し, リンクのリストとして返す.後者はこのリンクのリストを引数とし, move-target座標系をに対するヤコビアンを計算する.

concatenate result-type a bは a bを 連結しresult-type型に変換し返し,scale a b はベクトルbの全ての要素をス カラーa倍し,matrix-logは行列対数関数を計算する.

(if (not (boundp '*irtviewer*)) (make-irtviewer))

(load "irteus/demo/sample-arm-model.l")
(setq *sarm* (instance sarmclass :init))
(send *sarm* :reset-pose)
(setq *target* (make-coords :pos #f(350 200 400)))
(objects (list *sarm* *target*))

(do-until-key
  ;; step 3
  (setq c (send *sarm* :end-coords))
  (send c :draw-on :flush t)
  ;; step 4
  ;; step 4
  (setq dp (scale 0.001 (v- (send *target* :worldpos) (send c :worldpos))) ;; mm->m
        dw (matrix-log (m* (transpose (send c :worldrot)) (send *target* :worldrot))))
  (format t "dp = ~7,3f ~7,3f ~7,3f, dw = ~7,3f ~7,3f ~7,3f~%"
          (elt dp 0) (elt dp 1) (elt dp 2)
          (elt dw 0) (elt dw 1) (elt dw 2))
  ;; step 5
  (when (< (+ (norm dp) (norm dw)) 0.01) (return))
  ;; step 6
  (setq ll (send *sarm* :link-list (send *sarm* :end-coords :parent)))
  (setq j (send *sarm* :calc-jacobian-from-link-list
                ll :move-target (send *sarm* :end-coords)
                :trnaslation-axis t :rotation-axis t))
  (setq q (scale 1.0 (transform (pseudo-inverse j) (concatenate float-vector dp dw))))
  ;; step 7
  (dotimes (i (length ll))
    (send (send (elt ll i) :joint) :joint-angle (elt q i) :relative t))
  ;; draw
  (send *irtviewer* :draw-objects)
  (x::window-main-one))

実際のプログラミングでは:inverse-kinematicsというメソッドが用意されて おり,ここでは特異点や関節リミットの回避,あるいは自己衝突回避等の機能 が追加されている.

実際のロボットモデル

実際のロボットや環境を利用した実践的なサンプルプログラムを見てみよう.

まず,最初はロボットや環境のモデルファイルを読み込む.これらのファイル は$EUSDIR/modelsに,これらのファイルをロードしインスタンスを生成す るプログラムは以下のように書くことができる.(room73b2)(h7)はこれらのファイル内で定義されている関数である. ロボットのモデル(robot-model)はirtrobot.lファイルで定義 されており,cascaded-linkクラスの子クラスになっている. ロボットとはlarm,rarm,lleg,rleg,headのリンクのツリーからなる ものとして定義されており, (send *robot* :larm)(send *robot* :head)として ロボットのリム(limb)にアクセスでき,右手の逆運動学,左手の逆運動学等と いう利用方法が可能になっている.

(load "models/room73b2-scene.l")
(load "models/h7-robot.l")
(setq *room* (room73b2))
(setq *robot* (h7))
(objects (list *robot* *room*))

ロボットには:reset-poseというメソッドがありこれで初期姿勢をとる ことができる.

(send *robot* :reset-pose)

次に,ロボットを部屋の中で移動させたい.部屋内の代表的な座標は (send *room* :spots)で取得できる.この中から目的の座標を得る 場合はその座標の名前を引数として:spotメソッドを呼び出す. ちなみに,このメソッドの定義はprog/jskeus/irteus/irtscene.l にあり

(defmethod scene-model
  (:spots
   (&optional name)
   (append
    (mapcan
     #'(lambda(x)(if (derivedp x scene-model) (send x :spots name) nil))
     objs)
    (mapcan #'(lambda (o)
        (if (and (eq (class o) cascaded-coords)
             (or (null name) (string= name (send o :name))))
            (list o)))
        objs)))
  (:spot
   (name)
   (let ((r (send self :spots name)))
     (case (length r)
       (0 (warning-message 1 "could not found spot(~A)" name) nil)
       (1 (car r))
       (t (warning-message 1 "found multiple spot ~A for given name(~A)" r name) (car r)))))
  )

となっている.

ロボットもまたcoordinatesクラスの子クラスなので:move-to メソッドを利用できる.また,このロボットの原点は腰にあるので足が地面に つくように:locateメソッドを使って移動する.

(send *robot* :move-to (send *room* :spot "cook-spot") :world)
(send *robot* :locate #f(0 0 550))

現状では*irtviewer*の画面上でロボットが小さくなっているので, 以下のメソッド利用し,ロボットが画面いっぱいになるように調整する.

(send *irtviewer* :look-all
      (geo::make-bounding-box
       (flatten (send-all (send *robot* :bodies) :vertices))))

次に環境中の物体を選択する.ここでは:objectメソッドを利用する. これは,:spots, :spotと同様の振る舞いをするため, どのような物体があるかは,(send-all (send *room* :objects) :name) として知ることができる. room73b2-kettleの他に room73b2-mug-cuproom73b2-knife等を利用するとよい.

(setq *kettle* (send *room* :object "room73b2-kettle"))

環境モデルの初期化直後は物体は部屋にassocされているため,以下の用に 親子関係を解消しておく.こうしないと物体を把持するなどの場合に問題が生 じる.

(if (send *kettle* :parent) (send (send *kettle* :parent) :dissoc *kettle*))

ロボットの視線を対象物に向けるためのメソッドとして以下のようなものがあ る.

(send *robot* :head :look-at (send *kettle* :worldpos))

対象物体には,その物体を把持するための利用したらよい座標系が :handleメソッドとして記述されている場合がある.このメソッドは リストを返すため以下の様に(car (send *kettle* :handle))として その座標系を知ることができる.この座標がどこにあるか確認するためには (send (car (send *kettle* :handle)) :draw-on :flush t)とすると よい.

したがってこの物体手を伸ばすためには

(send *robot* :larm :inverse-kinematics
      (car (send *kettle* :handle))
      :link-list (send *robot* :link-list (send *robot* :larm :end-coords :parent))
      :move-target (send *robot* :larm :end-coords)
      :rotation-axis :z
      :debug-view t)

となる.

ここで,ロボットの手先と対象物体の座標系を連結し,

(send *robot* :larm :end-coords :assoc *kettle*)

以下の様にして世界座標系で100[mm]持ち上げることができる.

(send *robot* :larm :move-end-pos #f(0 0 100) :world
        :debug-view t :look-at-target t)

:look-at-targetは移動中に首の向きを常に対象を見つづけるようにす るという指令である.

inverse-kinematicsのtarget-coordsに関数を指定する例

Example of Dual Arm InverseKinematics

Example of Dual Arm InverseKinematics

:inverse-kinematicsの引数target-coordsは``coordinates``クラス以外に coordinatesクラスを返す関数を指定することができる。 以下に示すプログラムは2つの腕を利用してカクテルをふる動作を行うものである()。

(load "irteus/demo/sample-robot-model.l")
(setq *robot* (instance sample-robot :init))
(setq *obj* (make-cylinder 20 100))
(send *obj* :set-color #f(1 1 0))
(send *robot* :reset-pose)
(objects (list *robot* *obj*))

(send *robot* :inverse-kinematics
      (list (make-coords :pos #f(400 0 0)))
      :move-target
      (list (send *robot* :larm :end-coords))
      :link-list
      (list (send *robot* :link-list
                  (send (send *robot* :larm :end-coords) :parent)
                  (car (send *robot* :larm :links))))
      :translation-axis (list t)
      :rotation-axis (list nil))

(let* ((cnt 0.0))
  (do-until-key
   (incf cnt 0.1)
   (send *robot* :inverse-kinematics
         (list (make-coords :pos (float-vector (+ 400 (* 100 (sin cnt))) (* 50 (cos cnt)) 0))
               #'(lambda ()
                   (send (send (send *robot* :larm :end-coords) :copy-worldcoords)
                         :translate #f(0 0 100) :local)))
         :move-target
         (list (send *robot* :larm :end-coords)
               (send *robot* :rarm :end-coords))
         :link-list
         (list (send *robot* :link-list
                     (send (send *robot* :larm :end-coords) :parent)
                     (car (send *robot* :larm :links)))
               (send *robot* :link-list
                     (send (send *robot* :rarm :end-coords) :parent)
                     (car (send *robot* :rarm :links))))
         :translation-axis (list :z t)
         :rotation-axis (list nil :z))
   (send *obj* :newcoords (send (send *robot* :larm :end-coords) :copy-worldcoords))
   (send *irtviewer* :draw-objects)))
(list (make-coords :pos (float-vector (+ 400 (* 100 (sin cnt))) (* 50 (cos cnt)) 0))
      #'(lambda ()
          (send (send (send *robot* :larm :end-coords) :copy-worldcoords)
                :translate #f(0 0 100) :local)))

の行で実際にtarget-coordsに関数を指定している。 この例では、まずカクテルを持つ左手の位置を最初に決める。この時に :translation-axis :z, :rotation-axis nilとなっているため、 z方向の移動量と回転方向は左手の逆運動学の計算に考慮されない。 そして、決まった左手の位置に対して関数が評価されることで 手先のlocal座標から見てz方向に100の位置に対して右手の位置が決まる。 この時、右手の拘束条件は:translation-axis t, :rotation-axis :zとなっ ているためz方向、つまりカクテルの長さ方向を軸としてその軸に対する回転は許した条 件で逆運動学を解くことになる。 このように、拘束条件を踏まえて逆運動学を解きたい場合にはtarget-coordsを関数とし て扱うことが必要になる。

重心位置を考慮したfullbody-inverse-kinematicsの例

Example of InverseKinematics with root link virtual joint

Example of InverseKinematics with root link virtual joint

:fullbody-inverse-kinematicsはロボットの関節に加えてベースリンク仮想ジョイントを駆動した 逆運動学を解く関数である。以下に示すプログラムは、両足を地面に固定し、重心を両足の上に 位置させた状態で、左手を目標に到達させる動作を行うものである。

(load "irteus/demo/sample-robot-model.l")
(setq *robot* (instance sample-robot :init))
(send *robot* :reset-pose)
(setq *obj* (make-cylinder 10 600))
(send *obj* :rotate pi :x)
(send *obj* :set-color #f(1 1 0))
(objects (list *robot* *obj*))

(let* ((rleg-coords (send *robot* :rleg :end-coords :copy-worldcoords))
       (lleg-coords (send *robot* :lleg :end-coords :copy-worldcoords)))
  (send *robot* :torso :waist-p :joint-angle 10)
  (send *robot* :fullbody-inverse-kinematics
        (list rleg-coords
              lleg-coords
              (make-coords :pos (float-vector 400 100 -600)))
        :move-target
        (list (send *robot* :rleg :end-coords)
              (send *robot* :lleg :end-coords)
              (send *robot* :larm :end-coords))
        :link-list
        (list (send *robot* :link-list (send *robot* :rleg :end-coords :parent))
              (send *robot* :link-list (send *robot* :lleg :end-coords :parent))
              (send *robot* :link-list (send *robot* :larm :end-coords :parent)))
        :translation-axis (list t t t)
        :rotation-axis (list t t nil)
        :target-centroid-pos (midpoint 0.5
                                       (send *robot* :rleg :end-coords :worldpos)
                                       (send *robot* :lleg :end-coords :worldpos))
        :cog-translation-axis :z)
  (send *obj* :locate (send *robot* :centroid) :world)
  (send *irtviewer* :draw-objects))
(list rleg-coords
      lleg-coords
      (make-coords :pos (float-vector 400 100 -600)))

の行でtarget-coordsに右足、左足、左手の目標位置姿勢を指定している。 右足、左足は動かさないため、現在の座標をコピーしたものを与えている。 このときに、:translation-axis (list t t t), :rotation-axis (list t t nil) となっているため、右足、左足は位置姿勢を完全に拘束し、左手は姿勢の 回転は許した条件で逆運動学を解くことになる。

:target-centroid-pos (midpoint 0.5 (send *robot* :rleg :end-coords :worldpos)
                                   (send *robot* :lleg :end-coords :worldpos))
:cog-translation-axis :z)

の行では重心の逆運動学を指定している。:cog-translation-axis :zで z方向の重心の移動は許した状態で、:target-centroid-posで目標重心位置として 両足の中間の座標を与えることによって、重心のxy座標を両足の中間に一致させる 条件のもとで逆運動学を解くことができる。これらの引数は、デフォルト値になっている ので、省略可能である。

外力を考慮したfullbody-inverse-kinematicsを解く例

Example of InverseKinematics with external force

Example of InverseKinematics with external force

ロボットが外力、外モーメントを受ける場合、外力による足裏まわりのモーメントと 釣り合うようにロボットの重心をオフセットすることによって、バランスをとることができる。 以下に示すプログラムは両手に外力、外モーメントが加わる場合に、両手両足を目標の位置に 到達させかつバランスが取れる姿勢を逆運動学によって求めるものである。

(load "irteus/demo/sample-robot-model.l")
(setq *robot* (instance sample-robot :init))
(send *robot* :reset-pose)
(setq *obj* (make-cylinder 10 600))
(objects (list *robot*))

(let* ((force-list '(#f(-20 0 0) #f(-20 0 0)))
       (moment-list '(#f(10 0 0) #f(10 0 0))))

  (send *robot* :fullbody-inverse-kinematics
        (list (send *robot* :rleg :end-coords :copy-worldcoords)
              (send *robot* :lleg :end-coords :copy-worldcoords)
              (make-coords :pos #f(400 -300 0))
              (make-coords :pos #f(400 300 0)))
        :move-target (mapcar #'(lambda (x)
                                 (send *robot* x :end-coords))
                             (list :rleg :lleg :rarm :larm))
        :link-list (mapcar #'(lambda (x)
                               (send *robot* :link-list (send *robot* x :end-coords :parent)))
                           (list :rleg :lleg :rarm :larm))
        :centroid-offset-func #'(lambda () (send *robot* :calc-static-balance-point
                                             :force-list force-list
                                             :moment-list moment-list))
        :target-centroid-pos (midpoint 0.5 (send *robot* :rleg :end-coords :worldpos)
                                            (send *robot* :lleg :end-coords :worldpos))
        :cog-translation-axis :z)
  (send *irtviewer* :draw-objects)

  ;; draw force
  (mapcar
   #'(lambda (f cc)
       (let* ((prev-color (send *viewer* :viewsurface :color))
              (prev-width (send *viewer* :viewsurface :line-width)))
         (send *viewer* :viewsurface :color #F(1 0.3 1))
         (send *viewer* :viewsurface :line-width 5)
         (send *irtviewer* :viewer :draw-arrow
               (send cc :worldpos)
               (v+ (send cc :worldpos) (scale 10 f)))
         (send *viewer* :viewsurface :color prev-color)
         (send *viewer* :viewsurface :line-width prev-width)))
   force-list
   (list (send *robot* :rarm :end-coords)
         (send *robot* :larm :end-coords)))
  (send *irtviewer* :viewer :viewsurface :flush)
  )

この例では、

:centroid-offset-func #'(lambda () (send *robot* :calc-static-balance-point
                                     :force-list force-list
                                     :moment-list moment-list))

の行で外力、外モーメントを考慮している。force-listは右手に作用する外力と左手に作用する外力のリスト、force-listは右手に作用する外モーメントと左手に作用する外モーメントのリストであり、単位はそれぞれ[N]、[Nm]である。:calc-static-balance-pointは、現在の両手の位置に作用する外力外モーメントと現在の重心の位置に作用する重力に対して釣り合う足裏圧力中心の位置を返す関数である。:centroid-offset-funcはfloat-vectorクラスを返す関数を指定することができ、現在の重心位置の代わりにこの関数の返り値を用いて目標重心位置との距離を縮める逆運動学を解く。:cog-translation-axis :zでz方向の重心の移動は許した状態で:target-centroid-posで目標重心位置として両足の中間の座標を与えることによって、:centroid-offset-funcの返り値、即ち外力に釣り合いがとれる足裏圧力中心のxy座標を、両足の中間に一致させる逆運動学を解くことができる。

ロボットモデル

ロボットの身体はリンクとジョイントから構成されるが、それぞれ bodyset-linkjointクラスを利用しモデル絵を作成する。ロ ボットの身体はこれらの要素を含んだcascaded-linkという,連結リン クとしてモデルを生成する.

実際にはjointは抽象クラスであり rotational-joint,linear-joint, wheel-joint,omniwheel-joint, sphere-jointを選択肢、また四肢を持つロボットの場合は cascaded-link ではなくrobot-modelクラスを利用する。

joint

:super = ** propertied-object**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target
:init = `[method]
&key = (name (intern (format nil joint A (system:address self)) KEYWORD)) ((:child-link clink)) ((:parent-link plink)) (min -90) (max 90) ((:max-joint-velocity mjv)) ((:max-joint-torque mjt)) ((:joint-min-max-table mm-table)) ((:joint-min-max-target mm-target)) &allow-other-keys
abstract class of joint, users need to use rotational-joint, linear-joint, sphere-joint, 6dof-joint, wheel-joint or omniwheel-joint.
use :parent-link/:child-link for specifying links that this joint connect to and :min/:min for range of joint angle in degree.

:min-angle &optional v

If v is set, it updates min-angle of this instance. :min-angle returns minimal angle of this joint in degree.

:max-angle &optional v

If v is set, it updates max-angle of this instance. :max-angle returns maximum angle of this joint in degree.

:parent-link &rest args

Returns parent link of this joint. if any arguments is set, it is passed to the parent-link.

:child-link &rest args

Returns child link of this joint. if any arguments is set, it is passed to the child-link.

:joint-dof **

Returns Degree of Freedom of this joint.

:speed-to-angle &rest args

Returns values in deg/mm unit of input value in SI(rad/m) unit.

:angle-to-speed &rest args

Returns values in SI(rad/m) unit of input value in deg/mm unit.

:joint-velocity &optional jv

If jv is set, it updates joint-velocity of this instance. :joint-velocity returns velocity of this joint in SI(m/s, rad/s) unit.

:joint-acceleration &optional ja

If ja is set, it updates joint-acceleration of this instance. :joint-acceleration returns acceleration of this joint in SI(m/\(s^2\), rad/\(s^2\)) unit.

:joint-torque &optional jt

If jt is set, it updates joint-torque of this instance. :joint-torque returns torque of this joint in SI(N, Nm) unit.

:max-joint-velocity &optional mjv

If mjv is set, it updates min-joint-velocity of this instance. :min-joint-velocity returns velocity of this joint in SI(m/s, rad/s) unit.

:max-joint-torque &optional mjt

If mjt is set, it updates min-joint-torque of this instance. :min-joint-torque returns velocity of this joint in SI(N, Nm) unit.

:calc-dav-gain dav i periodic-time

:calc-jacobian &rest args

:joint-min-max-table &optional mm-table

:joint-min-max-target &optional mm-target

:joint-min-max-table-angle-interpolate target-angle min-or-max

:joint-min-max-table-min-angle &optional (target-angle (send joint-min-max-target :joint-angle))

:joint-min-max-table-max-angle &optional (target-angle (send joint-min-max-target :joint-angle))

:max-joint-torque &optional mjt

If mjt is set, it updates min-joint-torque of this instance. :min-joint-torque returns velocity of this joint in SI(N, Nm) unit.

:max-joint-velocity &optional mjv

If mjv is set, it updates min-joint-velocity of this instance. :min-joint-velocity returns velocity of this joint in SI(m/s, rad/s) unit.

:joint-torque &optional jt

If jt is set, it updates joint-torque of this instance. :joint-torque returns torque of this joint in SI(N, Nm) unit.

:joint-acceleration &optional ja

If ja is set, it updates joint-acceleration of this instance. :joint-acceleration returns acceleration of this joint in SI(m/\(s^2\), rad/\(s^2\)) unit.

:joint-velocity &optional jv

If jv is set, it updates joint-velocity of this instance. :joint-velocity returns velocity of this joint in SI(m/s, rad/s) unit.

:angle-to-speed &rest args

Returns values in SI(rad/m) unit of input value in deg/mm unit.

:speed-to-angle &rest args

Returns values in deg/mm unit of input value in SI(rad/m) unit.

:joint-dof **

Returns Degree of Freedom of this joint.

:child-link &rest args

Returns child link of this joint. if any arguments is set, it is passed to the child-link.

:parent-link &rest args

Returns parent link of this joint. if any arguments is set, it is passed to the parent-link.

:max-angle &optional v

If v is set, it updates max-angle of this instance. :max-angle returns maximum angle of this joint in degree.

:min-angle &optional v

If v is set, it updates min-angle of this instance. :min-angle returns minimal angle of this joint in degree.

:init = `[method]
&key = (name (intern (format nil joint A (system:address self)) KEYWORD)) ((:child-link clink)) ((:parent-link plink)) (min -90) (max 90) ((:max-joint-velocity mjv)) ((:max-joint-torque mjt)) ((:joint-min-max-table mm-table)) ((:joint-min-max-target mm-target)) &allow-other-keys
abstract class of joint, users need to use rotational-joint, linear-joint, sphere-joint, 6dof-joint, wheel-joint or omniwheel-joint.
use :parent-link/:child-link for specifying links that this joint connect to and :min/:min for range of joint angle in degree.

:joint-min-max-table-max-angle &optional (target-angle (send joint-min-max-target :joint-angle))

:joint-min-max-table-min-angle &optional (target-angle (send joint-min-max-target :joint-angle))

:joint-min-max-table-angle-interpolate target-angle min-or-max

:joint-min-max-target &optional mm-target

:joint-min-max-table &optional mm-table

:calc-jacobian &rest args

:calc-dav-gain dav i periodic-time

rotational-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = ((:axis ax) :z) ((:max-joint-velocity mjv) 5) ((:max-joint-torque mjt) 100) &allow-other-keys

create instance of rotational-joint. :axis is either (:x, :y, :z) or vector. :min-angle and :max-angle takes in radius, but velocity and torque are given in SI units.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

Return joint-angle if v is not set, if v is given, set joint angle. v is rotational value in degree.

:joint-dof **

Returns DOF of rotational joint, 1.

:speed-to-angle v

Returns degree of given input in radian

:angle-to-speed v

Returns radian of given input in degree

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian &rest args

:angle-to-speed v

Returns radian of given input in degree

:speed-to-angle v

Returns degree of given input in radian

:joint-dof **

Returns DOF of rotational joint, 1.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

Return joint-angle if v is not set, if v is given, set joint angle. v is rotational value in degree.

:init = `[method]
&rest args &key = ((:axis ax) :z) ((:max-joint-velocity mjv) 5) ((:max-joint-torque mjt) 100) &allow-other-keys

create instance of rotational-joint. :axis is either (:x, :y, :z) or vector. :min-angle and :max-angle takes in radius, but velocity and torque are given in SI units.

:calc-jacobian &rest args

:calc-angle-speed-gain dav i periodic-time

linear-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = ((:axis ax) :z) ((:max-joint-velocity mjv) (/ pi 4)) ((:max-joint-torque mjt) 100) &allow-other-keys

Create instance of linear-joint. :axis is either (:x, :y, :z) or vector. :min-angle and :max-angle takes in [mm], but velocity and torque are given in SI units.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is linear value in [mm].

:joint-dof **

Returns DOF of linear joint, 1.

:speed-to-angle v

Returns [mm] of given input in [m]

:angle-to-speed v

Returns [m] of given input in [mm]

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian &rest args

:angle-to-speed v

Returns [m] of given input in [mm]

:speed-to-angle v

Returns [mm] of given input in [m]

:joint-dof **

Returns DOF of linear joint, 1.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is linear value in [mm].

:init = `[method]
&rest args &key = ((:axis ax) :z) ((:max-joint-velocity mjv) (/ pi 4)) ((:max-joint-torque mjt) 100) &allow-other-keys

Create instance of linear-joint. :axis is either (:x, :y, :z) or vector. :min-angle and :max-angle takes in [mm], but velocity and torque are given in SI units.

:calc-jacobian &rest args

:calc-angle-speed-gain dav i periodic-time

wheel-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = (min (float-vector -inf-inf)) (max (float-vector infinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100)) &allow-other-keys

Create instance of wheel-joint.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is (float-vector translation-x[mm] rotation-z[deg])

:joint-dof **

Returns DOF of linear joint, 2.

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:joint-dof **

Returns DOF of linear joint, 2.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is (float-vector translation-x[mm] rotation-z[deg])

:init = `[method]
&rest args &key = (min (float-vector -inf-inf)) (max (float-vector infinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100)) &allow-other-keys

Create instance of wheel-joint.

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:calc-angle-speed-gain dav i periodic-time

omniwheel-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf)) (max (float-vector infinfinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ 0.08 0.05) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100 100)) &allow-other-keys

create instance of omniwheel-joint.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is (float-vector translation-x[mm] translation-y[mm] rotation-z[deg])

:joint-dof **

Returns DOF of linear joint, 3.

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:joint-dof **

Returns DOF of linear joint, 3.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is (float-vector translation-x[mm] translation-y[mm] rotation-z[deg])

:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf)) (max (float-vector infinfinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ 0.08 0.05) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100 100)) &allow-other-keys

create instance of omniwheel-joint.

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:calc-angle-speed-gain dav i periodic-time

sphere-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf)) (max (float-vector infinfinf)) ((:max-joint-velocity mjv) (float-vector (/ pi 4) (/ pi 4) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100 100)) &allow-other-keys

Create instance of sphere-joint. min/max are defind as a region of angular velocity in degree.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys
return joint-angle if v is not set, if v is given, set joint angle.
v is joint-angle vector [deg] by axis-angle representation, i.e (scale rotation-angle-from-default-coords[deg] axis-unit-vector)

:joint-angle-rpy &optional v &key relative

Return joint-angle if v is not set, if v is given, set joint-angle vector by RPY representation, i.e. (float-vector yaw[deg] roll[deg] pitch[deg])

:joint-dof **

Returns DOF of linear joint, 3.

:speed-to-angle dv

Returns degree of given input in radian

:angle-to-speed dv

Returns radian of given input in degree

:joint-euler-angle = `[method]
&key = (axis-order ’(:z :y :x)) ((:child-rot m) (send child-link :rot))

Return joint-angle if v is not set, if v is given, set joint-angle vector by euler representation.

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:joint-euler-angle = `[method]
&key = (axis-order ’(:z :y :x)) ((:child-rot m) (send child-link :rot))

Return joint-angle if v is not set, if v is given, set joint-angle vector by euler representation.

:angle-to-speed dv

Returns radian of given input in degree

:speed-to-angle dv

Returns degree of given input in radian

:joint-dof **

Returns DOF of linear joint, 3.

:joint-angle-rpy &optional v &key relative

Return joint-angle if v is not set, if v is given, set joint-angle vector by RPY representation, i.e. (float-vector yaw[deg] roll[deg] pitch[deg])

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys
return joint-angle if v is not set, if v is given, set joint angle.
v is joint-angle vector [deg] by axis-angle representation, i.e (scale rotation-angle-from-default-coords[deg] axis-unit-vector)
:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf)) (max (float-vector infinfinf)) ((:max-joint-velocity mjv) (float-vector (/ pi 4) (/ pi 4) (/ pi 4))) ((:max-joint-torque mjt) (float-vector 100 100 100)) &allow-other-keys

Create instance of sphere-joint. min/max are defind as a region of angular velocity in degree.

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:calc-angle-speed-gain dav i periodic-time

6dof-joint

:super = ** joint**
:slots axis
:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf-inf-inf-inf)) (max (float-vector infinfinfinfinfinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ 0.08 0.05) (/ 0.08 0.05) (/ pi 4) (/ pi 4) (/ pi 4))) ((:max-joint-mjt mjt) (float-vector 100 100 100 100 100 100)) (absolute-p nil) &allow-other-keys

Create instance of 6dof-joint.

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

Return joint-angle if v is not set, if v is given, set joint angle vector, which is 6D vector of 3D translation[mm] and 3D rotation[deg], i.e. (find-if #’(lambda (x) (eq (send (car x) :name) ’sphere-joint)) (documentation :joint-angle))

:joint-angle-rpy &optional v &key relative

Return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is 6D vector of 3D translation[mm] and 3D rotation[deg], for rotation, please see (find-if #’(lambda (x) (eq (send (car x) :name) ’sphere-joint)) (documentation :joint-angle-rpy))

:joint-dof **

Returns DOF of linear joint, 6.

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:calc-angle-speed-gain dav i periodic-time

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:angle-to-speed dv

Returns SI unit [m/rad] of given input in [mm/deg]

:speed-to-angle dv

Returns [mm/deg] of given input in SI unit [m/rad]

:joint-dof **

Returns DOF of linear joint, 6.

:joint-angle-rpy &optional v &key relative

Return joint-angle if v is not set, if v is given, set joint angle. v is joint-angle vector, which is 6D vector of 3D translation[mm] and 3D rotation[deg], for rotation, please see (find-if #’(lambda (x) (eq (send (car x) :name) ’sphere-joint)) (documentation :joint-angle-rpy))

:joint-angle = `[method]
&optional v &key = relative &allow-other-keys

Return joint-angle if v is not set, if v is given, set joint angle vector, which is 6D vector of 3D translation[mm] and 3D rotation[deg], i.e. (find-if #’(lambda (x) (eq (send (car x) :name) ’sphere-joint)) (documentation :joint-angle))

:init = `[method]
&rest args &key = (min (float-vector -inf-inf-inf-inf-inf-inf)) (max (float-vector infinfinfinfinfinf)) ((:max-joint-velocity mjv) (float-vector (/ 0.08 0.05) (/ 0.08 0.05) (/ 0.08 0.05) (/ pi 4) (/ pi 4) (/ pi 4))) ((:max-joint-mjt mjt) (float-vector 100 100 100 100 100 100)) (absolute-p nil) &allow-other-keys

Create instance of 6dof-joint.

:calc-jacobian fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

:calc-angle-speed-gain dav i periodic-time

bodyset-link

:super = ** bodyset**
:slots joint parent-link child-links analysis-level default-coords weight acentroid inertia-tensor angular-velocity angular-acceleration spacial-velocity spacial-acceleration momentum-velocity angular-momentum-velocity momentum angular-momentum force moment ext-force ext-moment
:init = `[method]
coords &rest args &key = ((:analysis-level level) :body) ((:weight w) 1) ((:centroid c) #f(0.0 0.0 0.0)) ((:inertia-tensor i) (unit-matrix 3)) &allow-other-keys

Create instance of bodyset-link.

:worldcoords &optional (level analysis-level)

Returns a coordinates object which represents this coord in the world by concatenating all the cascoords from the root to this coords.

:analysis-level &optional v

Change analysis level :coords only changes kinematics level and :body changes geometry too.

:weight &optional w

Returns a weight of the link. If w is given, set weight.

:centroid &optional c

Returns a centroid of the link. If c is given, set new centroid.

:inertia-tensor &optional i

Returns a inertia tensor of the link. If c is given, set new intertia tensor.

:joint &rest args

Returns a joint associated with this link. If args is given, args are forward to the joint.

:add-joint j

Set j as joint of this link

:del-joint **

Remove current joint of this link

:parent-link **

Returns parent link

:child-links **

Returns child links

:add-child-links l

Add l to child links

:add-parent-link l

Set l as parent link

:del-child-link l

Delete l from child links

:del-parent-link **

Delete parent link

:default-coords &optional c

:del-parent-link **

Delete parent link

:del-child-link l

Delete l from child links

:add-parent-link l

Set l as parent link

:add-child-links l

Add l to child links

:child-links **

Returns child links

:parent-link **

Returns parent link

:del-joint **

Remove current joint of this link

:add-joint j

Set j as joint of this link

:joint &rest args

Returns a joint associated with this link. If args is given, args are forward to the joint.

:inertia-tensor &optional i

Returns a inertia tensor of the link. If c is given, set new intertia tensor.

:centroid &optional c

Returns a centroid of the link. If c is given, set new centroid.

:weight &optional w

Returns a weight of the link. If w is given, set weight.

:analysis-level &optional v

Change analysis level :coords only changes kinematics level and :body changes geometry too.

:worldcoords &optional (level analysis-level)

Returns a coordinates object which represents this coord in the world by concatenating all the cascoords from the root to this coords.

:init = `[method]
coords &rest args &key = ((:analysis-level level) :body) ((:weight w) 1) ((:centroid c) #f(0.0 0.0 0.0)) ((:inertia-tensor i) (unit-matrix 3)) &allow-other-keys

Create instance of bodyset-link.

:default-coords &optional c

cascaded-link

:super = ** cascaded-coords**
:slots links joint-list bodies collision-avoidance-links end-coords-list
:init = `[method]
&rest args &key = name &allow-other-keys

Create cascaded-link.

:init-ending **

This method is to called finalize the instantiation of the cascaded-link. This update bodies and child-link and parent link from joint-list

:links &rest args

Returns links, or args is passed to links

:joint-list &rest args

Returns joint list, or args is passed to joints

:link name

Return a link with given name.

:joint name

Return a joint with given name.

:end-coords name

Returns end-coords with given name

:bodies &rest args

Return bodies of this object. If args is given it passed to all bodies

:faces **

Return faces of this object.

:angle-vector &optional vec (angle-vector (instantiate float-vector (calc-target-joint-dimension joint-list)))

Returns angle-vector of this object, if vec is given, it updates angles of all joint. If given angle-vector violate min/max range, the value is modified.

:link-list to &optional from

Find link list from to link to from link.

:plot-joint-min-max-table joint0 joint1

Plot joint min max table on Euslisp window.

:calc-jacobian-from-link-list = `[method]
link-list &rest args &key = move-target (transform-coords move-target) (rotation-axis (cond ((atom move-target) nil) (t (make-list (length move-target))))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (col-offset 0) (dim (send self :calc-target-axis-dimension rotation-axis translation-axis)) (fik-len (send self :calc-target-joint-dimension link-list)) fik (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) (tmp-v3a (instantiate float-vector 3)) (tmp-v3b (instantiate float-vector 3)) (tmp-m33 (make-matrix 3 3)) &allow-other-keys
Calculate jacobian matrix from link-list and move-target. Jacobian is represented in :transform-coords. Unit system is [m] or [rad], not [mm] or [deg].
Joint order for this jacobian matrix follows link-list order. Joint torque[Nm] order is also the same.
Ex1. One-Arm
(setq rarm-link-list(send robot:link-list (send robot:rarm :end-coords :parent)))
(send-all rarm-link-list:joint)
Ex2. Two-Arm
(setq arms-link-list(mapcar #’(lambda (l) (send robot:link-list (send robotl :end-coords :parent))) ’(:rarm :larm)))
(send-all (send robot:calc-union-link-list arms-link-list) :joint)
:move-joints-avoidance = `[method]
union-vel &rest args &key = union-link-list link-list (fik-len (send self :calc-target-joint-dimension union-link-list)) (weight (fill (instantiate float-vector fik-len) 1)) (null-space) (avoid-nspace-gain 0.01) (avoid-weight-gain 1.0) (avoid-collision-distance 200) (avoid-collision-null-gain 1.0) (avoid-collision-joint-gain 1.0) ((:collision-avoidance-link-pair pair-list) (send self :collision-avoidance-link-pair-from-link-list link-list :obstacles (cadr (memq :obstacles args)) :debug (cadr (memq :debug-view args)))) (cog-gain 0.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (additional-weight-list) (additional-nspace-list) (tmp-len (instantiate float-vector fik-len)) (tmp-len2 (instantiate float-vector fik-len)) (tmp-weight (instantiate float-vector fik-len)) (tmp-nspace (instantiate float-vector fik-len)) (tmp-mcc (make-matrix fik-len fik-len)) (tmp-mcc2 (make-matrix fik-len fik-len)) (debug-view) (jacobi) &allow-other-keys
:move-joints-avoidance is called in :inverse-kinematics-loop. In this method, calculation of joint position difference are executed and joint positon are moved.
Optional arguments:
  :weight
   float-vector of inverse weight of velocity of each joint or a function which returns the float-vector or a list which returns the float-vector. Length of the float-vector should be same as the number of columns of the jacobian. If :weight is a function or a list, it is called in each IK loop as (funcall weight union-link-list) or (eval weight). :weight is used in calculation of weighted norm of joint velocity for sr-inverse. Default is the float-vector filled with 1.
  :null-space
   float-vector of joint velocity or a function which returns the float-vector or a list which returns the float-vector. Length of the float-vector should be same as the number of columns of the jacobian. If :null-space is a function or a list, it is called in each IK loop as (funcall null-space) or (eval null-space). This joint velocity is applied in null space of main task in each IK loop. Default is nil.
  :avoid-nspace-gain
  gain of joint velocity to avoid joint limit applied in null space of main task in each IK loop. The avoiding velocity is calculated as \((((t\_max + t\_min)/2 - t) / ((t\_max - t\_min)/2))^2\). Default is 0.01.
  :avoid-weight-gain
   gain of dH/dt in calcuration of avoiding joint limits weight. :weight is devided by this avoiding joint limits weight. Default is 1.0.
   If :avoid-nspace-gain is 0, :weight is multipled by :weight instead.
  :avoid-collision-distance
   yellow zone. 0.1avoid-collision-distance is regarded as orange zone.
   If :avoid-collision-joint-gain is smaller than or equal to 0.0, yellow zone and orange zone become inactive. Default is 200[mm].
  :avoid-collision-null-gain
   \(k\_{null}\). Default is 1.0.
  :avoid-collision-joint-gain
   \(k\_{joint}\). Default is 1.0.
  :collision-avoidance-link-pair
   (list (list link1 link2) (list link3 link4) ...) with any length. Collision between paired links is cared. Default is (send self :collision-avoidance-link-pair-from-link-list link-list :obstacles (cadr (memq :obstacles args))).
  :additional-weight-list
   (list (list target-link1 additional-weight1) (list target-link2 additional-weight2) ...) with any length. The component of :weight corresponding to the parent joint of target-link is scaled by additional-weight. additional-weight should be float (if 1 dof), float-vector with length of the joint dof, or a function which returns the float or float-vector. if additional-weight is a function, it is called in each IK loop as (funcall additional-weight). Default is nil.
  :additional-nspace-list
   (list (list target-link1 var1) (list target-link2 var2) ...) with any length. In each IK loop, the parent joint of target-link is moved by the amount of var in null space of main task. var should be float (if 1dof), float-vector with the same length of the target joint dof, or a function which returns the float or float-vector.If var is float-vector, it is called in each IK loop as (funcall var). Default is nil.
  other-keys
   :manipulability-limit
    If manipulability of jacobian is smaller than manipulability-limit, diagonal matrix is added in calculation of sr-inverse. Default is 0.1.
  :manipulability-gain
   Weight of diagonal matrix in calculation of sr-inverse. Weight is calculated as (manipulability-gain (expt (- 1.0 (/ manipulability manipulability-limit)) 2)). Default is 0.001.
   :collision-distance-limit
    Threshold for collision detection. If collision is detected, the distance between the colliding links is considered to be :collision-distance-limit instead of actual distance. Default is 10[mm].
   :move-joints-hook
    A function which is called right after joints are moved in each IK loop as (funcall move-joints-hook). Default is nil.
:inverse-kinematics-loop = `[method]
dif-pos dif-rot &rest args &key = (stop 1) (loop 0) link-list move-target (rotation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (thre (cond ((atom move-target) 1) (t (make-list (length move-target) :initial-element 1)))) (rthre (cond ((atom move-target) (deg2rad 1)) (t (make-list (length move-target) :initial-element (deg2rad 1))))) (dif-pos-ratio 1.0) (dif-rot-ratio 1.0) union-link-list target-coords (jacobi) (additional-check) (additional-jacobi) (additional-vel) (centroid-thre 1.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (cog-gain 1.0) (min-loop (/ stop 10)) debug-view ik-args &allow-other-keys
:inverse-kinematics-loop is one loop calculation for :inverse-kinematics.
In this method, joint position difference satisfying workspace difference (dif-pos, dif-rot) are calculated and euslisp model joint angles are updated.
Optional arguments:
  :dif-pos-ratio
   Ratio of spacial velocity used in calculation of joint position difference to workspace difference (after :p-limit applied). Default is 1.0.
  :dif-rot-ratio
   Ratio of angular velocity used in calculation of joint position difference to workspace difference (after :r-limit applied). Default is 1.0.
  :jacobi
   A jacobian of all move-target or a function that returns the jacobian. When a function is given, It is called in every IK loop as (funcall jacobi link-list move-target translation-axis rotation-axis). Default is (sendself :calc-jacobian-from-link-list link-list :translation-axis translation-axis :rotation-axis rotation-axis :move-target move-target method-args).
  :additional-check
   This argument is to add optional best-effort convergence conditions. Default is nil (no additional check). :additional-check should be function or lambda.
   best-effort =>
    In :inverse-kinematics-loop, ’success’ is overwritten by ’(and success additional-check)’
    In :inverse-kinematics, ’success is not overwritten.
    So, :inverse-kinematics-loop wait until ’:additional-check’ becomes ’t’ as possible,
    but ’:additional-check’ is neglected in the final :inverse-kinematics return.
  :cog-gain
   Ratio of centroid velocity used in calculation of joint position difference to centroid position difference. max 1.0. Default is 1.0.
  :min-loop
   Minimam loop count. Defalt (/ stop 10).
   If integer is specified, :inverse-kinematics-loop does returns :ik-continues and continuing solving IK.
   If min-loop is nil, do not consider loop counting for IK convergence.
  other-keys
   :move-joints-avoidance is internally called and args are passed to it. See the explanation of :move-joints-avoidance.
   :p-limit
    Maximum spacial velocity of each move-target in one IK loop. Default is 100.0[mm].
   :r-limit
    Maximum angular velocity of each move-target in one IK loop. Default is 0.5[rad].
:inverse-kinematics = `[method]
target-coords &rest args &key = (stop 50) (link-list) (move-target) (debug-view) (warnp t) (revert-if-fail t) (rotation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (joint-args) (thre (cond ((atom move-target) 1) (t (make-list (length move-target) :initial-element 1)))) (rthre (cond ((atom move-target) (deg2rad 1)) (t (make-list (length move-target) :initial-element (deg2rad 1))))) (union-link-list) (centroid-thre 1.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (dump-command :fail-only) (periodic-time 0.5) (check-collision) (additional-jacobi) (additional-vel) &allow-other-keys
Move move-target to target-coords.
;; target-coords, link-list and move-target need to be given.
;; target-coords, move-target, rotation-axis, translation-axis, link-list
;; ->both list and atom OK.
:target-coords
  The coordinate of the target, or a function that returns coordinates. When a function is given, it is called in every IK loop as (funcall target-coords). Use a list of targets to solve the IK relative to multiple end links simultaneously.
:stop
  Maximum number for IK iteration. Default is 50.
:link-list
  List of links to control. When the target-coords is list, this should be a list of lists.
:move-target
  Specify end-effector coordinate. When the target-coords is list, this should be list too.
:debug-view
  Set t to show debug message and visualization. Use :no-message to just show the irtview image. Default is nil.
:warnp
  Set nil to not display debug message when the IK failed. Default is t.
:revert-if-fail
  Set nil to keep the angle posture of IK solve iteration. Default is t, which return to original position when IK fails.
:rotation-axis
  Use nil for position only IK. :x, :y, :z for the constraint around axis with plus direction, :-x :-y :-z for axis with minus direction. :zz :yy :zz for direction free axis. :xm :ym :zm for allowing rotation with respect to mirror direction. When the target-coords is list, this should be list too. Default is t.
:translation-axis
  :x :y :z for constraint along the x, y, z axis. :xy :yz :zx for plane. Default is t.
:joint-args
  Arguments passed to joint as (sendjoint :joint-angle angle :relative t joint-args). Default nil.
:thre
  Threshold for position error to terminate IK iteration. Default is 1 [mm].
:rthre
  Threshold for rotation error to terminate IK iteration. Default is 0.017453 [rad] (1 deg).
:union-link-list
  a function that returns union of link-list called as (funcall union-link-list link-list). Default is (send self :calc-union-link-list link-list).
:centroid-thre
  Threshold for centroid position error to terminate IK iteration. Default is 1 [mm].
:target-centroid-pos
  The float-vector of the target centroid position. Default is nil.
:centroid-offset-func
  A function that returns centroid position. This function is called in each IK loop as (funcall centroid-offset-func). Default is (send self :centroid).
:cog-translation-axis
  :x :y :z for constraint along the x, y, z axis. :xy :yz :zx for plane. t for point. Default is :z.
:cog-null-space
  t: centroid position task is solved in null space of the main task. Default is nil.
:dump-command
 should be t, nil, :always, :fail-only, :always-with-debug-log, or :fail-only-with-debug-log. Log are success/fail log and ik debug information log.
   t or :always : dump log both in success and fail (for success/fail log).
   :always-with-debug-log : dump log both in success and fail (for success/fail log and ik debug information log).
   :fail-only : dump log only in fail (for success/fail log).
   :always-with-debug-log : dump log only in fail (for success/fail log and ik debug information log).
   nil : do not dump log.
:periodic-time
  The amount of joint angle modification in each IK loop is scaled not to violate joint velocity limit times :periodic-time. Default is 0.5[s].
:check-collision
  Set t to return false when self collision occurs at found IK solution. Default is nil. To avoid collision within IK loop, use set links to collision-avoidance-links slot of cascaded-link.
:additional-jacobi
  The jacobian of the additional main task, or a function that returns the jacobian. When a function is given, it is called in every IK loop as (funcall additional-jacobi link-list). Use a list of additional-jacobi to solve the IK for multiple additional task. Default is nil.
:additional-vel
  The velocity of additional main task, or a function that returns the velocity. When a function is given, it is called in every IK loop as (funcall additional-vel link-list). The velocity should be expressed in the same coordinates as corresponding additional-jacobi. When the additional-jacobi is list, this should be a list of same length. Default is nil.
other-keys
  function :inverse-kinematics-loop is internally called and args are passed to it. See the explanation of :inverse-kinematics-loop.
:calc-grasp-matrix = `[method]
contact-points &key = (ret (make-matrix 6 (6 (length contact-points)))) (contact-rots (mapcar #’(lambda (r) (unit-matrix 3)) contact-points))
Calc grasp matrix.
Grasp matrix is defined as
| E_3 0 E_3 0 ... |
| p1x E_3 p2x E_3 ... |
Arguments:
contact-points is list of contact points[mm].
contact-rots is list of contact coords rotation[rad].
If contact-rots is specified, grasp matrix as follow:
| R1 0 R2 0 ... |
| p1xR1 R1 p2xR2 R2 ... |
:inverse-kinematics-for-closed-loop-forward-kinematics = `[method]
target-coords &rest args &key = (move-target) (link-list) (move-joints-hook) (additional-weight-list) (constrained-joint-list) (constrained-joint-angle-list) (min-loop 2) &allow-other-keys
Solve inverse-kinematics for closed loop forward kinematics.
Move move-target to target-coords with link-list.
link-list loop should be close when move-target reaches target-coords.
constrained-joint-list is list of joints specified given joint angles in closed loop.
constrained-joint-angle-list is list of joint-angle for constrained-joint-list.

:calc-jacobian-for-interlocking-joints link-list &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Calculate jacobian to keep interlocking joint velocity same.
dtheta_0 = dtheta_1 =>[... 0 1 0 ... 0 -1 0 .... ][...dtheta_0...dtheta_1...]

:calc-vel-for-interlocking-joints link-list &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Calculate 0 velocity for keeping interlocking joint at the same joint angle.

:set-midpoint-for-interlocking-joints &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Set interlocking joints at mid point of each joint angle.

:interlocking-joint-pairs **

Interlocking joint pairs.
pairs are (list (cons joint0 joint1) ... )
If users want to use interlocking joints, please overwrite this method.
:check-interlocking-joint-angle-validity = `[method]
&key = (angle-thre 0.001) (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Check if all interlocking joint pairs are same values.

:update-descendants &rest args

:find-link-route to &optional from

:make-joint-min-max-table l0 l1 joint0 joint1 &key (fat 0) (fat2 nil) (debug nil) (margin 0.0) (overwrite-collision-model nil)

:make-min-max-table-using-collision-check l0 l1 joint0 joint1 joint-range0 joint-range1 min-joint0 min-joint1 fat fat2 debug margin

:plot-joint-min-max-table-common joint0 joint1

:calc-target-axis-dimension rotation-axis translation-axis

:calc-union-link-list link-list

:calc-target-joint-dimension link-list

:calc-inverse-jacobian jacobi &rest args &key ((:manipulability-limit ml) 0.1) ((:manipulability-gain mg) 0.001) weight debug-view ret wmat tmat umat umat2 mat-tmp mat-tmp-rc tmp-mrr tmp-mrr2 &allow-other-keys

:calc-gradh-from-link-list link-list &optional (res (instantiate float-vector (length link-list)))

:calc-joint-angle-speed union-vel &rest args &key angle-speed (angle-speed-blending 0.5) jacobi jacobi# null-space i-j#j debug-view weight wmat tmp-len tmp-len2 fik-len &allow-other-keys

:calc-joint-angle-speed-gain union-link-list dav periodic-time

:collision-avoidance-links &optional l

:collision-avoidance-link-pair-from-link-list link-lists &key obstacles ((:collision-avoidance-links collision-links) collision-avoidance-links) debug

:collision-avoidance-calc-distance &rest args &key union-link-list (warnp t) ((:collision-avoidance-link-pair pair-list)) ((:collision-distance-limit distance-limit) 10) &allow-other-keys

:collision-avoidance-args pair link-list

:collision-avoidance &rest args &key avoid-collision-distance avoid-collision-joint-gain avoid-collision-null-gain ((:collision-avoidance-link-pair pair-list)) (union-link-list) (link-list) (weight) (fik-len (send self :calc-target-joint-dimension union-link-list)) debug-view &allow-other-keys

:move-joints union-vel &rest args &key union-link-list (periodic-time 0.05) (joint-args) (debug-view nil) (move-joints-hook) &allow-other-keys

:find-joint-angle-limit-weight-old-from-union-link-list union-link-list

:reset-joint-angle-limit-weight-old union-link-list

:calc-weight-from-joint-limit avoid-weight-gain fik-len link-list union-link-list debug-view weight tmp-weight tmp-len

:calc-inverse-kinematics-weight-from-link-list link-list &key (avoid-weight-gain 1.0) (union-link-list (send self :calc-union-link-list link-list)) (fik-len (send self :calc-target-joint-dimension union-link-list)) (weight (fill (instantiate float-vector fik-len) 1)) (additional-weight-list) (debug-view) (tmp-weight (instantiate float-vector fik-len)) (tmp-len (instantiate float-vector fik-len))

:calc-nspace-from-joint-limit avoid-nspace-gain union-link-list weight debug-view tmp-nspace

:calc-inverse-kinematics-nspace-from-link-list link-list &key (avoid-nspace-gain 0.01) (union-link-list (send self :calc-union-link-list link-list)) (fik-len (send self :calc-target-joint-dimension union-link-list)) (null-space) (debug-view) (additional-nspace-list) (cog-gain 0.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (weight (fill (instantiate float-vector fik-len) 1.0)) (update-mass-properties t) (tmp-nspace (instantiate float-vector fik-len))

:inverse-kinematics-args &rest args &key union-link-list rotation-axis translation-axis additional-jacobi-dimension &allow-other-keys

:draw-collision-debug-view **

:ik-convergence-check success dif-pos dif-rot rotation-axis translation-axis thre rthre centroid-thre target-centroid-pos centroid-offset-func cog-translation-axis &key (update-mass-properties t)

:calc-vel-from-pos dif-pos translation-axis &rest args &key (p-limit 100.0) (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) &allow-other-keys

:calc-vel-from-rot dif-rot rotation-axis &rest args &key (r-limit 0.5) (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) &allow-other-keys

:collision-check-pairs &key ((:links ls) (cons (car links) (all-child-links (car links))))

:self-collision-check &key (mode :all) (pairs (send self :collision-check-pairs)) (collision-func ’collision-check)

:plot-joint-min-max-table joint0 joint1

Plot joint min max table on Euslisp window.

:link-list to &optional from

Find link list from to link to from link.

:angle-vector &optional vec (angle-vector (instantiate float-vector (calc-target-joint-dimension joint-list)))

Returns angle-vector of this object, if vec is given, it updates angles of all joint. If given angle-vector violate min/max range, the value is modified.

:faces **

Return faces of this object.

:bodies &rest args

Return bodies of this object. If args is given it passed to all bodies

:end-coords name

Returns end-coords with given name

:joint name

Return a joint with given name.

:link name

Return a link with given name.

:joint-list &rest args

Returns joint list, or args is passed to joints

:links &rest args

Returns links, or args is passed to links

:init-ending **

This method is to called finalize the instantiation of the cascaded-link. This update bodies and child-link and parent link from joint-list

:init = `[method]
&rest args &key = name &allow-other-keys

Create cascaded-link.

:plot-joint-min-max-table-common joint0 joint1

:make-min-max-table-using-collision-check l0 l1 joint0 joint1 joint-range0 joint-range1 min-joint0 min-joint1 fat fat2 debug margin

:make-joint-min-max-table l0 l1 joint0 joint1 &key (fat 0) (fat2 nil) (debug nil) (margin 0.0) (overwrite-collision-model nil)

:find-link-route to &optional from

:update-descendants &rest args

:check-interlocking-joint-angle-validity = `[method]
&key = (angle-thre 0.001) (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Check if all interlocking joint pairs are same values.

:interlocking-joint-pairs **

Interlocking joint pairs.
pairs are (list (cons joint0 joint1) ... )
If users want to use interlocking joints, please overwrite this method.

:set-midpoint-for-interlocking-joints &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Set interlocking joints at mid point of each joint angle.

:calc-vel-for-interlocking-joints link-list &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Calculate 0 velocity for keeping interlocking joint at the same joint angle.

:calc-jacobian-for-interlocking-joints link-list &key (interlocking-joint-pairs (send self :interlocking-joint-pairs))

Calculate jacobian to keep interlocking joint velocity same.
dtheta_0 = dtheta_1 =>[... 0 1 0 ... 0 -1 0 .... ][...dtheta_0...dtheta_1...]
:inverse-kinematics-for-closed-loop-forward-kinematics = `[method]
target-coords &rest args &key = (move-target) (link-list) (move-joints-hook) (additional-weight-list) (constrained-joint-list) (constrained-joint-angle-list) (min-loop 2) &allow-other-keys
Solve inverse-kinematics for closed loop forward kinematics.
Move move-target to target-coords with link-list.
link-list loop should be close when move-target reaches target-coords.
constrained-joint-list is list of joints specified given joint angles in closed loop.
constrained-joint-angle-list is list of joint-angle for constrained-joint-list.
:calc-grasp-matrix = `[method]
contact-points &key = (ret (make-matrix 6 (6 (length contact-points)))) (contact-rots (mapcar #’(lambda (r) (unit-matrix 3)) contact-points))
Calc grasp matrix.
Grasp matrix is defined as
| E_3 0 E_3 0 ... |
| p1x E_3 p2x E_3 ... |
Arguments:
contact-points is list of contact points[mm].
contact-rots is list of contact coords rotation[rad].
If contact-rots is specified, grasp matrix as follow:
| R1 0 R2 0 ... |
| p1xR1 R1 p2xR2 R2 ... |
:inverse-kinematics = `[method]
target-coords &rest args &key = (stop 50) (link-list) (move-target) (debug-view) (warnp t) (revert-if-fail t) (rotation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (joint-args) (thre (cond ((atom move-target) 1) (t (make-list (length move-target) :initial-element 1)))) (rthre (cond ((atom move-target) (deg2rad 1)) (t (make-list (length move-target) :initial-element (deg2rad 1))))) (union-link-list) (centroid-thre 1.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (dump-command :fail-only) (periodic-time 0.5) (check-collision) (additional-jacobi) (additional-vel) &allow-other-keys
Move move-target to target-coords.
;; target-coords, link-list and move-target need to be given.
;; target-coords, move-target, rotation-axis, translation-axis, link-list
;; ->both list and atom OK.
:target-coords
  The coordinate of the target, or a function that returns coordinates. When a function is given, it is called in every IK loop as (funcall target-coords). Use a list of targets to solve the IK relative to multiple end links simultaneously.
:stop
  Maximum number for IK iteration. Default is 50.
:link-list
  List of links to control. When the target-coords is list, this should be a list of lists.
:move-target
  Specify end-effector coordinate. When the target-coords is list, this should be list too.
:debug-view
  Set t to show debug message and visualization. Use :no-message to just show the irtview image. Default is nil.
:warnp
  Set nil to not display debug message when the IK failed. Default is t.
:revert-if-fail
  Set nil to keep the angle posture of IK solve iteration. Default is t, which return to original position when IK fails.
:rotation-axis
  Use nil for position only IK. :x, :y, :z for the constraint around axis with plus direction, :-x :-y :-z for axis with minus direction. :zz :yy :zz for direction free axis. :xm :ym :zm for allowing rotation with respect to mirror direction. When the target-coords is list, this should be list too. Default is t.
:translation-axis
  :x :y :z for constraint along the x, y, z axis. :xy :yz :zx for plane. Default is t.
:joint-args
  Arguments passed to joint as (sendjoint :joint-angle angle :relative t joint-args). Default nil.
:thre
  Threshold for position error to terminate IK iteration. Default is 1 [mm].
:rthre
  Threshold for rotation error to terminate IK iteration. Default is 0.017453 [rad] (1 deg).
:union-link-list
  a function that returns union of link-list called as (funcall union-link-list link-list). Default is (send self :calc-union-link-list link-list).
:centroid-thre
  Threshold for centroid position error to terminate IK iteration. Default is 1 [mm].
:target-centroid-pos
  The float-vector of the target centroid position. Default is nil.
:centroid-offset-func
  A function that returns centroid position. This function is called in each IK loop as (funcall centroid-offset-func). Default is (send self :centroid).
:cog-translation-axis
  :x :y :z for constraint along the x, y, z axis. :xy :yz :zx for plane. t for point. Default is :z.
:cog-null-space
  t: centroid position task is solved in null space of the main task. Default is nil.
:dump-command
 should be t, nil, :always, :fail-only, :always-with-debug-log, or :fail-only-with-debug-log. Log are success/fail log and ik debug information log.
   t or :always : dump log both in success and fail (for success/fail log).
   :always-with-debug-log : dump log both in success and fail (for success/fail log and ik debug information log).
   :fail-only : dump log only in fail (for success/fail log).
   :always-with-debug-log : dump log only in fail (for success/fail log and ik debug information log).
   nil : do not dump log.
:periodic-time
  The amount of joint angle modification in each IK loop is scaled not to violate joint velocity limit times :periodic-time. Default is 0.5[s].
:check-collision
  Set t to return false when self collision occurs at found IK solution. Default is nil. To avoid collision within IK loop, use set links to collision-avoidance-links slot of cascaded-link.
:additional-jacobi
  The jacobian of the additional main task, or a function that returns the jacobian. When a function is given, it is called in every IK loop as (funcall additional-jacobi link-list). Use a list of additional-jacobi to solve the IK for multiple additional task. Default is nil.
:additional-vel
  The velocity of additional main task, or a function that returns the velocity. When a function is given, it is called in every IK loop as (funcall additional-vel link-list). The velocity should be expressed in the same coordinates as corresponding additional-jacobi. When the additional-jacobi is list, this should be a list of same length. Default is nil.
other-keys
  function :inverse-kinematics-loop is internally called and args are passed to it. See the explanation of :inverse-kinematics-loop.
:inverse-kinematics-loop = `[method]
dif-pos dif-rot &rest args &key = (stop 1) (loop 0) link-list move-target (rotation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (thre (cond ((atom move-target) 1) (t (make-list (length move-target) :initial-element 1)))) (rthre (cond ((atom move-target) (deg2rad 1)) (t (make-list (length move-target) :initial-element (deg2rad 1))))) (dif-pos-ratio 1.0) (dif-rot-ratio 1.0) union-link-list target-coords (jacobi) (additional-check) (additional-jacobi) (additional-vel) (centroid-thre 1.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (cog-gain 1.0) (min-loop (/ stop 10)) debug-view ik-args &allow-other-keys
:inverse-kinematics-loop is one loop calculation for :inverse-kinematics.
In this method, joint position difference satisfying workspace difference (dif-pos, dif-rot) are calculated and euslisp model joint angles are updated.
Optional arguments:
  :dif-pos-ratio
   Ratio of spacial velocity used in calculation of joint position difference to workspace difference (after :p-limit applied). Default is 1.0.
  :dif-rot-ratio
   Ratio of angular velocity used in calculation of joint position difference to workspace difference (after :r-limit applied). Default is 1.0.
  :jacobi
   A jacobian of all move-target or a function that returns the jacobian. When a function is given, It is called in every IK loop as (funcall jacobi link-list move-target translation-axis rotation-axis). Default is (sendself :calc-jacobian-from-link-list link-list :translation-axis translation-axis :rotation-axis rotation-axis :move-target move-target method-args).
  :additional-check
   This argument is to add optional best-effort convergence conditions. Default is nil (no additional check). :additional-check should be function or lambda.
   best-effort =>
    In :inverse-kinematics-loop, ’success’ is overwritten by ’(and success additional-check)’
    In :inverse-kinematics, ’success is not overwritten.
    So, :inverse-kinematics-loop wait until ’:additional-check’ becomes ’t’ as possible,
    but ’:additional-check’ is neglected in the final :inverse-kinematics return.
  :cog-gain
   Ratio of centroid velocity used in calculation of joint position difference to centroid position difference. max 1.0. Default is 1.0.
  :min-loop
   Minimam loop count. Defalt (/ stop 10).
   If integer is specified, :inverse-kinematics-loop does returns :ik-continues and continuing solving IK.
   If min-loop is nil, do not consider loop counting for IK convergence.
  other-keys
   :move-joints-avoidance is internally called and args are passed to it. See the explanation of :move-joints-avoidance.
   :p-limit
    Maximum spacial velocity of each move-target in one IK loop. Default is 100.0[mm].
   :r-limit
    Maximum angular velocity of each move-target in one IK loop. Default is 0.5[rad].
:move-joints-avoidance = `[method]
union-vel &rest args &key = union-link-list link-list (fik-len (send self :calc-target-joint-dimension union-link-list)) (weight (fill (instantiate float-vector fik-len) 1)) (null-space) (avoid-nspace-gain 0.01) (avoid-weight-gain 1.0) (avoid-collision-distance 200) (avoid-collision-null-gain 1.0) (avoid-collision-joint-gain 1.0) ((:collision-avoidance-link-pair pair-list) (send self :collision-avoidance-link-pair-from-link-list link-list :obstacles (cadr (memq :obstacles args)) :debug (cadr (memq :debug-view args)))) (cog-gain 0.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (additional-weight-list) (additional-nspace-list) (tmp-len (instantiate float-vector fik-len)) (tmp-len2 (instantiate float-vector fik-len)) (tmp-weight (instantiate float-vector fik-len)) (tmp-nspace (instantiate float-vector fik-len)) (tmp-mcc (make-matrix fik-len fik-len)) (tmp-mcc2 (make-matrix fik-len fik-len)) (debug-view) (jacobi) &allow-other-keys
:move-joints-avoidance is called in :inverse-kinematics-loop. In this method, calculation of joint position difference are executed and joint positon are moved.
Optional arguments:
  :weight
   float-vector of inverse weight of velocity of each joint or a function which returns the float-vector or a list which returns the float-vector. Length of the float-vector should be same as the number of columns of the jacobian. If :weight is a function or a list, it is called in each IK loop as (funcall weight union-link-list) or (eval weight). :weight is used in calculation of weighted norm of joint velocity for sr-inverse. Default is the float-vector filled with 1.
  :null-space
   float-vector of joint velocity or a function which returns the float-vector or a list which returns the float-vector. Length of the float-vector should be same as the number of columns of the jacobian. If :null-space is a function or a list, it is called in each IK loop as (funcall null-space) or (eval null-space). This joint velocity is applied in null space of main task in each IK loop. Default is nil.
  :avoid-nspace-gain
  gain of joint velocity to avoid joint limit applied in null space of main task in each IK loop. The avoiding velocity is calculated as \((((t\_max + t\_min)/2 - t) / ((t\_max - t\_min)/2))^2\). Default is 0.01.
  :avoid-weight-gain
   gain of dH/dt in calcuration of avoiding joint limits weight. :weight is devided by this avoiding joint limits weight. Default is 1.0.
   If :avoid-nspace-gain is 0, :weight is multipled by :weight instead.
  :avoid-collision-distance
   yellow zone. 0.1avoid-collision-distance is regarded as orange zone.
   If :avoid-collision-joint-gain is smaller than or equal to 0.0, yellow zone and orange zone become inactive. Default is 200[mm].
  :avoid-collision-null-gain
   \(k\_{null}\). Default is 1.0.
  :avoid-collision-joint-gain
   \(k\_{joint}\). Default is 1.0.
  :collision-avoidance-link-pair
   (list (list link1 link2) (list link3 link4) ...) with any length. Collision between paired links is cared. Default is (send self :collision-avoidance-link-pair-from-link-list link-list :obstacles (cadr (memq :obstacles args))).
  :additional-weight-list
   (list (list target-link1 additional-weight1) (list target-link2 additional-weight2) ...) with any length. The component of :weight corresponding to the parent joint of target-link is scaled by additional-weight. additional-weight should be float (if 1 dof), float-vector with length of the joint dof, or a function which returns the float or float-vector. if additional-weight is a function, it is called in each IK loop as (funcall additional-weight). Default is nil.
  :additional-nspace-list
   (list (list target-link1 var1) (list target-link2 var2) ...) with any length. In each IK loop, the parent joint of target-link is moved by the amount of var in null space of main task. var should be float (if 1dof), float-vector with the same length of the target joint dof, or a function which returns the float or float-vector.If var is float-vector, it is called in each IK loop as (funcall var). Default is nil.
  other-keys
   :manipulability-limit
    If manipulability of jacobian is smaller than manipulability-limit, diagonal matrix is added in calculation of sr-inverse. Default is 0.1.
  :manipulability-gain
   Weight of diagonal matrix in calculation of sr-inverse. Weight is calculated as (manipulability-gain (expt (- 1.0 (/ manipulability manipulability-limit)) 2)). Default is 0.001.
   :collision-distance-limit
    Threshold for collision detection. If collision is detected, the distance between the colliding links is considered to be :collision-distance-limit instead of actual distance. Default is 10[mm].
   :move-joints-hook
    A function which is called right after joints are moved in each IK loop as (funcall move-joints-hook). Default is nil.
:calc-jacobian-from-link-list = `[method]
link-list &rest args &key = move-target (transform-coords move-target) (rotation-axis (cond ((atom move-target) nil) (t (make-list (length move-target))))) (translation-axis (cond ((atom move-target) t) (t (make-list (length move-target) :initial-element t)))) (col-offset 0) (dim (send self :calc-target-axis-dimension rotation-axis translation-axis)) (fik-len (send self :calc-target-joint-dimension link-list)) fik (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) (tmp-v3a (instantiate float-vector 3)) (tmp-v3b (instantiate float-vector 3)) (tmp-m33 (make-matrix 3 3)) &allow-other-keys
Calculate jacobian matrix from link-list and move-target. Jacobian is represented in :transform-coords. Unit system is [m] or [rad], not [mm] or [deg].
Joint order for this jacobian matrix follows link-list order. Joint torque[Nm] order is also the same.
Ex1. One-Arm
(setq rarm-link-list(send robot:link-list (send robot:rarm :end-coords :parent)))
(send-all rarm-link-list:joint)
Ex2. Two-Arm
(setq arms-link-list(mapcar #’(lambda (l) (send robot:link-list (send robotl :end-coords :parent))) ’(:rarm :larm)))
(send-all (send robot:calc-union-link-list arms-link-list) :joint)

:self-collision-check &key (mode :all) (pairs (send self :collision-check-pairs)) (collision-func ’collision-check)

:collision-check-pairs &key ((:links ls) (cons (car links) (all-child-links (car links))))

:calc-vel-from-rot dif-rot rotation-axis &rest args &key (r-limit 0.5) (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) &allow-other-keys

:calc-vel-from-pos dif-pos translation-axis &rest args &key (p-limit 100.0) (tmp-v0 (instantiate float-vector 0)) (tmp-v1 (instantiate float-vector 1)) (tmp-v2 (instantiate float-vector 2)) (tmp-v3 (instantiate float-vector 3)) &allow-other-keys

:ik-convergence-check success dif-pos dif-rot rotation-axis translation-axis thre rthre centroid-thre target-centroid-pos centroid-offset-func cog-translation-axis &key (update-mass-properties t)

:draw-collision-debug-view **

:inverse-kinematics-args &rest args &key union-link-list rotation-axis translation-axis additional-jacobi-dimension &allow-other-keys

:calc-inverse-kinematics-nspace-from-link-list link-list &key (avoid-nspace-gain 0.01) (union-link-list (send self :calc-union-link-list link-list)) (fik-len (send self :calc-target-joint-dimension union-link-list)) (null-space) (debug-view) (additional-nspace-list) (cog-gain 0.0) (target-centroid-pos) (centroid-offset-func) (cog-translation-axis :z) (cog-null-space nil) (weight (fill (instantiate float-vector fik-len) 1.0)) (update-mass-properties t) (tmp-nspace (instantiate float-vector fik-len))

:calc-nspace-from-joint-limit avoid-nspace-gain union-link-list weight debug-view tmp-nspace

:calc-inverse-kinematics-weight-from-link-list link-list &key (avoid-weight-gain 1.0) (union-link-list (send self :calc-union-link-list link-list)) (fik-len (send self :calc-target-joint-dimension union-link-list)) (weight (fill (instantiate float-vector fik-len) 1)) (additional-weight-list) (debug-view) (tmp-weight (instantiate float-vector fik-len)) (tmp-len (instantiate float-vector fik-len))

:calc-weight-from-joint-limit avoid-weight-gain fik-len link-list union-link-list debug-view weight tmp-weight tmp-len

:reset-joint-angle-limit-weight-old union-link-list

:find-joint-angle-limit-weight-old-from-union-link-list union-link-list

:move-joints union-vel &rest args &key union-link-list (periodic-time 0.05) (joint-args) (debug-view nil) (move-joints-hook) &allow-other-keys

:collision-avoidance &rest args &key avoid-collision-distance avoid-collision-joint-gain avoid-collision-null-gain ((:collision-avoidance-link-pair pair-list)) (union-link-list) (link-list) (weight) (fik-len (send self :calc-target-joint-dimension union-link-list)) debug-view &allow-other-keys

:collision-avoidance-args pair link-list

:collision-avoidance-calc-distance &rest args &key union-link-list (warnp t) ((:collision-avoidance-link-pair pair-list)) ((:collision-distance-limit distance-limit) 10) &allow-other-keys

:collision-avoidance-link-pair-from-link-list link-lists &key obstacles ((:collision-avoidance-links collision-links) collision-avoidance-links) debug

:collision-avoidance-links &optional l

:calc-joint-angle-speed-gain union-link-list dav periodic-time

:calc-joint-angle-speed union-vel &rest args &key angle-speed (angle-speed-blending 0.5) jacobi jacobi# null-space i-j#j debug-view weight wmat tmp-len tmp-len2 fik-len &allow-other-keys

:calc-gradh-from-link-list link-list &optional (res (instantiate float-vector (length link-list)))

:calc-inverse-jacobian jacobi &rest args &key ((:manipulability-limit ml) 0.1) ((:manipulability-gain mg) 0.001) weight debug-view ret wmat tmat umat umat2 mat-tmp mat-tmp-rc tmp-mrr tmp-mrr2 &allow-other-keys

:calc-target-joint-dimension link-list

:calc-union-link-list link-list

:calc-target-axis-dimension rotation-axis translation-axis

eusmodel-validity-check robot

Check if the robot model is validate

calc-jacobian-default-rotate-vector paxis world-default-coords child-reverse transform-coords tmp-v3 tmp-m33

calc-jacobian-rotational fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

calc-jacobian-linear fik row column joint paxis child-link world-default-coords child-reverse move-target transform-coords rotation-axis translation-axis tmp-v0 tmp-v1 tmp-v2 tmp-v3 tmp-v3a tmp-v3b tmp-m33

calc-angle-speed-gain-scalar j dav i periodic-time

calc-angle-speed-gain-vector j dav i periodic-time

all-child-links s &optional (pred #’identity)

calc-dif-with-axis dif axis &optional tmp-v0 tmp-v1 tmp-v2

calc-target-joint-dimension joint-list

calc-joint-angle-min-max-for-limit-calculation j kk jamm

joint-angle-limit-weight j-l &optional (res (instantiate float-vector (calc-target-joint-dimension j-l)))

joint-angle-limit-nspace j-l &optional (res (instantiate float-vector (calc-target-joint-dimension j-l)))

calc-jacobian-from-link-list-including-robot-and-obj-virtual-joint link-list move-target obj-move-target robot &key (rotation-axis ’(t t)) (translation-axis ’(t t)) (fik (make-matrix (send robot :calc-target-axis-dimension rotation-axis translation-axis) (send robot :calc-target-joint-dimension link-list)))

append-obj-virtual-joint link-list target-coords &key (joint-class 6dof-joint) (joint-args) (vplink) (vplink-coords) (vclink-coords)

append-multiple-obj-virtual-joint link-list target-coords &key (joint-class ’(6dof-joint)) (joint-args ’(nil)) (vplink) (vplink-coords) (vclink-coords)

eusmodel-validity-check-one robot

line

:super = ** propertied-object**
:slots pvert nvert

:worldcoords **

Return a coordinates on the midpoint of the end points

coordinates

:super = ** propertied-object**
:slots rot pos

:difference-rotation coords &key (geometry::rotation-axis t)

return difference in rotation of given coords, rotation-axis can take (:x, :y, :z, :xx, :yy, :zz, :xm, :ym, :zm)

:difference-position coords &key (geometry::translation-axis t)

return difference in position of given coords, translation-axis can take (:x, :y, :z, :xy, :yz, :zx).

:axis geometry::axis

coordinates

:super = ** propertied-object**
:slots rot pos

:move-coords geometry::target geometry::at

fix ’at’ coords on ’self’ to ’target’

:transform geometry::c &optional (geometry::wrt :local)

:transformation geometry::c2 &optional (geometry::wrt :local)

:move-to geometry::c &optional (geometry::wrt :local) &aux geometry::cc

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed

coordinates

:super = ** propertied-object**
:slots rot pos

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed

coordinates

:super = ** propertied-object**
:slots rot pos

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed

bodyset

:super = ** cascaded-coords**
:slots (geometry::bodies :type cons)
:init = `[method]
coords &rest args &key = (name (intern (format nil bodyset A (system:address self)) KEYWORD)) ((:bodies geometry::bs)) &allow-other-keys

Create bodyset object

:bodies &rest args

:faces **

:worldcoords **

:draw-on &rest args

:init = `[method]
coords &rest args &key = (name (intern (format nil bodyset A (system:address self)) KEYWORD)) ((:bodies geometry::bs)) &allow-other-keys

Create bodyset object

:draw-on &rest args

:worldcoords **

:faces **

:bodies &rest args

midcoords geometry::p geometry::c1 geometry::c2

Returns mid (or p) coordinates of given two cooridnates c1 and c2

orient-coords-to-axis geometry::target-coords geometry::v &optional (geometry::axis :z) (geometry::eps epsilon)

orient ’axis’ in ’target-coords’ to the direction specified by ’v’ destructively.
’v’ must be non-zero vector.

geometry::face-to-triangle-aux geometry::f

triangulate the face.

geometry::face-to-triangle geometry::f

convert face to set of triangles.

geometry::face-to-tessel-triangle geometry::f geometry::num &optional (epsilon1.000000e-10)

return polygon if triangable, return nil if it is not.

body-to-faces geometry::abody

return triangled faces of given body

make-sphere geometry::r &rest args

make sphere of given r

make-ring geometry::ring-radius geometry::pipe-radius &rest args &key (geometry::segments 16)

make ring of given ring and pipe radius

make-fan-cylinder = `[function]
geometry::radius geometry::height &rest args &key = (geometry::segments 12) (angle 2pi) (geometry::mid-angle (/ angle 2.0))
make a cylinder whose base face is a fan. the angle of fan
is defined by :angle keyword. and, the csg of the returned body is
(:cylinder radius height segments angle)

x-of-cube geometry::cub

return x of cube.

y-of-cube geometry::cub

return y of cube.

z-of-cube geometry::cub

return z of cube.

height-of-cylinder geometry::cyl

return height of cylinder.

radius-of-cylinder geometry::cyl

return radius of cylinder.

radius-of-sphere geometry::sp

return radius of shape.

geometry::make-faceset-from-vertices geometry::vs

create faceset from vertices.

matrix-to-euler-angle geometry::m geometry::axis-order

return euler angle from matrix.

geometry::quaternion-from-two-vectors geometry::a geometry::b

Comupute quaternion which rotate vector a into b.

transform-coords geometry::c1 geometry::c2 &optional (geometry::c3 (let ((geometry::dim (send geometry::c1 :dimension))) (instance coordinates :newcoords (unit-matrix geometry::dim) (instantiate float-vector geometry::dim))))

geometry::face-to-triangle-rest-polygon geometry::f geometry::num geometry::edgs

geometry::face-to-triangle-make-simple geometry::f

body-to-triangles geometry::abody &optional (geometry::limit 50)

geometry::triangle-to-triangle geometry::aface &optional (geometry::limit 50)

robot-model

:super = ** cascaded-link**
:slots larm-end-coords rarm-end-coords lleg-end-coords rleg-end-coords head-end-coords torso-end-coords larm-root-link rarm-root-link lleg-root-link rleg-root-link head-root-link torso-root-link larm-collision-avoidance-links rarm-collision-avoidance-links larm rarm lleg rleg torso head force-sensors imu-sensors cameras support-polygons

:camera sensor-name

Returns camera with given name

:force-sensor sensor-name

Returns force sensor with given name

:imu-sensor sensor-name

Returns imu sensor of given name

:force-sensors **

Returns force sensors.

:imu-sensors **

Returns imu sensors.

:cameras **

Returns camera sensors.

:look-at-hand l/r

look at hand position, l/r supports :rarm, :larm, :arms, and ’(:rarm :larm)

:inverse-kinematics = `[method]
target-coords &rest args &key = look-at-target (move-target) (link-list (if (atom move-target) (send self :link-list (send move-target :parent)) (mapcar #’(lambda (mt) (send self :link-list (send mt :parent))) move-target))) &allow-other-keys
solve inverse kinematics, move move-target to target-coords
target-coords and move-target should be given.
link-list is set by default based on move-target ->root link link-list
:look-at-target
  target head looks at. This task is best-effort and only head joints are used. :look-at-target supports t, nil, float-vector, coords, list of float-vector, list of coords.
other-keys
  :inverse-kinematics internally calls :inverse-kinematics of cascaded-cords class and args are passed to it. See the explanation of :inverse-kinematics of cascaded-cords class.
:inverse-kinematics-loop = `[method]
dif-pos dif-rot &rest args &key = target-coords debug-view look-at-target (move-target) (link-list (if (atom move-target) (send self :link-list (send move-target :parent)) (mapcar #’(lambda (mt) (send self :link-list (send mt :parent))) move-target))) &allow-other-keys
move move-target using dif-pos and dif-rot,
look-at-target suppots t, nil, float-vector, coords, list of float-vector, list of coords
link-list is set by default based on move-target ->root link link-list
:inverse-kinematics-loop internally calls :inverse-kinematics-loop function of cascaded-coords class. See the explanation of :inverse-kinematics-loop in cascaded-coords class.

:look-at-target look-at-target &key (target-coords)

move robot head to look at targets, look-at-target support t/nil float-vector coordinates, center of list of float-vector or list of coordinates

:init-pose **

Set robot to initial posture.

:torque-vector = `[method]
&key = (force-list) (moment-list) (target-coords) (debug-view nil) (calc-statics-p t) (dt 0.005) (av (send self :angle-vector)) (root-coords (send (car (send self :links)) :copy-worldcoords)) (calc-torque-buffer-args (send self :calc-torque-buffer-args)) (distribute-total-wrench-to-torque-method (if (and (not (every #’null (send self :legs))) (not (and force-list moment-list target-coords))) :distribute-total-wrench-to-torque-method-default))

Returns torque vector

:calc-force-from-joint-torque = `[method]
limb all-torque &key = (move-target (send self limb :end-coords)) (use-torso)

Calculates end-effector force and moment from joint torques.

:fullbody-inverse-kinematics = `[method]
target-coords &rest args &key = (move-target) (link-list) (min (float-vector -500 -500 -500 -20 -20 -10)) (max (float-vector 500 500 25 20 20 10)) (root-link-virtual-joint-weight #f(0.1 0.1 0.1 0.1 0.5 0.5)) (target-centroid-pos (apply #’midpoint 0.5 (send self :legs :end-coords :worldpos))) (cog-gain 1.0) (cog-translation-axis :z) (centroid-offset-func nil) (centroid-thre 5.0) (additional-weight-list) (joint-args nil) (cog-null-space nil) (min-loop 2) &allow-other-keys
fullbody inverse kinematics for legged robot.
necessary args : target-coords, move-target, and link-list must include legs’ (or leg’s) parameters
ex. (send robot:fullbody-inverse-kinematics (list rarm-tc rleg-tc lleg-tc) :move-target (list rarm-mt rleg-mt lleg-mt) :link-list (list rarm-ll rleg-ll lleg-ll))
:min
  lower position limit of root link virtual joint (x y z roll pitch yaw). Default is #f(-500[mm] -500[mm] -500[mm] -20[deg] -20[deg] -10[deg]).
:max
  upper position limit of root link virtual joint (x y z roll pitch yaw). Default is #f(500[mm] 500[mm] 25[mm] 20[deg] 20[deg] 10[deg]).
:root-link-virtual-joint-weight
  float-vector of inverse weight of velocity of root link virtual joint or a function which returns the float-vector (x y z roll pitch yaw). This works in the same way as :additional-weight-list in cascaded-coords::inverse-kinematics. Default is #f(0.1 0.1 0.1 0.1 0.5 0.5).
:joint-args
  list of other arguments passed to :init function of root link virtual joint (6dof-joint class).
   :max-joint-velocity
    limit of velocity of root link virtual joint (x y z roll pitch yaw). Default is #f((/ 0.08 0.05)[m/s] (/ 0.08 0.05)[m/s] (/ 0.08 0.05)[m/s] (/ pi 4)[rad/s] (/ pi 4)[rad/s] (/ pi 4)[rad/s]))
other-keys
  :fullbody-inverse-kinematics internally calls :inverse-kinematics and args are passed to it. See the explanation of :inverse-kinematics.

:print-vector-for-robot-limb vec

Print angle vector with limb alingment and limb indent.
For example, if robot is rarm, larm, and torso, print result is:
#f(
rarm-j0 ... rarm-jN
larm-j0 ... larm-jN
torso-j0 ... torso-jN
)
:calc-zmp-from-forces-moments = `[method]
forces moments &key = (wrt :world) (limbs (if (send self :force-sensors) (remove nil (mapcar #’(lambda (fs) (find-if #’(lambda (l) (equal fs (car (send self l :force-sensors)))) ’(:rleg :lleg))) (send self :force-sensors))) ’(:rleg :lleg))) (force-sensors (mapcar #’(lambda (l) (car (send self l :force-sensors))) limbs)) (cop-coords (mapcar #’(lambda (l) (send self l :end-coords)) limbs)) (fz-thre 0.001) (limb-cop-fz-list (mapcar #’(lambda (fs f m cc) (let ((fsp (scale 0.001 (send fs :worldpos))) (nf (send fs :rotate-vector f)) (nm (send fs :rotate-vector m))) (send self :calc-cop-from-force-moment nf nm fs cc :fz-thre fz-thre :return-all-values t))) force-sensors forces moments cop-coords))
Calculate zmp[mm] from sensor local forces and moments
If force_z is large, zmp can be defined and returns 3D zmp.
Otherwise, zmp cannot be defined and returns nil.

:foot-midcoords &optional (mid 0.5)

Calculate midcoords of :rleg and :lleg end-coords.
In the following codes, leged robot is assumed.
:fix-leg-to-coords = `[method]
fix-coords &optional (l/r :both) &key = (mid 0.5) &allow-other-keys
Fix robot’s legs to a coords
In the following codes, leged robot is assumed.
:move-centroid-on-foot = `[method]
leg fix-limbs &rest args &key = (thre (mapcar #’(lambda (x) (if (memq x ’(:rleg :lleg)) 1 5)) fix-limbs)) (rthre (mapcar #’(lambda (x) (deg2rad (if (memq x ’(:rleg :lleg)) 1 5))) fix-limbs)) (mid 0.5) (target-centroid-pos (if (eq leg :both) (apply #’midpoint mid (mapcar #’(lambda (tmp-leg) (send self tmp-leg :end-coords :worldpos)) (remove-if-not #’(lambda (x) (memq x ’(:rleg :lleg))) fix-limbs))) (send self leg :end-coords :worldpos))) (fix-limbs-target-coords (mapcar #’(lambda (x) (send self x :end-coords :copy-worldcoords)) fix-limbs)) (root-link-virtual-joint-weight #f(0.1 0.1 0.0 0.0 0.0 0.5)) &allow-other-keys
Move robot COG to change centroid-on-foot location,
leg : legs for target of robot’s centroid, which should be :both, :rleg, and :lleg.
fix-limbs : limb names which are fixed in this IK.
:calc-walk-pattern-from-footstep-list = `[method]
footstep-list &key = (default-step-height 50) (dt 0.1) (default-step-time 1.0) (solve-angle-vector-args) (debug-view nil) ((:all-limbs al) (if (send self :force-sensors) (remove nil (mapcar #’(lambda (fs) (find-if #’(lambda (l) (equal fs (car (send self l :force-sensors)))) ’(:rleg :lleg))) (send self :force-sensors))) ’(:rleg :lleg))) ((:default-zmp-offsets dzo) (mapcan #’(lambda (x) (list x (float-vector 0 0 0))) al)) (init-pose-function #’(lambda nil (send self :move-centroid-on-foot :both ’(:rleg :lleg)))) (start-with-double-support t) (end-with-double-support t) (ik-thre 1) (ik-rthre (deg2rad 1)) (q 1.0) (r 1.000000e-06) (calc-zmp t)
Calculate walking pattern from foot step list and return pattern list as a list of angle-vector, root-coords, time, and so on.
footstep-list should be given.
:footstep-list
  (list footstep1 footstep2 ...). :footstep-list can be any length. Each footstep indicates the destinations of swing legs in each step.
  footstep should be list of coordinate whose :name is identical with one swing leg and whose coords is the destination of that leg. If number of swing legs in a step is one, the footstep can be a coordinate.
  footstep1 is only for intialization and not executed.
:default-step-height
  Height of swing leg cycloid trajectories. Default is 50[mm].
:dt
  Sampling time of preview control and output walk pattern. Default is 0.1[s].
:default-step-time
  Reference time of each step. The first 10 percent and the last 10 percent of default-step-time is double support phase. Default is 1.0[s].
:solve-angle-vector-args
  :move-centroid-on-foot is used to solve IK in :calc-walk-pattern-from-footstep-list. :solve-angle-vector-args is passed to :move-centroid-on-foot in the form of (sendself :move-centroid-on-foot ... solve-angle-vector-args). Default is nil.
:debug-view
  Set t to show visualization. Default is nil.
:all-limbs
  list of limb names. In each walking step, limbs in :all-limbs but not assigned as swing legs by :footstep-list are considered to be support legs. Default is ’(:rleg :lleg) sorted in force-sensors order.
:default-zmp-offsets
  (list limbname1 offset1 limbname2 offset2 ...). :default-zmp-offsets should include every limb in :all-limbs. offset is a float-vector[mm] and local offset of reference zmp position from end-coords. Default offset is #F(0 0 0)[mm].
:init-pose-function
  A function which initialize robot’s pose. Walking pattern is generated from this initial pose. :init-pose-function is called once at the start of walking pattern generation in the form of (funcall init-pose-function). Default is #’(lambda () (send self :move-centroid-on-foot :both ’(:rleg :lleg))).
:start-with-double-support
  At the start of walking pattern generation, the initial position of reference zmp is
   t: midpoint of all-limbs.
   nil: midpoint of swing legs of footstep1.
  Default is t.
:end-with-double-support
  At the end of walking pattern generation, the final position of reference zmp is
   t: midpoint of all-limbs.
   nil: midpoint of support legs of the last footstep.
  Default is t.
:ik-thre
  Threshold for position error to terminate IK iteration. Default is 1[mm].
:ik-rthre
  Threshold for rotation error to terminate IK iteration. Default is (deg2rad 1)[rad].
:q
  Weight Q of the cost function of preview control. Default is 1.0.
:r
  Weight R of the cost function of preview control. Default is 1e-6.
:calc-zmp
  Set t to calculate resultant ZMP after IK. The calculated ZMP is visualized if :debug-view is t, and stored as czmp in return value. Default is t.

:gen-footstep-parameter &key (ratio 1.0)

Generate footstep parameter

:go-pos-params->footstep-list = `[method]
xx yy th &key = ((:footstep-parameter prm) (send self :footstep-parameter)) ((:default-half-offset defp) (cadr (memq :default-half-offset prm))) ((:forward-offset-length xx-max) (cadr (memq :forward-offset-length prm))) ((:outside-offset-length yy-max) (cadr (memq :outside-offset-length prm))) ((:rotate-rad th-max) (abs (rad2deg (cadr (memq :rotate-rad prm))))) (gen-go-pos-step-node-func #’(lambda (mc leg leg-translate-pos) (let ((cc (send (send mc :copy-worldcoords) :translate (cadr (assoc leg leg-translate-pos))))) (send cc :name leg) cc)))

Calculate foot step list from goal x position [mm], goal y position [mm], and goal yaw orientation [deg].

:go-pos-quadruped-params->footstep-list xx yy th &key (type :crawl)

Calculate foot step list for quadruped walking from goal x position [mm], goal y position [mm], and goal yaw orientation [deg].

:support-polygons **

Return support polygons.

:support-polygon name

Return support polygon.
If name is list, return convex hull of all polygons.
Otherwise, return polygon with given name

:make-default-linear-link-joint-between-attach-coords attach-coords-0 attach-coords-1 end-coords-name linear-joint-name

Make default linear arctuator module such as muscle and cylinder and append lins and joint-list.
Module includes parent-link =>(j0) =>l0 =>(j1) =>l1 (linear actuator) =>(j2) =>l2 =>end-coords.
attach-coords-0 is root side coords which linear actulator is attached to.
attach-coords-1 is end side coords which linear actulator is attached to.
end-coords-name is the name of end-coords.
linear-joint-name is the name of linear actuator.
:calc-static-balance-point = `[method]
&key = (target-points (mapcar #’(lambda (tmp-arm) (send (send self tmp-arm :end-coords) :worldpos)) ’(:rarm :larm))) (force-list (make-list (length target-points) :initial-element (float-vector 0 0 0))) (moment-list (make-list (length target-points) :initial-element (float-vector 0 0 0))) (static-balance-point-height (elt (apply #’midpoint 0.5 (send self :legs :end-coords :worldpos)) 2)) (update-mass-properties t)
Calculate static balance point which is equivalent to static extended ZMP.
The output is expressed by the world coordinates.
target-points are end-effector points on which force-list and moment-list apply.
force-list [N] and moment-list [Nm] are list of force and moment that robot receives at target-points.
static-balance-point-height is height of static balance point [mm].

:init-ending **

:rarm-end-coords **

:larm-end-coords **

:rleg-end-coords **

:lleg-end-coords **

:head-end-coords **

:torso-end-coords **

:rarm-root-link **

:larm-root-link **

:rleg-root-link **

:lleg-root-link **

:head-root-link **

:torso-root-link **

:limb limb method &rest args

:inverse-kinematics-loop-for-look-at limb &rest args

:gripper limb &rest args

:get-sensor-method sensor-type sensor-name

:get-sensors-method-by-limb sensors-type limb

:larm &rest args

:rarm &rest args

:lleg &rest args

:rleg &rest args

:head &rest args

:torso &rest args

:arms &rest args

:legs &rest args

:distribute-total-wrench-to-torque-method-default **

:joint-angle-limit-nspace-for-6dof &key (avoid-nspace-gain 0.01) (limbs ’(:rleg :lleg))

:joint-order limb &optional jname-list

:draw-gg-debug-view end-coords-list contact-state rz cog pz czmp dt

:footstep-parameter **

:make-support-polygons **

:make-sole-polygon name

:calc-zmp-from-forces-moments = `[method]
forces moments &key = (wrt :world) (limbs (if (send self :force-sensors) (remove nil (mapcar #’(lambda (fs) (find-if #’(lambda (l) (equal fs (car (send self l :force-sensors)))) ’(:rleg :lleg))) (send self :force-sensors))) ’(:rleg :lleg))) (force-sensors (mapcar #’(lambda (l) (car (send self l :force-sensors))) limbs)) (cop-coords (mapcar #’(lambda (l) (send self l :end-coords)) limbs)) (fz-thre 0.001) (limb-cop-fz-list (mapcar #’(lambda (fs f m cc) (let ((fsp (scale 0.001 (send fs :worldpos))) (nf (send fs :rotate-vector f)) (nm (send fs :rotate-vector m))) (send self :calc-cop-from-force-moment nf nm fs cc :fz-thre fz-thre :return-all-values t))) force-sensors forces moments cop-coords))
Calculate zmp[mm] from sensor local forces and moments
If force_z is large, zmp can be defined and returns 3D zmp.
Otherwise, zmp cannot be defined and returns nil.

:print-vector-for-robot-limb vec

Print angle vector with limb alingment and limb indent.
For example, if robot is rarm, larm, and torso, print result is:
#f(
rarm-j0 ... rarm-jN
larm-j0 ... larm-jN
torso-j0 ... torso-jN
)
:fullbody-inverse-kinematics = `[method]
target-coords &rest args &key = (move-target) (link-list) (min (float-vector -500 -500 -500 -20 -20 -10)) (max (float-vector 500 500 25 20 20 10)) (root-link-virtual-joint-weight #f(0.1 0.1 0.1 0.1 0.5 0.5)) (target-centroid-pos (apply #’midpoint 0.5 (send self :legs :end-coords :worldpos))) (cog-gain 1.0) (cog-translation-axis :z) (centroid-offset-func nil) (centroid-thre 5.0) (additional-weight-list) (joint-args nil) (cog-null-space nil) (min-loop 2) &allow-other-keys
fullbody inverse kinematics for legged robot.
necessary args : target-coords, move-target, and link-list must include legs’ (or leg’s) parameters
ex. (send robot:fullbody-inverse-kinematics (list rarm-tc rleg-tc lleg-tc) :move-target (list rarm-mt rleg-mt lleg-mt) :link-list (list rarm-ll rleg-ll lleg-ll))
:min
  lower position limit of root link virtual joint (x y z roll pitch yaw). Default is #f(-500[mm] -500[mm] -500[mm] -20[deg] -20[deg] -10[deg]).
:max
  upper position limit of root link virtual joint (x y z roll pitch yaw). Default is #f(500[mm] 500[mm] 25[mm] 20[deg] 20[deg] 10[deg]).
:root-link-virtual-joint-weight
  float-vector of inverse weight of velocity of root link virtual joint or a function which returns the float-vector (x y z roll pitch yaw). This works in the same way as :additional-weight-list in cascaded-coords::inverse-kinematics. Default is #f(0.1 0.1 0.1 0.1 0.5 0.5).
:joint-args
  list of other arguments passed to :init function of root link virtual joint (6dof-joint class).
   :max-joint-velocity
    limit of velocity of root link virtual joint (x y z roll pitch yaw). Default is #f((/ 0.08 0.05)[m/s] (/ 0.08 0.05)[m/s] (/ 0.08 0.05)[m/s] (/ pi 4)[rad/s] (/ pi 4)[rad/s] (/ pi 4)[rad/s]))
other-keys
  :fullbody-inverse-kinematics internally calls :inverse-kinematics and args are passed to it. See the explanation of :inverse-kinematics.
:calc-force-from-joint-torque = `[method]
limb all-torque &key = (move-target (send self limb :end-coords)) (use-torso)

Calculates end-effector force and moment from joint torques.

:torque-vector = `[method]
&key = (force-list) (moment-list) (target-coords) (debug-view nil) (calc-statics-p t) (dt 0.005) (av (send self :angle-vector)) (root-coords (send (car (send self :links)) :copy-worldcoords)) (calc-torque-buffer-args (send self :calc-torque-buffer-args)) (distribute-total-wrench-to-torque-method (if (and (not (every #’null (send self :legs))) (not (and force-list moment-list target-coords))) :distribute-total-wrench-to-torque-method-default))

Returns torque vector

:init-pose **

Set robot to initial posture.

:look-at-target look-at-target &key (target-coords)

move robot head to look at targets, look-at-target support t/nil float-vector coordinates, center of list of float-vector or list of coordinates

:inverse-kinematics-loop = `[method]
dif-pos dif-rot &rest args &key = target-coords debug-view look-at-target (move-target) (link-list (if (atom move-target) (send self :link-list (send move-target :parent)) (mapcar #’(lambda (mt) (send self :link-list (send mt :parent))) move-target))) &allow-other-keys
move move-target using dif-pos and dif-rot,
look-at-target suppots t, nil, float-vector, coords, list of float-vector, list of coords
link-list is set by default based on move-target ->root link link-list
:inverse-kinematics-loop internally calls :inverse-kinematics-loop function of cascaded-coords class. See the explanation of :inverse-kinematics-loop in cascaded-coords class.
:inverse-kinematics = `[method]
target-coords &rest args &key = look-at-target (move-target) (link-list (if (atom move-target) (send self :link-list (send move-target :parent)) (mapcar #’(lambda (mt) (send self :link-list (send mt :parent))) move-target))) &allow-other-keys
solve inverse kinematics, move move-target to target-coords
target-coords and move-target should be given.
link-list is set by default based on move-target ->root link link-list
:look-at-target
  target head looks at. This task is best-effort and only head joints are used. :look-at-target supports t, nil, float-vector, coords, list of float-vector, list of coords.
other-keys
  :inverse-kinematics internally calls :inverse-kinematics of cascaded-cords class and args are passed to it. See the explanation of :inverse-kinematics of cascaded-cords class.

:look-at-hand l/r

look at hand position, l/r supports :rarm, :larm, :arms, and ’(:rarm :larm)

:cameras **

Returns camera sensors.

:imu-sensors **

Returns imu sensors.

:force-sensors **

Returns force sensors.

:imu-sensor sensor-name

Returns imu sensor of given name

:force-sensor sensor-name

Returns force sensor with given name

:camera sensor-name

Returns camera with given name

:joint-order limb &optional jname-list

:joint-angle-limit-nspace-for-6dof &key (avoid-nspace-gain 0.01) (limbs ’(:rleg :lleg))

:distribute-total-wrench-to-torque-method-default **

:legs &rest args

:arms &rest args

:torso &rest args

:head &rest args

:rleg &rest args

:lleg &rest args

:rarm &rest args

:larm &rest args

:get-sensors-method-by-limb sensors-type limb

:get-sensor-method sensor-type sensor-name

:gripper limb &rest args

:inverse-kinematics-loop-for-look-at limb &rest args

:limb limb method &rest args

:torso-root-link **

:head-root-link **

:lleg-root-link **

:rleg-root-link **

:larm-root-link **

:rarm-root-link **

:torso-end-coords **

:head-end-coords **

:lleg-end-coords **

:rleg-end-coords **

:larm-end-coords **

:rarm-end-coords **

:init-ending **

:calc-static-balance-point = `[method]
&key = (target-points (mapcar #’(lambda (tmp-arm) (send (send self tmp-arm :end-coords) :worldpos)) ’(:rarm :larm))) (force-list (make-list (length target-points) :initial-element (float-vector 0 0 0))) (moment-list (make-list (length target-points) :initial-element (float-vector 0 0 0))) (static-balance-point-height (elt (apply #’midpoint 0.5 (send self :legs :end-coords :worldpos)) 2)) (update-mass-properties t)
Calculate static balance point which is equivalent to static extended ZMP.
The output is expressed by the world coordinates.
target-points are end-effector points on which force-list and moment-list apply.
force-list [N] and moment-list [Nm] are list of force and moment that robot receives at target-points.
static-balance-point-height is height of static balance point [mm].

:make-default-linear-link-joint-between-attach-coords attach-coords-0 attach-coords-1 end-coords-name linear-joint-name

Make default linear arctuator module such as muscle and cylinder and append lins and joint-list.
Module includes parent-link =>(j0) =>l0 =>(j1) =>l1 (linear actuator) =>(j2) =>l2 =>end-coords.
attach-coords-0 is root side coords which linear actulator is attached to.
attach-coords-1 is end side coords which linear actulator is attached to.
end-coords-name is the name of end-coords.
linear-joint-name is the name of linear actuator.

:support-polygon name

Return support polygon.
If name is list, return convex hull of all polygons.
Otherwise, return polygon with given name

:support-polygons **

Return support polygons.

:go-pos-quadruped-params->footstep-list xx yy th &key (type :crawl)

Calculate foot step list for quadruped walking from goal x position [mm], goal y position [mm], and goal yaw orientation [deg].

:go-pos-params->footstep-list = `[method]
xx yy th &key = ((:footstep-parameter prm) (send self :footstep-parameter)) ((:default-half-offset defp) (cadr (memq :default-half-offset prm))) ((:forward-offset-length xx-max) (cadr (memq :forward-offset-length prm))) ((:outside-offset-length yy-max) (cadr (memq :outside-offset-length prm))) ((:rotate-rad th-max) (abs (rad2deg (cadr (memq :rotate-rad prm))))) (gen-go-pos-step-node-func #’(lambda (mc leg leg-translate-pos) (let ((cc (send (send mc :copy-worldcoords) :translate (cadr (assoc leg leg-translate-pos))))) (send cc :name leg) cc)))

Calculate foot step list from goal x position [mm], goal y position [mm], and goal yaw orientation [deg].

:gen-footstep-parameter &key (ratio 1.0)

Generate footstep parameter

:calc-walk-pattern-from-footstep-list = `[method]
footstep-list &key = (default-step-height 50) (dt 0.1) (default-step-time 1.0) (solve-angle-vector-args) (debug-view nil) ((:all-limbs al) (if (send self :force-sensors) (remove nil (mapcar #’(lambda (fs) (find-if #’(lambda (l) (equal fs (car (send self l :force-sensors)))) ’(:rleg :lleg))) (send self :force-sensors))) ’(:rleg :lleg))) ((:default-zmp-offsets dzo) (mapcan #’(lambda (x) (list x (float-vector 0 0 0))) al)) (init-pose-function #’(lambda nil (send self :move-centroid-on-foot :both ’(:rleg :lleg)))) (start-with-double-support t) (end-with-double-support t) (ik-thre 1) (ik-rthre (deg2rad 1)) (q 1.0) (r 1.000000e-06) (calc-zmp t)
Calculate walking pattern from foot step list and return pattern list as a list of angle-vector, root-coords, time, and so on.
footstep-list should be given.
:footstep-list
  (list footstep1 footstep2 ...). :footstep-list can be any length. Each footstep indicates the destinations of swing legs in each step.
  footstep should be list of coordinate whose :name is identical with one swing leg and whose coords is the destination of that leg. If number of swing legs in a step is one, the footstep can be a coordinate.
  footstep1 is only for intialization and not executed.
:default-step-height
  Height of swing leg cycloid trajectories. Default is 50[mm].
:dt
  Sampling time of preview control and output walk pattern. Default is 0.1[s].
:default-step-time
  Reference time of each step. The first 10 percent and the last 10 percent of default-step-time is double support phase. Default is 1.0[s].
:solve-angle-vector-args
  :move-centroid-on-foot is used to solve IK in :calc-walk-pattern-from-footstep-list. :solve-angle-vector-args is passed to :move-centroid-on-foot in the form of (sendself :move-centroid-on-foot ... solve-angle-vector-args). Default is nil.
:debug-view
  Set t to show visualization. Default is nil.
:all-limbs
  list of limb names. In each walking step, limbs in :all-limbs but not assigned as swing legs by :footstep-list are considered to be support legs. Default is ’(:rleg :lleg) sorted in force-sensors order.
:default-zmp-offsets
  (list limbname1 offset1 limbname2 offset2 ...). :default-zmp-offsets should include every limb in :all-limbs. offset is a float-vector[mm] and local offset of reference zmp position from end-coords. Default offset is #F(0 0 0)[mm].
:init-pose-function
  A function which initialize robot’s pose. Walking pattern is generated from this initial pose. :init-pose-function is called once at the start of walking pattern generation in the form of (funcall init-pose-function). Default is #’(lambda () (send self :move-centroid-on-foot :both ’(:rleg :lleg))).
:start-with-double-support
  At the start of walking pattern generation, the initial position of reference zmp is
   t: midpoint of all-limbs.
   nil: midpoint of swing legs of footstep1.
  Default is t.
:end-with-double-support
  At the end of walking pattern generation, the final position of reference zmp is
   t: midpoint of all-limbs.
   nil: midpoint of support legs of the last footstep.
  Default is t.
:ik-thre
  Threshold for position error to terminate IK iteration. Default is 1[mm].
:ik-rthre
  Threshold for rotation error to terminate IK iteration. Default is (deg2rad 1)[rad].
:q
  Weight Q of the cost function of preview control. Default is 1.0.
:r
  Weight R of the cost function of preview control. Default is 1e-6.
:calc-zmp
  Set t to calculate resultant ZMP after IK. The calculated ZMP is visualized if :debug-view is t, and stored as czmp in return value. Default is t.
:move-centroid-on-foot = `[method]
leg fix-limbs &rest args &key = (thre (mapcar #’(lambda (x) (if (memq x ’(:rleg :lleg)) 1 5)) fix-limbs)) (rthre (mapcar #’(lambda (x) (deg2rad (if (memq x ’(:rleg :lleg)) 1 5))) fix-limbs)) (mid 0.5) (target-centroid-pos (if (eq leg :both) (apply #’midpoint mid (mapcar #’(lambda (tmp-leg) (send self tmp-leg :end-coords :worldpos)) (remove-if-not #’(lambda (x) (memq x ’(:rleg :lleg))) fix-limbs))) (send self leg :end-coords :worldpos))) (fix-limbs-target-coords (mapcar #’(lambda (x) (send self x :end-coords :copy-worldcoords)) fix-limbs)) (root-link-virtual-joint-weight #f(0.1 0.1 0.0 0.0 0.0 0.5)) &allow-other-keys
Move robot COG to change centroid-on-foot location,
leg : legs for target of robot’s centroid, which should be :both, :rleg, and :lleg.
fix-limbs : limb names which are fixed in this IK.
:fix-leg-to-coords = `[method]
fix-coords &optional (l/r :both) &key = (mid 0.5) &allow-other-keys
Fix robot’s legs to a coords
In the following codes, leged robot is assumed.

:foot-midcoords &optional (mid 0.5)

Calculate midcoords of :rleg and :lleg end-coords.
In the following codes, leged robot is assumed.

:make-sole-polygon name

:make-support-polygons **

:footstep-parameter **

:draw-gg-debug-view end-coords-list contact-state rz cog pz czmp dt

make-default-robot-link len radius axis name &optional extbody

センサモデル

sensor-model

:super = ** body**
:slots data profile

:init shape &key name &allow-other-keys

:draw-sensor v

:read **

:simulate model

:signal rawinfo

:profile &optional p

bumper-model

:super = ** sensor-model**
:slots bumper-threshold
:init = `[method]
b &rest args &key = ((:bumper-threshold bt) 20) name

Create bumper model, b is the shape of an object and bt is the threshold in distance[mm].

:simulate objs

Simulate bumper, with given objects, return 1 if the sensor detects an object and 0 if not.

:draw vwer

:draw-sensor vwer

:simulate objs

Simulate bumper, with given objects, return 1 if the sensor detects an object and 0 if not.

:init = `[method]
b &rest args &key = ((:bumper-threshold bt) 20) name

Create bumper model, b is the shape of an object and bt is the threshold in distance[mm].

:draw-sensor vwer

:draw vwer

camera-model

:super = ** sensor-model**
:slots (vwing :forward (:projection :newprojection :screen :view :viewpoint :view-direction :viewdistance :yon :hither)) img-viewer pwidth pheight
:init = `[method]
b &rest args &key = ((:width pw) 320) ((:height ph) 240) (view-up #f(0.0 1.0 0.0)) (viewdistance 100.0) (hither 100.0) (yon 10000.0) &allow-other-keys

Create camera model. b is the shape of an object

:create-viewer &optional cv &key (no-window nil)

Create camera viewer, or set viewer

:width **

Returns width of the camera in pixel.

:height **

Returns height of the camera in pixel.

:fovy **

Returns field of view in degree

:cx **

Returns center x.

:cy **

Returns center y.

:fx **

Returns focal length of x.

:fy **

Returns focal length of y.

:screen-point pos

Returns point in screen corresponds to the given pos.

:3d-point x y d

Returns 3d position

:ray x y

Returns ray vector of given x and y.

:draw-on = `[method]
&rest args &key = ((:viewer vwer) viewer) &allow-other-keys

Draw camera raw in irtviewer, ex (send cam :draw-on :flush t)

:draw-objects objs

Draw objects in camera viewer, expected type of objs is list of objects

:get-image = `[method]
&key = (with-points) (with-colors)

Get image objects you need to call :draw-objects before calling this function

:select-drawmode mode objs

Change drawmode for drawing with :draw-objects methods. mode is symbol of mode, ’hid is symbol for hidden line mode, the other symbols indicate default mode. objs is the same objects using :draw-objects.

:viewing &rest args

:image-viewer &rest args

:draw-sensor vwer &key flush (width 1) (color (float-vector 1 1 1))

:draw-objects-raw vwr objs

:get-image-raw vwr &key (points) (colors)

:select-drawmode mode objs

Change drawmode for drawing with :draw-objects methods. mode is symbol of mode, ’hid is symbol for hidden line mode, the other symbols indicate default mode. objs is the same objects using :draw-objects.

:get-image = `[method]
&key = (with-points) (with-colors)

Get image objects you need to call :draw-objects before calling this function

:draw-objects objs

Draw objects in camera viewer, expected type of objs is list of objects

:draw-on = `[method]
&rest args &key = ((:viewer vwer) viewer) &allow-other-keys

Draw camera raw in irtviewer, ex (send cam :draw-on :flush t)

:ray x y

Returns ray vector of given x and y.

:3d-point x y d

Returns 3d position

:screen-point pos

Returns point in screen corresponds to the given pos.

:fy **

Returns focal length of y.

:fx **

Returns focal length of x.

:cy **

Returns center y.

:cx **

Returns center x.

:fovy **

Returns field of view in degree

:height **

Returns height of the camera in pixel.

:width **

Returns width of the camera in pixel.

:create-viewer &optional cv &key (no-window nil)

Create camera viewer, or set viewer

:init = `[method]
b &rest args &key = ((:width pw) 320) ((:height ph) 240) (view-up #f(0.0 1.0 0.0)) (viewdistance 100.0) (hither 100.0) (yon 10000.0) &allow-other-keys

Create camera model. b is the shape of an object

:get-image-raw vwr &key (points) (colors)

:draw-objects-raw vwr objs

:draw-sensor vwer &key flush (width 1) (color (float-vector 1 1 1))

:image-viewer &rest args

:viewing &rest args

make-camera-from-param = `[function]
&key = pwidth pheight fx fy cx cy (tx 0) (ty 0) parent-coords name create-viewer (no-window nil)

Create camera object from given parameters.

環境モデル

scene-model

:super = ** cascaded-coords**
:slots name objs
:init = `[method]
&rest args &key = ((:name n) scene) ((:objects o)) ((:remove-wall w)) &allow-other-keys

Create scene model

:objects **

Returns objects in the scene.

:add-objects objects

Add objects to scene with identifiable names. Returns all objects.

:add-object obj

Add object to scene with identifiable name. Returns all objects.

:remove-objects objs-or-names

Remove objects or objects with given names from scene. Returns removed objects.

:remove-object obj-or-name

Remove object or object with given name from scene. Returns removed object.

:find-object name

Returns objects with given name.

:add-spots spots

Add spots to scene with identifiable names. All spots will be :assoc with this scene. Returns T if added spots successfly, otherwise returns NIL.

:add-spot spot

Add spot to scene with identifiable name. The spot will be :assoc with this scene. Returns T if spot is added successfly, otherwise returns NIL.

:remove-spots spots

Remove spots from this scene. All spots will be :dissoc with this scene. Returns removed spots.

:remove-spot spot

Remove spot from scene. the spot will be :dissoc with this scene. Returns removed spot.

:spots **

Return all spots in the scene.

:object name

Return an object of given name.

:spot name

Return a spot of given name.

:bodies **

:spot name

Return a spot of given name.

:object name

Return an object of given name.

:spots **

Return all spots in the scene.

:remove-spot spot

Remove spot from scene. the spot will be :dissoc with this scene. Returns removed spot.

:remove-spots spots

Remove spots from this scene. All spots will be :dissoc with this scene. Returns removed spots.

:add-spot spot

Add spot to scene with identifiable name. The spot will be :assoc with this scene. Returns T if spot is added successfly, otherwise returns NIL.

:add-spots spots

Add spots to scene with identifiable names. All spots will be :assoc with this scene. Returns T if added spots successfly, otherwise returns NIL.

:find-object name

Returns objects with given name.

:remove-object obj-or-name

Remove object or object with given name from scene. Returns removed object.

:remove-objects objs-or-names

Remove objects or objects with given names from scene. Returns removed objects.

:add-object obj

Add object to scene with identifiable name. Returns all objects.

:add-objects objects

Add objects to scene with identifiable names. Returns all objects.

:objects **

Returns objects in the scene.

:init = `[method]
&rest args &key = ((:name n) scene) ((:objects o)) ((:remove-wall w)) &allow-other-keys

Create scene model

:bodies **

動力学計算・歩行動作生成

歩行動作生成

歩行動作は予見制御を用いて生成される。文献 [15] [16] [17]_に述べられている式や文章を引用しつつ、説明する。

歩行動作は以下の手順で生成される。

  1. 脚の逆運動学が解ける範囲内の歩幅で、ロボットが足をつく位置と時間を計画する。
  2. 地面についていない足は、次につく位置までサイクロイド補間する。
  3. ZMPが地面についている足の位置とできる限り一致するような重心軌道を生成する。
  4. 計画された足と重心の軌道を満たすような関節角度軌道を逆運動学によって逐次求める。

ここでは、3の手順について詳しく説明する。

X方向の運動について、始めに次のような制御系を考える。Y方向の運動についても同様に議論することが可能である。

\[\begin{split}\begin{aligned} && \left\{ \begin{array}{l} x_{k+1} = A x_k + b u_k \\ p_k = c x_k \end{array} \right. \eqlabel{preview_control}\\ && x_k \equiv \left[ \begin{array}{c} x(k\Delta t)\\ \dot x(k\Delta t)\\ \ddot x(k\Delta t) \end{array} \right] ~~~~ u_k \equiv u(k\Delta t) ~~~~ p_k \equiv p(k\Delta t)\nonumber\\ && A \equiv \left[ \begin{array}{c c c} 1 & \Delta t & \Delta t^2 / 2\\ 0 & 1 & \Delta t\\ 0 & 0 & 1 \end{array} \right] ~~~~ b \equiv \left[ \begin{array}{c} \Delta t^3 / 6\\ \Delta t^2 / 2\\ \Delta t \end{array} \right] ~~~~ c \equiv \left[ \begin{array}{c c c} 1 & 0 & -z_c/g \end{array} \right]\nonumber\end{aligned}\end{split}\]

\(x\)はロボットの重心位置、\(u\)は重心の加速度の時間微分(jerk)、\(p\)はZMPである。

次に、このシステムを次のような拡大系に置き換える。

\[\begin{split}\begin{aligned} && \left\{ \begin{array}{l} x^\ast_{k+1} = \tilde{A} x^\ast_k + \tilde{b} \Delta u_k \\ p_k = \tilde{c} x^\ast_k \end{array} \right. \eqlabel{extended_preview_control}\\ && \Delta u_k \equiv u_k - u_{k-1} ~~~~ \Delta x_k \equiv x_k - x_{k-1} ~~~~ x^\ast_k \equiv \left[ \begin{array}{c} p_k\\ \Delta x_k \end{array} \right] \nonumber\\ && \tilde{A} \equiv \left[ \begin{array}{c c} 1 & cA\\ 0 & A \end{array} \right] ~~~~ \tilde{b} \equiv \left[ \begin{array}{c} cb\\ b \end{array} \right] ~~~~ \tilde{c} \equiv \left[ \begin{array}{c c c c} 1 & 0 & 0 & 0 \end{array} \right]\nonumber\end{aligned}\end{split}\]

こののシステムに対して、次のコスト関数を最小化するような制御入力を求める。

\[ \begin{align}\begin{aligned} \begin{aligned} J_k = \sum_{j=k}^{\infty} \{Q(p_{j}^{ref} - p_{j})^2 + R\Delta u_{j}^2\} \eqlabel{extended_preview_control_costfunc}\end{aligned}\\これは、以下のようにして求められる。\end{aligned}\end{align} \]

まず、十分大きい自然数\(M\)を用いて次のコスト関数を考え、次に\(M \rightarrow \infty\)とすることでを最小化する制御入力を得る。

\[\begin{aligned} J_k^M = \sum_{j=k}^{M-1} \{Q(p_{j}^{ref} - p_{j})^2 + R\Delta u_{j}^2\} \eqlabel{extended_preview_control_costfuncM}\end{aligned}\]

\(J_k^M\)の最小値を\(J_k^{M\ast}\)とすると、から次の関係が成り立つ。

\[ \begin{align}\begin{aligned} \begin{aligned} J_k^{M\ast} = \min_{\Delta u_k} \{Q(p_k^{ref} - p_k)^2 + R\Delta u_k^2 + J_{k+1}^{M\ast}\} \eqlabel{extended_preview_control_costfunc2}\end{aligned}\\ここで、\ :math:`J_k^{M\ast}`\ を次のようにおく。\end{aligned}\end{align} \]
\[\begin{aligned} J_k^{M\ast} = x_k^{\ast T} P_k^M x_k^\ast + \theta_k^{MT} x_k^\ast + \phi_k^M \eqlabel{extended_preview_control_J}\end{aligned}\]

これを用いて、の右辺を\(\Delta u_k\)で偏微分した値が0であることから、次の式を得る。

\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} 0 = && \frac{\partial}{\partial \Delta u_k} \{ Q(p_k^{ref} - p_k)^2 + R\Delta u_k^2 + (\tilde{A} x^\ast_k + \tilde{b} \Delta u_k)^T P_{k+1}^M (\tilde{A} x^\ast_k + \tilde{b} \Delta u_k) + \theta_{k+1}^{MT} (\tilde{A} x^\ast_k + \tilde{b} \Delta u_k) + \phi_{k+1}^M \} \nonumber\\ 0 =&& \Delta u_k^T R + \Delta u_k^T \tilde{b}^T P_{k+1}^M \tilde{b} + x_k^{\ast T} \tilde{A}^T P_{k+1}^M \tilde{b} + \frac{1}{2} \theta_{k+1}^{MT} \tilde{b} \nonumber \\ \Delta u_k =&& -(\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T P_{k+1}^M \tilde{A} x_k^\ast - \frac{1}{2} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T \theta_{k+1}^M\eqlabel{extended_preview_control_u}\end{aligned}\end{split}\\これをに代入することで、以下を得る。\end{aligned}\end{align} \]
\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} && x_k^{\ast T} P_k^M x_k^\ast + \theta_k^{M T} x_k^\ast + \phi_k^M \nonumber \\ =&& x_k^{\ast T} (\tilde{c}^T Q \tilde{c} + \tilde{A}^T P_{k+1}^M \tilde{A} - \tilde{A}^T P_{k+1}^M \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T P_{k+1}^M \tilde{A}) x_k^\ast \nonumber\\ && + \{-2 \tilde{c}^T Q p_k^{ref} + \tilde{A}^T \theta_{k+1}^M - \tilde{A}^T P_{k+1}^M \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T \theta_{k+1}^M \}^T x_k^\ast \nonumber\\ && + Q p_k^{ref 2} - \frac{1}{4} \theta_{k+1}^{MT} \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T \theta_{k+1}^M + \phi_{k+1}^M\end{aligned}\end{split}\\これが任意の\ :math:`x_k^{\ast T}`\ に対し成り立つので、\end{aligned}\end{align} \]
\[\begin{split}\begin{aligned} P_k^M &=& \tilde{c}^T Q \tilde{c} + \tilde{A}^T P_{k+1}^M \tilde{A} - \tilde{A}^T P_{k+1}^M \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T P_{k+1}^M \tilde{A} \eqlabel{extended_preview_control_P}\\ \theta_k^M &=& -2 \tilde{c}^T Q p_k^{ref} + \{\tilde{A}^T - \tilde{A}^T P_{k+1}^M \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T\} \theta_{k+1}^M \eqlabel{extended_preview_control_theta}\\ \phi_k^M &=& Q p_k^{ref 2} - \frac{1}{4} \theta_{k+1}^{MT} \tilde{b} (\tilde{b}^T P_{k+1}^M \tilde{b} + R )^{-1} \tilde{b}^T \theta_{k+1}^M + \phi_{k+1}^M\end{aligned}\end{split}\]

境界条件を考えると、は\(k = M\)において\(J_{k+M}^{M\ast} = 0\)であるから、\(k = M\)においてが任意の\(x_{M}^\ast\)で恒等的に成り立つ条件を考えて、\(P_{M}^M = 0\)\(\theta_{M}^M = 0\)\(\phi_{M}^M = 0\)である。したがって、十分小さい\(j\)において\(P_{k+j}^M\)はの定常解\(P\)となり、次の式を満たす。

\[\begin{aligned} P &=& \tilde{c}^T Q \tilde{c} + \tilde{A}^T P \tilde{A} - \tilde{A}^T P \tilde{b} (\tilde{b}^T P \tilde{b} + R )^{-1} \tilde{b}^T P \tilde{A} \eqlabel{extended_preview_control_P2}\end{aligned}\]

以後、\(M \rightarrow \infty\)として考える。自然数\(N\)を考えて、\(j > N\)において\(p_{k+j}^{ref} = p_{k+N}^{ref}\)と仮定すると、は次のように表せる。(は十分小さい\(j\)における\(P_{k+j}\)でのみ成り立たつが、十分大きな\(j\)では\((\tilde{A} - \tilde{b} K)^{T j} \rightarrow 0\)と仮定し無視した。)(\(K \equiv (\tilde{b}^T P \tilde{b} + R )^{-1} \tilde{b}^T P \tilde{A}\)とおいた。)

\[ \begin{align}\begin{aligned}\begin{split} \begin{aligned} \theta_k &=& -2 \tilde{c}^T Q p_k^{ref} + (\tilde{A} - \tilde{b} K)^T \theta_{k+1} \nonumber\\ &=& -2 \{ \tilde{c}^T Q p_k^{ref} + (\tilde{A} - \tilde{b} K)^T \tilde{c}^T Q p_{k+1}^{ref} + \cdots + (\tilde{A} - \tilde{b} K)^{T N-2} \tilde{c}^T Q p_{k+N-1}^{ref} \nonumber\\ & & + (\tilde{A} - \tilde{b} K)^{T N-1} \tilde{c}^T Q p_{k+N}^{ref} + (\tilde{A} - \tilde{b} K)^{T N} \tilde{c}^T Q p_{k+N+1}^{ref} + (\tilde{A} - \tilde{b} K)^{T (N+1)} \tilde{c}^T Q p_{k+N+2}^{ref} + \cdots \} \nonumber \\ &=& -2 \{ \tilde{c}^T Q p_k^{ref} + (\tilde{A} - \tilde{b} K)^T \tilde{c}^T Q p_{k+1}^{ref} + \cdots + (\tilde{A} - \tilde{b} K)^{T N-2} \tilde{c}^T Q p_{k+N-1}^{ref} \nonumber\\ & & + (\tilde{A} - \tilde{b} K)^{T N-1} \tilde{c}^T Q p_{k+N}^{ref} + (\tilde{A} - \tilde{b} K)^{T N} \tilde{c}^T Q p_{k+N}^{ref} + (\tilde{A} - \tilde{b} K)^{T (N+1)} \tilde{c}^T Q p_{k+N}^{ref} + \cdots \} \nonumber \\ &=& -2 \sum_{j=1}^{N-1} \{ (\tilde{A} - \tilde{b} K)^{T j-1} \tilde{c}^T Q p_{k+j}^{ref} \} -2 \sum_{j=N}^{\infty} \{ (\tilde{A} - \tilde{b} K)^{T j-1} \tilde{c}^T Q p_{k+N}^{ref} \}\eqlabel{extended_preview_control_theta2}\end{aligned}\end{split}\\ここでを\ :math:`K`\ を用いて表現すると、\end{aligned}\end{align} \]
\[ \begin{align}\begin{aligned} \begin{aligned} P &=& \tilde{c}^T Q \tilde{c} + (\tilde{A} - \tilde{b} K)^T P \tilde{A} \eqlabel{extended_preview_control_P3}\end{aligned}\\が得られる。この両辺に\ :math:`P \tilde{A}`\ を加え整理すると、\end{aligned}\end{align} \]
\[\begin{aligned} (I - (\tilde{A} - \tilde{b} K)^{T}) P \tilde{A} &=& P (\tilde{A} - I) + \tilde{c}^T Q \tilde{c} \eqlabel{extended_preview_control_P4}\end{aligned}\]

となる。ここで\(\tilde{A} = \left[\begin{array}{c c} 1 & cA\\ 0 & A \end{array} \right]\)\(\tilde{c} = \left[\begin{array}{c c c c} 1 & 0 & 0 & 0 \end{array} \right]\)を利用すると、の第1列目の等式から、

\[ \begin{align}\begin{aligned} \begin{aligned} (I - (\tilde{A} - \tilde{b} K)^{T}) P \tilde{c}^T &=& \tilde{c}^T Q \eqlabel{extended_preview_control_P5}\end{aligned}\\が成り立つ。このをに代入すると、\end{aligned}\end{align} \]
\[\begin{aligned} \theta_k &=& -2 \sum_{j=1}^{N-1} \{ (\tilde{A} - \tilde{b} K)^{T j-1} \tilde{c}^T Q p_{k+j}^{ref} \} -2 (\tilde{A} - \tilde{b} K)^{T N-1} P \tilde{c}^T p_{k+N}^{ref} \eqlabel{extended_preview_control_theta3}\end{aligned}\]

を得る。このをに代入することで、を最小化する最適制御入力\(\Delta u_k\)が得られる。

\[\begin{split}\begin{aligned} \Delta u_k &=& -K x_k^\ast + \sum_{j=1}^N \tilde{f}_j p_{k+j}^{ref}\eqlabel{extended_preview_control_u2}\\ \tilde{f}_j &=& \begin{cases} (\tilde{b}^T P \tilde{b} + R )^{-1} \tilde{b}^T (\tilde{A} - \tilde{b} K)^{T j-1} \tilde{c}^T Q & (j<N) \\ (\tilde{b}^T P \tilde{b} + R )^{-1} \tilde{b}^T (\tilde{A} - \tilde{b} K)^{T N-1} P \tilde{c}^T & (j=N) \end{cases}\nonumber\end{aligned}\end{split}\]

初期状態\(x_1^\ast\)と目標ZMP軌道\(p_{1}^{ref},~p_{2}^{ref},~\cdots\)が与えられれば、とのシステムによって\(\Delta u_1,~x_2^\ast,~\Delta u_2,~x_3^\ast,~\cdots\)が順次求まる。これによって、ZMPが地面についている足の位置とできる限り一致するような重心軌道を生成することができる。

歩行動作生成の例

Example of walk pattern generation

Example of walk pattern generation

robot-modelクラスには、オフライン歩行動作生成を行い歩行軌道を返す関数:calc-walk-pattern-from-footstep-listが定義されている。この関数は、1歩ごとの足をつく位置のリストを与えると、ZMPがこの位置に出来る限り近くなるような歩行動作を生成する。以下に示すプログラムは、:calc-walk-pattern-from-footstep-listを用いて歩行動作生成を行うものである()。

(load "irteus/demo/sample-robot-model.l")
(setq *robot* (instance sample-robot :init))
(send *robot* :reset-pose)
(send *robot* :fix-leg-to-coords (make-coords))
(objects (list *robot*))

(let ((footstep-list
       (list (make-coords :coords (send *robot* :rleg :end-coords :copy-worldcoords) :name :rleg)
             (make-coords :coords (send (send *robot* :lleg :end-coords :copy-worldcoords)
                                        :translate #f(100 0 0)) :name :lleg)
             (make-coords :coords (send (send *robot* :rleg :end-coords :copy-worldcoords)
                                        :translate #f(200 0 0)) :name :rleg)
             (make-coords :coords (send (send *robot* :lleg :end-coords :copy-worldcoords)
                                        :translate #f(300 0 0)) :name :lleg)
             (make-coords :coords (send (send *robot* :rleg :end-coords :copy-worldcoords)
                                        :translate #f(400 0 0)) :name :rleg)
             (make-coords :coords (send (send *robot* :lleg :end-coords :copy-worldcoords)
                                        :translate #f(400 0 0)) :name :lleg))))
  (objects (append (list *robot*) footstep-list))

  (send *robot* :calc-walk-pattern-from-footstep-list
        footstep-list
        :default-step-height 50
        :default-step-time 1.0
        :dt 0.1
        :debug-view t)
  )

変数footstep-listに足をつく位置のリストをセットし、:calc-walk-pattern-from-footstep-listに与えている。footstep-listの各要素は、:nameにいずれの脚かを指定する必要がある。footstep-listの最初の要素は初期化のために用いられ、実際にロボットが脚を踏み出すのは次の要素以降の位置に対してである。:default-step-height 50では遊脚をサイクロイド補間するときの高さを50[mm]に指定している。:default-step-time 1.0は一歩あたりの時間を1.0[s]に指定している。:dt 0.1は予見制御のサンプリングタイムと生成される軌道の間隔を0.1[s]に指定している。なお、:default-step-height:default-step-time:dtはデフォルト値がこの値となっているため、実際にはこれらの値を設定する必要はない。

次に示すプログラムは、移動したい目的地を与えるとfootstep-listを自動で生成して歩行動作生成を行うものである。

(load "irteus/demo/sample-robot-model.l")
(setq *robot* (instance sample-robot :init))
(send *robot* :reset-pose)
(send *robot* :fix-leg-to-coords (make-coords))
(objects (list *robot*
               (apply #'midcoords 0.5 (send *robot* :legs :end-coords))
               (send (send (apply #'midcoords 0.5 (send *robot* :legs :end-coords))
                           :translate #F(500 150 0)) :rotate (deg2rad 45) :z)))

(send *robot* :calc-walk-pattern-from-footstep-list
      (send *robot* :go-pos-params->footstep-list
            500 150 45) ;; x[mm] y[mm] th[deg]
      :debug-view t
      )

footstep-listとして(send *robot* :go-pos-params->footstep-list 500 150 45)の返り値を与えて、先の例と同様:calc-walk-pattern-from-footstep-list関数で歩行動作を生成している。

:go-pos-params->footstep-list関数は、2本足で立ったロボットについて、脚の逆運動学が解ける範囲内で現在の位置から目的地までのfootstep-listを生成する関数であり、ここでは前に500[mm]、左に150[mm]移動し、左に45[deg]体を回転させるようなfootstep-listを生成している。

joint

:super = ** propertied-object**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target

rotational-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

linear-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

omniwheel-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

sphere-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

6dof-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

bodyset-link

:super = ** bodyset**
:slots rot pos parent descendants worldcoords manager changed geometry::bodies joint parent-link child-links analysis-level default-coords weight acentroid inertia-tensor angular-velocity angular-acceleration spacial-velocity spacial-acceleration momentum-velocity angular-momentum-velocity momentum angular-momentum force moment ext-force ext-moment

cascaded-link

:super = ** cascaded-coords**
:slots rot pos parent descendants worldcoords manager changed links joint-list bodies collision-avoidance-links end-coords-list

joint

:super = ** propertied-object**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target

rotational-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

linear-joint

:super = ** joint**
:slots parent-link child-link joint-angle min-angle max-angle default-coords joint-velocity joint-acceleration joint-torque max-joint-velocity max-joint-torque joint-min-max-table joint-min-max-target axis

bodyset-link

:super = ** bodyset**
:slots rot pos parent descendants worldcoords manager changed geometry::bodies joint parent-link child-links analysis-level default-coords weight acentroid inertia-tensor angular-velocity angular-acceleration spacial-velocity spacial-acceleration momentum-velocity angular-momentum-velocity momentum angular-momentum force moment ext-force ext-moment

cascaded-link

:super = ** cascaded-coords**
:slots rot pos parent descendants worldcoords manager changed links joint-list bodies collision-avoidance-links end-coords-list

:inertia-tensor &optional (update-mass-properties t)

Calculate total robot inertia tensor [g \(mm^2\)] around total robot centroid in euslisp world coordinates.
If update-mass-properties argument is t, propagate total mass prop calculation for all links and returns total robot inertia tensor.
Otherwise, do not calculate total mass prop, just returns pre-computed total robot inertia tensor.

:centroid &optional (update-mass-properties t)

Calculate total robot centroid (Center Of Gravity, COG) [mm] in euslisp world coordinates.
If update-mass-properties argument is t, propagate total mass prop calculation for all links and returns total robot centroid.
Otherwise, do not calculate total mass prop, just returns pre-computed total robot centroid.

:weight &optional (update-mass-properties t)

Calculate total robot weight [g].
If update-mass-properties argument is t, propagate total mass prop calculation for all links and returns total robot weight.
Otherwise, do not calculate total weight, just returns pre-computed total robot weight.
:calc-zmp = `[method]
&optional (av (send self :angle-vector)) (root-coords (send (car (send self :links)) :copy-worldcoords)) &key = (pzmpz 0.0) (dt 0.005) (update t) (debug-view) (calc-torque-buffer-args (send self :calc-torque-buffer-args))
Calculate Zero Moment Point based on Inverse Dynamics.
The output is expressed by the world coordinates,
and depends on historical robot states of the past 3 steps. Step is incremented when this method is called.
After solving Inverse Dynamics, ZMP is calculated from total root-link force and moment.
necessary arguments ->av and root-coords.
If update is t, call inverse dynamics, otherwise, just return zmp from total root-link force and moment.
dt [s] is time step used only when update is t.
pZMPz is ZMP height [mm].
After this method, (send robot :get :zmp) is ZMP and (send robot :get :zmp-moment) is moment around ZMP.

:preview-control-dynamics-filter dt avs &key (preview-controller-class preview-controller) (cog-method :move-base-pos) (delay 0.8)

:draw-torque vwer &key flush (width 2) (size 100) (color (float-vector 1 0.3 0)) (warning-color (float-vector 1 0 0)) (torque-threshold nil) (torque-vector (send self :torque-vector)) ((:joint-list jlist) (send self :joint-list))

:calc-contact-wrenches-from-total-wrench target-pos-list &key (total-wrench) (weight (fill (instantiate float-vector (6 (length target-pos-list))) 1))

:wrench-list->wrench-vector wrench-list

:wrench-vector->wrench-list wrench-vector

:calc-cop-from-force-moment force moment sensor-coords cop-coords &key (fz-thre 1) (return-all-values)

:calc-torque-from-ext-wrenches &key (force-list) (moment-list) (target-coords) ((:jacobi tmp-jacobi))

:calc-av-vel-acc-from-pos dt av

:calc-root-coords-vel-acc-from-pos dt root-coords

:calc-torque-from-vel-acc &key (debug-view nil) (jvv (instantiate float-vector (length joint-list))) (jav (instantiate float-vector (length joint-list))) (root-spacial-velocity (float-vector 0 0 0)) (root-angular-velocity (float-vector 0 0 0)) (root-spacial-acceleration (float-vector 0 0 0)) (root-angular-acceleration (float-vector 0 0 0)) (calc-torque-buffer-args (send self :calc-torque-buffer-args))

:calc-torque-without-ext-wrench &key (debug-view nil) (calc-statics-p t) (dt 0.005) (av (send self :angle-vector)) (root-coords (send (car (send self :links)) :copy-worldcoords)) (calc-torque-buffer-args (send self :calc-torque-buffer-args))

:calc-torque &key (debug-view nil) (calc-statics-p t) (dt 0.005) (av (send self :angle-vector)) (root-coords (send (car (send self :links)) :copy-worldcoords)) (force-list) (moment-list) (target-coords) (calc-torque-buffer-args (send self :calc-torque-buffer-args))

:calc-torque-buffer-args **

:torque-ratio-vector &rest args &key (torque (sendself :torque-vector args))

:max-torque-vector **

riccati-equation

:super = ** propertied-object**
:slots a b c p q r k a-bkt r+btpb-1

:solve **

:init aa bb cc qq rr

preview-controller

:super = ** riccati-equation**
:slots xk uk delay f1-n y1-n queue-index initialize-queue-p additional-data-queue finishedp initialized-p output-dim input-dim
:init = `[method]
dt &key = (q) (r) ((:delay d)) ((:a _a)) ((:b _b)) ((:c _c)) (state-dim (array-dimension _a 0)) ((:output-dim odim) (array-dimension _c 0)) ((:input-dim idim) (array-dimension _b 1)) (init-xk (instantiate float-vector (array-dimension _a 0))) (init-uk (make-matrix (array-dimension _b 1) 1)) ((:initialize-queue-p iqp))
Initialize preview-controller.
Q is weighting of output error and R is weighting of input.
dt is sampling time [s].
delay is preview time [s].
init-xk is initial state value.
A, B, C are state eq matrices.
If initialize-queue-p is t, fill all queue by the first input at the begenning, otherwise, do not fill queue at the first.

:update-xk p &optional (add-data)

Update xk by inputting reference output.
Return value : nil (initializing) =>return values (middle) =>nil (finished)
If p is nil, automatically the last value in queue is used as input and preview controller starts finishing.

:finishedp **

Finished or not.

:last-reference-output-vector **

Last value of reference output queue vector (y_k+N_ref).
Last value is latest future value.

:current-reference-output-vector **

First value of reference output queue vector (y_k_ref).
First value is oldest future value and it can be used as current reference value.

:current-state-vector **

Current state value (xk).

:current-output-vector **

Current output value (yk).

:current-additional-data **

Current additional data value.
First value of additional-data-queue.

:pass-preview-controller reference-output-vector-list

Get preview controller results from reference-output-vector-list and returns list.

:calc-f **

:calc-u **

:calc-xk **

:pass-preview-controller reference-output-vector-list

Get preview controller results from reference-output-vector-list and returns list.

:current-additional-data **

Current additional data value.
First value of additional-data-queue.

:current-output-vector **

Current output value (yk).

:current-state-vector **

Current state value (xk).

:current-reference-output-vector **

First value of reference output queue vector (y_k_ref).
First value is oldest future value and it can be used as current reference value.

:last-reference-output-vector **

Last value of reference output queue vector (y_k+N_ref).
Last value is latest future value.

:finishedp **

Finished or not.

:update-xk p &optional (add-data)

Update xk by inputting reference output.
Return value : nil (initializing) =>return values (middle) =>nil (finished)
If p is nil, automatically the last value in queue is used as input and preview controller starts finishing.
:init = `[method]
dt &key = (q) (r) ((:delay d)) ((:a _a)) ((:b _b)) ((:c _c)) (state-dim (array-dimension _a 0)) ((:output-dim odim) (array-dimension _c 0)) ((:input-dim idim) (array-dimension _b 1)) (init-xk (instantiate float-vector (array-dimension _a 0))) (init-uk (make-matrix (array-dimension _b 1) 1)) ((:initialize-queue-p iqp))
Initialize preview-controller.
Q is weighting of output error and R is weighting of input.
dt is sampling time [s].
delay is preview time [s].
init-xk is initial state value.
A, B, C are state eq matrices.
If initialize-queue-p is t, fill all queue by the first input at the begenning, otherwise, do not fill queue at the first.

:calc-xk **

:calc-u **

:calc-f **

extended-preview-controller

:super = ** preview-controller**
:slots orga orgb orgc xk
:init = `[method]
dt &key = (q) (r) ((:delay d)) ((:a _orga)) ((:b _orgb)) ((:c _orgc)) (init-xk (instantiate float-vector (array-dimension _orga 0))) (init-uk (make-matrix (array-dimension _orgb 1) 1)) (state-dim (array-dimension _orga 0)) ((:initialize-queue-p iqp)) (q-mat)
Initialize preview-controller in extended system (error system).
Q is weighting of output error and R is weighting of input.
dt is sampling time [s].
delay is preview time [s].
init-xk is initial state value.
A, B, C are state eq matrices for original system and slot variables A,B,C are used for error system matrices.
If initialize-queue-p is t, fill all queue by the first input at the begenning, otherwise, do not fill queue at the first.

:current-output-vector **

Current additional data value.
First value of additional-data-queue.

:calc-f **

:calc-u **

:calc-xk **

:current-output-vector **

Current additional data value.
First value of additional-data-queue.
:init = `[method]
dt &key = (q) (r) ((:delay d)) ((:a _orga)) ((:b _orgb)) ((:c _orgc)) (init-xk (instantiate float-vector (array-dimension _orga 0))) (init-uk (make-matrix (array-dimension _orgb 1) 1)) (state-dim (array-dimension _orga 0)) ((:initialize-queue-p iqp)) (q-mat)
Initialize preview-controller in extended system (error system).
Q is weighting of output error and R is weighting of input.
dt is sampling time [s].
delay is preview time [s].
init-xk is initial state value.
A, B, C are state eq matrices for original system and slot variables A,B,C are used for error system matrices.
If initialize-queue-p is t, fill all queue by the first input at the begenning, otherwise, do not fill queue at the first.

:calc-xk **

:calc-u **

:calc-f **

preview-control-cart-table-cog-trajectory-generator

:super = ** propertied-object**
:slots pcs cog-z zmp-z
:init = `[method]
dt _zc &key = (q 1) (r 1.000000e-06) ((:delay d) 1.6) (init-xk (float-vector 0 0 0)) ((:a _a) (make-matrix 3 3 (list (list 1 dt (0.5 dt dt)) (list 0 1 dt) (list 0 0 1)))) ((:b _b) (make-matrix 3 1 (list (list ((/ 1.0 6.0) dt dt dt)) (list (0.5 dt dt)) (list dt)))) ((:c _c) (make-matrix 1 3 (list (list 1.0 0.0 (- (/ _zc (elt g-vec2))))))) ((:initialize-queue-p iqp)) (preview-controller-class extended-preview-controller)
COG (xy) trajectory generator using preview-control convert reference ZMP from reference COG.
dt ->sampling time[s], _zc is height of COG [mm].
preview-controller-class is preview controller class (extended-preview-controller by default).
For other arguments, please see preview-controller and extended-preview-controller :init documentation.

:refcog **

Reference COG [mm].

:cart-zmp **

Cart-table system ZMP[mm] as an output variable.

:last-refzmp **

Reference zmp at the last of queue.

:current-refzmp **

Current reference zmp at the first of queue.

:update-xk p &optional (add-data)

Update xk and returns zmp and cog values.
For arguments, please see preview-controller and extended-preview-controller :update-xk.

:finishedp **

Finished or not.

:current-additional-data **

Current additional data value.

:pass-preview-controller reference-output-vector-list

Get preview controller results from reference-output-vector-list and returns list.

:cog-z **

COG Z [mm].

:update-cog-z zc

:cog-z **

COG Z [mm].

:pass-preview-controller reference-output-vector-list

Get preview controller results from reference-output-vector-list and returns list.

:current-additional-data **

Current additional data value.

:finishedp **

Finished or not.

:update-xk p &optional (add-data)

Update xk and returns zmp and cog values.
For arguments, please see preview-controller and extended-preview-controller :update-xk.

:current-refzmp **

Current reference zmp at the first of queue.

:last-refzmp **

Reference zmp at the last of queue.

:cart-zmp **

Cart-table system ZMP[mm] as an output variable.

:refcog **

Reference COG [mm].

:init = `[method]
dt _zc &key = (q 1) (r 1.000000e-06) ((:delay d) 1.6) (init-xk (float-vector 0 0 0)) ((:a _a) (make-matrix 3 3 (list (list 1 dt (0.5 dt dt)) (list 0 1 dt) (list 0 0 1)))) ((:b _b) (make-matrix 3 1 (list (list ((/ 1.0 6.0) dt dt dt)) (list (0.5 dt dt)) (list dt)))) ((:c _c) (make-matrix 1 3 (list (list 1.0 0.0 (- (/ _zc (elt g-vec2))))))) ((:initialize-queue-p iqp)) (preview-controller-class extended-preview-controller)
COG (xy) trajectory generator using preview-control convert reference ZMP from reference COG.
dt ->sampling time[s], _zc is height of COG [mm].
preview-controller-class is preview controller class (extended-preview-controller by default).
For other arguments, please see preview-controller and extended-preview-controller :init documentation.

:update-cog-z zc

gait-generator

:super = ** propertied-object**
:slots robot dt footstep-node-list support-leg-list support-leg-coords-list swing-leg-dst-coords-list swing-leg-src-coords refzmp-cur-list refzmp-next refzmp-prev step-height-list one-step-len index-count default-step-height default-double-support-ratio default-zmp-offsets finalize-p apreview-controller all-limbs end-with-double-support ik-thre ik-rthre swing-leg-proj-ratio-interpolation-acc swing-leg-proj-ratio-interpolation-vel swing-leg-proj-ratio-interpolation-pos swing-rot-ratio-interpolation-acc swing-rot-ratio-interpolation-vel swing-rot-ratio-interpolation-pos

:cycloid-midcoords ratio start goal height &key (top-ratio 0.5) (rot-ratio ratio)

:cycloid-midpoint ratio start goal height &key (top-ratio 0.5)

:solve-av-by-move-centroid-on-foot support-leg support-leg-coords swing-leg-coords cog robot &rest args &key (cog-gain 3.5) (stop 100) (additional-nspace-list) &allow-other-keys

:solve-angle-vector support-leg support-leg-coords swing-leg-coords cog &key (solve-angle-vector :solve-av-by-move-centroid-on-foot) (solve-angle-vector-args)

:update-current-gait-parameter **

:proc-one-tick &key (type :shuffling) (solve-angle-vector :solve-av-by-move-centroid-on-foot) (solve-angle-vector-args) (debug nil)

:calc-one-tick-gait-parameter type

:calc-current-refzmp prev cur next

:calc-ratio-from-double-support-ratio **

:calc-current-swing-leg-coords ratio src dst &key (type :shuffling) (step-height default-step-height)

:calc-hoffarbib-pos-vel-acc tmp-remain-time tmp-goal old-acc old-vel old-pos

:make-gait-parameter **

:finalize-gait-parameter **

:initialize-gait-parameter fsl time cog &key ((:default-step-height dsh) 50) ((:default-double-support-ratio ddsr) 0.2) (delay 1.6) ((:all-limbs al) ’(:rleg :lleg)) ((:default-zmp-offsets dzo) (mapcan #’(lambda (x) (list x (float-vector 0 0 0))) al)) (q 1.0) (r 1.000000e-06) (thre 1) (rthre (deg2rad 1)) (start-with-double-support t) ((:end-with-double-support ewds) t)

:get-swing-limbs limbs

:get-limbs-zmp limb-coords limb-names

:get-limbs-zmp-list limb-coords limb-names

:get-counter-footstep-limbs fs

:get-footstep-limbs fs

:init rb _dt

calc-inertia-matrix-rotational mat row column paxis m-til c-til i-til axis-for-angular child-link world-default-coords translation-axis rotation-axis tmp-v0 tmp-v1 tmp-v2 tmp-va tmp-vb tmp-vc tmp-vd tmp-m

calc-inertia-matrix-linear mat row column paxis m-til c-til i-til axis-for-angular child-link world-default-coords translation-axis rotation-axis tmp-v0 tmp-v1 tmp-v2 tmp-va tmp-vb tmp-vc tmp-vd tmp-m

[1]Inverse kinematic solutions with singularity robustness for robot manipulator control: Y.Nakamura and H. Hanafusa, Journal of Dynamic Systems, Measurement, and Control, vol. 108, pp 163-171, 1986
[2]ロボットアームの可操作度, 吉川恒夫, 日本ロボット学会誌, vol. 2, no. 1, pp. 63-67, 1984.
[3]Hybrid Position/Force Control: A Correct Formuration, William D. Fisher, M. Shahid Mujtaba, The Internationaltional Journal of Robotics Research, vol. 11, no. 4, pp. 299-311, 1992.
[4]A unified approach for motion and force control of robot manipulators: The operational space formulation, O. Khatib, IEEE Journal of Robotics and Automation, vol. 3, no. 1, pp. 43-53, 1987.
[5]Exploiting Task Intervals for Whole Body Robot Control, Michael Gienger and Herbert Jansen and Christian Goeric In Proceedings of the 2006 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS’06), pp. 2484 - 2490, 2006
[6]A weighted least-norm solution based scheme for avoiding jointlimits for redundant joint manipulators, Tan Fung Chan and Dubey R.V., Robotics and Automation, IEEE Transactions on, pp. 286-292,1995
[7]Efficient gradient projection optimization for manipulators withmultiple degrees of redundancy, Zghal H., Dubey R.V., Euler J.A., 1990 IEEE International Conference on Robotics and Automation, pp. 1006-1011, 1990.
[8]Real-Time Self Collision Avoidance for Humanoids by means of Nullspace Criteria and Task Intervals, H. Sugiura, M. Gienger, H. Janssen, C. Goerick, Proceedings of the 2006 IEEE-RAS International Conference on Humanoid Robots, pp. 575-580, 2006.
[9]Real-time collision avoidance with whole body motion control for humanoid robots, Hisashi Sugiura, Michael Gienger, Herbert Janssen, Christian Goerick, In Proceedings of the 2007 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS’07), pp. 2053 - 2068, 2007
[10]Fast distance queries with rectangular swept sphere volumes, Larsen E., Gottschalk S., Lin M.C., Manocha D, Proceedings of The 2000 IEEE International Conference on Robotics and Automation, pp. 3719-3726, 2000.
[11]アーム・多指ハンド機構による把握と操り, 永井 清, 吉川 恒夫, 日本ロボット学会誌, vol. 13, no. 7, pp. 994-1005, 1995.
[12]一般化ヤコビ行列を用いた宇宙用ロボットマニピュレータの分解速度制御, 梅谷 陽二, 吉田 和哉, 日本ロボット学会誌, vol. 4, no. 7, pp. 63-73, 1989.
[13]Control of Free-Floating Humanoid Robots Through Task Prioritization, Luis Sentis and Oussama Khatib, Proceedings of The 2005 IEEE International Conference on Robotics and Automation, pp. 1718-1723, 2005
[14]Resolved Momentum Control:Humanoid Motion Planning based on the Linear and Angular Momentum, S.Kajita, F.Kanehiro, K.Kaneko, K.Fujiwara, K.Harada, K.Yokoi,H.Hirukawa, In Proceedings of the 2003 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS’03), pp. 1644-1650, 2003
[15]Humanoid Robot (in Japanese), Shuji Kajita, Ohmsha, 2005, ISBN 4-274-20058-2
[16]Biped Walking Pattern Generation by using Preview Control of Zero-Moment Point, Shuji Kajita and Fumio Kanehiro and Kenji Kaneko and Kiyoshi Fujiwara and Kensuke Harada and Kazuhito Yokoi and Hirohisa Hirukawa, ICRA 2003, p.1620-1626, 2006
[17]最適予見制御と一般化予測制御, 江上 正 and土谷 武士, 計測と制御, 39 巻, 5 号, p.337-342, 2000

ロボットビューワ

デフォルトのIrtviewerを作成する().

(make-irtviewer)
Default irtviewer

Default irtviewer

Irtviewerを作成して,xy平面のグリッドを描画する().

(make-irtviewer)
(send *irtviewer* :draw-floor 100)
(send *irtviewer* :draw-objects)
Irtviewer with floor grid

Irtviewer with floor grid

Irtviewerを作成して,背景を白にして,xy平面のグリッドを黒で描画する().

(make-irtviewer)
(send *irtviewer* :change-background (float-vector 1 1 1))
(send *irtviewer* :draw-floor 100)
(send *irtviewer* :floor-color #f(0 0 0))
(send *irtviewer* :draw-objects)
Irtviewer with white background and floor grid

Irtviewer with white background and floor grid

viewer

:super = ** propertied-object**
:slots geometry::eye geometry::port geometry::surface

x::irtviewer

:super = ** x:panel**
:slots x::viewer x::objects x::draw-things x::previous-cursor-pos x::left-right-angle x::up-down-angle x::viewpoint x::viewtarget x::drawmode x::draw-origin x::draw-floor x::floor-color x::image-sequence x::logging-flag

:draw-origin &optional (x::tmp-draw-origin :null)

get/set draw-origin

:draw-floor &optional (x::tmp-draw-floor :null)

get/set draw-floor

:floor-color &optional (x::tmp-floor-color :null)

get/set floor-color

:logging &optional (x::flag :on)

start/stop logging
:clear Clear log
:start Start logging
:restart Stop and restart logging
:stop Stop logging
:save-mpeg = `[method]
&key = (fname anim.mpg) (x::delay 5) (delete t)
’:save-mpeg’ saves logged images as mpeg.
To start image log, run ’:logging :start’ and to stop log, run ’:logging :stop’.
Note that ’:logging :stop’ did not clear the logged sequence, so you need to run
’:logging :clear’.
:save-anmigif’ did not stop nor clear the image sequence, so you have to run them manuualy
:save-animgif = `[method]
&key = (fname anim.gif) (x::delay 5) (x::transparent t) (loop t) (delete t)
’:save-anmigif’ saves logged images as animation gif.
To start image log, run ’:logging :start’ and to stop log, run ’:logging :stop’.
Note that ’:logging :stop’ did not clear the logged sequence, so you need to run
’:logging :clear’.
:save-anmigif’ did not stop nor clear the image sequence, so you have to run them manuualy

:save-image x::filename

save curent view to image, supported formats are jpg/png/pnm

:create &rest args &key (x::title IRT viewer) (x::view-name (gensym title)) (x::hither 200.0) (x::yon 50000.0) (x::width 500) (x::height 500) ((:draw-origin do) 150) ((:draw-floor x::df) nil) ((:floor-color x::fc) #f(1.0 1.0 1.0)) (x::call-super t) &allow-other-keys

:viewer &rest args

:redraw **

:expose x:event

:resize x::newwidth x::newheight

:configurenotify x:event

:viewtarget &optional x::p

:viewpoint &optional x::p

:look1 &optional (x::vt x::viewtarget) (x::lra x::left-right-angle) (x::uda x::up-down-angle)

:look-all &optional x::bbox

:move-viewing-around-viewtarget x:event x::x x::y x::dx x::dy x::vwr

:set-cursor-pos-event x:event

:move-coords-event x:event

:draw-event x:event

:draw-objects &rest args

:objects &rest args

:select-drawmode x::mode

:flush **

:change-background x::col

:clear-log **

:push-image **

:clear-image-sequence **

:image-sequence **

:floor-color &optional (x::tmp-floor-color :null)

get/set floor-color

:draw-floor &optional (x::tmp-draw-floor :null)

get/set draw-floor

:draw-origin &optional (x::tmp-draw-origin :null)

get/set draw-origin

:change-background x::col

:flush **

:select-drawmode x::mode

:objects &rest args

:draw-objects &rest args

:draw-event x:event

:move-coords-event x:event

:set-cursor-pos-event x:event

:move-viewing-around-viewtarget x:event x::x x::y x::dx x::dy x::vwr

:look-all &optional x::bbox

:look1 &optional (x::vt x::viewtarget) (x::lra x::left-right-angle) (x::uda x::up-down-angle)

:viewpoint &optional x::p

:viewtarget &optional x::p

:configurenotify x:event

:resize x::newwidth x::newheight

:expose x:event

:redraw **

:viewer &rest args

:create &rest args &key (x::title IRT viewer) (x::view-name (gensym title)) (x::hither 200.0) (x::yon 50000.0) (x::width 500) (x::height 500) ((:draw-origin do) 150) ((:draw-floor x::df) nil) ((:floor-color x::fc) #f(1.0 1.0 1.0)) (x::call-super t) &allow-other-keys

:save-image x::filename

save curent view to image, supported formats are jpg/png/pnm

:save-animgif = `[method]
&key = (fname anim.gif) (x::delay 5) (x::transparent t) (loop t) (delete t)
’:save-anmigif’ saves logged images as animation gif.
To start image log, run ’:logging :start’ and to stop log, run ’:logging :stop’.
Note that ’:logging :stop’ did not clear the logged sequence, so you need to run
’:logging :clear’.
:save-anmigif’ did not stop nor clear the image sequence, so you have to run them manuualy
:save-animgif = `[method]
&key = (fname anim.gif) (x::delay 5) (x::transparent t) (loop t) (delete t)
’:save-anmigif’ saves logged images as animation gif.
To start image log, run ’:logging :start’ and to stop log, run ’:logging :stop’.
Note that ’:logging :stop’ did not clear the logged sequence, so you need to run
’:logging :clear’.
:save-anmigif’ did not stop nor clear the image sequence, so you have to run them manuualy
:save-mpeg = `[method]
&key = (fname anim.mpg) (x::delay 5) (delete t)
’:save-mpeg’ saves logged images as mpeg.
To start image log, run ’:logging :start’ and to stop log, run ’:logging :stop’.
Note that ’:logging :stop’ did not clear the logged sequence, so you need to run
’:logging :clear’.
:save-anmigif’ did not stop nor clear the image sequence, so you have to run them manuualy

:logging &optional (x::flag :on)

start/stop logging
:clear Clear log
:start Start logging
:restart Stop and restart logging
:stop Stop logging

:image-sequence **

:clear-image-sequence **

:push-image **

:clear-log **

viewing

:super = ** cascaded-coords**
:slots rot pos parent descendants worldcoords manager changed geometry::viewcoords

viewer-dummy

:super = ** propertied-object**
:slots nil

:nomethod &rest args

irtviewer-dummy

:super = ** propertied-object**
:slots objects draw-things

:nomethod &rest args

:objects &rest args

irtviewer-no-window

:super = ** propertied-object**
:slots irtviewer

:nomethod &rest args

:resize newwidth newheight

:create &rest args

:init &rest args

make-irtviewer &rest args

Create irtviewer
:view-name title
:hither near cropping plane
:yon far cropping plane
:width width of the window
:height height of the window
:draw-origin size of origin arrow, use nil to disable it
:draw-floor use t to view floor
:floor-color floor color. default is #f(1 1 1), i.e. white.

x::make-lr-ud-coords x::lra x::uda

x::make-mpeg-from-images x::mpgfile x::images &key (delete t) (x::delay 1)

x::make-animgif-from-images x::giffile x::images &key (delete t) x::transparent (loop t) (x::delay 10) (x::background 000000)

x::draw-things x::objs

objects &optional (objs t) vw

make-irtviewer-dummy &rest args

geometry::default-pixmapsurface &rest args

make-irtviewer-no-window &rest args

干渉計算

干渉計算の概要

干渉計算は2組の幾何モデルが交差するかを判定しその距離を求める処理である. 主に以下の2つ機能を提供する.

  • 2つのモデルが交差するかを判定する衝突検出 (collision-check関数)
  • 2つのモデル間の最短距離を算出する距離計算 (collision-distance関数)

irteusでは,他言語インターフェースを介して外部ライブラリを呼び出すことで干渉計算を実行する. 外部ライブラリとして,PQPとBulletの呼び出しが実装されており,デフォルトではPQPが利用される. 以下のように,select-collision-algorithm関数により使用するライブラリを切り替えることができる.

(select-collision-algorithm *collision-algorithm-pqp*) ;; use PQP
(select-collision-algorithm *collision-algorithm-bullet*) ;; use Bullet

個々の外部ライブラリの特徴については以降で詳しく説明する. 他の干渉計算ソフトウェアパッケージについては http://gamma.cs.unc.edu/research/collision/に詳しい.(情報が古い可能性があるので注意.例えばBulletは載っていない.)

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed

:make-collisionmodel &rest args &key &allow-other-keys

Make collision model and save pointer.

collision-distance model1 model2 &rest args &key &allow-other-keys

Calculate collision distance between model1 and model2.
Return value is (list [distance] [nearest point on model1] [nearest point on model2]).

collision-check model1 model2 &rest args

Check collision between model1 and model2.
If return value is 0, no collision.
Otherwise (return value is 1), collision.

collision-check-objects obj1 obj2 &rest args &key &allow-other-keys

Check collision between obj1 and obj2.
obj1 and obj2 should be list of models.
If return value is nil, no collision.
Otherwise (return value is t), collision.

select-collision-algorithm alg

Select collision algorithm.
:pqp and :bullet are supported.

物体形状モデル同士の干渉計算例

以下は,collision-checkやcollision-distanceを利用して,2つの立方体の衝突検出と距離計算を行い,最近点どうしを結ぶ線分を描画する例である. 干渉が生じているときにcollision-distance関数で得られる最近点は,PQPとBulletで仕様が異なる.詳しくは以降のBulletに関する説明を参照.

;; Make models
(setq *b0* (make-cube 100 100 100))
(setq *b1* (make-cube 100 100 100))

;; Case 1 : no collision
(send *b0* :newcoords (make-coords :pos #f(100 100 -100)
                                   :rpy (list (deg2rad 10) (deg2rad -20) (deg2rad 30))))
(objects (list *b0* *b1*))
(print (collision-check *b0* *b1*)) ;; Check collision
(let ((ret (collision-distance *b0* *b1*))) ;; Check distance and nearest points
  (print (car ret)) ;; distance
  (send (cadr ret) :draw-on :flush nil :size 20 :color #f(1 0 0)) ;; nearest point on *b0*
  (send (caddr ret) :draw-on :flush nil :size 20 :color #f(1 0 0)) ;; nearest point on *b1*
  (send *irtviewer* :viewer :draw-line (cadr ret) (caddr ret))
  (send *irtviewer* :viewer :viewsurface :flush))

;; Case 2 : collision
(send *b0* :newcoords (make-coords :pos #f(50 50 -50)
                                   :rpy (list (deg2rad 10) (deg2rad -20) (deg2rad 30))))
(objects (list *b0* *b1*))
(print (collision-check *b0* *b1*)) ;; Check collision
(let ((ret (collision-distance *b0* *b1*))) ;; Check distance and nearest points
  (print (car ret)) ;; distance
  ;; In case of collision, nearest points are insignificant values.
  (send (cadr ret) :draw-on :flush nil :size 20 :color #f(1 0 0)) ;; nearest point on *b0*
  (send (caddr ret) :draw-on :flush nil :size 20 :color #f(1 0 0)) ;; nearest point on *b1*
  (send *irtviewer* :viewer :draw-line (cadr ret) (caddr ret))
  (send *irtviewer* :viewer :viewsurface :flush))
Collision detection

Collision detection

ロボット動作と干渉計算

ハンドで物体をつかむ,という動作の静的なシミュレーションを行う場合に手(指)のリンクと対象物体の干渉を調べ,これが起こるところで物体をつかむ動作を停止させるということが出来る.

(load "irteus/demo/sample-arm-model.l")
(setq *sarm* (instance sarmclass :init))
(send *sarm* :reset-pose)
(setq a 42)
(send *sarm* :move-fingers a)
(setq *target* (make-cube 30 30 30))
(send *target* :translate #f(350 200 400))
(objects (list *sarm* *target*))

(send *sarm* :inverse-kinematics *target* :move-target (send *sarm* :end-coords) :debug-view t)
(while (> a 0)
  (if (collision-check-objects
       (list (send *sarm* :joint-fr :child-link)
             (send *sarm* :joint-fl :child-link))
       (list *target*))
      (return))
  (decf a 0.1)
  (send *irtviewer* :draw-objects)
  (send *sarm* :move-fingers a))
(send *sarm* :end-coords :assoc *target*)

(dotimes (i 100)
  (send *sarm* :joint0 :joint-angle 1 :relative t)
  (send *irtviewer* :draw-objects))
(send *sarm* :end-coords :dissoc *target*)
(dotimes (i 100)
  (send *sarm* :joint0 :joint-angle -1 :relative t)
  (send *irtviewer* :draw-objects))

同様の機能が,“irteus/demo/sample-arm-model.l”ファイルの:open-hand, :close-handというメソッドで提供されている.

PQPによる干渉計算

PQPはノースカロライナ大学のLin氏らのグループにより開発された干渉計算ライブラリである. PQPソフトウェアパッケージの使い方はirteus/PQP/README.txtに 書いてあり,irteus/PQP/src/PQP.hを読むことで理解できるようになっている.

irteusでPQPを使うためのファイルは CPQP.C, euspqp.c, pqp.l からなる. 2つの幾何モデルが衝突してしるか否かを判定するためには,

(defun pqp-collision-check (model1 model2
                       &optional (flag PQP_FIRST_CONTACT) &key (fat 0) (fat2 nil))
  (let ((m1 (get model1 :pqpmodel))  (m2 (get model2 :pqpmodel))
        (r1 (send model1 :worldrot)) (t1 (send model1 :worldpos))
        (r2 (send model2 :worldrot)) (t2 (send model2 :worldpos)))
    (if (null fat2) (setq fat2 fat))
    (if (null m1) (setq m1 (send model1 :make-pqpmodel :fat fat)))
    (if (null m2) (setq m2 (send model2 :make-pqpmodel :fat fat2)))
    (pqpcollide r1 t1 m1 r2 t2 m2 flag)))

を呼び出せば良い. r1,r1,r2,t1はそれぞれの物体の並進ベクトル,回転行列となり, (get model1 :pqpmodel)でPQPの幾何モデルへのポインタを参照する. このポインタは:make-pqpmodelメソッドの中で以下のよう計算される.

(defmethod cascaded-coords
  (:make-pqpmodel
   (&key (fat 0))
   (let ((m (pqpmakemodel))
         vs v1 v2 v3 (id 0))
     (setf (get self :pqpmodel) m)
     (pqpbeginmodel m)
     (dolist (f (send self :faces))
       (dolist (poly (face-to-triangle-aux f))
         (setq vs (send poly :vertices)
               v1 (send self :inverse-transform-vector (first vs))
               v2 (send self :inverse-transform-vector (second vs))
               v3 (send self :inverse-transform-vector (third vs)))
         (when (not (= fat 0))
           (setq v1 (v+ v1 (scale fat (normalize-vector v1)))
                 v2 (v+ v2 (scale fat (normalize-vector v2)))
                 v3 (v+ v3 (scale fat (normalize-vector v3)))))
         (pqpaddtri m v1 v2 v3 id)
         (incf id)))
     (pqpendmodel m)
     m)))

ここでは,まず(pqpmakemodel)が呼び出されている. pqpmakemodelの中では,euqpqp.cで定義されている,

pointer PQPMAKEMODEL(register context *ctx, int n, register pointer *argv)
{
    int addr = PQP_MakeModel();
    return makeint(addr);
}

が呼び出されており,これは,CPQP.Cの

PQP\_Model *PQP_MakeModel()
{
    return new PQP_Model();
}

が呼ばれている.PQP_Model()はPQP.hで定義されているものであり, この様にしてeuslisp内の関数が実際のPQPライブラリの関数に渡されてい る以降,(pqpbeginmodel m)でPQPの幾何モデルのインスタンスを作成し, (pqpaddtri m v1 v2 v3 id)として面情報を登録している.

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed
pqp-collision-check = `[function]
geometry::model1 geometry::model2 &optional (geometry::flag geometry::pqp_first_contact) &key = (geometry::fat 0) (geometry::fat2 nil)
Check collision between model1 and model2 using PQP.
If return value is 0, no collision.
Otherwise (return value is 1), collision.
pqp-collision-distance = `[function]
geometry::model1 geometry::model2 &key = (geometry::fat 0) (geometry::fat2 nil) (geometry::qsize 2)
Calculate collision distance between model1 and model2 using PQP.
Return value is (list [distance] [nearest point on model1] [nearest point on model2]).
If collision occurs, [distance] is 0 and nearest points are insignificant values.

pqp-collision-check-objects geometry::obj1 geometry::obj2 &key (geometry::fat 0.2)

return nil or t

Bulletによる干渉計算

Bulletは物理演算エンジンであり,その一部として干渉計算機能が提供されている. irteusでBulletを使うためのファイルは CBULLET.cpp, eusbullet.c, bullet.l からなる. 関数内部の呼び出し順序はPQPと同様である.

PQPとBulletの違いとして以下が挙げられる.

  • 干渉が生じているときにcollision-distanceを呼ぶと,PQPでは,距離として0が返り,最近点として意味のない点が返される.一方Bulletでは,距離として干渉をなくすために動かすべき最短距離(penetration depthと呼ばれる)が返る.また,最近点としては,干渉をなくすための最短距離の両端の点が返される.
  • PQPは非凸のメッシュモデルをそのまま扱うことができるが,Bulletでは非凸のモデルの凸包を内部で計算しそれを扱っている.

cascaded-coords

:super = ** coordinates**
:slots rot pos parent descendants worldcoords manager changed
:make-btmodel = `[method]
&key = (geometry::fat 0) ((:faces geometry::fs))

Make bullet model and save pointer of the bullet model.

geometry::bt-make-model-from-body = `[function]
geometry::b &key = (csg (send geometry::b :csg)) (geometry::margin 0)

Make bullet model from body.

bt-collision-distance = `[function]
geometry::model1 geometry::model2 &key = (geometry::fat 0) (geometry::fat2 nil) (geometry::qsize)
Calculate collision distance between model1 and model2 using Bullet.
Return value is (list [distance] [nearest point on model1] [nearest point on model2]).
qsize argument is not used, just for compatibility with pqp-collision-distance.
bt-collision-check = `[function]
geometry::model1 geometry::model2 &key = (geometry::fat 0) (geometry::fat2 nil)
Check collision between model1 and model2 using Bullet.
If return value is 0, no collision.
Otherwise (return value is 1), collision.

BVHデータ

bvh-link

:super = ** bodyset-link**
:slots type offset channels neutral

:init name typ offst chs parent children

create link for bvh model

:type **

:offset **

:channels **

:init name typ offst chs parent children

create link for bvh model

:channels **

:offset **

:type **

bvh-sphere-joint

:super = ** sphere-joint**
:slots axis-order bvh-offset-rotation
:init = `[method]
&rest args &key = (order (list :z :x :y)) ((:bvh-offset-rotation bvh-rotation) (unit-matrix 3)) &allow-other-keys

create joint for bvh model

:joint-angle-bvh &optional v

:joint-angle-bvh-offset &optional v

:joint-angle-bvh-impl v bvh-offset

:axis-order **

:bvh-offset-rotation **

:init = `[method]
&rest args &key = (order (list :z :x :y)) ((:bvh-offset-rotation bvh-rotation) (unit-matrix 3)) &allow-other-keys

create joint for bvh model

:bvh-offset-rotation **

:axis-order **

:joint-angle-bvh-impl v bvh-offset

:joint-angle-bvh-offset &optional v

:joint-angle-bvh &optional v

bvh-6dof-joint

:super = ** 6dof-joint**
:slots scale axis-order bvh-offset-rotation

:bvh-offset-rotation **

:axis-order **

:joint-angle-bvh-impl v bvh-offset

:joint-angle-bvh-offset &optional v

:joint-angle-bvh &optional v

:init &rest args &key (order (list :x :y :z :z :x :y)) ((:scale scl)) ((:bvh-offset-rotation bvh-rotation) (unit-matrix 3)) &allow-other-keys

bvh-robot-model

:super = ** robot-model**
:slots nil
:init = `[method]
&rest args &key = tree coords ((:scale scl))

create robot model for bvh model

:make-bvh-link tree &key parent ((:scale scl))

:angle-vector &optional vec (angle-vector (instantiate float-vector (calc-target-joint-dimension joint-list)))

:dump-joints links &key (depth 0) (strm standard-output)

:dump-hierarchy &optional (strm standard-output)

:dump-motion &optional (strm standard-output)

:copy-state-to robot

:fix-joint-angle i limb joint-name joint-order a

:fix-joint-order jo limb

:bvh-offset-rotate name

:init-end-coords **

:init-root-link **

:init = `[method]
&rest args &key = tree coords ((:scale scl))

create robot model for bvh model

:bvh-offset-rotate name

:fix-joint-order jo limb

:fix-joint-angle i limb joint-name joint-order a

:copy-state-to robot

:dump-motion &optional (strm standard-output)

:dump-hierarchy &optional (strm standard-output)

:dump-joints links &key (depth 0) (strm standard-output)

:angle-vector &optional vec (angle-vector (instantiate float-vector (calc-target-joint-dimension joint-list)))

:make-bvh-link tree &key parent ((:scale scl))

motion-capture-data

:super = ** propertied-object**
:slots frame model animation

:animate &rest args &key (start 0) (step 1) (end (send self :frame-length)) (interval 20) &allow-other-keys

:frame-length **

:frame &optional f

:animation &rest args

:model &rest args

:init fname &key (coords (make-coords)) ((:scale scl))

:init-root-link **

:init-end-coords **

rikiya-bvh-robot-model

:super = ** bvh-robot-model**
:slots nil

:copy-state-to robot

:copy-joint-to robot limb joint &optional (sign 1)

:head-neck &rest args

:torso-chest &rest args

:rleg-ankle &rest args

:rleg-knee &rest args

:rleg-crotch &rest args

:lleg-ankle &rest args

:lleg-knee &rest args

:lleg-crotch &rest args

:rarm-wrist &rest args

:rarm-elbow &rest args

:rarm-shoulder &rest args

:rarm-collar &rest args

:larm-wrist &rest args

:larm-elbow &rest args

:larm-shoulder &rest args

:larm-collar &rest args

:init &rest args

tum-bvh-robot-model

:super = ** bvh-robot-model**
:slots nil

:init &rest args

cmu-bvh-robot-model

:super = ** bvh-robot-model**
:slots nil

:init &rest args

read-bvh fname &key scale

read bvh file

bvh2eus = `[function]
fname &rest args &key = ((:objects obj) nil) &allow-other-keys
read bvh file and anmiate robot model in the viewer
for Supported bvh data, such as
- CMU motion capture database
- The TUM Kitchen Data Set
Use
(tum-bvh2eus ”Take 005.bvh”) ;; tum
(rikiya-bvh2eus ”A01.bvh”) ;; rikiya
(cmu-bvh2eus ”01_01.bvh”) ;; cmu
Other Sites are:
(bvh2eus ”poses.bvh”)
load-mcd = `[function]
fname &key = (scale) (coords) (bvh-robot-model-class bvh-robot-model) &allow-other-keys

load motion capture data

rikiya-bvh2eus fname &rest args

read rikiya bvh file and anmiate robot model in the viewer
(rikiya-bvh2eus ”A01.bvh”)

cmu-bvh2eus fname &rest args

read cmu bvh file and anmiate robot model in the viewer
CMU motion capture database
(cmu-bvh2eus ”01_01.bvh” :scale 100.0)

tum-bvh2eus fname &rest args

read tum file and anmiate robot model in the viewer
The TUM Kitchen Data Set
(tum-bvh2eus ”Take 005.bvh” :scale 10.0)

parse-bvh-sexp src &key ((:scale scl))

make-bvh-robot-model bvh-data &rest args

rikiya-file &key (num 1) (cls ’a)

tum-kitchen-file &key (num 1) (cls 0)

cmu-mocap-file &key (num 1) (cls 1)

Colladaデータ

collada::eusmodel-description collada::model

convert a ‘model’ to eusmodel-description

collada::eusmodel-link-specs collada::links

convert ‘links’ to <link-specs>

collada::eusmodel-joint-specs collada::joints

convert ‘joints’ to <joint-specs>

collada::eusmodel-description->collada name collada::description &key (scale 0.001)

convert eusmodel-descrption to collada sxml

collada::matrix->collada-rotate-vector collada::mat

convert a rotation matrix to axis-angle.

convert-irtmodel-to-collada collada::model-file &optional (collada::output-full-dir (send (truename ./) :namestring)) (collada::model-name) (collada::exit-p t)

convert irtmodel to collada model. (convert-irtmodel-to-collada irtmodel-file-path &optional (output-full-dir (send (truename ”./”) :namestring)) (model-name))

collada::symbol->string collada::sym

collada::->string collada::val

collada::string-append &rest args

collada::make-attr collada::l collada::ac

collada::make-xml collada::x collada::bef collada::aft

collada::sxml->xml collada::sxml

collada::xml-output-to-string-stream collada::ss collada::l

collada::cat-normal collada::l collada::s

collada::cat-clark collada::l collada::s collada::i

collada::verificate-unique-strings names

collada::eusmodel-link-spec collada::link

collada::eusmodel-mesh-spec collada::link collada::rt-cds

collada::eusmodel-joint-spec collada::_joint

collada::eusmodel-limit-spec collada::_joint

collada::eusmodel-endcoords-specs collada::model

collada::eusmodel-link-description collada::description

collada::eusmodel-joint-description collada::description

collada::eusmodel-endcoords-description collada::description

collada::setup-collada-filesystem collada::obj-name collada::base-dir

collada::range2 collada::n

eus2collada collada::obj collada::full-root-dir &key (scale 0.001) (collada::file-suffix .dae)

collada::collada-node-id collada::link-descrption

collada::collada-node-name collada::link-descrption

collada::links-description->collada-library-materials collada::links-desc

collada::link-description->collada-materials collada::link-desc

collada::mesh-description->collada-material collada::mat collada::effect

collada::links-description->collada-library-effects collada::links-desc

collada::link-description->collada-effects collada::link-desc

collada::mesh-description->collada-effect collada::mesh id

collada::matrix->collada-string collada::mat

collada::find-parent-liks-from-link-description collada::target-link collada::desc

collada::eusmodel-description->collada-node-transformations collada::target-link collada::desc

collada::eusmodel-description->collada-node collada::target-link collada::desc

collada::eusmodel-description->collada-library-visual-scenes name collada::desc

collada::mesh-description->instance-material collada::s

collada::link-description->collada-bind-material collada::link

collada::eusmodel-description->collada-library-kinematics-scenes name collada::desc

collada::eusmodel-description->collada-library-kinematics-models name collada::desc

collada::eusmodel-description->collada-kinematics-model name collada::desc

collada::eusmodel-description->collada-library-physics-scenes name collada::desc

collada::eusmodel-description->collada-library-physics-models name collada::desc

collada::find-root-link-from-joints-description collada::joints-description

collada::find-link-from-links-description name collada::links-description

collada::eusmodel-description->collada-links collada::description

collada::find-joint-from-link-description collada::target collada::joints

collada::find-child-link-descriptions collada::parent collada::links collada::joints

collada::eusmodel-description->collada-library-articulated-systems collada::desc name

collada::eusmodel-endcoords-description->openrave-manipulator collada::end-coords collada::description

collada::eusmodel-description->collada-links-tree collada::target collada::links collada::joints

collada::joints-description->collada-instance-joints collada::joints-desc

collada::joint-description->collada-instance-joint collada::joint-desc

collada::eusmodel-description->collada-library-joints collada::description

collada::joints-description->collada-joints collada::joints-description

collada::collada-joint-id collada::joint-description

collada::joint-description->collada-joint collada::joint-description

collada::linear-joint-description->collada-joint collada::joint-description

collada::rotational-joint-description->collada-joint collada::joint-description

collada::eusmodel-description->collada-scene collada::description

collada::eusmodel-description->collada-library-geometries collada::description

collada::collada-geometry-id-base collada::link-descrption

collada::collada-geometry-name-base collada::link-descrption

collada::links-description->collada-geometries collada::links-description

collada::mesh-object->collada-mesh collada::mesh id

collada::link-description->collada-geometry collada::link-description

collada::mesh->collada-indices collada::mesh

collada::mesh-vertices->collada-string collada::mesh

collada::mesh-normals->collada-string collada::mesh

collada::float-vector->collada-string collada::v

collada::enum-integer-list collada::n

collada::search-minimum-rotation-matrix collada::mat

collada::estimate-class-name collada::model-file

collada::remove-directory-name fname

ポイントクラウドデータ

pointcloud

:super = ** cascaded-coords**
:slots parray carray narray curvature pcolor psize awidth asize box height width view-coords drawnormalmode transparent tcarray
:init = `[method]
&rest args &key = ((:points mat)) ((:colors cary)) ((:normals nary)) ((:curvatures curv)) ((:height ht)) ((:width wd)) (point-color (float-vector 0 1 0)) (point-size 2.0) (fill) (arrow-width 2.0) (arrow-size 0.0)

Create point cloud object

:size-change &optional wd ht

change width and height, this method does not change points data

:points &optional pts wd ht

replace points, pts should be list of points or n\(times\) matrix

:colors &optional cls

replace colors, cls should be list of points or n\(times\) matrix

:normals &optional nmls

replace normals by, nmls should be list of points or n\(times\)3 matrix

:point-list &optional (remove-nan)

return list of points

:color-list **

return list of colors

:normal-list **

return list of normals

:centroid **

retrun centroid of this point cloud

:append point-list &key (create t)

append point cloud list to this point cloud.
if :create is true, return appended point cloud and original point cloud does not change.
:filter = `[method]
&rest args &key = create &allow-other-keys
this method can take the same keywords with :filter-with-indices method.
if :create is true, return filtered point cloud and original point cloud does not change.
:filter-with-indices = `[method]
idx-lst &key = (create) (negative)
filter point cloud with list of index (points which are indicated by indices will remain).
if :create is true, return filtered point cloud and original point cloud does not change.
if :negative is true, points which are indicated by indices will be removed.
:filtered-indices = `[method]
&key = key ckey nkey pckey pnkey pcnkey negative &allow-other-keys
create list of index where filter function retrun true.
key, ckey, nkey are filter function for points, colors, normals. They are expected to take one argument and return t or nil.
pckey, pnkey are filter function for points and colors, points and normals. They are expected to take two arguments and return t or nil.
pcnkey is filter function for points, colors and normals. It is expected to take three arguments and return t or nil.
:step = `[method]
step &key = (fixsize) (create)

downsample points with step

:copy-from pc

update object by pc

:transform-points coords &key (create)

transform points and normals with coords.
if :create is true, return transformed point cloud and original point cloud does not change.

:convert-to-world &key (create)

transform points and normals with self coords. converted points data should be at the same position as displayed

:move-origin-to neworigin &key (create)

origin of point cloud is moved to neworigin. moved points data should be at the same position as displayed

:reset-box **

:box **

:vertices **

:size **

:width **

:height **

:view-coords &optional vc

:curvatures &optional curv

:curvature-list **

:set-color col &optional (_transparent)

:point-color &optional pc

:point-size &optional ps

:axis-length &optional al

:axis-width &optional aw

:clear-color **

:clear-normal **

:nfilter &rest args

:viewangle-inlier &key (min-z 0.0) (hangle 44.0) (vangle 35.0)

:image-position-inlier &key (ipkey) (height 144) (width 176) (cy (/ (float (- height 1)) 2)) (cx (/ (float (- width 1)) 2)) negative

:image-circle-filter dist &key (height 144) (width 176) (cy (/ (float (- height 1)) 2)) (cx (/ (float (- width 1)) 2)) create negative

:step-inlier step offx offy

:generate-color-histogram-hs &key (h-step 9) (s-step 7) (hlimits (cons 360.0 0.0)) (vlimits (cons 1.0 0.15)) (slimits (cons 1.0 0.25)) (rotate-hue) (color-scale 255.0) (sizelimits 1)

:set-offset cds &key (create)

:drawnormalmode &optional mode

:transparent &optional trs

:draw vwer

:move-origin-to neworigin &key (create)

origin of point cloud is moved to neworigin. moved points data should be at the same position as displayed

:convert-to-world &key (create)

transform points and normals with self coords. converted points data should be at the same position as displayed

:transform-points coords &key (create)

transform points and normals with coords.
if :create is true, return transformed point cloud and original point cloud does not change.

:copy-from pc

update object by pc

:step = `[method]
step &key = (fixsize) (create)

downsample points with step

:filtered-indices = `[method]
&key = key ckey nkey pckey pnkey pcnkey negative &allow-other-keys
create list of index where filter function retrun true.
key, ckey, nkey are filter function for points, colors, normals. They are expected to take one argument and return t or nil.
pckey, pnkey are filter function for points and colors, points and normals. They are expected to take two arguments and return t or nil.
pcnkey is filter function for points, colors and normals. It is expected to take three arguments and return t or nil.
:filter-with-indices = `[method]
idx-lst &key = (create) (negative)
filter point cloud with list of index (points which are indicated by indices will remain).
if :create is true, return filtered point cloud and original point cloud does not change.
if :negative is true, points which are indicated by indices will be removed.
:filter = `[method]
&rest args &key = create &allow-other-keys
this method can take the same keywords with :filter-with-indices method.
if :create is true, return filtered point cloud and original point cloud does not change.

:append point-list &key (create t)

append point cloud list to this point cloud.
if :create is true, return appended point cloud and original point cloud does not change.

:centroid **

retrun centroid of this point cloud

:normal-list **

return list of normals

:color-list **

return list of colors

:point-list &optional (remove-nan)

return list of points

:normals &optional nmls

replace normals by, nmls should be list of points or n\(times\)3 matrix

:colors &optional cls

replace colors, cls should be list of points or n\(times\) matrix

:points &optional pts wd ht

replace points, pts should be list of points or n\(times\) matrix

:size-change &optional wd ht

change width and height, this method does not change points data

:init = `[method]
&rest args &key = ((:points mat)) ((:colors cary)) ((:normals nary)) ((:curvatures curv)) ((:height ht)) ((:width wd)) (point-color (float-vector 0 1 0)) (point-size 2.0) (fill) (arrow-width 2.0) (arrow-size 0.0)

Create point cloud object

:draw vwer

:transparent &optional trs

:drawnormalmode &optional mode

:set-offset cds &key (create)

:generate-color-histogram-hs &key (h-step 9) (s-step 7) (hlimits (cons 360.0 0.0)) (vlimits (cons 1.0 0.15)) (slimits (cons 1.0 0.25)) (rotate-hue) (color-scale 255.0) (sizelimits 1)

:step-inlier step offx offy

:image-circle-filter dist &key (height 144) (width 176) (cy (/ (float (- height 1)) 2)) (cx (/ (float (- width 1)) 2)) create negative

:image-position-inlier &key (ipkey) (height 144) (width 176) (cy (/ (float (- height 1)) 2)) (cx (/ (float (- width 1)) 2)) negative

:viewangle-inlier &key (min-z 0.0) (hangle 44.0) (vangle 35.0)

:nfilter &rest args

:clear-normal **

:clear-color **

:axis-width &optional aw

:axis-length &optional al

:point-size &optional ps

:point-color &optional pc

:set-color col &optional (_transparent)

:curvature-list **

:curvatures &optional curv

:view-coords &optional vc

:height **

:width **

:size **

:vertices **

:box **

:reset-box **

make-random-pointcloud &key (num 1000) (with-color) (with-normal) (scale 100.0)

グラフ表現

node

:super = ** propertied-object**
:slots arc-list image

:image &optional im

:unlink n

:remove-all-arcs **

:remove-arc a

:add-arc a

:successors **

:arc-list **

:init n &optional image

arc

:super = ** propertied-object**
:slots from to

:prin1 &optional (strm t) &rest msgs

:to **

:from **

:init from_ to_

directed-graph

:super = ** propertied-object**
:slots nodes

:write-to-dot-stream &optional (strm standard-output) result-path (title output)

write graph structure to stream as dot(graphviz) style
Args:
strm: stream class for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-dot fname &optional result-path (title output)

write graph structure to dot(graphviz) file
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-file basename &optional result-path title (type pdf)

write graph structure to various type of file
Args:
basename: basename for output (output filename is ’basename.type’)
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph
type: type of output

:write-to-pdf fname &optional result-path (title (string-right-trim .pdf fname))

write graph structure to pdf
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-png fname &optional result-path (title (string-right-trim .png fname))

write graph structure to png
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:original-draw-mode **

change draw-mode to original mode

:current-draw-mode **

change draw-mode to latest mode

:draw-both-arc &optional (bothq :both)

change draw-mode, if true is set, draw bidirectional arc as two arcs

:draw-arc-label &optional (writeq :write)

change draw-mode, if true is set, draw label(name) of arcs

:draw-merged-result &optional (mergeq :merge)

change draw-mode, if true is set, draw result arc as red. if not, draw red arc independently

:init **

:successors node &rest args

:node name

:nodes &optional arg

:add-node n

:remove-node n

:clear-nodes **

:add-arc-from-to from to

:remove-arc arc

:adjacency-matrix **

:adjacency-list **

:adjacency-list **

:adjacency-matrix **

:remove-arc arc

:add-arc-from-to from to

:clear-nodes **

:remove-node n

:add-node n

:nodes &optional arg

:node name

:successors node &rest args

:init **

costed-arc

:super = ** arc**
:slots cost

:cost **

:init from to c

costed-graph

:super = ** directed-graph**
:slots nil

:path-cost from arc to

:add-arc-from-to from to cost &key (both nil)

:add-arc from to cost &key (both nil)

graph

:super = ** costed-graph**
:slots start-state goal-state

:add-arc-from-to from to &key (both nil)

:add-arc from to &key (both nil)

:goal-state &optional arg

:start-state &optional arg

:path-cost from arc to

:goal-test gs

:draw-merged-result &optional (mergeq :merge)

change draw-mode, if true is set, draw result arc as red. if not, draw red arc independently

:draw-arc-label &optional (writeq :write)

change draw-mode, if true is set, draw label(name) of arcs

:draw-both-arc &optional (bothq :both)

change draw-mode, if true is set, draw bidirectional arc as two arcs

:current-draw-mode **

change draw-mode to latest mode

:original-draw-mode **

change draw-mode to original mode

:write-to-png fname &optional result-path (title (string-right-trim .png fname))

write graph structure to png
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-pdf fname &optional result-path (title (string-right-trim .pdf fname))

write graph structure to pdf
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-file basename &optional result-path title (type pdf)

write graph structure to various type of file
Args:
basename: basename for output (output filename is ’basename.type’)
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph
type: type of output

:write-to-dot fname &optional result-path (title output)

write graph structure to dot(graphviz) file
Args:
fname: filename for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:write-to-dot-stream &optional (strm standard-output) result-path (title output)

write graph structure to stream as dot(graphviz) style
Args:
strm: stream class for output
result-path: list of solver-node, it’s result of (send solver :solve graph)
title: title of graph

:neighbors &optional args

:add-neighbor n &optional a

arced-node

:super = ** node**
:slots nil

:neighbor-action-alist **

:find-action n

:init &key name

solver-node

:super = ** propertied-object**
:slots state cost parent action memorized-path

:action &optional arg

:parent &optional arg

:cost &optional arg

:state &optional arg

:expand prblm &rest args

:path &optional (prev nil)

:init st &key ((:cost c) 0) ((:parent p) nil) ((:action a) nil)

solver

:super = ** propertied-object**
:slots nil

:solve-by-name prblm s g &key (verbose nil)

:solve prblm

:init **

graph-search-solver

:super = ** solver**
:slots open-list close-list

:close-list &optional arg

:open-list &optional arg

:pop-from-open-list &key (debug)

:add-object-to-open-list lst

:add-list-to-open-list lst

:clear-open-list **

:null-open-list? **

:add-to-open-list obj/list

:solve prblm &key (verbose nil)

:find-node-in-close-list n

:solve-init prblm

breadth-first-graph-search-solver

:super = ** graph-search-solver**
:slots nil

:pop-from-open-list &key (debug)

:add-object-to-open-list obj

:add-list-to-open-list lst

:clear-open-list **

:init **

depth-first-graph-search-solver

:super = ** graph-search-solver**
:slots nil

:pop-from-open-list &key (debug)

:add-object-to-open-list obj

:add-list-to-open-list lst

:clear-open-list **

:init **

best-first-graph-search-solver

:super = ** graph-search-solver**
:slots aproblem

:fn n p

:pop-from-open-list &key (debug nil)

:add-object-to-open-list obj

:add-list-to-open-list lst

:clear-open-list **

:init p

a-graph-search-solver

:super = ** best-first-graph-search-solver**
:slots nil

:hn n p

:gn n p

:fn n p &key (debug nil)

:init p

irteus拡張

GL/X表示

polygon

:super = ** plane**
:slots normal distance convexp edges vertices model-normal model-distance

line

:super = ** propertied-object**
:slots pvert nvert

faceset

:super = ** cascaded-coords**
:slots rot pos parent descendants worldcoords manager changed box faces edges vertices model-vertices

:set-color gl::color &optional (gl::transparent)

Set color of given color name, color sample and color name are referenced from http://en.wikipedia.org/wiki/X11_color_names

:paste-texture-to-face gl::aface &key gl::file gl::image (gl::tex-coords (list (float-vector 0 0) (float-vector 0 1) (float-vector 1 1) (float-vector 1 0)))

:draw-on &key ((:viewer gl::vwer) viewer) gl::flush (gl::width 1) (gl::color #f(1.0 1.0 1.0))

coordinates

:super = ** propertied-object**
:slots rot pos

float-vector

:super = ** vector**
:slots nil

gl::glvertices

:super = ** cascaded-coords**
:slots gl::mesh-list gl::filename gl::bbox

:set-color gl::color &optional (gl::transparent)

set color as float vector of 3 elements, and transparent as float, all values are betwenn 0 to 1

:actual-vertices **

return list of vertices(float-vector), it returns all vertices of this object

:calc-bounding-box **

calculate and set bounding box of this object

:vertices **

return list of vertices(float-vector), it returns vertices of bounding box of this object

:reset-offset-from-parent **

move vertices in this object using self transformation, this method change values of vertices. coordinates’s method such as :transform just change view of this object

:expand-vertices **

expand vertices number as same number of indices, it enable to set individual normal to every vertices

:use-flat-shader **

use flat shader mode, use opengl function of glShadeModel(GL_FLAT)

:use-smooth-shader **

use smooth shader mode, use opengl function of glShadeModel(GL_SMOOTH) default

:calc-normals &optional (gl::force nil) (gl::expand t) (gl::flat t)

normal calculation
if force option is true, clear current normalset.
if exapnd option is ture, do :expand-vertices.
if flat option is true, use-flat-shader
:mirror-axis = `[method]
&key = (gl::create t) (gl::invert-faces t) (gl::axis :y)

creating mirror vertices respect to :axis

:convert-to-faces = `[method]
&rest args &key = (gl::wrt :local) &allow-other-keys

create list of faces using vertices of this object

:convert-to-faceset &rest args

create faceset using vertices of this object

:set-offset gl::cds &key (gl::create)

move vertices in this object using given coordinates, this method change values of vertices. coordinates’s method such as :transform just change view of this object

:convert-to-world &key (gl::create)

move vertices in this object using self’s coordinates. vertices data should be moved as the same as displayed

:glvertices &optional (name) (gl::test #’string=)

create individual glvertices objects from mesh-list. if name is given, search mesh has the same name

:append-glvertices gl::glv-lst

append list of glvertices to this object

:init gl::mlst &rest args &key ((:filename gl::fn)) &allow-other-keys

:filename &optional gl::nm

:get-meshinfo gl::key &optional (pos -1)

:set-meshinfo gl::key gl::info &optional (pos -1)

:get-material &optional (pos -1)

:set-material gl::mat &optional (pos -1)

:expand-vertices-info gl::minfo

:faces **

:draw-on &key ((:viewer gl::vwer) viewer)

:draw gl::vwr &rest args

:collision-check-objects &rest args

:box **

:make-pqpmodel &key (gl::fat 0)

:append-glvertices gl::glv-lst

append list of glvertices to this object

:glvertices &optional (name) (gl::test #’string=)

create individual glvertices objects from mesh-list. if name is given, search mesh has the same name

:convert-to-world &key (gl::create)

move vertices in this object using self’s coordinates. vertices data should be moved as the same as displayed

:set-offset gl::cds &key (gl::create)

move vertices in this object using given coordinates, this method change values of vertices. coordinates’s method such as :transform just change view of this object

:convert-to-faceset &rest args

create faceset using vertices of this object

:convert-to-faces = `[method]
&rest args &key = (gl::wrt :local) &allow-other-keys

create list of faces using vertices of this object

:mirror-axis = `[method]
&key = (gl::create t) (gl::invert-faces t) (gl::axis :y)

creating mirror vertices respect to :axis

:calc-normals &optional (gl::force nil) (gl::expand t) (gl::flat t)

normal calculation
if force option is true, clear current normalset.
if exapnd option is ture, do :expand-vertices.
if flat option is true, use-flat-shader

:use-smooth-shader **

use smooth shader mode, use opengl function of glShadeModel(GL_SMOOTH) default

:use-flat-shader **

use flat shader mode, use opengl function of glShadeModel(GL_FLAT)

:expand-vertices **

expand vertices number as same number of indices, it enable to set individual normal to every vertices

:reset-offset-from-parent **

move vertices in this object using self transformation, this method change values of vertices. coordinates’s method such as :transform just change view of this object

:vertices **

return list of vertices(float-vector), it returns vertices of bounding box of this object

:calc-bounding-box **

calculate and set bounding box of this object

:actual-vertices **

return list of vertices(float-vector), it returns all vertices of this object

:set-color gl::color &optional (gl::transparent)

set color as float vector of 3 elements, and transparent as float, all values are betwenn 0 to 1

:make-pqpmodel &key (gl::fat 0)

:box **

:collision-check-objects &rest args

:draw gl::vwr &rest args

:draw-on &key ((:viewer gl::vwer) viewer)

:faces **

:expand-vertices-info gl::minfo

:set-material gl::mat &optional (pos -1)

:get-material &optional (pos -1)

:set-meshinfo gl::key gl::info &optional (pos -1)

:get-meshinfo gl::key &optional (pos -1)

:filename &optional gl::nm

:init gl::mlst &rest args &key ((:filename gl::fn)) &allow-other-keys

gl::glbody

:super = ** body**
:slots gl::aglvertices

:set-color &rest args

:draw gl::vwr

:glvertices &rest args

gl::find-color gl::color

returns color vector of given color name, the name is defined in https://github.com/euslisp/jskeus/blob/master/irteus/irtglrgb.l

gl::transparent gl::abody gl::param

Set abody to transparent with param

gl::make-glvertices-from-faceset gl::fs &key (gl::material)

returns glvertices instance
fs is geomatry::faceset

gl::make-glvertices-from-faces gl::flst &key (gl::material)

returns glvertices instance
flst is list of geomatry::face

gl::write-wrl-from-glvertices fname gl::glv &rest args

write .wrl file from instance of glvertices

gl::set-stereo-gl-attribute **

gl::reset-gl-attribute **

gl::delete-displaylist-id gl::dllst

gl::transpose-image-rows gl::img &optional gl::ret

gl::draw-globjects gl::vwr gl::draw-things &key (gl::clear t) (gl::flush t) (gl::draw-origin 150) (gl::draw-floor nil) (gl::floor-color #f(1.0 1.0 1.0))

gl::draw-glbody gl::vwr gl::abody

gl::_dump-wrl-shape gl::strm gl::mesh &key ((:scale gl::scl) 1.0) (gl::use_ambient nil) (gl::use_normal nil) (gl::use_texture nil) &allow-other-keys

x:xwindow

:super = ** x:xdrawable**
:slots x::display x::drawable x::gcon x::bg-color x::width x::height x::parent x::subwindows x::visual x::backing-pixmap x::event-forward

x:panel

:super = ** x:xwindow**
:slots x::display x::drawable x::gcon x::bg-color x::width x::height x::parent x::subwindows x::visual x::backing-pixmap x::event-forward x::pos x::items x::fontid x::rows x::columns x::next-x x::next-y x::item-width x::item-height x::dark-edge-color x::light-edge-color x::topleft-edge-polygon x::active-menu

x:xscroll-bar

:super = ** x:xwindow**
:slots x::display x::drawable x::gcon x::bg-color x::width x::height x::parent x::subwindows x::visual x::backing-pixmap x::event-forward x::arrow-length x::handle-pos x::handle-length x::verticalp x::handle-grabbed

x::tabbed-panel

:super = ** x:panel**
:slots x::tabbed-buttons x::tabbed-panels x::selected-tabbed-panel

:resize x::w h

:tabbed-panel name &rest args

:tabbed-button name &rest args

:change-tabbed-panel x::obj

:add-tabbed-panel name

:create &rest args

x::panel-tab-button-item

:super = ** x:button-item**
:slots nil

:draw-label &optional (x::state :up) (x::offset 0)

x::window-main-one &optional fd

x::event-far x::e

x::event-near x::e

ユーティリティ関数

mtimer

:super = ** object**
:slots buf

:init **

Initialize timer object.

:start **

Start timer.

:stop **

Stop timer and returns elapsed time in seconds.

:stop **

Stop timer and returns elapsed time in seconds.

:start **

Start timer.

:init **

Initialize timer object.

interpolator

:super = ** propertied-object**
:slots (position-list :type cons) (time-list :type cons) (position :type float-vector) (time :type float) (segment-num :type integer) (segment-time :type float) (segment :type integer) (interpolatingp :type symbol)

:init **

Abstract class of interpolator

:reset = `[method]
&rest args &key = ((:position-list pl) (send self :position-list)) ((:time-list tl) (send self :time-list)) &allow-other-keys
Initialize interpolator
position-list: list of control point
time-list: list of time from start for each control point, time in first contrall point is zero, so length of this list is length of control point minus 1

:position-list **

returns position list

:position **

returns current position

:time-list **

returns time list

:time **

returns current time

:segment-time **

returns time[sec] with in each segment

:segment **

returns index of segment which is currently processing

:segment-num **

returns number of total segment

:interpolatingp **

returns if it is currently processing

:start-interpolation **

start interpolation

:stop-interpolation **

stop interpolation

:pass-time dt

process interpolation for dt[sec]

:pass-time dt

process interpolation for dt[sec]

:stop-interpolation **

stop interpolation

:start-interpolation **

start interpolation

:interpolatingp **

returns if it is currently processing

:segment-num **

returns number of total segment

:segment **

returns index of segment which is currently processing

:segment-time **

returns time[sec] with in each segment

:time **

returns current time

:time-list **

returns time list

:position **

returns current position

:position-list **

returns position list

:reset = `[method]
&rest args &key = ((:position-list pl) (send self :position-list)) ((:time-list tl) (send self :time-list)) &allow-other-keys
Initialize interpolator
position-list: list of control point
time-list: list of time from start for each control point, time in first contrall point is zero, so length of this list is length of control point minus 1

:init **

Abstract class of interpolator

linear-interpolator

:super = ** interpolator**
:slots nil

:interpolation **

Linear interpolator

:interpolation **

Linear interpolator

minjerk-interpolator

:super = ** interpolator**
:slots velocity acceleration velocity-list acceleration-list

:velocity **

returns current velocity

:velocity-list **

returns velocity list

:acceleration **

returns current acceleration

:acceleration-list **

returns acceleration list

:reset = `[method]
&rest args &key = ((:velocity-list vl) (send self :velocity-list)) ((:acceleration-list al) (send self :acceleration-list)) &allow-other-keys
minjerk interopolator
position-list : list of control point
velocity-list : list of velocity in each control point
acceleration-list : list of acceleration in each control point

:interpolation **

Minjerk interpolator, a.k.a Hoff & Arbib
Example code is:
(setq l (instance minjerk-interpolator :init))
(send l :reset :position-list (list #f(1 2 3) #f(3 4 5) #f(1 2 3)) :time-list (list 0.1 0.18))
(send l :start-interpolation)
(while (send l :interpolatingp) (send l :pass-time 0.02) (print (send l :position)))

:interpolation **

Minjerk interpolator, a.k.a Hoff & Arbib
Example code is:
(setq l (instance minjerk-interpolator :init))
(send l :reset :position-list (list #f(1 2 3) #f(3 4 5) #f(1 2 3)) :time-list (list 0.1 0.18))
(send l :start-interpolation)
(while (send l :interpolatingp) (send l :pass-time 0.02) (print (send l :position)))
:reset = `[method]
&rest args &key = ((:velocity-list vl) (send self :velocity-list)) ((:acceleration-list al) (send self :acceleration-list)) &allow-other-keys
minjerk interopolator
position-list : list of control point
velocity-list : list of velocity in each control point
acceleration-list : list of acceleration in each control point

:acceleration-list **

returns acceleration list

:acceleration **

returns current acceleration

:velocity-list **

returns velocity list

:velocity **

returns current velocity

forward-message-to to args

forward _args_ message to _to_ object

forward-message-to-all to args

forward _args_ message to all _to_ object

permutation lst n

Returns permutation of given list

combination lst n

Returns combination of given list

find-extreams = `[function]
datum &key = (key #’identity) (identity #’=) (bigger #’>)

Returns the elements of datum which maximizes key function

eus-server &optional (port 6666) &key (host (unix:gethostname))

Create euslisp interpreter server, data sent to socket is evaluated as lisp expression

connect-server-until-success = `[function]
host port &key = (max-port (+ port 20)) (return-with-port nil)

Connect euslisp interpreter server until success

format-array arr &optional (header ) (in 7) (fl 3) (strm error-output) (use-line-break t)

print formatted array

his2rgb h &optional (i 1.0) (s 1.0) ret

convert his to rgb (0 <= h <= 360, 0.0 <= i <= 1.0, 0.0 <= s <= 1.0)

hvs2rgb h &optional (i 1.0) (s 1.0) ret

convert hvs to rgb (0 <= h <= 360, 0.0 <= i <= 1.0, 0.0 <= s <= 1.0)

rgb2his r &optional g b ret

convert rgb to his (0 <= r,g,b <= 255)

rgb2hvs r &optional g b ret

convert rt to hvs (0 <= r,g,b <= 255)

color-category10 i

Choose good color from 10 colors

color-category20 i

Choose good color from 20 colors

kbhit **

Checks the console for a keystroke. returns keycode value if a key has been pressed, otherwise it returns nil. Note that this does not work well on Emacs Shell mode, run EusLisp program from terminal shell.

piped-fork-returns-list cmd &optional args

piped fork returning result as list

make-robot-model-from-name name &rest args

make a robot model from string: (make-robot-model ”pr2”)

mapjoin expr seq1 seq2

need-thread n &optional (lsize (512 1024)) (csize lsize)

termios-c_iflag lisp::s

set-termios-c_iflag lisp::s lisp::val

termios-c_oflag lisp::s

set-termios-c_oflag lisp::s lisp::val

termios-c_cflag lisp::s

set-termios-c_cflag lisp::s lisp::val

termios-c_lflag lisp::s

set-termios-c_lflag lisp::s lisp::val

termios-c_line lisp::s

set-termios-c_line lisp::s lisp::val

termios-c_cc lisp::s &optional lisp::i

set-termios-c_cc lisp::s lisp::i &rest lisp::val

termios-c_ispeed lisp::s

set-termios-c_ispeed lisp::s lisp::val

termios-c_ospeed lisp::s

set-termios-c_ospeed lisp::s lisp::val

gnuplot

:super = ** propertied-object**
:slots strm data data-length last-command debug
:init = `[method]
host &key = (clear t) ((:debug _debug))

Initialize gnuplot interface object with given host name

:clear **

Clear graph

:draw &rest vs

Draw graph with given float vectors,
:range, :xrange, :yrange, : range of each axis
:title : title of graph
:line-width : line width
:direction : direction of the graph (:right, :left)
:xscale, :xoffset : scale and offset for data
:y2tics : list variable to specify when y2 range is used
:y2range : set y2 tics and specify range
:type : specify type of the graph (:lines, :2dmap)

:save f &key (type postscript eps color ”Times-Roman” 24)

save graph as eps file

:replot **

:reset **

:command msg

:quit **

:proc-length &optional n

:proc-clear **

:proc-one vs &rest args

:save f &key (type postscript eps color ”Times-Roman” 24)

save graph as eps file

:draw &rest vs

Draw graph with given float vectors,
:range, :xrange, :yrange, : range of each axis
:title : title of graph
:line-width : line width
:direction : direction of the graph (:right, :left)
:xscale, :xoffset : scale and offset for data
:y2tics : list variable to specify when y2 range is used
:y2range : set y2 tics and specify range
:type : specify type of the graph (:lines, :2dmap)

:clear **

Clear graph

:init = `[method]
host &key = (clear t) ((:debug _debug))

Initialize gnuplot interface object with given host name

:proc-one vs &rest args

:proc-clear **

:proc-length &optional n

:quit **

:command msg

:reset **

:replot **

gnuplot &key (host (unix:gethostname))

Returns gnuplot interface instance
ex)
(setq g(gnuplot))
(send g:draw #f(0 1 2 3 4 5) #f(5 4 3 2 1 0) :xrange ’(0 10) :yrange ’(0 10) :title ’(”data1” ”data2”))
see irteus/gnuplotlib.l for more info
graph-view = `[function]
ordinate-list &optional (abscissa-list (let ((idx -1)) (mapcar #’(lambda (x) (incf idx)) (make-list (length (car ordinate-list)))))) &key = (title Graph) (xlabel X) (ylabel Y) (zlabel Z) (dump-graph nil) (graph-fname (format nil  A.eps (substitute 95 (elt 0) title))) (mode lines) keylist xrange yrange zrange x11 additional-func no-dump ((:graph-instance gp) (if (boundp ’gp) gp(setq gp(gnuplot)))) (fname (format nil data A (system:address gp)))
plot function for 2d or 3d plot
ordinate-list : list of data for ordinate axis
2D = (list (list y00 y01 ... y0n), ... (list ym0 ym1 ... ymn))
3D = (list (list z00 z01 ... z0n), ... (list zm0 zm1 ... zmn))
abscissa-list : list of data for abscissa axes
2D = (list x0 x1 ... xn)
3D = (list xylist0 ... xylistn) ;; xylist = (list x y)
:title : title of graph
:xlabel, :ylabel, zlabel : label for each axis
:keylist : legend of each data
:xrange, :yrange, :zrange : range of each axis
:mode : ”lines” or ”points”

数学関数

inverse-matrix mat

returns inverse matrix of mat

inverse-matrix-complex cmat

returns inverse matrix of complex square matrix

m-complex cmat1 cmat2

returns complex matrix 1 complex matrix 2

diagonal v

make diagonal matrix from given vecgtor, diagonal #f(1 2) ->#2f((1 0)(0 2))

minor-matrix m ic jc

return a matrix removing ic row and jc col elements from m

atan2 y x

returns atan2 of y and x (atan (/ y x))

outer-product-matrix v &optional (ret (unit-matrix 3))

returns outer product matrix of given v
matrix(a) v = a v 0 -w2 w1 w2 0 -w0 -w1 w0 0

matrix2quaternion m

returns quaternion (w x y z) of given matrix

quaternion2matrix q

returns matrix of given quaternion (w x y z)

matrix-log m

returns matrix log of given m, it returns [-pi, pi]

matrix-exponent omega &optional (p 1.0)

returns exponent of given omega

midrot p r1 r2

returns mid (or p) rotation matrix of given two matrix r1 and r2

pseudo-inverse mat &optional weight-vector ret wmat mat-tmp

returns pseudo inverse of given mat

sr-inverse mat &optional (k 1.0) weight-vector ret wmat tmat umat umat2 mat-tmp mat-tmp-rc mat-tmp-rr mat-tmp-rr2

returns sr-inverse of given mat

manipulability jacobi &optional tmp-mrr tmp-mcr

return manipulability of given matrix

random-gauss &optional (m 0) (s 1)

make random gauss, m:mean s:standard-deviation

gaussian-random dim &optional (m 0) (s 1)

make random gauss vector, replacement for quasi-random defined in matlib.c

eigen-decompose-complex m

returns eigen decomposition from real square matrix

solve-non-zero-vector-from-det0-matrix m

solves non-zero-vector v from real square determinant-zero-matrix mat, when matv=O and det(mat)=0

concatenate-matrix-column &rest args

Concatenate matrix in column direction.

concatenate-matrix-row &rest args

Concatenate matrix in row direction.

concatenate-matrix-diagonal &rest args

Concatenate matrix in diagonal.

vector-variance vector-list

returns vector, each element represents variance of elements in the same index of vector within vector-list

covariance-matrix vector-list

make covariance matrix of given input vector-list

normalize-vector v &optional r (eps 1.000000e-20)

calculate normalize-vector #f(0 0 0)->#f(0 0 0).

pseudo-inverse-org m &optional ret winv mat-tmp-cr

sr-inverse-org mat &optional (k 1) me mat-tmp-cr mat-tmp-rr

eigen-decompose m

lms point-list

lms-estimate res point-

lms-error result point-list

lmeds point-list &key (num 5) (err-rate 0.3) (iteration) (ransac-threshold) (lms-func #’lms) (lmeds-error-func #’lmeds-error) (lms-estimate-func #’lms-estimate)

lmeds-error result point-list &key (lms-estimate-func #’lms-estimate)

lmeds-error-mat result mat &key (lms-estimate-func #’lms-estimate)

画像関数

read-image-file fname

read image of given fname. It returns instance of grayscale-image or color-image24.

write-image-file fname image::img

write img to given fname

read-png-file fname

write-png-file fname image::img