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

パラメータの変更箇所の決定 #1

Open
aiba0921 opened this issue Nov 22, 2024 · 24 comments
Open

パラメータの変更箇所の決定 #1

aiba0921 opened this issue Nov 22, 2024 · 24 comments

Comments

@aiba0921
Copy link
Collaborator

定格を調査するにあたりG1のどの関節のトルクと角速度のパラメータを変更し調査するのかを決める。
Isaac Lab内のunitree.pyでは一律effort_limit=300,velocity_limit=100.0,になっているがunitreeが公開しているgithubのG1のurdfでは異なる値になっている。下半身の関節の値を変更するとしてunitree.pyにおける下半身をlegとfeetの項目とするとleg内の "._hip_yaw_joint","._hip_roll_joint","._hip_pitch_joint", "torso_joint",はeffort="88" velocity="32"となっており、"._knee_joint"は effort="139" velocity="20"となっている。feetの"._ankle_pitch_joint", "._ankle_roll_joint"は effort="40" velocity="53"となっていた。どこにどのモータが使用されているのかの構成はまだ見つけられていないが、これを見る限りではleg内の腰と足の付け根のモータは同じで膝のみが異なったモータになっている。またfeetの足首のモータもどちらとも違う値になっているため異なるモータとなっている。

@yasuohayashibara
Copy link
Member

以下で良いでしょうか?
手法の提案という観点からは最もトルクの大きな膝関節だけで良い気がします.

  • effort=88 velocity=32
    hip_yaw_joint
    hip_roll_joint
    hip_pitch_joint
    torso_joint

  • effort=139 velocity=20
    knee_joint

  • effort=40 velocity=53
    ankle_pitch_joint
    ankle_roll_joint

@aiba0921
Copy link
Collaborator Author

effort_limit=300,velocity_limit=100.0,がunitree.pyのにおける変更の該当箇所になるのですが膝関節だけを変更しようとしてもlegsの項目の中に「hip_yaw_joint、hip_roll_joint、hip_pitch_joint」、「torso_joint」、「knee_joint」があるのでこのままでは腰や足の付け根の値も同時に変わってしまうことになるため、膝関節だけというのは難しいかもしれません。

        "legs": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_hip_yaw_joint",
                ".*_hip_roll_joint",
                ".*_hip_pitch_joint",
                ".*_knee_joint",
                "torso_joint",
            ],
            effort_limit=300,
            velocity_limit=100.0,
            stiffness={
                ".*_hip_yaw_joint": 150.0,
                ".*_hip_roll_joint": 150.0,
                ".*_hip_pitch_joint": 200.0,
                ".*_knee_joint": 200.0,
                "torso_joint": 200.0,
            },
            damping={
                ".*_hip_yaw_joint": 5.0,
                ".*_hip_roll_joint": 5.0,
                ".*_hip_pitch_joint": 5.0,
                ".*_knee_joint": 5.0,
                "torso_joint": 5.0,
            },
            armature={
                ".*_hip_.*": 0.01,
                ".*_knee_joint": 0.01,
                "torso_joint": 0.01,
            },
        ),

@yasuohayashibara
Copy link
Member

技術的な問題で妥協しましたというのは,あまり筋の良くない議論になってしまいます.
周囲の方にも協力してもらってなんとかできないかを議論したほうが良いと思います.
もしくは,逆に制約の中で議論する内容を考えても良いかもしれませんが,そちらの方が難しい気がします.

@aiba0921
Copy link
Collaborator Author

unitree.pyのG1_CFGを以下のように変更しました。変更点としては膝関節をlegsの項目から分け、上半身の方もURDF上のトルクと角速度が腕と手で異なるパラメータとなっていたのでそちらも分けました。またG1のパラメータの値を全てURDF準拠の値とし、このパラメータで一旦整地の歩行を学習したところ問題なく歩きました。変更する膝のパラメータですがトルクは小川先輩に提案いただいた「140, 120, 100, 80, 60, 40, 20, 10」で角速度の方は「2,4,6,8,10,12,14,16,18,20」のような分け方でよろしいでしょうか

@yasuohayashibara
Copy link
Member

トルク 140, 120, 100, 80, 60, 40, 20, 10
角速度 2,4,6,8,10,12,14,16,18,20

8 x 10 x 10 = 800回になりますが,大丈夫ですか?
あと,どこかで歩けなくなると思いますので,それ以下は行わなくても良いと思います.

@aiba0921
Copy link
Collaborator Author

8 x 10 x 10 = 800回になりますが,大丈夫ですか?

端から10回ずつやると間に合わないので一旦はそれぞれの組み合わせで5回ずつ行いまんべんなく組み合わせを試そうと思います。

あと,どこかで歩けなくなると思いますので,それ以下は行わなくても良いと思います.

