2014年7月29日火曜日

ClassNotFoundException: processing.core.PAplet への対処

ネットへの恩返しをしておこう。
Processingを利用して、色々といじっている内に
 ClassNotFoundException: processing.core.PAplet
というエラーが出て、Serialライブラリが使えなくなった。
(Mac OS X 10.9.4, Processing 2.0.3)

対処方法は、
 /Library/Java/Extension
に入れたものを出す(空にする)、であった。

以下のサイトには、
http://blog.livedoor.jp/reona396/archives/54536269.html
core.jar
を入れろとある。私の場合は、ArduinoとのZigBee通信のために試行錯誤している途中で、RXTX.jar, Serial.jarなどを上記 Extension フォルダに入れていたのが悪さをしていた。

Javaがどのライブラリを見るか迷ったのが原因のようだ。
上記のサイトに書いてある内容を見てヒントを思いついたので、感謝をこめて、私のメモをアップする。

以上

2014年7月28日月曜日

ZigBee (API)通信用のProcessingプログラム(3台の子機)

「ZigBee (API) + Arduino -- ZigBee (API) + Macの通信」でアップしたProcessingプログラムを、3台のZigBee+Arduinoから受信するように改良した。

ZigBeeのアドレステーブルをPCで保持し、アドレスを確認してそれぞれにデータを保持する。

// サンプル
import processing.serial.*;
import java.util.concurrent.*;
import java.util.Queue;
import org.apache.log4j.PropertyConfigurator;

XBee xbee;
Queue<XBeeResponse> queue = new ConcurrentLinkedQueue<XBeeResponse>();
boolean message;
XBeeResponse response;

String senderAddress = "00:13:A2:00:40:B9:3C:CB";
String rxStr = "********";
String txStatus = "";
int rssi = 0;
int rxVarC, rxErrC, tblC;

String[] addressTbl = new String[3];
int[] rxVar = new int[3];
int[] oldrxVar = new int[3];
int[] rxErr = new int [3];

void setup()
{
  size(640,200);
  colorMode(RGB,256);
  background(0,0,0);

  setUpDataTble(); // センサノードに対応した状態管理の初期化
  
  try {
    //optional.  set up logging
    //PropertyConfigurator.configure(dataPath("")+"/log4j.properties");
    xbee = new XBee();
    // replace with your COM port
    xbee.open("/dev/tty.usbserial-A5025X1E", 9600); // xbeeを繋いでいるシリアルポートを指定
    xbee.addPacketListener(new PacketListener() { // xbeeのレスポンスを待つパケット監視を設定
      public void processResponse(XBeeResponse response) {
        queue.offer(response);
      }
    }
    );
  } 
  catch (Exception e) {
    System.out.println("XBee failed to initialize");
    e.printStackTrace();
    System.exit(1);
  }
}

void setUpDataTble() {
  //int[] idTbl = new int[3];
  //int[] rxVar = new int[3];
  //int[] oldrxVar = new int[3];
  //int[] rxErr = new int [3];
  tblC = rxVarC = rxErrC = 0;
}

int setData(String nad, int rx) {
  int id = -1;
  for (int i = 0; i < tblC; i++) {
    if (addressTbl[i].equals(nad)) id = i;
  };
  if (id == -1) {
    addressTbl[tblC] = nad;
    id = tblC++;
  };
  
  rxVar[id] = rx;
  if (rxVar[id] != oldrxVar[id] + 1) rxErr[id]++;
  oldrxVar[id] = rxVar[id];
  
  return id;
};

void draw(){
  // パケット読み取り
  try {
    readPackets();
  }
  catch (Exception e) {
    e.printStackTrace();
  }
  
  background(255);
  textAlign(LEFT);
  textSize(20);
  
  // 受信強度の表示
  fill(0); text("RSSI", 10, 25); fill(0,0,255);
  text(String.format("%d", rssi) + "dB", 100, 25);
  
  // 受信元アドレスを表示
  fill(0); text("Address", 10, 50); fill(0,0,255);
  text(senderAddress, 100, 50);

  // 受信データの表示  
  fill(0);
  text("Rx Data", 10, 75);
  fill(0,0,255);
  //text(rxStr, 100, 75);
  text(rxVarC, 200, 75);
  text("ERR:"+rxErrC, 300, 75);
  
  for (int i = 0; i < tblC; i++) {
    text(addressTbl[i] +" = "+rxVar[i], 110, 100 + i * 25);
  };
  
  // 受信状態の表示
  fill(255,0,0);
  text(txStatus, 10, 100);
}

// パケットの読み込みとエコー、ATDBの送信
void readPackets() throws Exception {

  while ((response = queue.poll()) != null) {
    // we got something!
    try {
      if (response.getApiId() == ApiId.ZNET_RX_RESPONSE && !response.isError()) {
        ZNetRxResponse rxResponse = (ZNetRxResponse) response;
        
        // アドレスをintで取得
        int[] addressArray = rxResponse.getRemoteAddress64().getAddress();
        String[] hexAddress = new String[addressArray.length];
        // 16進数のStringへ
        for(int i=0; i<addressArray.length;i++){
          hexAddress[i] = String.format("%02x",addressArray[i]);
        }
        // 送信元アドレスを文字列で保存
        senderAddress = join(hexAddress,":");
        
        //受信データを取得
        int[] rxData = rxResponse.getData();
        rxStr = "";
        for(int i=0; i<rxData.length; i++){
          rxStr += String.format("%c", rxData[i]);
        }
        // Arduinoのプログラムと対応して、2バイトのintデータを前提にしている。
        rxVarC = rxData[0] << 8 | rxData[1];
        int id = setData(senderAddress, rxVarC);
        rxVarC = rxVar[id];
        rxErrC = rxErr[id];
        
        // エコー (送られてきたデータを、そのまま返信)
        int[] payload = rxData;
        XBeeAddress64 addr64 = new XBeeAddress64(addressArray); // データの送信元アドレスを設定
        ZNetTxRequest request = new ZNetTxRequest(addr64, payload); // 送られてきたデータをAPIパケットに変換
        try {
          // データ送信
          ZNetTxStatusResponse response = (ZNetTxStatusResponse) xbee.sendSynchronous(request);
          txStatus = "";
        } catch (Exception e) {
          txStatus = "tx request timed out";
        }
        
        // ATコマンドを送信し、RSSIを取得
        AtCommand  at = new AtCommand("DB"); // ATDBで、RSSIを取得し、電波強度を調査する。
        AtCommandResponse response = (AtCommandResponse) xbee.sendSynchronous(at, 5000);
        if (response.isOk()) {
          // 成功
          rssi = response.getValue()[0];
          rssi = rssi * (-1);
        }
      }
    }
    catch (ClassCastException e) {
      // not an IO Sample
    }
  }
}

2014年7月27日日曜日

Xbee+ArduinoとXbee+Macを繋ぐ方法(つまづきメモ)

2014年7月27日

「XBee+ArduinoとXBee+Macを繋ぐ方法」
http://airshipnewsjapan.blogspot.jp/2014/07/xbeearduinoxbeemac.html
をまとめるに至った過程で、苦労したことをメモとして記録しておく。

XBee+Arduino+バッテリーで、センサノードをばらまいて、PCでデータ収集をするシステムを作るのが目的だ。

XBee WIFIで作ろうかと思ったが、インターネットへの接続はPCで集約した方が便利なのと、センサノードの省電力化をはかりたいと思ったため、ZigBeeを扱えるXbee ZBで作ってみることにした。

最初はキーワードが全然わからず苦労した。
XBeeとZigBeeとArduino、さらに懐かしいATコマンドのそれぞれの用語がある。

