
Genesis å ¥é (10) - ãœãããããã
ãGenesisãã®ããœãããããããã«ã€ããŠãŸãšããŸããã
ã»Soft Robots
åå
1. ãœãããããã
ãGenesisãã¯ãããœãããããããã®ãMPMããšãFEMãã䜿çšãããVolumetric Muscle ã·ãã¥ã¬ãŒã·ã§ã³ãããµããŒãããŠããŸããæ¬¡ã®äŸã§ã¯ãæ£åŒŠæ³¢å¶åŸ¡ä¿¡å·ã«ãã£ãŠäœåããçäœããã£ãåããéåžžã«ã·ã³ãã«ãªããœãããããããã瀺ããŸãã
import numpy as np
import genesis as gs
# åæå
gs.init(seed=0, precision='32', logging_level='debug')
# ã·ãŒã³ã®äœæ
dt = 5e-4
scene = gs.Scene(
sim_options=gs.options.SimOptions(
substeps=10,
gravity=(0, 0, 0),
),
viewer_options= gs.options.ViewerOptions(
camera_pos=(1.5, 0, 0.8),
camera_lookat=(0.0, 0.0, 0.0),
camera_fov=40,
),
mpm_options=gs.options.MPMOptions(
dt=dt,
lower_bound=(-1.0, -1.0, -0.2),
upper_bound=( 1.0, 1.0, 1.0),
),
fem_options=gs.options.FEMOptions(
dt=dt,
damping=45.,
),
vis_options=gs.options.VisOptions(
show_world_frame=False,
),
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
scene.add_entity(morph=gs.morphs.Plane())
E, nu = 3.e4, 0.45
rho = 1000.
robot_mpm = scene.add_entity(
morph=gs.morphs.Sphere(
pos=(0.5, 0.2, 0.3),
radius=0.1,
),
material=gs.materials.MPM.Muscle(
E=E,
nu=nu,
rho=rho,
model='neohooken',
),
)
robot_fem = scene.add_entity(
morph=gs.morphs.Sphere(
pos=(0.5, -0.2, 0.3),
radius=0.1,
),
material=gs.materials.FEM.Muscle(
E=E,
nu=nu,
rho=rho,
model='stable_neohooken',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
# å®è¡
scene.reset()
for i in range(1000):
actu = np.array([0.2 * (0.5 + np.sin(0.01 * np.pi * i))])
robot_mpm.set_actuation(actu)
robot_fem.set_actuation(actu)
scene.step()
ã³ãŒãã®å€§éšåã¯ãéåžžã®å€åœ¢å¯èœãªEntityãã€ã³ã¹ã¿ã³ã¹åããã®ãšæ¯ã¹ããšããªãæšæºçã§ãã 圹ç«ã€ã®ã¯ã次ã®2ã€ã®éãã ãã§ãã
ã»ãœãããããã robot_mpm ãš robot_fem ãã€ã³ã¹ã¿ã³ã¹åãããšãã¯ããããã gs.materials.MPM.Muscle ãš gs.materials.FEM.Muscle ãšãããããªã¢ã«ã䜿çšããŸãã
ã»ã·ãã¥ã¬ãŒã·ã§ã³ãã¹ãããå®è¡ãããšãã¯ãrobot_mpm.set_actuation ãŸã㯠robot_fem.set_actuation ã䜿çšããŠçèã®ã¢ã¯ãã¥ãšãŒã·ã§ã³ãèšå®ããŸãã
ããã©ã«ãã§ã¯ãããããã®ããã£å šäœã«åºããçèã¯1ã€ã ãã§ãããçèã®æ¹åã¯å°é¢ã«å¯ŸããŠåçŽã§ã [0, 0, 1]ã
次ã®äŸã§ã¯ã次ã«ç€ºãããã«çèã®ã°ã«ãŒããšæ¹åãèšå®ããŠãåæ¹ã«éãã¯ãŒã ãã·ãã¥ã¬ãŒãããæ¹æ³ã瀺ããŸãã(å®å šãªã¹ã¯ãªãã㯠tutorials/advanced_worm.py ã«ãããŸãã)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
worm = scene.add_entity(
morph=gs.morphs.Mesh(
file='meshes/worm/worm.obj',
pos=(0.3, 0.3, 0.001),
scale=0.1,
euler=(90, 0, 0),
),
material=gs.materials.MPM.Muscle(
E=5e5,
nu=0.45,
rho=10000.,
model='neohooken',
n_groups=4,
),
)
# çèã®æå®
def set_muscle_by_pos(robot):
if isinstance(robot.material, gs.materials.MPM.Muscle):
pos = robot.get_state().pos
n_units = robot.n_particles
elif isinstance(robot.material, gs.materials.FEM.Muscle):
pos = robot.get_state().pos[robot.get_el2v()].mean(1)
n_units = robot.n_elements
else:
raise NotImplementedError
pos = pos.cpu().numpy()
pos_max, pos_min = pos.max(0), pos.min(0)
pos_range = pos_max - pos_min
lu_thresh, fh_thresh = 0.3, 0.6
muscle_group = np.zeros((n_units,), dtype=int)
mask_upper = pos[:, 2] > (pos_min[2] + pos_range[2] * lu_thresh)
mask_fore = pos[:, 1] < (pos_min[1] + pos_range[1] * fh_thresh)
muscle_group[ mask_upper & mask_fore] = 0 # upper fore body
muscle_group[ mask_upper & ~mask_fore] = 1 # upper hind body
muscle_group[~mask_upper & mask_fore] = 2 # lower fore body
muscle_group[~mask_upper & ~mask_fore] = 3 # lower hind body
muscle_direction = np.array([[0, 1, 0]] * n_units, dtype=float)
robot.set_muscle(
muscle_group=muscle_group,
muscle_direction=muscle_direction,
)
set_muscle_by_pos(worm)
# å®è¡
scene.reset()
for i in range(1000):
actu = np.array([0, 0, 0, 1. * (0.5 + np.sin(0.005 * np.pi * i))])
worm.set_actuation(actu)
scene.step()
ã»ãããªã¢ã« gs.materials.MPM.Muscle ãæå®ãããšãã«ã远å ã®åŒæ° n_groups = 4 ãèšå®ããŸããããã¯ããã®ããããã«ã¯æå€§4ã€ã®ç°ãªãçèãååšããå¯èœæ§ãããããšãæå³ããŸãã
ã»çèãèšå®ããã«ã¯ãmuscle_group ãš Muscle_direction ãå ¥åãšããŠåãåã robot.set_muscle ãåŒã³åºããŸããã©ã¡ãã n_units ãšåãé·ãã§ããMPM ã® n_units ã¯ç²åã®æ°ã§ãFEM ã® n_units ã¯èŠçŽ ã®æ°ã§ããmuscle_group 㯠0 ãã n_groups - 1 ãŸã§ã®æŽæ°ã®é åã§ãããããæ¬äœã®ãŠããããã©ã®çèã°ã«ãŒãã«å±ãããã瀺ããŸããmuscle_direction ã¯ãçèã®æ¹åã®ãã¯ãã«ãæå®ããæµ®åå°æ°ç¹æ°ã®é åã§ããæ£èŠåã¯è¡ããªããããå ¥åã® Muscle_direction ããã§ã«æ£èŠåãããŠããããšã確èªããããšããå§ãããŸãã
ã»ãã®ã¯ãŒã ã®äŸã®çèãèšå®ããæ¹æ³ã¯ãåã«äœã4ã€ã®éšåã«åå²ããããšã§ããäžéšåéšãäžéšåŸéšãäžéšåéšãäžéšåŸéšã§ããäžéš/äžéšéã®ãããå€èšå®ã«ã¯ lu_thresh ã䜿çšããåéš/åŸéšéã®ãããå€èšå®ã«ã¯ fh_thresh ã䜿çšããŸãã
ã»ããã§4ã€ã®çèã°ã«ãŒããäžããããset_actuation ãä»ããŠã³ã³ãããŒã«ãèšå®ãããšãã¢ã¯ãã¥ãšãŒã·ã§ã³å ¥åã¯åœ¢ç¶ (4,) ã®é åã«ãªããŸãã
2. ãã€ããªãããããã
å¥ã¿ã€ãã®ããœãããããããã¯ãããªãžããããã£ãã®å éšéªšæ Œã䜿çšããŠããœããããã£ãã®å€ç®ãäœåããããã®ã§ãããæ£ç¢ºã«èšãã°ããã€ããªãããããããã§ããããªãžããããã£ããšããœããããã£ãã®äž¡æ¹ã®ãã€ããã¯ã¹ããã§ã«å®è£ ãããŠããããããGenesisãã¯ããã€ããªãããããããããµããŒãããŠããŸããæ¬¡ã®äŸã¯ã2ãªã³ã¯ã®éªšæ Œããœããã¹ãã³ã§å ãã§ãªãžããããŒã«ãæŒããŠãããã€ããªããããããã§ãã
import numpy as np
import genesis as gs
# åæå
gs.init(seed=0, precision='32', logging_level='debug')
# ã·ãŒã³ã®äœæ
dt = 3e-3
scene = gs.Scene(
sim_options=gs.options.SimOptions(
substeps=10,
),
viewer_options= gs.options.ViewerOptions(
camera_pos=(1.5, 1.3, 0.5),
camera_lookat=(0.0, 0.0, 0.0),
camera_fov=40,
),
rigid_options=gs.options.RigidOptions(
dt=dt,
gravity=(0, 0, -9.8),
enable_collision=True,
enable_self_collision=False,
),
mpm_options=gs.options.MPMOptions(
dt=dt,
lower_bound=( 0.0, 0.0, -0.2),
upper_bound=( 1.0, 1.0, 1.0),
gravity=(0, 0, 0), # mimic gravity compensation
enable_CPIC=True,
),
vis_options=gs.options.VisOptions(
show_world_frame=True,
visualize_mpm_boundary=False,
),
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
scene.add_entity(morph=gs.morphs.Plane())
robot = scene.add_entity(
morph=gs.morphs.URDF(
file="urdf/simple/two_link_arm.urdf",
pos=(0.5, 0.5, 0.3),
euler=(0.0, 0.0, 0.0),
scale=0.2,
fixed=True,
),
material=gs.materials.Hybrid(
mat_rigid=gs.materials.Rigid(
gravity_compensation=1.,
),
mat_soft=gs.materials.MPM.Muscle( # to allow setting group
E=1e4,
nu=0.45,
rho=1000.,
model='neohooken',
),
thickness=0.05,
damping=1000.,
func_instantiate_rigid_from_soft=None,
func_instantiate_soft_from_rigid=None,
func_instantiate_rigid_soft_association=None,
),
)
ball = scene.add_entity(
morph=gs.morphs.Sphere(
pos=(0.8, 0.6, 0.1),
radius=0.1,
),
material=gs.materials.Rigid(rho=1000, friction=0.5),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
# å®è¡
scene.reset()
for i in range(1000):
dofs_ctrl = np.array([
1. * np.sin(2 * np.pi * i * 0.001),
] * robot.n_dofs)
robot.control_dofs_velocity(dofs_ctrl)
scene.step()
ã»ãã€ããªããããããã¯ãgs.materials.Rigid ãš gs.materials.MPM.Muscle ã§æ§æããããããªã¢ã« gs.materials.Hybrid ã§æå®ã§ããŸãããã€ããªãããããªã¢ã«ã¯ Muscle çšã«å®è£ ããã Muscle_group ãå éšçã«åå©çšãããããããã§ã¯ MPM ã®ã¿ããµããŒããããMuscle ã¯ã©ã¹ã§ããå¿ èŠããããŸãã
ã»ãããããå¶åŸ¡ããå Žåãã¢ã¯ãã¥ãšãŒã·ã§ã³ãå éšã®ãªãžããããã£ã¹ã±ã«ãã³ããè¡ãããããšãèãããšããªãžããããã£ãããããšåæ§ã®ã€ã³ã¿ãŒãã§ã€ã¹ (control_dofs_velocityãcontrol_dofs_forceãcontrol_dofs_position ãªã©) ããããŸãããŸããå¶åŸ¡ãã£ã¡ã³ã·ã§ã³ã¯å éšã¹ã±ã«ãã³ã® DoF ãšåãã§ã (äžèšã®äŸã§ã¯ 2)ã
ã»ã¹ãã³ã¯å éšã¹ã±ã«ãã³ã®åœ¢ç¶ã«ãã£ãŠæ±ºå®ãããåã¿ã¯ã¹ã±ã«ãã³ãå ããšãã®ã¹ãã³ã®åããæ±ºå®ããŸãã
ã»ããã©ã«ãã§ã¯ãã¹ãã³ã¯ã¹ã±ã«ãã³ã®åœ¢ç¶ã«åºã¥ããŠæé·ããŸãããã㯠morph (ãã®äŸã§ã¯ urdf/simple/two_link_arm.urdf) ã«ãã£ãŠæå®ãããŸãã gs.materials.Hybrid ã®åŒæ° func_instantiate_soft_from_rigid ã¯ãåäœã¢ãŒãã«åºã¥ããŠã¹ãã³ãã©ã®ããã«æé·ããããå ·äœçã«å®çŸ©ããŸããgenesis/engine/entities/hybrid_entity.py ã«ã¯ãdefault_func_instantiate_soft_from_rigid ãšããããã©ã«ãã®å®è£ ããããŸããç¬èªã®é¢æ°ãå®è£ ããããšãã§ããŸãã
ã»ã¢ãŒãã URDF ã§ã¯ãªã Mesh ã®å Žåãã¡ãã·ã¥ã¯æãããå€åŽã®ããã£ãæå®ããå åŽã®ã¹ã±ã«ãã³ã¯ã¹ãã³ã®åœ¢ç¶ã«åºã¥ããŠæé·ããŸãããã㯠func_instantiate_rigid_from_soft ã«ãã£ãŠå®çŸ©ãããŸãããŸããdefault_func_instantiate_rigid_from_soft ãšããããã©ã«ãã®å®è£ ããããããã¯åºæ¬çã« 3D ã¡ãã·ã¥ã®ã¹ã±ã«ãã³åãå®è£ ããŸãã
ã»gs.materials.Hybrid ã®åŒæ° func_instantiate_rigid_soft_association ã¯ãåã¹ã±ã«ãã³ããŒããã¹ãã³ãšã©ã®ããã«é¢é£ä»ããããããæ±ºå®ããŸããããã©ã«ãã®å®è£ ã§ã¯ã硬ãéªšæ Œéšåã«æãè¿ãæãããç®èã®ç²åãèŠã€ããŸãã