一先ず現状で最も小さい値の組み合わせであるeffort_limit=10,velocity_limit=2.0,で整地、不整地それぞれ2,3回ずつ学習させたところ整地では脚を真っ直ぐに伸ばした状態で脚を引きずるように歩きました。
https://drive.google.com/file/d/1HwfftxmvHpqq49ag7ppObROJqvXM40g4/view?usp=sharing
不整地では立ってはいますが歩くことはほとんどできておらず。わずかに移動できても段差などで転倒していました
https://drive.google.com/file/d/1wFKHjOUDeKe6M6fRU-NSpozXVkhijbTE/view?usp=drive_link

@aiba0921
Copy link
Collaborator Author

山崎先輩に教えていただいた静力学を解いたところ以下の画像のようになった角度は参考にできそうな資料が見つかっていないため想像になってしまっているが、この結果からは中腰で歩くには膝のトルクは10程度は必要だと思います。
Screenshot from 2024-11-24 19-36-23

先日行った学習の結果ではeffort_limit=10,velocity_limit=2.0の組み合わせで足を伸ばしてかろうじて歩ける程度のものとなっており、また試しにeffort_limit=5,velocity_limit=2.0の組み合わせで行ってみたところ以下の動画のようになり、立つことはできていますが全く歩けなくなっていたため、計算の結果とも合致しているのではないかと考えています。
https://drive.google.com/file/d/1D3v58N71d49BSwNv-Zv2UHS3XixZOpBT/view?usp=sharing

@aiba0921
Copy link
Collaborator Author

effort_limit=10,velocity_limit=4.0、effort_limit=10,velocity_limit=5.0で何度か学習を行ったが以下の動画のようになりeffort_limit=10,velocity_limit=2.0の時とほとんど違いがなかった
https://drive.google.com/file/d/1xLi9_AlblR3CdG-m7qWP9FQQGLKtC3GN/view?usp=sharing
また報酬の推移も以下のようになり、ほとんど違いがなかったため、パラメータの間隔を「4,8,12,16,20」もしくは「5,10,15,20」でもいいかもしれません。現在実装中の転倒回数の計測機能と併せ明日中には決めます。
Screenshot from 2024-11-25 01-24-49
水:effort_limit=139,velocity_limit=20.0、青:effort_limit=10,velocity_limit=5.0黃:effort_limit=10,velocity_limit=2.0、緑:effort_limit=10,velocity_limit=4.0

@yasuohayashibara
Copy link
Member

8 x 10 x 10 = 800回になりますが,大丈夫ですか?

そういえばこちら段差に関して考慮していませんでした.
5つぐらいの段差を設定するとして,

8 x 10 x 10 x 5 = 4000回

でした.現実的な数字ではないと思いますので,できるだけ省けるところは省いたほうが良いと思います.

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Nov 25, 2024

8 x 10 x 10 x 5 = 4000回
でした.現実的な数字ではないと思いますので,できるだけ省けるところは省いたほうが良いと思います.

パラメータの組み合わせは
トルク 140, 120, 100, 80, 60, 40, 20, 10
角速度 5,10,15,20
8x4x10x5=1600回
1600/(3人x1日20時間)=27日
全パターン5回ずつ優先
27/2=13.5日
で行っていきます。
段差の変更についてrough.pyに記述されていたのですが段差の幅や坂の傾斜などを個別にかなり細かく変更できるようになっていたのですが先生の意図としてはどの箇所を変更する意図でしょうか

@yasuohayashibara
Copy link
Member

段差の変更についてrough.pyに記述されていたのですが段差の幅や坂の傾斜などを個別にかなり細かく変更できるようになっていたのですが先生の意図としてはどの箇所を変更する意図でしょうか

そちらの検討はできていません.
パラメータ複数あることも知りませんので,できれば該当箇所を示しながらどのパラメータがどのような影響を及ぼすのかをissueにまとめてもらえると助かります.
その上で,みなさんの方で変更すべきパラメータを選定できない場合は,次回のヒューマノイドのミーティングにでも直接議論した方が良い気がします.

ちなみに,当初から段差の話はあったと記憶していますので,新しい話題では無いという認識です.
もし疑問を持った場合は,この議論は研究ノートで行ったほうが良いかもしれません.
段差を含めないと,おそらくこの議論は研究として評価されるものにはなりません.

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Nov 26, 2024

調査した限りでは各パラメータを変更したところ以下のような変化が確認できました。これを見ると自分としては変更する箇所は段差の高さの範囲や傾斜の角度なのかなと感じました。
デフォルト
Screenshot from 2024-11-26 13-52-27

        "pyramid_stairs": terrain_gen.MeshPyramidStairsTerrainCfg(
            proportion=0.2,
            step_height_range=(0.05, 0.23→2.0),
            step_width=0.3,
            platform_width=3.0,
            border_width=1.0,
            holes=False,
        ),

proportion: この地形の割合(全体の20%)。
step_height_range: 階段の段差の高さの範囲(0.05~0.23m)。
画像では一段の高さの最大値を2mにしている。そのため奥から一段の高さが0.05mかから0.195mずつ増えている
step_width: 各段差の奥行き(0.3m)。
platform_width: 平らな部分の幅。
border_width: 階段の周囲の余白。
Screenshot from 2024-11-26 13-56-56

        "pyramid_stairs_inv": terrain_gen.MeshInvertedPyramidStairsTerrainCfg(
            proportion=0.2,
            step_height_range=(0.05, 0.23),
            step_width=0.3→0.05,
            platform_width=3.0,
            border_width=1.0,
            holes=False,
        ),

パラメータはpyramid_stairsと同じで画像は各段の奥行きを0.05mにしているため一段がとても薄く四角錐のようになっている
Screenshot from 2024-11-26 13-57-55

        "boxes": terrain_gen.MeshRandomGridTerrainCfg(
            proportion=0.2, grid_width=0.45, grid_height_range=(0.05, 0.2→2.0), platform_width=2.0
        ),

grid_width: 各グリッドの幅。
grid_height_range: グリッドの高さの範囲。
画像ではグリッドと呼ばれる四角柱の高さの幅の最大を2mにしたことでデフォルトよりも凹凸が激しくなっている
platform_width: 平坦部分の幅。
Screenshot from 2024-11-26 13-58-46

        "random_rough": terrain_gen.HfRandomUniformTerrainCfg(
            proportion=0.2, noise_range=(0.02, 0.10→2.0), noise_step=0.02→0.1, border_width=0.25
        ),

noise_range: ノイズ(高さ)の範囲。
ノイズと呼ばれている突起の高さの最大値を2mにしたことでこちらもデフォルトよりも凹凸が激しくなっている
noise_step: ノイズのステップサイズ。
ノイズのステップサイズというのは突起の細かさを表しており値を小さくすると突起が細かく複雑な地形になり、値を大きくすると突起があまり細分化されずに地形がなだらかになる。左下の画像は最大値2mでステップサイズを変えておらず右下は0.1に変化させた様子になっており、細分化されないためか本来複数の突起になるところが合わさり頂点部分が平面のようになっている
Screenshot from 2024-11-26 14-01-11

        "hf_pyramid_slope": terrain_gen.HfPyramidSlopedTerrainCfg(
            proportion=0.1, slope_range=(0.0, 0.4→0.7), platform_width=2.0, border_width=0.25
        ),

slope_range: 傾斜の範囲(0~40%)。
画像では傾斜を70%にしたことで傾斜が急になっている
platform_width: 平坦部分の幅。
Screenshot from 2024-11-26 14-03-15

        "hf_pyramid_slope_inv": terrain_gen.HfInvertedPyramidSlopedTerrainCfg(
            proportion=0.1, slope_range=(0.0, 0.4), platform_width=2.0→0.5, border_width=0.25
        ),

パラメータはhf_pyramid_slopeと同じでこちらは傾斜の中央にある平坦な部分の幅を0.5mにしたことで四角錐のようになっている
Screenshot from 2024-11-26 14-06-18

@yasuohayashibara
Copy link
Member

@aiba0921
ありがとう.詳しく解説してくれてありがとう.
さまざまな不整地を生成することができるのですね.
ちなみに,G1などのヒューマノイドのサンプルで不整地の歩行生成に用いているのはどちらになりますか?

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Nov 27, 2024

@yasuohayashibara
不整地のパラメータは今回の調査まで変更したことはなかったので、すべて以下のデフォルトの値を使用しており、先のコメントの一番上の画像の不整地を使用しています

        "pyramid_stairs": terrain_gen.MeshPyramidStairsTerrainCfg(
            proportion=0.2,
            step_height_range=(0.05, 0.23),
            step_width=0.3,
            platform_width=3.0,
            border_width=1.0,
            holes=False,
        ),
        "pyramid_stairs_inv": terrain_gen.MeshInvertedPyramidStairsTerrainCfg(
            proportion=0.2,
            step_height_range=(0.05, 0.23),
            step_width=0.3,
            platform_width=3.0,
            border_width=1.0,
            holes=False,
        ),
        "boxes": terrain_gen.MeshRandomGridTerrainCfg(
            proportion=0.2, grid_width=0.45, grid_height_range=(0.05, 0.2), platform_width=2.0
        ),
        "random_rough": terrain_gen.HfRandomUniformTerrainCfg(
            proportion=0.2, noise_range=(0.02, 0.10), noise_step=0.02, border_width=0.25
        ),
        "hf_pyramid_slope": terrain_gen.HfPyramidSlopedTerrainCfg(
            proportion=0.1, slope_range=(0.0, 0.4), platform_width=2.0, border_width=0.25
        ),
        "hf_pyramid_slope_inv": terrain_gen.HfInvertedPyramidSlopedTerrainCfg(
            proportion=0.1, slope_range=(0.0, 0.4), platform_width=2.0, border_width=0.25
        ),

どのように変更していくかについて階段は建築基準法で一段の高さが0.23m以内、奥行き0.15m以上と決まっているそうなので一段の高さを変えるというよりは奥行きを薄くしていくような変更の仕方になると思います。傾斜についてこちらの記事で自動車が登れるのが45度=傾斜100%なのでこちらも変更する傾斜の最大値は100%が限界かなと思います

@yasuohayashibara
Copy link
Member

議論をシンプルにするためには,不整地は1つの地形に絞ったほうが良いです.
ChatGPTに聞いてみましたが,このとおりだと思いますので,random_roughが良いと思います.


不整地の代表として適切な地形を選ぶには、以下の基準を考慮する必要があります:

  1. 多様性を持つ地形か
    不整地は一般的にランダム性や不規則性が特徴です。そのため、地形が多様であることが望ましいです。
  2. ロボットの挑戦度が高いか
    ロボットの歩行性能や安定性を試すために、一定の難易度を持つ地形が適しています。
  3. テストの再現性
    地形がパラメータ化されており、再現性が高いことが検証には重要です。
    各地形の特徴と評価
    pyramid_stairs

階段状の段差で構成された地形。
利点: ロボットの脚部可動域や段差超え能力を評価しやすい。
欠点: 地形が比較的規則的で、ランダム性が少ない。
pyramid_stairs_inv

逆ピラミッド状の階段地形。
利点: 中央部分が狭くなるため、狭い足場でのバランス能力を評価可能。
欠点: 一部のロボットには特異なシナリオになり、汎用性に欠ける。
boxes

ランダムな高さの箱状地形。
利点: 段差の高さがランダムで不整地の特性に近い。
欠点: 箱状地形が単調になる場合がある。
random_rough

ランダムノイズで生成される不整地。
利点: 不整地としての多様性が高く、自然地形に近い。
欠点: ランダム性が強いため、再現性が低い場合がある。
hf_pyramid_slope

傾斜がついたピラミッド状地形。
利点: 傾斜を含む歩行性能を評価できる。
欠点: 段差要素が含まれないため、評価項目が限定的。
hf_pyramid_slope_inv

逆傾斜のピラミッド地形。
利点: 狭い足場でのバランス能力や段差適応能力を評価できる。
欠点: 特殊な形状であるため汎用性に欠ける。
おすすめの地形: random_rough
理由:
ランダム性が高く、自然地形に近い。
不整地の特性を代表する要素を多く含む。
ロボットの歩行能力全般をバランスよく評価できる。
補足: 再現性を考慮する場合は、noise_rangeやnoise_stepを適切に設定しておくと良いでしょう。
もし段差を重視したい場合は、boxes や pyramid_stairs が次点として適しています。

@yasuohayashibara
Copy link
Member

こちらもChatGPT任せですが,noise_rangeの変更で良いと思います.
比較が難しくなるので,他のパラメータは変更しなくて良いと思います.
まずは極端な値で試して,挙動を確認してもらうと良いかなと思います.


random_rough 地形で不整地の段差をどの程度乗り越えられるかを議論するためには、以下のパラメータを変更して実験を行うのが適切です。

  1. noise_range
    説明: 地形のノイズ(高さ)の範囲を定義します。範囲を広げることで、段差の高さが増大し、不整地の困難度を調整できます。
    現在の設定: (0.02, 0.10)
    変更案:
    小さな範囲: (0.02, 0.05) → 段差が小さい地形での安定性をテスト。
    大きな範囲: (0.02, 0.20) → 大きな段差を含む地形での歩行能力をテスト。

  2. noise_step
    説明: ノイズの変化ステップを定義します。値を小さくすると地形が滑らかになり、大きくすると段差が鋭くなります。
    現在の設定: 0.02
    変更案:
    小さいステップ: 0.01 → より滑らかな不整地。
    大きいステップ: 0.05 → 階段状の段差が強調された地形。

  3. border_width
    説明: 地形の境界幅を設定します。値を小さくすると不整地エリアが広がり、大きくすると段差の多いエリアが狭くなります。
    現在の設定: 0.25
    変更案:
    狭い幅: 0.10 → 不整地エリアを拡大して段差をより頻繁に経験。
    広い幅: 0.50 → 平坦なエリアが増え、不整地の挑戦が軽減。

実験シナリオ例

シナリオ 1: 段差を小さくしてテスト
noise_range: (0.02, 0.05)
noise_step: 0.01
目的: 小さな段差での安定性と適応能力を検証。

シナリオ 2: 段差を大きくして挑戦度を上げる
noise_range: (0.02, 0.20)
noise_step: 0.05
目的: 大きな段差を含む地形での段差乗り越え能力を検証。