XBeeをArduinoに搭載するには、XBeeとArduinoを接続する必要がある。簡単なのはシールドを用いることだ。ところが3つ購入したシールドの内の一つが不良であった。4個のXBeeを相互接続したところ、どうしても4つ目が認識せず、Arduinoのせいなのか、XBeeのせいなのか、シールドのせいなのか分からず切り分け試験に苦労した。

ArduinoやXBeeを交換してもなおらないので、シールドが妖しいとにらんだが、プログラムの方も自信がなかったので、確信が持てなかった。シールドの代わりに、XBeeをピッチ変換基板(細かなハンダつけが必要)に載せ変えたところ、問題なく動いた。

3カ所以上のハンダづけは久しぶりだったが、昔取った杵柄なんだね、身体が覚えていた。

なお、ここまでの試験では、ATモードで接続していた。
XBeeに関するATモードでの設定は、スイッチサイエンスのホームページが詳しい。
丁寧に記述されていて、この通りにすれば設定できる。

さてここでATモードというのが出てきたが、XBeeには、ATモードとAPIモードという2種類がある。ATモードは別名「透過モード」とも言う。ZigBeeは本来、規格にあったパケットをやりとりすることで通信する。それがAPIモードである。しかしAPIモードは数字列で普通のプログラマが直接やりとりするには低レベルすぎる。

そこでXBeeでは、APIモードのパケットを独自に変換して、直接シリアルモデムで接続されているかのように見せてくれるモードが用意されている。つまり、ATモードだと、
 PC--シリアル--モデム----モデム--シリアル--Arduino
というイメージで使える。

ただし簡易モードなので、1対1通信程度なら問題ないが、センサノードを複数台扱おうとすると無理がある。ただ、無理がある、といろんなホームページに書かれているが、どの程度無理があるのかと思って、1対3で接続してテストしてみた。PC1台に、センサノード3台をつなげてみた。

PCに繋いだXBeeはCoordinator ATで設定し、ブロードキャスト設定(送信先をDH=0, DL=FFFFにする)で、センサノードは全て、Router ATで設定して、送付先をPCに繋いだCoordinatorにした。


なお、ここでまた新しい用語が出てきた。Coordinatorと Routerである。あとEnd Nodeというのがある。ZigBeeにはこの3種類がある。Coordinatorというのは、一つのネットワークの監視役である。Routerは中継に使われる。End Nodeというのは末端のセンサノードである。End Nodeにはスリープする機能がある。

設定方法は、「Xbee+ArduinoとXbee+Macを繋ぐ方法」に書いた通りで、xctuというソフトを使う。xctuにはWindows版しかない、と多くのホームページで書かれているが、今はちゃんとMac版がある。けっこう使い勝手の良いソフトである。

Coordinatorとか、Routerとか、またはATモードとかAPIモードとかの変更は、ファームを変えることで行う。単に設定変更ではできない。

さて、元に戻って、ATモードの限界についてだが。テストしたのは、Coordinatorから1, 2, 3,...と番号を1秒おきにブロードキャストして、センサノードにそれぞれ番号を割り当てて、自分の番号が送られてきたら、値を返す、という単純なテストである。

最初はうまく行っていた。順調に値が返ってきていた。ところが何十回かやっていると、通信が一時停止することがわかった。細かく追っていないが、ブロードキャストが滞っているものと推察される。その理由はブロードキャストタイミングを早めて、1/10秒ごとに番号を送るようにすると、あっという間に滞るためだ。

滞るのも、1、2秒なら良いが酷い場合には、10秒も20秒も滞る。これでは使い物にならない。ブロードキャストの範囲などを細かく制限すれば、大丈夫になるのかもしれないが、あまり深入りしても時間の無駄なので、ここでATモードとはおさらばすることにした。

さてAPIモードを使おうと思ったが、直接APIパケットを作るのはいくらなんでもやりたくないので、便利なものが無いか探した。最初は小林さん@IAMASたちが作ったfunnelを使おうかと思ったが、Processing 2.0に対応していないというのと、カプセル化が強く、高レベルすぎるのが気になり、もう少し低レベルで扱えるライブラリを探した。

