Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

両手先にcubeをassocしてcubeの姿勢変化についてIKをときたい #582

Open
knorth55 opened this issue Aug 8, 2020 · 16 comments

Comments

@knorth55
Copy link
Contributor

knorth55 commented Aug 8, 2020

euslispに詳しくないのですが、
下のようにassocされたcubeを手先座標にみたててIKをとくのは、どのようにみなさんは解いていますか?
:move-targetや:link-listにcubeを追加して解くことはできますか?
cubeは:larmにassocされています。

pr2_dualarm_cube

@knorth55
Copy link
Contributor Author

knorth55 commented Aug 8, 2020

ちなみにこんな感じでできないかな、と書いてみたのですができなかったです。

1.irteusgl$ (send *pr2* :inverse-kinematics (send (send (send *cube* :worldcoords) :copy-worldcoords) :rotate 0.78 :z) :move-target (send *cube* :worldcoords) :link-list (append (send *pr2* :link-list (send (send *pr2* :larm :end-coords) :parent)) *cube*) :rotation-axis t)
Call Stack (max depth: 20):
  0: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  1: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  2: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  3: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  4: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  5: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  6: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  7: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  8: at (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  9: at (send-super* :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)
  10: at (cond (use-base (setq diff-pos-rot (concatenate float-vector (send start-coords :difference-position self) (send start-coords :difference-rotation self))) (send self :move-to start-coords :world) (with-append-root-joint (ll self link-list :joint-class omniwheel-joint :joint-args base-range) (send (caar ll) :joint :joint-angle (float-vector (elt diff-pos-rot 0) (elt diff-pos-rot 1) (rad2deg (elt diff-pos-rot 5)))) (send-super* :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (append (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005)) (list (car (send self :links)) (if (eq use-base t) 0.1 use-base))) additional-weight-list) :link-list ll :move-target move-target args))) (t (send-super* :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)))
  11: at (let (diff-pos-rot) (unless move-arm (setq move-arm (send self :select-target-arm target-coords))) (unless move-target (if (consp move-arm) (setq move-target (mapcar #'(lambda (arm) (send self arm :end-coords)) move-arm)) (setq move-target (send self move-arm :end-coords)))) (unless link-list (setq link-list (if (consp target-coords) (mapcar #'(lambda (target) (let ((l target) move-arm) (while l (cond ((memq l (send self :larm)) (setq move-arm :larm)) ((memq l (send self :rarm)) (setq move-arm :rarm))) (setq l (send l :parent))) (send self :link-list (send target :parent) (unless use-torso (car (send self move-arm)))))) move-target) (send self :link-list (send move-target :parent) (unless use-torso (car (send self move-arm))))))) (cond (use-base (setq diff-pos-rot (concatenate float-vector (send start-coords :difference-position self) (send start-coords :difference-rotation self))) (send self :move-to start-coords :world) (with-append-root-joint (ll self link-list :joint-class omniwheel-joint :joint-args base-range) (send (caar ll) :joint :joint-angle (float-vector (elt diff-pos-rot 0) (elt diff-pos-rot 1) (rad2deg (elt diff-pos-rot 5)))) (send-super* :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (append (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005)) (list (car (send self :links)) (if (eq use-base t) 0.1 use-base))) additional-weight-list) :link-list ll :move-target move-target args))) (t (send-super* :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args))))
  12: at (send *pr2* :inverse-kinematics (send (send (send *cube* :worldcoords) :copy-worldcoords) :rotate 0.78 :z) :move-target (send *cube* :worldcoords) :link-list (append (send *pr2* :link-list (send (send *pr2* :larm :end-coords) :parent)) *cube*) :rotation-axis t)
  13: at #<compiled-code #X598f278>
/opt/ros/kinetic/share/euslisp/jskeus/eus/Linux64/bin/irteusgl 0 error: cannot find method :parent in (apply #'send-message self (class . super) :inverse-kinematics target-coords :rthre rthre :thre thre :stop stop :additional-weight-list (list (list (send self :torso_lift_joint :child-link) (if (numberp use-torso) use-torso 0.005))) :link-list link-list :move-target move-target args)

@knorth55
Copy link
Contributor Author

knorth55 commented Aug 8, 2020

ちなみにですが、cube側に:handleのようにcas-coordsをassocして回転させて、そこに対してIKを解く、という方法で北川はやっています。
しかしこれだと、ものを持った時にあたかも手が伸びたようにIKをとくという直感的な書き方、ではない気が個人的にしています。

@Naoki-Hiraoka
Copy link
Contributor

Naoki-Hiraoka commented Aug 9, 2020

以下のコードで可能です.

(load "package://pr2eus/pr2-interface.l")
(setq *robot* (pr2))
(send *robot* :reset-pose)
(setq *cube* (make-cube 300 300 300))
(send *cube* :newcoords (send (send *robot* :larm :end-coords :copy-worldcoords) :translate #F(0 0 150)))
(send *robot* :larm :end-coords :assoc *cube*)
(send *cube* :put :end-coords
      (make-cascoords
       :coords (send (send *cube* :copy-worldcoords) :translate #F(0 0 150))
       :parent *cube*))
(objects (list *robot* *cube*))

(send *robot* :inverse-kinematics
      (send (send (send *cube* :get :end-coords) :copy-worldcoords) :rotate 0.78 :z)
      :move-target (send *cube* :get :end-coords)
      :link-list (send *robot* :link-list (send (send *robot* :larm :end-coords) :parent))
      :rotation-axis t
      :debug-view t
      )

:link-listはリンクのリストではなく,動かせる関節(の子リンク)のリストなので,cubeを含める必要はありません.また,:move-targetcascaded-coordsクラスである必要があります( (send *cube* :worldcoords)でなく*cube*でよい).

@knorth55
Copy link
Contributor Author

knorth55 commented Aug 9, 2020

@Naoki-Hiraoka

ありがとう

ちなみにですが、cube側に:handleのようにcas-coordsをassocして回転させて、そこに対してIKを解く、という方法で北川はやっています。

伝わりにくくてごめんなさい
平岡君が書いてくれているやり方は、北川が書いているやり方とほぼ同じだと思いました。
このやり方でできることはわかっているんだけど、直感的な書き方ではないな、と個人的に思ってIssueで聞いてみました。

例えば
(send *robot* :larm :end-coords :assoc *cube*)してしまえば

(send *cube* :put :end-coords
      (make-cascoords
       :coords (send (send *cube* :copy-worldcoords) :translate #F(0 0 150))
       :parent *cube*))

とか消せないかと思っています。
つまり上のコードだとこんな感じでかけないかな、と思っていたのですが、どうでしょうか?

(load "package://pr2eus/pr2-interface.l")
(setq *robot* (pr2))
(send *robot* :reset-pose)
(setq *cube* (make-cube 300 300 300))
(send *cube* :translate #f(500 0 800))
(send *robot* :larm :inverse-kinematics
      (make-coords :pos #f(500 0 950)) :rotation-axis :z)
(send *robot* :rarm :inverse-kinematics
      (make-coords :pos #f(500 0 650)) :rotation-axis :z)
(send *robot* :larm :end-coords :assoc *cube*)
(setq *target-coords* (make-coords :pos #f(500 0 900)))
(objects (list *robot* *cube*))

(send *robot* :inverse-kinematics *target-coords*
      :move-target (send *cube* :worldcoords)
      :link-list (append (send *robot* :link-list (send (send *robot* :larm :end-coords) :parent))
                         (list *cube*))
      :rotation-axis t
      :debug-view t)

@Naoki-Hiraoka
Copy link
Contributor

添付していただいたコードの最後の逆運動学を解く部分を,

(send *robot* :inverse-kinematics *target-coords*
      :move-target *cube*
      :link-list (send *robot* :link-list (send (send *robot* :larm :end-coords) :parent))
      :rotation-axis t
      :debug-view t)

とすれば解けると思います.

この書き方は*cube*の中心の座標系の目標姿勢を指定していますが,
*cube*の底面の座標系の目標姿勢(机の上など)を指定したい場合には先のコメントで自分が添付したような書き方になると思います.

@knorth55
Copy link
Contributor Author

knorth55 commented Aug 9, 2020

pr2_dualarm_ik

お、できました、ありがとう
ただ双腕だとhandleとかつけたほうが楽そうですね、両手に:assocしてこういうふうにik解きたいですね

(load "package://pr2eus/pr2-interface.l")
(setq *robot* (pr2))
(send *robot* :reset-pose)
(setq *cube* (make-cube 300 300 300))
(send *cube* :translate #f(500 0 800))
(send *robot* :larm :inverse-kinematics
      (make-coords :pos #f(500 0 950)) :rotation-axis :z)
(send *robot* :rarm :inverse-kinematics
      (make-coords :pos #f(500 0 650)) :rotation-axis :z)
(send *robot* :larm :end-coords :assoc *cube*)
(setq *target-coords* (make-coords :pos #f(500 0 900) :rpy #f(45 0 0)))
(objects (list *robot* *cube*))

(send *robot* :inverse-kinematics *target-coords*
      :move-target *cube*
      :link-list (send *robot* :link-list (send (send *robot* :larm :end-coords) :parent))
      :rotation-axis t
      :debug-view t)

@Naoki-Hiraoka
Copy link
Contributor

両手に:assocしてこういうふうにik解きたいですね

:assocで閉リンクを作ることはできませんが,
euslisp上で「rarmがcubeの底面の点と一致」「larmがcubeの上面の点と一致(cubeをlarmにassocすれば不要)」という条件のもとで「cubeをtargetに一致させる」という逆運動学を解くことは可能です.

  1. 「AとBを一致させる」のAとBが両方動く
  2. 「一致させる」タスクに優先度がついている

という2つの要素に対応する必要があり,

  • irteusは,:additional-jacobiを用いることで2に対応可能ですが,1には対応していない
  • optmotiongenは,1,2両方に対応可能.ただし2は重み付き逆運動学を用いるので厳密ではない
  • nlopt-ikは,1,2両方に対応可能.ただしコードが古いかもしれません.
  • prioritized-inverse-kinematicsの場合は,1,2両方に対応可能

となっています.

@knorth55
Copy link
Contributor Author

knorth55 commented Aug 9, 2020

@Naoki-Hiraoka

:assocで閉リンクを作ることはできませんが,
euslisp上で「rarmがcubeの底面の点と一致」「larmがcubeの上面の点と一致(cubeをlarmにassocすれば不要)」という条件のもとで「cubeをtargetに一致させる」という逆運動学を解くことは可能です.
「AとBを一致させる」のAとBが両方動く
「一致させる」タスクに優先度がついている
という2つの要素に対応する必要があり,
irteusは,:additional-jacobiを用いることで2に対応可能ですが,1には対応していない
optmotiongenは,1,2両方に対応可能.ただし2は重み付き逆運動学を用いるので厳密ではない
nlopt-ikは,1,2両方に対応可能.ただしコードが古いかもしれません.
prioritized-inverse-kinematicsの場合は,1,2両方に対応可能
となっています.

IKを制約付きの問題として考えて、制約式を書く方式はやっぱり玄人向けじゃないかな、とおもう。
できるかできないかではなく、プログラミングという観点からみると、
制約式を書き下すというのは難しいのではないか、
今やろうとしているのは幾何制約の等式制約なので、もっと簡単に出来ないかなと思ってしまう。
そして幾何制約の等式制約であれば、IRTViewer内で表現できるはずなので、
双腕:assoc:assocでなくても:contactでもいい)みたいなものでIRTViewerで表現してしまえば、
その状況下での:inverse-kinematicsはその幾何制約を勝手に考えてくれる、というのがいいな、とおもいました

具体的には擬似コードですが

(load "package://pr2eus/pr2-interface.l")
(setq *robot* (pr2))
(send *robot* :reset-pose)
(setq *cube* (make-cube 300 300 300))
(send *cube* :translate #f(500 0 800))
(objects (list *robot* *cube*))
(send *robot* :larm :inverse-kinematics
      (make-coords :pos #f(500 0 950)) :rotation-axis :z)
(send *robot* :rarm :inverse-kinematics
      (make-coords :pos #f(500 0 650)) :rotation-axis :z)

;; ここで制約式をかいていることになる + IRTViewer内でも拘束される
(send *robot* :larm :end-coords :contact *cube*)
(send *robot* :rarm :end-coords :contact *cube*)

;; あとは何も考えずにIKをとく
(send *robot* :inverse-kinematics *target-coords*
      :move-target *cube*
      :rotation-axis t
      :debug-view t)

@knorth55 knorth55 changed the title 手先に新たに:assocしたcubeなどを:move-target, :link-listに追加して:inverse-kinematicsはとけますか? 手先にcubeをassocして双腕でIKをときたい Aug 9, 2020
@knorth55
Copy link
Contributor Author

knorth55 commented Aug 9, 2020

@Naoki-Hiraoka

  • irteusは,:additional-jacobiを用いることで2に対応可能ですが,1には対応していない
  • optmotiongenは,1,2両方に対応可能.ただし2は重み付き逆運動学を用いるので厳密ではない
  • nlopt-ikは,1,2両方に対応可能.ただしコードが古いかもしれません.
  • prioritized-inverse-kinematicsの場合は,1,2両方に対応可能

あと少し気になったのですが、optmotiongenになくてprioritized-inverse-kinematicsにある厳密さ、
というのは何で効いてくるんでしょう?
例えばバランスに関してはそちらが必要という話かな?
そうなるとスーツケース持ち上げ動作みたいなのはprioritized-inverse-kinematicsでよりよくなったりするのかな?

@knorth55 knorth55 changed the title 手先にcubeをassocして双腕でIKをときたい 両手先にcubeをassocして双腕でIKをときたい Aug 9, 2020
@knorth55 knorth55 changed the title 両手先にcubeをassocして双腕でIKをときたい 両手先にcubeをassocしてcubeの姿勢変化について双腕IKをときたい Aug 9, 2020
@knorth55 knorth55 changed the title 両手先にcubeをassocしてcubeの姿勢変化について双腕IKをときたい 両手先にcubeをassocしてcubeの姿勢変化についてIKをときたい Aug 9, 2020
@Naoki-Hiraoka
Copy link
Contributor

Naoki-Hiraoka commented Aug 10, 2020

;; ここで制約式をかいていることになる + IRTViewer内でも拘束される
(send *robot* :larm :end-coords :contact *cube*)
(send *robot* :rarm :end-coords :contact *cube*)

確かにこのように扱えると便利ですね.
実装自体は可能だと思うのですが,この制約があるときに,
(send *robot* :larm :shoulder-p :joint-angle 90)(send *cube* :translate #F(100 0 0))
が呼ばれた時の挙動などをよく考えたいです.(幾何拘束を無視して肩の関節角度が90度になる のか, 幾何拘束を満たす範囲内で肩の関節角度を可能な限り90度に近づけるように他の関節まで自動で修正する のか)

あと少し気になったのですが、optmotiongenになくてprioritized-inverse-kinematicsにある厳密さ、
というのは何で効いてくるんでしょう?

:inverse-kinematicsが解ける場合は差はないのですが,解けなくても:revert-if-fail nilで可能な限り目標に近い関節角度を得たいという場合に効いてきます.optmotiongenで用いられている重み付き逆運動学の場合は,「rarm*cube*の相対位置のエラー」と「*cube**target-coords*の相対位置のエラー」の大きさの比が例えば1:10になるような関節角度が返ってきます.例えば,rarmをこれ以上上に上げられないときに*cube*を11cm上に移動させようとすると,*cube*が1cmだけ上に移動して(残りのエラー10cm),rarm*cube*の相対位置が1cmずれる(エラー1cm)というようなことが起こり,実際にはロボットが*cube*を落としてしまいます.エラーの大きさの比を例えば1:1e6のように大きくなるような重みを設定してしまえば解決しそうですが,SR-Inverseの正則化項的な項の重みのチューンが極めて難しくなったり,桁落ちが発生したりして,計算が不安定になります.そのため,エラーの比が0:1になる優先度付き逆運動学が実装されているprioritized-inverse-kinematicsや,非線形最適化の計算の安定化のための様々な技術が利用可能なnlopt-ikが必要になってくると考えています.

@k-okada
Copy link
Member

k-okada commented Aug 10, 2020

https://github.com/euslisp/jskeus/blob/4ffcc5344fb006890f86ae024a5ec7a1bb20eb79/irteus/demo/dual-manip-ik.l
みたいなvirtual joint を使う,という方法はでてこないのかな?
それとも,

irteusは,:additional-jacobiを用いることで2に対応可能ですが,1には対応していない

がvirtual jointに対応している?また,これ 1 に対応していないのかな.両手先とも同時に動いていたんじゃないかと思うんだけど.

https://github.com/Naoki-Hiraoka/jsk_control/tree/prioritized-ik/eus_qp/prioritized-inverse-kinematics

は良いのでPR送りましょう.タイトルに[WIP]と書けばマージしないでね,という意味になります.
このなかの,inverse-kinematics-task と priotarized-inverse-kinematics は違うもの?
で,0:1というのは何のことかな.

⊿θ = J# ⊿d → で,11cm は ⊿d の話だよね?で実際には思ったとおり動かないから,J⊿θを計算すると左手は10cm動いて右手は1cmでした,というのを1:10と読んでいるのかな?で,これが0:1になる?あるいは,右手と左手が10cm動かないとそもそも動かないような条件?

@Naoki-Hiraoka
Copy link
Contributor

https://github.com/euslisp/jskeus/blob/4ffcc5344fb006890f86ae024a5ec7a1bb20eb79/irteus/demo/dual-manip-ik.l
みたいなvirtual joint を使う,という方法はでてこないのかな?

このコードの存在は把握していませんでした.ありがとうございます.
irteusは,:additional-jacobiを用いることで2に対応可能ですが,1には対応していない
irteusは,:additional-jacobiを用いることで2に対応可能で,:jacobiを用いることで1に対応可能
でした.
jskeusの方法は擬似逆行列を用いるので,計算コストは先に挙げた手法の中で最小なのですが,関節角度上下限や干渉回避といった不等式制約の扱いが苦手なので制約付近の動作が作りにくく,自分はあまり使いません...

PR送りましょう.タイトルに[WIP]と書けばマージしないでね,という意味になります.
このなかの,inverse-kinematics-task と priotarized-inverse-kinematics は違うもの?

送りました.jsk-ros-pkg/jsk_control#751
priotarized-inverse-kinematicsが優先度付き逆運動学を解く関数です.
優先度付き逆運動学を解くために必要な情報は,

  • タスクは何か(一致させたい目標や,関節角度上下限)
  • 探索変数は何か(動かして良いjoint.:link-listに相当)

なので,それらをそれぞれinverse-kinematics-task inverse-kinematics-variableクラスで表現してpriotarized-inverse-kinematics関数に渡すことで,
ロボットが複数あっても,物体が複数あっても,タスクや優先度が幾つになっても,同じ枠組みで扱えるようにしています.

で,0:1というのは何のことかな.
⊿θ = J# ⊿d → で,11cm は ⊿d の話だよね?で実際には思ったとおり動かないから,J⊿θを計算すると左手は10cm動いて右手は1cmでした,というのを1:10と読んでいるのかな?で,これが0:1になる?あるいは,右手と左手が10cm動かないとそもそも動かないような条件?

0:1ではなく0:11の方が分かりやすかったです.

*cube*を左手にassocしているとして,両手で持ったを*cube*を11cm上に動かしたいとき,
左手と右手の相対位置の⊿dは0cm,左手の上に上げる量の⊿dは11cmです.
関節角度上下限などで右手をこれ以上上に上げることが出来ない場合に,
重み付き逆運動学だと,J⊿θを計算すると左手は1cm動いて右手は0cmでした.という解が返ってきます.
右手と左手は一緒に動いて欲しいのに,一方は0cmでもう一方は1cm動いた(エラー1cm)
左手は11cm動いて欲しいのに1cmしか動かなかった(エラー10cm)
として,エラーが1:10と呼びました.

優先度付き逆運動学だと,左手と右手の相対位置を守った上で可能な限り左手を上に上げるので,
J⊿θを計算すると左手も右手も0cmでした.という解が返って来て,この場合,
右手は左手と一緒に動いた(エラー0cm)
左手は0cmしか動かなかった.(エラー11cm)
として,エラーが0:11となります

@knorth55
Copy link
Contributor Author

@k-okada

virtual-jointは存在は知っていましたが、使ったことがありませんでした。
:jacobiをつかうことで両腕がいっぺんに動くというのもしらなかったです。

@Naoki-Hiraoka

:inverse-kinematicsが解ける場合は差はないのですが,解けなくても:revert-if-fail nilで可能な限り目標に近い関節角度を得たいという場合に効いてきます.optmotiongenで用いられている重み付き逆運動学の場合は,「rarmとcubeの相対位置のエラー」と「cubetarget-coordsの相対位置のエラー」の大きさの比が例えば1:10になるような関節角度が返ってきます.例えば,rarmをこれ以上上に上げられないときにcubeを11cm上に移動させようとすると,cubeが1cmだけ上に移動して(残りのエラー10cm),rarmとcubeの相対位置が1cmずれる(エラー1cm)というようなことが起こり,実際にはロボットがcubeを落としてしまいます.エラーの大きさの比を例えば1:1e6のように大きくなるような重みを設定してしまえば解決しそうですが,SR-Inverseの正則化項的な項の重みのチューンが極めて難しくなったり,桁落ちが発生したりして,計算が不安定になります.そのため,エラーの比が0:1になる優先度付き逆運動学が実装されているprioritized-inverse-kinematicsや,非線形最適化の計算の安定化のための様々な技術が利用可能なnlopt-ikが必要になってくると考えています.

cubeを左手にassocしているとして,両手で持ったをcubeを11cm上に動かしたいとき,
左手と右手の相対位置の⊿dは0cm,左手の上に上げる量の⊿dは11cmです.
関節角度上下限などで右手をこれ以上上に上げることが出来ない場合に,
重み付き逆運動学だと,J⊿θを計算すると左手は1cm動いて右手は0cmでした.という解が返ってきます.
右手と左手は一緒に動いて欲しいのに,一方は0cmでもう一方は1cm動いた(エラー1cm)
左手は11cm動いて欲しいのに1cmしか動かなかった(エラー10cm)
として,エラーが1:10と呼びました.

よくわかってないですが、目標座標に到達できないのであれば動かなくていいわけではないのですね
どういうユースケースがあるんでしょうか、バランス制約とかがある足のIKとかはそっちのほうがいいのかな

@Naoki-Hiraoka
Copy link
Contributor

よくわかってないですが、目標座標に到達できないのであれば動かなくていいわけではないのですね
どういうユースケースがあるんでしょうか、バランス制約とかがある足のIKとかはそっちのほうがいいのかな

ベストエフォートで行いたいときです.例えば,

  • 重心をできるだけ支持領域の中央にして安定余裕を最大化したい場合
  • 関節角度をできるだけ上下限の中央付近にしたり干渉しそうな物体との距離をできるだけ離したりすることで以後の動作を行いやすくするというような場合
  • カメラの中央をできるだけ対象物に向けたい場合
  • 物を掴むときに:rotation-axis zではあるが大きくずれてはほしくない場合

などがあると思います.
2つ目については実際に,:inverse-kinematics関数の中で自動的に行われています.

@Naoki-Hiraoka
Copy link
Contributor

あ,でも落ち着いて考えてみると,
「両手先にcubeをassocしてcubeの姿勢変化についてIKを解きたい」
という問題の場合,
逆運動学が解きやすい位置であれば普通に解けますし,
やや解きにくい位置でも:rotation-axis :translation-axisを指定すれば大体解けると考えると,
わざわざ優先度をつける必要は無く,
優先度の話と両手先にassocする話は別の話かもしれません.

手先ではなく膝をつくような自由度の少ない閉リンクになると,「目標座標に到達できないのであれば動かない」というアプローチだと:rotation-axis :translation-axisをチューンしても殆ど到達できないので動くことができず,優先度が必要になるのですが,自分はそのイメージに引っ張られすぎていたかもしれません.

@k-okada
Copy link
Member

k-okada commented Aug 13, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants