Jansenリンク機構を物理ライブラリで動かして軌跡を見る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/80cf9ee7-2486-aa81-bec9-0f2601193814.png)

# はじめに
　通称Jansen機構と呼ばれているものを、Processingの物理ライブラリfisicaを使って実装し、軌跡を確認します。sodaplayを思い出します。

# きっかけ
　歩くロボットを見ていて「もっと自然にならないものか」「モーターのトルクもっと少なくて歩けるんじゃないか」とよく思います。人間の歩行はかなり省エネにできていると感じるし、持続的に歩ける構造になっている気がします。
　まだ、みのもんたが朝いた頃の番組中で、ゆるい下り坂を、人間の軽い支えのみで、重力だけで、下っていく二足歩行機構が紹介されていて、衝撃的でした。脚の本数が増えていいなら、支えがいらないはずです。Jansen機構よりも、人間の脚の機構に似ているので、比較すると面白い気がして、とりあえず実装しました。

# プログラム
　wikiを参考に、各ジョイントの長さを適用して計算。固定する２点が、動いてしまうので、何度かステップを繰り返して、収束するように工夫。
　初期座標はイラレで、なんとかした。
　もう少し、簡潔に書いて、クラス化したい。

https://en.wikipedia.org/wiki/Jansen%27s_linkage

```java:processing:JansenLinkage.pde
import fisica.*;

FWorld w;

FCircle c1, c2, c3, c4, c5, c6, c7, c8;

float a = 38.0;
float b = 41.5;
float c = 39.3;
float d = 40.1;
float e = 55.8;
float f = 39.4;
float g = 36.7;
float h = 65.7;
float i = 49.0;
float j = 50.0;
float k = 61.9;
float l =  7.8;
float m = 15.0;

void setup() {
  size(500, 500);

  Fisica.init(this);

  w = new FWorld();
  w.setEdges();
  w.setGravity(0, 0);

  c1 = new FCircle(10);
  c2 = new FCircle(10);
  c3 = new FCircle(10);
  c4 = new FCircle(10);
  c5 = new FCircle(10);
  c6 = new FCircle(10);
  c7 = new FCircle(10);
  c8 = new FCircle(10);
  c1.setPosition(width/2, height/2);
  c2.setPosition(width/2+8.4, height/2-13);
  c3.setPosition(width/2-38.0, height/2-33.8);
  c4.setPosition(width/2-38.0, height/2+7.8);
  c5.setPosition(width/2-78.5, height/2+5.4);
  c6.setPosition(width/2-19.5, height/2+43.1);
  c7.setPosition(width/2-56.4, height/2+40.5);
  c8.setPosition(width/2-18, height/2+93);
  w.add(c1);
  w.add(c2);
  w.add(c3);
  w.add(c4);
  w.add(c5);
  w.add(c6);
  w.add(c7);
  w.add(c8);
  FDistanceJoint j_b = addJoint(c3, c4);
  FDistanceJoint j_c = addJoint(c4, c6);
  FDistanceJoint j_d = addJoint(c4, c5);
  FDistanceJoint j_e = addJoint(c3, c5);
  FDistanceJoint j_f = addJoint(c5, c7);
  FDistanceJoint j_g = addJoint(c6, c7);
  FDistanceJoint j_h = addJoint(c7, c8);
  FDistanceJoint j_i = addJoint(c6, c8);
  FDistanceJoint j_j = addJoint(c2, c3);
  FDistanceJoint j_k = addJoint(c2, c6);
  FDistanceJoint j_m = addJoint(c1, c2);
  j_b.setLength(b);
  j_c.setLength(c);
  j_d.setLength(d);
  j_e.setLength(e);
  j_f.setLength(f);
  j_g.setLength(g);
  j_h.setLength(h);
  j_i.setLength(i);
  j_j.setLength(j);
  j_k.setLength(k);
  j_m.setLength(m);
}

void draw() {
  background(255);

  for (int i=0; i<10; i++) {
    c1.setPosition(width/2, height/2);
    float x = m*cos(frameCount*0.05)+width/2;
    float y = m*sin(frameCount*0.05)+height/2;
    c2.setPosition(x, y);
    c4.setPosition(width/2-38.0, height/2+7.8);

    w.step();
  }
  w.draw();
  println(c8.getX(), c8.getY());
}

FDistanceJoint addJoint(FBody s, FBody t) {
  FDistanceJoint j = new FDistanceJoint(s, t);
  w.add(j);
  return(j);
}
```

　さきっちょの座標を書き出して、エクセルでグラフ化する。回転運動から足先の水平運動へ変換されるのがキモ。なぜか、右回転と左回転で、さきっちょの軌跡が、大きく異なる。Jointの計算が減衰バネ系だから？スタート条件の関係？　

 
オレンジがクランクを反時計回り
青がクランクを時計回り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/1839aa2d-6281-71be-a1b0-4ada9bbab411.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/053b13d9-edb6-5899-4276-e4ea4dbc0003.png)

# 今後の予定
　この軌跡と、人間の歩行の軌跡、走行の軌跡について、比較します。可能であれば、必要なエネルギーも比較したい。

# 補足

　記憶では、Jansenのスケッチの中には、長さを整数比で記述されていました。しかし、Jansenの展覧会の図録を見かえしても載ってなかったので、展覧会の中の展示物だったのかと思います。写真は探していません。ネットで探した中だと、レゴで再現しているものが、整数比に一番近いものでした。

# 関連研究
Computational Design of Linkage-Based Characters
https://crl.ethz.ch/papers/SIG2014_linkages.pdf

https://www.youtube.com/watch?v=XlV-LFozQSc

Computational Design of Mechanical Characters
https://www.ri.cmu.edu/pub_files/2013/0/CDMC_final.pdf

https://www.youtube.com/watch?v=DfznnKUwywQ

# メモ

https://en.wikipedia.org/wiki/Chebyshev_linkage

ロボットでよく使われるらしいChebyshev_lambda_linkage

https://en.wikipedia.org/wiki/Chebyshev_lambda_linkage

https://en.wikipedia.org/wiki/Jansen%27s_linkage

https://roomba.hatenablog.com/entry/2015/02/25/133951

http://www.ricardmarxer.com/fisica/reference/fisica/FDistanceJoint.html