ただ、だいぶ自分の頭が整理できたので、funnelを使うことを再検討してみても良い。

funnelは、小林さんの「Prototyping Lab--「作りながら考える」ためのArduino実践レシピ」の前提とされているライブラリで、未踏で作られたかなりできの良いものだ。2009年に完成しているので、その後のアップデートが滞っているのだろうか?

funnelだと、Arduino側の設定も、PC側からできてしまう。ProcessingでArduinoの入出力まで制御できるというすごいライブラリだ。ただ、このアクロバットをこなすために、ちょっと凝ったことがしてある。私としては、Arduinoは、Arduinoでコーディングして、PCは受信したデータを扱ったり、Arduinoに指令を出すなどの役割分担をする方が、気持ち的に良い。オブジェクト指向的というか。

調べてみると、Arduinoには、XBee-Arduinoというライブラリが、ProcessingというかJavaには、xbee-apiというライブラリがあることがわかった。いずれも

 APIモード
 エスケープモード
を扱えるライブラリである。
今回、「XBee+ArduinoとXBee+Macを繋ぐ方法」で解説しているのは、この方法である。

さて、ここでまた新しい用語「エスケープモード」が出てきた。APIモードでは、すべてのパケットは0x7Eで始まる。よってパケットの中に0x7Eを含むデータがあると、パケットの先頭と間違える可能性がある。そこで、パケット内の0x7Eを別の値に退避(エスケープ)させることで、0x7Eを扱えるようにするモードである。

実はXBeeをこのモードに設定する方法がわからず、けっこう苦労した。結論としてはxctuで、AP-API Enableという設定項目を「2」に変更することで行う。

エスケーブモードにしていないとライブラリは全然動いてくれない。

また二つのライブラリを使うので、どっちのライブラリの使用方法にエラーがあるのか、の切り分け試験ができずに苦労した。

これは結論としては、PC側はシリアルモニタで監視できるので、最初にXBee-Arduino側から確認する、のが良いことに気づいた。

まずXBee-Arduinoをインストールして、データをZigBeeに送り出す簡単なサンプルプログラムをArduinoに転送することとした。XBeeを繋いだPCでシリアルモニタにより、シリアルを監視すると、値が一定時間毎に送られているのを確認できる。

ここでシリアルモニタとしては、Cool Termが良い。HEX表示もあり、使い勝手が良い。

ちゃんと値が送られてこない場合は、XBee-Arduino側に問題がある。私の場合は、エスケープモードになっていなかったためだった。

次に、Processing側のxbee-apiの設定をした。ちなみにxbee-apiに関しては、あまり日本語の情報が多くない。javaでxbeeを使おうという人がまだ多くないということだろうか?

ちなみにProcessingとは、MITで開発された簡易言語である。ここまで読むような人で知らない人はいないよね。javaベースで、javaネイティブで書くより簡単に可視化などのプログラミングができる。ProcessingのIDEは、ArduinoのIDEと見た目や使い勝手がそっくりなのも、Arduinoと一緒に使うときの敷居を下げている。

xbee-apiで苦労したのは、ドキュメントが少なく、未だに更新され続けているためだった。
例えばProcessing 2.0.3までは、私がアップしたコードで動く。しかし、2014年3月の最新のProcessingでは、RXTXというシリアルを扱うライブラリが使われなくなっており、xbee-apiが前提としているため、RXTXを別にインストールしないと使えない。

なおlog4jは使わなくても動く。log4jを使わないようにコメントアウトすると警告(Warning)が出るが、通信自体には影響がない。

Arduinoにモバイルバッテリーを繋いで、PCから離して、寝室に置いてみた。3DKの鉄筋コンクリートで、リビング-寝室間は-92dBとかなり電波状況が悪い。1秒一回の通信で5000回のテストの間に15回エラーが生じている。まぁ、そんなものか。

