
Genesis å ¥é (3) - ããããã®æäœ
ãGenesisãã®ããããã®æäœã«ã€ããŠãŸãšããŸããã
åå
1. ããããã®æäœ
ããããã¢ãŒã ã¯ãå¶åŸ¡åã(actuation force) ãäžããªããšãéåã§èœäžããŸããGenesisã«ã¯ããç®æšé¢ç¯äœçœ®ããŸãã¯ãé床ããå ¥åãšããŠåãåããPDã³ã³ãããŒã©ããçµã¿èŸŒãŸããŠããŸãããŸããåé¢ç¯ã«çŽæ¥ããã«ã¯/åããèšå®ããããšãã§ããŸãã
2. é¢ç¯ãšèªç±åºŠ
2-1. é¢ç¯ãšèªç±åºŠ
ããããã·ãã¥ã¬ãŒã·ã§ã³ã®æèã§ã¯ããé¢ç¯ã(joint)ãšãèªç±åºŠã(dof : degree-of-freedom) ã¯é¢é£ããŠãããã®ã®ç°ãªãæŠå¿µã§ãã
ã»é¢ç¯ (joint)
ããããã®2ã€ã®ãªã³ã¯ïŒåäœïŒãæ¥ç¶ããçžå¯Ÿçãªåããå¯èœã«ããæ©æ§ãåããç¹å®ã®çš®é¡ïŒå転ã䞊é²ãªã©ïŒã«éå®ã
ã»èªç±åºŠ (dof : degree-of-freedom)
åååŠçãŸãã¯éååŠçã«ç¬ç«ããŠå¶åŸ¡å¯èœãªåãã®æ°ããããããç°å¢å ã§åããå¯èœãªåãã®å¹ ã瀺ãã
ä»åæ±ãFrankaã¢ãŒã ã¯ãã¢ãŒã ã«7ã€ã®å転é¢ç¯ãã°ãªãããŒã«2ã€ã®äžŠé²é¢ç¯ãæã£ãŠããŸãããã¹ãŠã®é¢ç¯ã¯1èªç±åºŠã®ããã9èªç±åºŠã®é¢ç¯äœãšãªã£ãŠããŸããããäžè¬çãªã±ãŒã¹ã§ã¯ãããªãŒãžã§ã€ã³ã (6èªç±åºŠ) ãããŒã«ãžã§ã€ã³ã (3èªç±åºŠ) ã®ããã«ãè€æ°ã®èªç±åºŠãæã€é¢ç¯ã¿ã€ããååšããŸããäžè¬çã«ãåèªç±åºŠã¯ã¢ãŒã¿ãŒãšããŠèããããšãã§ããç¬ç«å¶åŸ¡ã§ããŸãã
2-2. é¢ç¯åãèªç±åºŠã®ã€ã³ããã¯ã¹ã«ãããã³ã°
ã©ã®é¢ç¯ïŒèªç±åºŠïŒãå¶åŸ¡ããããç¥ãããã«ãURDF/MJCFãã¡ã€ã«ã§ïŒãŠãŒã¶ãŒãšããŠïŒå®çŸ©ããé¢ç¯åãã·ãã¥ã¬ãŒã¿å ã®å®éã®èªç±åºŠã€ã³ããã¯ã¹ã«ãããã³ã°ããå¿ èŠããããŸãã
# é¢ç¯åãèªç±åºŠã®ã€ã³ããã¯ã¹ã«ãããã³ã°
jnt_names = [
'joint1',
'joint2',
'joint3',
'joint4',
'joint5',
'joint6',
'joint7',
'finger_joint1',
'finger_joint2',
]
dofs_idx = [franka.get_joint(name).dof_idx_local for name in jnt_names]ãjoint.dof_idx_localãã§ããããããšã³ãã£ãã£èªäœã«å¯Ÿããèªç±åºŠã®ããŒã«ã«ã€ã³ããã¯ã¹ãååŸããŠããŸãããjoint.dof_idxãã§ãã·ãŒã³å ã®åé¢ç¯ã®ã°ããŒãã«èªç±åºŠã€ã³ããã¯ã¹ã«ã¢ã¯ã»ã¹ããããšãã§ããŸãã
2-3. åèªç±åºŠã®å¶åŸ¡ã²ã€ã³ã®èšå®
ãå¶åŸ¡ã²ã€ã³ã (Gain) ã¯ãå¶åŸ¡ã·ã¹ãã ã«ãããŠãå ¥åãšåºåã®é¢ä¿ã調æŽããããã®ä¿æ°ã§ããå¶åŸ¡éïŒãã«ã¯ãåïŒãç®æšå€ãšçŸåšã®å€ã®å·®ïŒåå·®ïŒã«æ¯äŸããŠèšç®ããŸããåå·®ã倧ããå Žåã倧ããªåã§ç®æšå€ã«è¿ã¥ããããšããåå·®ãå°ãããªãã«ã€ããŠãåºåããåãå°ãããªããŸãã
éåžžããããã®æ å ±ã¯ãMJCFããŸãã¯ãURDFãããè§£æãããŸãããæåã§ãã¥ãŒãã³ã°ãããããªã³ã©ã€ã³ã§ååã«ãã¥ãŒãã³ã°ãããå€ãåç §ããããšãæšå¥šããŸãã
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ã²ã€ã³ãèšå®
franka.set_dofs_kp(
kp = np.array([4500, 4500, 3500, 3500, 2000, 2000, 2000, 100, 100]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®é床ã²ã€ã³ãèšå®
franka.set_dofs_kv(
kv = np.array([450, 450, 350, 350, 200, 200, 200, 10, 10]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®åã®ç¯å²ãèšå® (å®å
šã®ãã)
franka.set_dofs_force_range(
lower = np.array([-87, -87, -87, -87, -12, -12, -12, -100, -100]),
upper = np.array([ 87, 87, 87, 87, 12, 12, 12, 100, 100]),
dofs_idx_local = dofs_idx,
)ãããã®APIã¯ãèšå®ããå®éã®å€ãšã察å¿ããèªç±åºŠã®ã€ã³ããã¯ã¹ãåãåããŸããã»ãšãã©ã®å¶åŸ¡é¢é£APIã¯ãã®èŠåã«åŸã£ãŠããŸãã
3. ããŒããªã»ããã«ããããããæäœ
ç©ççã«çŸå®çãªãPDã³ã³ãããŒã©ãã䜿çšãã代ããã«ãããããã®æ§æãæåã§èšå®ããŠã¿ãŸãããããã®APIã¯ç©çæ³åã«åŸããã«ããããã®ç¶æ ãçªç¶å€æŽããããšãã§ããŸãã
# ããŒããªã»ãã
for i in range(150):
if i < 50:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]), dofs_idx)
elif i < 100:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]), dofs_idx)
else:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]), dofs_idx)
scene.step()ãã¥ãŒã¢ãŒããªã³ã«ããŠããå Žåã50ã¹ãããããšã«ããããã®ç¶æ ãå€åããã®ãèŠããŸãã
4. PDã³ã³ãããŒã©ã«ããããããæäœ
çµã¿èŸŒã¿ã®ãPDã³ã³ãããŒã©ãã䜿ã£ãŠãããããå¶åŸ¡ããŠã¿ãŸãããGenesisãã®APIèšèšã¯æ§é åããããã¿ãŒã³ã«åŸã£ãŠããŸããset_dofs_positionã䜿ã£ãŠèªç±åºŠã®äœçœ®ãçŽæ¥èšå®ããŸãããããã§ã¯ãset_*ãcontrol_*ã«å€æŽããŠã察å¿ããå¶åŸ¡åšAPIã䜿çšããŸãã以äžã§ããããããå¶åŸ¡ããããŸããŸãªæ¹æ³ã瀺ããŸãã
# PDã³ã³ãããŒã©
for i in range(1250):
if i == 0:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]),
dofs_idx,
)
elif i == 250:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]),
dofs_idx,
)
elif i == 500:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
elif i == 750:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])[1:],
dofs_idx[1:],
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšé床ãèšå®
franka.control_dofs_velocity(
np.array([1.0, 0, 0, 0, 0, 0, 0, 0, 0])[:1],
dofs_idx[:1],
)
elif i == 1000:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšå¶åŸ¡åãèšå®
franka.control_dofs_force(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
# å¶åŸ¡ã³ãã³ããå
ã«èšç®ãããå¶åŸ¡å
print('control force:', franka.get_dofs_control_force(dofs_idx))
# å®éã«åããå
print('internal force:', franka.get_dofs_force(dofs_idx))
scene.step()ã»ã¹ããã0ãã500ãŸã§
ãã¹ãŠã®èªç±åºŠã«å¯ŸããŠäœçœ®å¶åŸ¡ã䜿çšããããããã3ã€ã®ç®æšäœçœ®ã«é 次移åãããŠããŸããcontrol_* APIã§ã¯ãç®æšå€ãäžåºŠèšå®ããããšãå éšã«ä¿åããããããç®æšãåãã§ããéãã以éã®ã¹ãããã§ç¹°ãè¿ãã³ãã³ããã·ãã¥ã¬ãŒã·ã§ã³ã«éãå¿ èŠã¯ãããŸããã
ã»ã¹ããã750
ç°ãªãèªç±åºŠã«å¯ŸããŠç°ãªãå¶åŸ¡ãå¯èœã§ããããšã瀺ããŠããŸãïŒæåã®èªç±åºŠïŒdof 0ïŒã«ã¯é床ã³ãã³ããéããæ®ãã¯äœçœ®å¶åŸ¡ã³ãã³ãã«åŸããŸã
ã»ã¹ããã1000
ãã«ã¯ïŒåïŒå¶åŸ¡ã«åãæ¿ãããã¹ãŠã®èªç±åºŠã«ãŒãåã³ãã³ããéããšãããããã¯åã³éåã«ãã£ãŠåºã«èœäžããŸãã
åã¹ãããã®æåŸã«ãget_dofs_control_force() ãš get_dofs_force() ã®2çš®é¡ã®åãåºåããŸãã
ã»get_dofs_control_force()
PDã³ã³ãããŒã©ã«ãã£ãŠé©çšãããåãè¿ããŸããäœçœ®å¶åŸ¡ãé床å¶åŸ¡ã®å Žåãããã¯ç®æšã³ãã³ããšå¶åŸ¡ã²ã€ã³ã䜿çšããŠèšç®ããŸããåïŒãã«ã¯ïŒå¶åŸ¡ã®å Žåãããã¯å ¥åå¶åŸ¡ã³ãã³ããšåãã«ãªããŸãã
ã»get_dofs_force()
åèªç±åºŠãå®éã«çµéšããåãè¿ããŸããããã¯PDã³ã³ãããŒã©ã«ãã£ãŠé©çšãããåãšãè¡çªåãã³ãªãªãªåãªã©ã®ä»ã®å éšåã®çµã¿åããã«ãªããŸãã
ã»è¡çªå (Impact Force)
ç©äœåå£«ãæ¥è§Šããéã«çããåãçãæéã§å€§ããªåãçºçããã®ãç¹åŸŽã
ã»ã³ãªãªãªå (Coriolis Force)
å転ããåç §ãã¬ãŒã å ã§èŠ³æž¬ãããèŠããã®åã®äžçš®ã§ãç©äœãç§»åããéã«ããã®åããæ²ããããããã«èŠããåå ãšãªãã

Genesisã®åäœç¢ºèª (3)https://t.co/BVNlo2UsXA pic.twitter.com/Oa8gofc5UZ
â åžçå·è±äž / Hidekazu Furukawa (@npaka123) December 21, 2024
5. å®å šãªã³ãŒã
以äžã¯ãå®å šãªã³ãŒãã§ãã
import numpy as np
import genesis as gs
# åæå
gs.init(backend=gs.gpu)
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
viewer_options = gs.options.ViewerOptions(
camera_pos = (0, -3.5, 2.5),
camera_lookat = (0.0, 0.0, 0.5),
camera_fov = 30,
res = (960, 640),
max_FPS = 60,
),
sim_options = gs.options.SimOptions(
dt = 0.01,
),
show_viewer = True,
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
plane = scene.add_entity(
gs.morphs.Plane(),
)
franka = scene.add_entity(
gs.morphs.MJCF(
file = 'xml/franka_emika_panda/panda.xml',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
# é¢ç¯åãèªç±åºŠã®ã€ã³ããã¯ã¹ã«ãããã³ã°
jnt_names = [
'joint1',
'joint2',
'joint3',
'joint4',
'joint5',
'joint6',
'joint7',
'finger_joint1',
'finger_joint2',
]
dofs_idx = [franka.get_joint(name).dof_idx_local for name in jnt_names]
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ã²ã€ã³ãèšå®
franka.set_dofs_kp(
kp = np.array([4500, 4500, 3500, 3500, 2000, 2000, 2000, 100, 100]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®é床ã²ã€ã³ãèšå®
franka.set_dofs_kv(
kv = np.array([450, 450, 350, 350, 200, 200, 200, 10, 10]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®åã®ç¯å²ãèšå® (å®å
šã®ãã)
franka.set_dofs_force_range(
lower = np.array([-87, -87, -87, -87, -12, -12, -12, -100, -100]),
upper = np.array([ 87, 87, 87, 87, 12, 12, 12, 100, 100]),
dofs_idx_local = dofs_idx,
)
# ããŒããªã»ãã
for i in range(150):
if i < 50:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]), dofs_idx)
elif i < 100:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]), dofs_idx)
else:
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
franka.set_dofs_position(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]), dofs_idx)
scene.step()
# PDã³ã³ãããŒã«
for i in range(1250):
if i == 0:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]),
dofs_idx,
)
elif i == 250:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]),
dofs_idx,
)
elif i == 500:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
elif i == 750:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])[1:],
dofs_idx[1:],
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšé床ãèšå®
franka.control_dofs_velocity(
np.array([1.0, 0, 0, 0, 0, 0, 0, 0, 0])[:1],
dofs_idx[:1],
)
elif i == 1000:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšå¶åŸ¡åãèšå®
franka.control_dofs_force(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
# å¶åŸ¡ã³ãã³ããå
ã«èšç®ãããå¶åŸ¡å
print('control force:', franka.get_dofs_control_force(dofs_idx))
# å®éã«åããå
print('internal force:', franka.get_dofs_force(dofs_idx))
scene.step()ãããŸãã Macçã®ã³ãŒã
import genesis as gs
import numpy as np
def main():
# åæå
gs.init(backend=gs.cpu)
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
viewer_options = gs.options.ViewerOptions(
camera_pos = (0, -3.5, 2.5),
camera_lookat = (0.0, 0.0, 0.5),
camera_fov = 30,
res = (960, 640),
max_FPS = 60,
),
sim_options = gs.options.SimOptions(
dt = 0.01,
),
show_viewer = True,
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
plane = scene.add_entity(
gs.morphs.Plane(),
)
franka = scene.add_entity(
gs.morphs.MJCF(
file = 'xml/franka_emika_panda/panda.xml',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
# ã¹ã¬ããã®éå§
gs.tools.run_in_another_thread(fn=run_sim, args=(scene, franka))
# ã·ãã¥ã¬ãŒã¿ã®éå§
scene.viewer.start()
def run_sim(scene, franka):
# é¢ç¯åãèªç±åºŠã®ã€ã³ããã¯ã¹ã«ãããã³ã°
jnt_names = [
'joint1',
'joint2',
'joint3',
'joint4',
'joint5',
'joint6',
'joint7',
'finger_joint1',
'finger_joint2',
]
dofs_idx = [franka.get_joint(name).dof_idx_local for name in jnt_names]
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ã²ã€ã³ãèšå®
franka.set_dofs_kp(
kp = np.array([4500, 4500, 3500, 3500, 2000, 2000, 2000, 100, 100]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®é床ã²ã€ã³ãèšå®
franka.set_dofs_kv(
kv = np.array([450, 450, 350, 350, 200, 200, 200, 10, 10]),
dofs_idx_local = dofs_idx,
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®åã®ç¯å²ãèšå® (å®å
šã®ãã)
franka.set_dofs_force_range(
lower = np.array([-87, -87, -87, -87, -12, -12, -12, -100, -100]),
upper = np.array([ 87, 87, 87, 87, 12, 12, 12, 100, 100]),
dofs_idx_local = dofs_idx,
)
# ããŒããªã»ãã
for i in range(150):
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
if i < 50:
franka.set_dofs_position(np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]), dofs_idx)
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
elif i < 100:
franka.set_dofs_position(np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]), dofs_idx)
# ãšã³ãã£ãã£ã®èªç±åºŠã®äœçœ®ãèšå®
else:
franka.set_dofs_position(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]), dofs_idx)
scene.step()
# PDã³ã³ãããŒã«
for i in range(1250):
if i == 0:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([1, 1, 0, 0, 0, 0, 0, 0.04, 0.04]),
dofs_idx,
)
elif i == 250:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([-1, 0.8, 1, -2, 1, 0.5, -0.5, 0.04, 0.04]),
dofs_idx,
)
elif i == 500:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
elif i == 750:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšäœçœ®ãèšå®
franka.control_dofs_position(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])[1:],
dofs_idx[1:],
)
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšé床ãèšå®
franka.control_dofs_velocity(
np.array([1.0, 0, 0, 0, 0, 0, 0, 0, 0])[:1],
dofs_idx[:1],
)
elif i == 1000:
# ãšã³ãã£ãã£ã®èªç±åºŠã®ç®æšå¶åŸ¡åãèšå®
franka.control_dofs_force(
np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]),
dofs_idx,
)
# å¶åŸ¡ã³ãã³ããå
ã«èšç®ãããå¶åŸ¡å
print('control force:', franka.get_dofs_control_force(dofs_idx))
# å®éã«åããå
print('internal force:', franka.get_dofs_force(dofs_idx))
scene.step()
if __name__ == "__main__":
main()