シナリオ 3: ランダム性を強調した不整地
noise_range: (0.05, 0.15)
noise_step: 0.03
目的: 自然地形に近い環境での適応力を評価。

推奨パラメータ
最初に noise_range を調整するのがおすすめです。これは段差の高さに直接関与し、不整地の難易度に大きな影響を与えるためです。段差の高さがロボットの性能限界に近づくポイントを見つけることで、議論を深められます。

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Dec 1, 2024

不整地のフィールドを全てrandom_roughにして学習を行いました。以下は一枚目がnoise_rangeがデフォルトの値で二枚目が最大値を2.0にしたときの様子です
Screenshot from 2024-12-01 21-32-33
Screenshot from 2024-12-02 02-29-20
それぞれの環境でunitree.pyの値はeffort=139 velocity=20から変えず学習を行ったところ、こちらのissueで報告している転倒のカウント機能を使用して確認した際には画像一枚目の環境では200秒ほどで全てのエージェントが転倒し二枚目の環境では10秒ほどで全て倒れるという結果になりました

@yasuohayashibara
Copy link
Member

yasuohayashibara commented Dec 2, 2024

どのように不整地が生成されるかを熟知していないところはありますが,一般的に2.0mの不整地は乗り越えられないような気がします.
極端と言っても,歩けるか歩けないかぎりぎりのラインで検証したほうが良くて,そこまで極端な値にする必要は無いかなと思います.

まずは,0.1m, 0.2m, 0.3m,もし値が変化しないようであれば0.4mぐらいも試したほうが良いかもしれません.
あと,引きの画像だけではなくて,寄った画像も欲しいです.

人間でも歩けそうも無い不整地の場合は調整したほうが良いと思いますので.

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Dec 2, 2024

0.4mで学習を行ったところ2.3歩移動してその場にしゃがみ込むというような結果になりました。
2024-12-02_05-03-19.webm
報酬は以下のようになり灰色がデフォルトで水色が0.4mのときのものになっており、0.4mの方はエピソードが進んでもほとんど報酬に変化がないことがわかります
Screenshot from 2024-12-02 16-37-32
また一枚目がデフォルトの不整地の様子で二枚目が高さの最大値を0.4にした際のものになります
Screenshot from 2024-12-02 16-27-18
Screenshot from 2024-12-02 16-21-29

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Dec 3, 2024

不整地の環境で区画ごとに隙間があったのを削除した。random_roughborder_width=0.25を0にすれば隙間が消えると思っていたが消えず、原因を調査したところrough.pyのフィールドそのものの定義を行っている部分に各区画を8m四方ごとに10行20列で分け、その外周に余白として20mずつの平地を生成するという以下の記述があった。

    size=(8→164.75, 8→82.25),
    border_width=20.0,
    num_rows=10→1,
    num_cols=20→1,

そのためそれを両方1に変更し1区画のサイズを元々の不整地部分全体のサイズであった
8mx10行+隙間0.25mx9(区画が10で分けられているので隙間は9)=82.25m
8mx20列+隙間0.25mx19(区画が20で分けられているので隙間は19)=164.75m
に変更した。
Screenshot from 2024-12-04 02-11-12
また、外周の余白を0に変更すると以下のようになった
Screenshot from 2024-12-04 02-16-22

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Dec 6, 2024

先日不整地環境のフィールドをrandom_roughのみにしてサイズを160mx80mにし、周囲の平地の余白があると議論が複雑化する恐れがあったため削除した。その際1エピソードの中での最大ステップ数や目標となる移動速度によってはフィールドの外に出てしまうのではないかという懸念があったため調査を行った

目標速度

主にrough_env_cfg.pyを参照
self.commands.base_velocity.ranges.lin_vel_x = (0.0, 1.0)
ロボットの前進・後退方向(X軸)における線形速度の目標範囲を0.0~1.0に設定していてロボットは前進速度として最大1.0m/sまで出すことができる。後退方向の速度は0.0に固定されており、後退しないように制限されている

self.commands.base_velocity.ranges.lin_vel_y = (-0.0, 0.0)
ロボットの横移動方向(Y軸)における線形速度の目標範囲を-0.0~0.0に設定しています。横移動は完全に制限されており、ロボットは前後方向の移動のみを主に目標とする

self.commands.base_velocity.ranges.ang_vel_z = (-1.0, 1.0)
ロボットのZ軸回転方向の角速度の目標範囲を-1.0~1.0に設定しています。ロボットは左右に最大±1.0rad/sで方向転換することができる

以上のことからエージェントは基本的には前進+左右方向への方向転換の目標値が入力される

エピソード

主にmanager_based_rl_env_cfg.pyvelocity_env_cfg.pyを参照

1エピソードのステップ長を求める計算式