以上










XBee+ArduinoとXBee+Macを繋ぐ方法

Xbee APIモードの扱い方
なるべく簡単に、かつ間違いなく、安定してXBee+ArduinoとXBee+Macを繋ぐ方法

必要品は、「XBeeをはじめてみよう(ZB編)」
で用いている物に、Mac (MacBook Air)である。

1. xctuのダウンロードとインストール
「ArduinoUnoとXBeeとMac... Mac版のX-CTUを使って設定しちゃおう」
に記載のあるnew xctu for Mac
をダウンロードし、インストールする。

2. XBeeの設定
XBeeをXBee USB アダプターにセットし、それをMacに接続する。
xctuを起動する。
「Add Device」でusbserialを選んで、XBeeを設定できる状態にする。
最終的にMacに接続するXBeeは、
Coordinator API
に設定する。設定方法は、ファーム更新で選択する。

PAN-IDを好きな4桁の数字にする。これがZigBeeネットワークの識別番号、
相互接続する他のXBeeも同じ数字をPAN-IDに入れる。

AP-API Enable 2にする。これでEscモードになる。

一旦、USBを抜いて、XBeeをArduinoに搭載する側に交換する。
Arduino側のXbeeは、
Router API
に設定する。
PAN-IDは上記と同じ数字。AP-API Enableも同じく2とする。

3. XBeeとArduinoの結合
XBeeをXbeeシールドに載せ、XBeeシールドをArduinoに載せる。
XBeeシールドの小さなスイッチをUSB側にする。
ArduinoをUSBで、Macのもう一つのUSBに接続する。
Arduino-IDE(アプリケーション名はArduino)を起動する。

4. XBee-Arduino
XBee-Arduinoのサイトに行き、
xbee-arduino-0.5.zip(番号は更新されているかもしれない)をダウンロードする。
Arduino-IDEの「スケッチ->ライブラリを使用->Add Library...」でダウンロードしたファイルを選択する。

5. サンプルプログラムをArduinoに転送
以下のサンプルプログラムを、Arduino-IDEで「マイコンボードに書き込む」。
一旦ArduinoをUSBから外し、XBeeシールドの小さなスイッチをMICROに変更する。
再びArduinoをUSBでMacに接続する。

----
#include <XBee.h>

XBee xbee = XBee();

// 送付データは1バイトづつの配列に入れる
uint8_t sendData[] = { 'H', 'L' };

// 送付先のXbeeのアドレス (PCに繋いだCoordinatorのアドレスを入れる。アドレスはXbeeの裏に印刷されている。
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x40b93ccb);

// 送付データをAPIパケットに変換する。詳細な説明は以下:
// http://xbee-arduino.googlecode.com/svn/trunk/docs/api/class_z_b_tx_request.html
ZBTxRequest zbTx = ZBTxRequest(remoteAddress, sendData, sizeof(sendData)); 

// counterは送付データの例delay毎に+1する。
int pin5, counter;

void setup() {
  Serial.begin(9600); // シリアルを9600bpsで使用開始
  xbee.setSerial(Serial); // xbeeが受け持つシリアルを設定
  counter=0;
};

void loop() {
  // pin5を使っているのは、Arduinoのpin入力データを送付するイメージだから。今はダミーのcounterを送っている。
  pin5 = counter++;
  
  // 送付データはHigh, Lowの2つに分けて送付する。この作業の役割に関しては以下の解説が詳しい。
  // http://yoppa.org/tau_bmaw13/4832.html
  sendData[0] = pin5 >> 8 & 0xff;
  sendData[1] = pin5 & 0xff;
  
  // データを含んだパケットを送付
  xbee.send(zbTx);
  
  delay(1000); // ちょっと待つ
};

----