主にmanager_based_rl_env_cfg.py参照
ステップ長は
episode_length_steps = ceil(episode_length_s / (decimation_rate * physics_time_step))という計算式で求められる
episode_length_s :1エピソードの時間的な長さ(秒単位) を設定している部分です。この値は、シミュレーション環境におけるエピソード(タスクを完了する1回の試行)の最大継続時間を表している
decimation: 制御周期を調整。物理タイムステップの値を現実的な制御周期へ調整するための値
physics_time_step: シミュレーションで1ステップ進むのに必要な物理的時間。
シミュレーション内で物理エンジンが計算を行うのにかかる時間。シミュレーションの物理タイムステップなどと言われている
例として示されているdecimation_rate = 10、physics_time_step = 0.01、episode_length_s = 10 の場合、1エピソードのステップ長は 100 ステップ

    episode_length_s: float = MISSING
    """Duration of an episode (in seconds).

    Based on the decimation rate and physics time step, the episode length is calculated as:

    .. code-block:: python

        episode_length_steps = ceil(episode_length_s / (decimation_rate * physics_time_step))

    For example, if the decimation rate is 10, the physics time step is 0.01, and the episode length is 10 seconds,
    then the episode length in steps is 100.
    """

今回の環境における1エピソードの最大ステップ長

velocity_env_cfg.pyを参照
self.decimation = 4
デシメーションレート: シミュレーションが何ステップごとに制御ステップを実行するかを表します。つまり、物理シミュレーションが4ステップ進むごとに、エージェントの制御が1回適用されます。

self.episode_length_s = 20.0
エピソードの時間長さ: エピソードが最大で20秒間続くことを表します。

self.sim.dt = 0.005
シミュレーションのタイムステップ: シミュレーションが1ステップ進むのにかかる物理的な時間(秒単位)です。この場合、1ステップは0.005秒間(200Hz)で進むことができる。ただし実際の制御は sim.dt * decimation 制御周期: 0.02秒50Hz)毎に実行される。
以上の値が今回の環境で用いられているパラメータなので計算式に当てはめると
20/(4*0.005)=1000となり1エピソードの最大ステップ数が1000であるということが分かる

        # general settings
        self.decimation = 4
        self.episode_length_s = 20.0
        # simulation settings
        self.sim.dt = 0.005

またrsl_rl_ppo_cfg.pynum_steps_per_env = 24 とあり、この値は「1更新で各環境が実行するシミュレーションステップ数」を表している
例えば今回の環境に用いられているPPOアルゴリズムの場合、1更新中にこの24ステップの経験が収集され、それに基づいて学習が行われている

最大移動距離

最大移動距離についてはコード内に記述が見つけられていないが
目標値1.0m/s * 制御周期0.02s * 1000ステップ(1エピソード)=20mとなるので1エピソードで移動できる最大の距離は20mだと考えられる

@aiba0921
Copy link
Collaborator Author

aiba0921 commented Dec 12, 2024

変更箇所マニュアル

学習を進めていくうえで各ファイルのどの部分を変更するのかをまとめた

unitree.py

G1_CFGを以下のように変更する