6. Cool Termで確認
Macで、Cool Term
を起動する。(入れていないならダウンロードしてインストールする)
Cool Termで、Arduinoではなく、Xbee+USBアダプターが入っている方のシリアルをオープンする。名前はusbserial-...と言った名称である。
文字列が一定時間おきに、ばらばら出てくるようなら接続成功。
Arduino->XBee---->XBee->Mac
という接続がなされている。

7. Processingでサンプルソフトを起動
新しいスケッチ画面を開く。
xbee-apiをダウンロードする。
展開したフォルダの直下にある xbee-api-0.9.jarと、libフォルダに入っているlog4j.jar, RXTXcomm.jarを新しいスケッチ画面にドラッグアンドドロップする。
もしくは、スケッチのcodeフォルダにコピーする。
スケッチのdataフォルダに、xbee-api-0.9フォルダ直下の、log4j.propertiesをコピーする。
以下のサンプルプログラムをスケッチにコピーする。
Runすると、画面に数字などが表示される。数字が更新されていればProcessingでデータを取得できている。

----
// KYDrill氏のコードを元に作成(オリジナルは以下のURL)
import processing.serial.*;
import java.util.concurrent.*;
import java.util.Queue;
import org.apache.log4j.PropertyConfigurator;

XBee xbee;
Queue<XBeeResponse> queue = new ConcurrentLinkedQueue<XBeeResponse>();
boolean message;
XBeeResponse response;

String senderAddress = "00:13:A2:00:40:B9:3C:CB";
String rxStr = "********";
String txStatus = "";
int rssi = 0;
int rxVar, oldrxVar, rxErr;

void setup()
{
  size(640,150);
  colorMode(RGB,256);
  background(0,0,0);
  rxVar = oldrxVar = rxErr = -1;
  
  try {
    //optional.  set up logging
    //PropertyConfigurator.configure(dataPath("")+"/log4j.properties");
    xbee = new XBee();
    // replace with your COM port
    xbee.open("/dev/tty.usbserial-A5025X1E", 9600); // xbeeを繋いでいるシリアルポートを指定
    xbee.addPacketListener(new PacketListener() { // xbeeのレスポンスを待つパケット監視を設定
      public void processResponse(XBeeResponse response) {
        queue.offer(response);
      }
    }
    );
  } 
  catch (Exception e) {
    System.out.println("XBee failed to initialize");
    e.printStackTrace();
    System.exit(1);
  }
}

void draw(){
  // パケット読み取り
  try {
    readPackets();
  }
  catch (Exception e) {
    e.printStackTrace();
  }
  
  background(255);
  textAlign(LEFT);
  textSize(20);
  
  // 受信強度の表示
  fill(0); text("RSSI", 10, 25); fill(0,0,255);
  text(String.format("%d", rssi) + "dB", 100, 25);
  
  // 受信元アドレスを表示
  fill(0); text("Address", 10, 50); fill(0,0,255);
  text(senderAddress, 100, 50);

  // 受信データの表示  
  fill(0);
  text("Rx Data", 10, 75);
  fill(0,0,255);
  //text(rxStr, 100, 75);
  text(rxVar, 200, 75);
  text("ERR:"+rxErr, 300, 75);
  
  // 受信状態の表示
  fill(255,0,0);
  text(txStatus, 10, 100);
}