G1_CFG = ArticulationCfg(
    spawn=sim_utils.UsdFileCfg(
        usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/Unitree/G1/g1.usd",
        activate_contact_sensors=True,
        rigid_props=sim_utils.RigidBodyPropertiesCfg(
            disable_gravity=False,
            retain_accelerations=False,
            linear_damping=0.0,
            angular_damping=0.0,
            max_linear_velocity=1000.0,
            max_angular_velocity=1000.0,
            max_depenetration_velocity=1.0,
        ),
        articulation_props=sim_utils.ArticulationRootPropertiesCfg(
            enabled_self_collisions=False, solver_position_iteration_count=8, solver_velocity_iteration_count=4
        ),
    ),
    init_state=ArticulationCfg.InitialStateCfg(
        pos=(0.0, 0.0, 0.74),
        joint_pos={
            ".*_hip_pitch_joint": -0.20,
            ".*_knee_joint": 0.42,
            ".*_ankle_pitch_joint": -0.23,
            ".*_elbow_pitch_joint": 0.87,
            "left_shoulder_roll_joint": 0.16,
            "left_shoulder_pitch_joint": 0.35,
            "right_shoulder_roll_joint": -0.16,
            "right_shoulder_pitch_joint": 0.35,
            "left_one_joint": 1.0,
            "right_one_joint": -1.0,
            "left_two_joint": 0.52,
            "right_two_joint": -0.52,
        },
        joint_vel={".*": 0.0},
    ),
    soft_joint_pos_limit_factor=0.9,
    actuators={
        "legs": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_hip_yaw_joint",
                ".*_hip_roll_joint",
                ".*_hip_pitch_joint",
                "torso_joint",
            ],
            effort_limit=88,
            velocity_limit=32.0,
            stiffness={
                ".*_hip_yaw_joint": 150.0,
                ".*_hip_roll_joint": 150.0,
                ".*_hip_pitch_joint": 200.0,
                "torso_joint": 200.0,
            },
            damping={
                ".*_hip_yaw_joint": 5.0,
                ".*_hip_roll_joint": 5.0,
                ".*_hip_pitch_joint": 5.0,
                "torso_joint": 5.0,
            },
            armature={
                ".*_hip_.*": 0.01,
                "torso_joint": 0.01,
            },
        ),
        "knee": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_knee_joint",
            ],
            effort_limit=139,
            velocity_limit=20.0,
            stiffness={
                ".*_knee_joint": 200.0,
            },
            damping={
                ".*_knee_joint": 5.0,
            },
            armature={
                ".*_knee_joint": 0.01,
            },
        ),

        "feet": ImplicitActuatorCfg(
            effort_limit=40,
            velocity_limit=53.0,
            joint_names_expr=[".*_ankle_pitch_joint", ".*_ankle_roll_joint"],
            stiffness=20.0,
            damping=2.0,
            armature=0.01,
        ),
        "arms": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_shoulder_pitch_joint",
                ".*_shoulder_roll_joint",
                ".*_shoulder_yaw_joint",
                ".*_elbow_pitch_joint",
                ".*_elbow_roll_joint",
            ],
            effort_limit=21,
            velocity_limit=53.0,
            stiffness=40.0,
            damping=10.0,
            armature={
                ".*_shoulder_.*": 0.01,
                ".*_elbow_.*": 0.01,
            },
        ),
        "hand": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_five_joint",
                ".*_three_joint",
                ".*_six_joint",
                ".*_four_joint",
                ".*_zero_joint",
                ".*_one_joint",
                ".*_two_joint",
            ],
            effort_limit=0.7,
            velocity_limit=23.0,
            stiffness=40.0,
            damping=10.0,
            armature={
                ".*_five_joint": 0.001,
                ".*_three_joint": 0.001,
                ".*_six_joint": 0.001,
                ".*_four_joint": 0.001,
                ".*_zero_joint": 0.001,
                ".*_one_joint": 0.001,
                ".*_two_joint": 0.001,
            },
        ),
    },
)

特にG1_CFGの以下の個所を変更することでG1の膝のトルク[Nm]と角速度[rad/s]を変更する

        "knee": ImplicitActuatorCfg(
            joint_names_expr=[
                ".*_knee_joint",
            ],
            effort_limit=139, # トルク変更箇所
            velocity_limit=20.0, # 角速度変更箇所
            stiffness={
                ".*_knee_joint": 200.0,
            },
            damping={
                ".*_knee_joint": 5.0,
            },
            armature={
                ".*_knee_joint": 0.01,
            },
        ),

rough.py

以下のように不整地の環境のサイズを70mx70mに変更する※12/13 サイズを70x70に再変更
デフォルトでは周囲に20mの余白(平地)があるため0に変更する
不整地の内容はデフォルトでは階段やブロック状など様々なものがあるが今回はrandom_roughのみを使用するためそれ以外の部分をコメントアウトする
変更するのはnoise_range=(0.02, 0.10)の部分で0.1でデータがとり終わったら0.2,0.3と変更する

    size=(70.0, 70.0), # 不整地のサイズ
    border_width=0.0, # 周囲の余白のサイズ
    num_rows=1,
    num_cols=1,
    horizontal_scale=0.1,
    vertical_scale=0.005,
    slope_threshold=0.75,
    use_cache=False,
    sub_terrains={
#        "pyramid_stairs": terrain_gen.MeshPyramidStairsTerrainCfg(
#            proportion=0.2,
#            step_height_range=(0.05, 0.23),
#            step_width=0.3,
#            platform_width=3.0,
#            border_width=1.0,
#            holes=False,
#        ),
#        "pyramid_stairs_inv": terrain_gen.MeshInvertedPyramidStairsTerrainCfg(
#            proportion=0.2,
#            step_height_range=(0.05, 0.23),
#            step_width=0.3,
#            platform_width=3.0,
#            border_width=1.0,
#            holes=False,
#        ),
#        "boxes": terrain_gen.MeshRandomGridTerrainCfg(
#            proportion=0.2, grid_width=0.45, grid_height_range=(0.05, 0.2), platform_width=2.0
#        ),
        "random_rough": terrain_gen.HfRandomUniformTerrainCfg(
            proportion=1.0, noise_range=(0.02, 0.10), noise_step=0.02, border_width=0.0
        ),
#        "hf_pyramid_slope": terrain_gen.HfPyramidSlopedTerrainCfg(
#            proportion=0.1, slope_range=(0.0, 0.4), platform_width=2.0, border_width=0.25
#        ),
#        "hf_pyramid_slope_inv": terrain_gen.HfInvertedPyramidSlopedTerrainCfg(
#            proportion=0.1, slope_range=(0.0, 0.4), platform_width=2.0, border_width=0.25
#        ),
    },
)

simulation_cfg.py

以下の部分がデフォルトでは2^21だがそのままだと全面をランダムな不整地に変更したことで衝突判定に要するメモリが許容量を超えて学習中にエラーが出て学習時間が大幅に伸びてしまう。そのため2^23にすることで使用するメモリを増やしエラーを回避する。

    gpu_total_aggregate_pairs_capacity: int = 2**23
    """Capacity of total number of aggregate pairs allocated in GPU global memory. Default is 2**23."""

@aiba0921
Copy link
Collaborator Author

各パラメータにおける追従率と転倒回数の比較

現時点での各パラメータ時の平地における歩行でのxy軸の並進速度、z軸の角速度、転倒回数の比較を行った。各速度は10秒毎に目標値が変化するため基本的にどの追従率もその周期で追従率の上下が繰り返されるようになっている。計算は10ステップ毎に行っているが目標値の更新が10秒毎なので計算もそれに併せたほうがいいかもしれない。y軸については目標値が常に0となっているので追従率が計算できなかったため0を基準としてそこからどの程度値が外れているのかを計算している。また平地であり基本的にどのパラメータでも歩行はある程度できているので一定時間における転倒数では大きな差がつくことはあまりないことが多かった

e=139,v=20

x軸の追従率が100%近辺で安定していた。z軸の追従率は40%程度が最大だったがこれでも他のパラメータの時と比較すると最大の値であった。y軸は0から若干のズレはあるものの値は安定していた。
x軸追従率

y,z軸追従率

転倒回数

e=139,v=5

やはり静歩行に近いためなのか追従率は100%近辺で最も安定していた。またy軸も0近辺で安定しているがz軸の角速度のの追従率がe=139,v=20のとき比較すると最大が10%程度低くなっていたため並進速度の追従はできても方向転換などにおける追従率はe=139,v=20のときよりも明らかに低くなっていると考えられる。
x軸追従率

y,z軸追従率

転倒回数

e=10,v=20

x軸の追従率は80%を切ることが多く、y軸もe=139,v=20のときよりも0から値が外れることが多く、z軸の追従率も20〜30%程度となっておりやはりトルクを下げるほうが歩行への影響は大きそうである。
x軸追従率

y,z軸追従率

転倒回数

e=10,v=5

x軸の追従率はe=139,v=20程水準が高いわけでもなくe=139,v=5ほど安定しているわけでもないような状態になっているy軸の0からの外れ方も最も大きくなっておりz軸についても最大が30%に届いていない。そのため歩行できてはいるが、目標に追従できているのかどうかで言えばやはり1番できていないと考えられる。
x軸追従率

y,z軸追従率

転倒回数

計算方法

各エージェントで10ステップ(制御周期が0.02秒なので0.2秒)分の値を取得→10ステップでの平均算出→各エージェントの10ステップ毎の平均をもとに全エージェントの10ステップ毎の平均を算出
同様の方法で目標速度も計算し追従率を計算している。本来毎ステップで計算したほうがいいがそうなると0.02秒毎に計算することになり計算負荷が大きくGUIがカクついたので一旦保留

@aiba0921
Copy link
Collaborator Author

不整地環境におけるフィールドの広さについて

どの程度の広さのフィールドが適しているのか不明瞭であったため調査を行った。どのフィールドの広さでも凹凸の最大値が0.1mのときは1時間半から2時間弱で終了したが最大値が0.3mのときは大きく異なっていた。エージェントは基本的に1エピソードで最大20m進むが最大値が0.3mのときはx軸追従率を調査したところ90〜200%を乱高下していることが分かった。そのため学習がある程度進んでくると最大で50〜60m程度移動することができているエージェントがいる可能性がありフィールドの外に落ちてしまっている可能性が高い。そうなるとエージェントは長く歩けば歩くほどフィールドの外に落ちる=確実に転倒するということになり報酬が上がらなくなり、時間がかかったと考えられる。そのためか40x40、50x50では学習が終了しても結果的に歩行できていない。ただフィールドを広くしすぎると接触判定に割くメモリの量が増えてそれはそれで負荷が大きくなってしまうので現状70x70が理想である可能性が高い
40x40:紫3時間50x50:橙3時間半60x60:灰2時間半70x70:黃2時間80x80:青2時間
Screenshot from 2024-12-14 15-44-32
縦軸:報酬の値、横軸:時間s
Screenshot from 2024-12-14 16-09-07
縦軸:1エピソードのステップ長、横軸:時間s
size(80,80)
e=139,v=20
noise_range=(0.02, 0.30)のときの追従率
2024-12-05_02-34-08e139v20rough0 3x
2024-12-05_02-34-08e139v20rough0 3y,z

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

2 participants