// パケットの読み込みとエコー、ATDBの送信
void readPackets() throws Exception {

  while ((response = queue.poll()) != null) {
    // we got something!
    try {
      if (response.getApiId() == ApiId.ZNET_RX_RESPONSE && !response.isError()) {
        ZNetRxResponse rxResponse = (ZNetRxResponse) response;
        
        // アドレスをintで取得
        int[] addressArray = rxResponse.getRemoteAddress64().getAddress();
        String[] hexAddress = new String[addressArray.length];
        // 16進数のStringへ
        for(int i=0; i<addressArray.length;i++){
          hexAddress[i] = String.format("%02x",addressArray[i]);
        }
        // 送信元アドレスを文字列で保存
        senderAddress = join(hexAddress,":");
        
        //受信データを取得
        int[] rxData = rxResponse.getData();
        rxStr = "";
        for(int i=0; i<rxData.length; i++){
          rxStr += String.format("%c", rxData[i]);
        }
        // Arduinoのプログラムと対応して、2バイトのintデータを前提にしている。
        rxVar = rxData[0] << 8 | rxData[1];
        if (rxVar != oldrxVar + 1) rxErr++;
        oldrxVar = rxVar;
        
        // エコー (送られてきたデータを、そのまま返信)
        int[] payload = rxData;
        XBeeAddress64 addr64 = new XBeeAddress64(addressArray); // データの送信元アドレスを設定
        ZNetTxRequest request = new ZNetTxRequest(addr64, payload); // 送られてきたデータをAPIパケットに変換
        try {
          // データ送信
          ZNetTxStatusResponse response = (ZNetTxStatusResponse) xbee.sendSynchronous(request);
          txStatus = "";
        } catch (Exception e) {
          txStatus = "tx request timed out";
        }
        
        // ATコマンドを送信し、RSSIを取得
        AtCommand  at = new AtCommand("DB"); // ATDBで、RSSIを取得し、電波強度を調査する。
        AtCommandResponse response = (AtCommandResponse) xbee.sendSynchronous(at, 5000);
        if (response.isOk()) {
          // 成功
          rssi = response.getValue()[0];
          rssi = rssi * (-1);
        }
      }
    }
    catch (ClassCastException e) {
      // not an IO Sample
    }
  }
}



----

以上




2014年4月13日日曜日

論理哲学論考を読んで

『論理哲学論考』(岩波文庫)を読み終えた。単に読み終えただけで、細かく論証を追った訳ではない。とりあえず何が書いてあるか知って、それに対して現時点で自分がどう考えるかを知りたかったからだ。

読み始めてすぐに思ったのは、論理学の教科書のようだということだ。大学で論理プログラミング、ひいては数理論理学を学んだので、懐かしい、という印象が最初にあった。記号論理学の教科書的内容にそれなりに多くの項目が割かれている。

関数の扱いや等号理論にも彼なりの記述があって、それもなかなか面白かった。私が習ったのとは多少違うが、ラッセル・ホワイトヘッドのプリンキピアマテマティカ以降、どういう流れで、現代の数理論理学に来ているのかは知らないため、違いの意味までは追えなかった。ウィトゲンシュタインはゲーデルのことは知っていたのだろうか。

最初は哲学の本だと思って読み始めたら、論理学、それも意味論の話だったので、若干肩すかしであった。ところが全編を読んでみて、なるほどこれは哲学の本だと分かった。その自分の中での変化が面白かった。

私にとっての哲学的意味は、冒頭と最後あたりに現れる、語りえぬもののエッジに関する記載にある。沈黙しなければならない所に、人間は自然と点線を引いてしまう。それは私にとっては、神、美、善、夢想といった域外の何かである。彼は当然何も語らないのだが、ぎりぎりまで追いつめることによって、より鮮明に私の心に浮かぶ何か。ホラー映画で、化け物が登場する直前の、ぎりぎりの瞬間が最も怖いのと同じように。これは人間の思考のどういう仕組みだろうか。

訳者による注釈が丁寧で読みやすい。ラッセルによる解説も、たしかに勘違いはありそうだが、これはこれでラッセルの見方が読み取れて面白い。さらに訳者による解説もいい。さすが岩波文庫だと思う。

この『論理哲学論考』という薄い本にはたしかに、妖しい魅力がつまっている。私にはボルヘスの短編を彷彿とさせた。


2014年3月21日金曜日

気合いの入っていないパン

いま住んでいる東京都世田谷区には、たくさんのパン屋がある。
家の近所にも徒歩圏内に10軒近くはあるだろう。
いろんなパンを食べ比べられる贅沢な場所にいるせいか、
気になることがある。それはパンの「気合い」とでもいうべき味
の違いだ。

まず、その違いに敏感になるのは、大手のパン屋チェーンが新し
く出店した店でパンを買う際だ。

例えば、成城学園前と仙川に、アンデルセンが出店している。
開店当初のパンには「気合い」が入っていて、さすがの味だった。
おそらく本店からベテランの職人さんが、開店に合わせて来て
アントニオ猪木のように気合いを注入しているに違いない。

ところが、開店から半年もすると、徐々に味が「なまってきて」、
「キレがなくなり」、全体にメリハリの無い味になっていく。
皮のパリッとした感じとか、中の水分量とか、フィリングや
混ぜ込まれた材料の感じとか、がダメダメになっていく。

私はパン屋に勤めたことはないので、何が違うとあぁいう風に
なるのか分からないのだけど、味がゆっくりとではある
が明らかに落ちて、「気合い」が感じられなくなってくる。

そして、恐らく、作っている職人たちは、それほど変化がある
ことに気づいていない。毎日作っているので、小さな変化に気づ
かない。

でも、時々買いにくるお客さんには、違いは、久しぶりにあった
親戚の子供の成長のように、この場合は逆だが、衰えぶりが
ハッとするぐらいわかる。

墨繪が豪徳寺に出店していて、そこも、アンデルセンほどでは
ないが、新宿で買うのとは明らかに違って、気合いが足りない。
あの新宿の墨繪で買える、ゴツゴツとした頑固な美味さには少し
届いていない。

硬いから気合いが入っているとか、いうのではない。材料が贅沢
に使われているから良いというものでもない。

例えば近所にオンカという、とても柔らかいパンを作っているパン屋
がある。押し付けるとペシャンコになってしまいそうな柔らかいパン
だが、きちんと角のたった気合いが感じられる。ラ・ヴィ・エクスキ
ーズのパンは弱ハード系で、焦げ目もしっかりしていて、明らかに
キリッとしている。仙川にはムッシュ・ピエールというとても小さな
パンを売っている、小さなパン屋があるが、あのパンの気合いは何か
ご主人の精神が固まったかのような感じすらする。

大手のチェーン店だから駄目という訳ではない。ディーンアンドデル
ーカは比較的味を維持しているし、個人経営のつまらないパン屋もた
くさんある。ただ、なんか作っている人の、配慮というか、バランス
感覚というか、技術と責任感が、一個一個のパンに現れるのだと思う。
大手だと、その配慮が届きにくいのかもしれない。

上述したように、この気合いが、作っている人には分かりづらく、
客には鮮明に分かる、というあたりが、物を売る仕事の難しさだと
思う。

美味しいパンに出会いたいなぁ。










2012年10月23日火曜日

自分から自由になる

私は会社ではない
私は仕事ではない
私は、私の父ではない、私の母でもない、私の妻でも、娘でもない、私の家族ではない
私は、私の本でもなければ、私の服でもなければ、私の自動車でも、私の家でもない
私は、私のきている服や、持っている鞄や、食べている食事でもない
私の肉体や、私の脳も、私ではない
それらは私の拘束条件、私の使える道具、頼れる仲間ではあるが、私ではない
私とは、いまこの瞬間に生起しつつあるものだ
私の過去は、私ではない
私の未来も、私ではない
なにやら様々な縛りで身動きがとれなくなっているとき
私は、私を拡大解釈している
それら重たい私を脱いで、横に置いて眺めてみる
脱いだまま、空を眺めてみる
風の音を聴いてみる
小さな惑星の表面に張り付く一人の人間を宇宙から眺めてみる
星々の誕生から消滅までの時間の中に、一人の人間の一生を鉛筆で書き込んでみる
私だと思っている色々なものの儚さを感じ
それでも私は何がしたいのかと問うてみる
私から自由になって何がしたいのかと