chore: release v0.3.0

This commit is contained in:
motphys-developers
2026-04-02 03:45:10 +00:00
parent c84d382b8c
commit e1421d1055
232 changed files with 20258 additions and 2004 deletions

View File

@@ -4,12 +4,12 @@ build-backend = "uv_build"
[project]
name = "motrix-envs"
version = "0.2.0"
version = "0.3.0"
description = "Robot simulation environment library based on MotrixSim providing multi-task RL environments."
authors = [{ name = "Motphys", email = "developers@motphys.com" }]
requires-python = "==3.10.*"
readme = "README.md"
license = "Apache-2.0"
dependencies = [
"motrixsim>=0.6.0b1",
"motrixsim>=0.7.0",
]

View File

@@ -21,8 +21,11 @@ from . import ( # noqa: F401 import to register envs
finger,
hopper,
humanoid,
lqr,
manipulator,
pendulum,
point_mass,
quadruped,
reacher,
walker,
)

View File

@@ -22,6 +22,7 @@ from motrix_envs.base import EnvCfg
model_file = os.path.dirname(__file__) + "/acrobot.xml"
# -- docs-tag-start: acrobot-env-cfg --
@registry.envcfg("acrobot")
@dataclass
class AcrobotEnvCfg(EnvCfg):
@@ -31,3 +32,6 @@ class AcrobotEnvCfg(EnvCfg):
render_spacing: float = 2.0
sim_dt: float = 0.01
ctrl_dt: float = 0.02
# -- docs-tag-end: acrobot-env-cfg --

View File

@@ -28,7 +28,7 @@ turn_hard_model_file = os.path.dirname(__file__) + "/finger_turn_hard.xml"
@dataclass
class FingerBaseCfg(EnvCfg):
model_file: str = model_file
max_episode_seconds: float = 20.0
max_episode_seconds: float = 10.0
sim_dt: float = 0.01
ctrl_dt: float = 0.02

View File

@@ -23,8 +23,6 @@ from motrix_envs.np.env import NpEnv, NpEnvState
def _sanitize_joint_limits(low: np.ndarray, high: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
low = low.copy()
high = high.copy()
low = np.where(np.isfinite(low), low, -np.pi)
high = np.where(np.isfinite(high), high, np.pi)
return low, high

View File

@@ -54,7 +54,7 @@ class Humanoid3DEnv(NpEnv):
def _build_qpos_limits(self, model) -> tuple[np.ndarray, np.ndarray]:
num_dof_pos = int(model.num_dof_pos)
jl = np.asarray(model.joint_limits, dtype=np.float32)
jl = model.joint_limits
if jl.ndim != 2 or jl.shape[0] != 2:
low = np.full((num_dof_pos,), -np.inf, dtype=np.float32)
high = np.full((num_dof_pos,), np.inf, dtype=np.float32)
@@ -168,17 +168,17 @@ class Humanoid3DEnv(NpEnv):
return obs, {}
def _get_obs(self, data: mtx.SceneData) -> np.ndarray:
joint_angles = np.asarray(data.dof_pos[:, 7:], dtype=np.float32)
head_height = self._get_head_height(data).astype(np.float32)[:, None]
extremities = self._get_extremities(data).astype(np.float32)
joint_angles = data.dof_pos[:, 7:]
head_height = self._get_head_height(data)[:, None]
extremities = self._get_extremities(data)
torso_rot = self._torso.get_rotation_mat(data)
torso_vertical = np.asarray(torso_rot[:, 2, :], dtype=np.float32)
torso_vertical = torso_rot[:, 2, :]
com_vel = np.asarray(self._model.get_sensor_value("torso_subtreelinvel", data), dtype=np.float32)
com_vel = self._model.get_sensor_value("torso_subtreelinvel", data)
qvel = np.asarray(data.dof_vel, dtype=np.float32)
target_direction_local = self._get_target_direction_local(data).astype(np.float32)
qvel = data.dof_vel
target_direction_local = self._get_target_direction_local(data)
obs = np.concatenate(
[joint_angles, head_height, extremities, torso_vertical, com_vel, qvel, target_direction_local], axis=-1
@@ -186,14 +186,14 @@ class Humanoid3DEnv(NpEnv):
return obs
def _get_head_height(self, data: mtx.SceneData) -> np.ndarray:
return np.asarray(self._head.get_position(data)[:, 2], dtype=np.float32)
return self._head.get_position(data)[:, 2]
def _get_pelvis_height(self, data: mtx.SceneData) -> np.ndarray:
return np.asarray(self._pelvis.get_position(data)[:, 2], dtype=np.float32)
return self._pelvis.get_position(data)[:, 2]
def _get_torso_upright(self, data: mtx.SceneData) -> np.ndarray:
torso_rot = self._torso.get_rotation_mat(data)
return np.asarray(torso_rot[:, 2, 2], dtype=np.float32)
return torso_rot[:, 2, 2]
def _get_extremities(self, data: mtx.SceneData) -> np.ndarray:
torso_rot = self._torso.get_rotation_mat(data)
@@ -206,12 +206,10 @@ class Humanoid3DEnv(NpEnv):
self._right_foot.get_position(data),
]
out = []
torso_rot_f32 = np.asarray(torso_rot, dtype=np.float32)
torso_pos_f32 = np.asarray(torso_pos, dtype=np.float32)
for p in parts:
torso_to_limb = np.asarray(p, dtype=np.float32) - torso_pos_f32
v_body = np.einsum("ni,nij->nj", torso_to_limb, torso_rot_f32)
torso_to_limb = p - torso_pos
v_body = np.einsum("ni,nij->nj", torso_to_limb, torso_rot)
out.append(v_body)
return np.concatenate(out, axis=-1)
@@ -219,9 +217,8 @@ class Humanoid3DEnv(NpEnv):
def _get_target_direction_local(self, data: mtx.SceneData) -> np.ndarray:
n = int(data.shape[0])
torso_rot = self._torso.get_rotation_mat(data)
torso_rot_f32 = np.asarray(torso_rot, dtype=np.float32)
target_world = np.ones((n, 3), dtype=np.float32) * self._target_direction[None, :]
target_local = np.einsum("ni,nij->nj", target_world, torso_rot_f32)
target_local = np.einsum("ni,nij->nj", target_world, torso_rot)
return target_local
def _compute_reward(
@@ -251,39 +248,27 @@ class Humanoid3DEnv(NpEnv):
torso_upright: np.ndarray,
pelvis_height: np.ndarray,
) -> np.ndarray:
stand_reward = (
reward.tolerance(
head_height,
bounds=(self._head_height_min, float("inf")),
margin=0.5,
)
.astype(np.float32)
.flatten()
)
stand_reward = reward.tolerance(
head_height,
bounds=(self._head_height_min, float("inf")),
margin=0.5,
).flatten()
upright_reward = (
reward.tolerance(
torso_upright,
bounds=(0.9, float("inf")),
sigmoid="linear",
margin=0.9,
)
.astype(np.float32)
.flatten()
)
upright_reward = reward.tolerance(
torso_upright,
bounds=(0.9, float("inf")),
sigmoid="linear",
margin=0.9,
).flatten()
pelvis_height_reward = (
reward.tolerance(
pelvis_height,
bounds=(self._pelvis_height_min, float("inf")),
sigmoid="linear",
margin=self._pelvis_height_margin,
)
.astype(np.float32)
.flatten()
)
pelvis_height_reward = reward.tolerance(
pelvis_height,
bounds=(self._pelvis_height_min, float("inf")),
sigmoid="linear",
margin=self._pelvis_height_margin,
).flatten()
return (stand_reward * upright_reward * pelvis_height_reward).astype(np.float32)
return stand_reward * upright_reward * pelvis_height_reward
def _compute_speed_and_energy_reward(
self,
@@ -291,50 +276,38 @@ class Humanoid3DEnv(NpEnv):
) -> tuple[np.ndarray, np.ndarray]:
target_dir_xy = self._target_direction_xy
ctrls = np.asarray(data.actuator_ctrls, dtype=np.float32)
com_vel = np.asarray(self._model.get_sensor_value("torso_subtreelinvel", data), dtype=np.float32)
ctrls = data.actuator_ctrls
com_vel = self._model.get_sensor_value("torso_subtreelinvel", data)
if self._move_speed <= 0.0:
energy_reward = np.exp(-1.0 * np.mean(np.square(ctrls), axis=-1)).astype(np.float32)
actual_speed = np.linalg.norm(com_vel[:, :2], axis=-1).astype(np.float32)
speed_reward = (
reward.tolerance(
actual_speed,
bounds=(self._move_speed, self._move_speed),
margin=1.0,
value_at_margin=0.01,
)
.astype(np.float32)
.flatten()
)
energy_reward = np.exp(-1.0 * np.mean(np.square(ctrls), axis=-1))
actual_speed = np.linalg.norm(com_vel[:, :2], axis=-1)
speed_reward = reward.tolerance(
actual_speed,
bounds=(self._move_speed, self._move_speed),
margin=1.0,
value_at_margin=0.01,
).flatten()
elif self._move_speed <= 3.0:
energy_reward = np.exp(-0.5 * np.mean(np.square(ctrls), axis=-1)).astype(np.float32)
actual_speed = np.sum(com_vel[:, :2] * target_dir_xy, axis=-1).astype(np.float32)
speed_reward = (
reward.tolerance(
actual_speed,
bounds=(self._move_speed, self._move_speed),
margin=self._move_speed,
value_at_margin=0.0,
sigmoid="linear",
)
.astype(np.float32)
.flatten()
)
energy_reward = np.exp(-0.5 * np.mean(np.square(ctrls), axis=-1))
actual_speed = np.sum(com_vel[:, :2] * target_dir_xy, axis=-1)
speed_reward = reward.tolerance(
actual_speed,
bounds=(self._move_speed, self._move_speed),
margin=self._move_speed,
value_at_margin=0.0,
sigmoid="linear",
).flatten()
else:
energy_reward = np.exp(-0.3 * np.mean(np.square(ctrls), axis=-1)).astype(np.float32)
actual_speed = np.sum(com_vel[:, :2] * target_dir_xy, axis=-1).astype(np.float32)
speed_reward = (
reward.tolerance(
actual_speed,
bounds=(self._move_speed, float("inf")),
margin=self._move_speed,
value_at_margin=0.0,
sigmoid="linear",
)
.astype(np.float32)
.flatten()
)
energy_reward = np.exp(-0.3 * np.mean(np.square(ctrls), axis=-1))
actual_speed = np.sum(com_vel[:, :2] * target_dir_xy, axis=-1)
speed_reward = reward.tolerance(
actual_speed,
bounds=(self._move_speed, float("inf")),
margin=self._move_speed,
value_at_margin=0.0,
sigmoid="linear",
).flatten()
return speed_reward, energy_reward
@@ -346,17 +319,13 @@ class Humanoid3DEnv(NpEnv):
margin,
) -> np.ndarray:
dot = np.sum(forward_vec * target_dir, axis=-1)
return (
reward.tolerance(
dot,
bounds=bounds,
margin=margin,
value_at_margin=0.0,
sigmoid="linear",
)
.astype(np.float32)
.flatten()
)
return reward.tolerance(
dot,
bounds=bounds,
margin=margin,
value_at_margin=0.0,
sigmoid="linear",
).flatten()
def _compute_gait_reward(self, data: mtx.SceneData) -> np.ndarray:
target_dir = self._target_direction
@@ -365,49 +334,36 @@ class Humanoid3DEnv(NpEnv):
head_rot = self._head.get_rotation_mat(data)
pelvis_rot = self._pelvis.get_rotation_mat(data)
torso_forward = np.asarray(torso_rot[:, 0, 0:3], dtype=np.float32)
torso_forward = torso_rot[:, 0, 0:3]
torso_heading_reward = self._compute_heading_reward(torso_forward, target_dir, bounds=(0.9, 1.0), margin=0.3)
head_forward = np.asarray(head_rot[:, 0, 0:3], dtype=np.float32)
head_forward = head_rot[:, 0, 0:3]
head_heading_reward = self._compute_heading_reward(head_forward, target_dir, bounds=(0.9, 1.0), margin=0.3)
pelvis_forward = np.asarray(pelvis_rot[:, 0, 0:3], dtype=np.float32)
pelvis_forward = pelvis_rot[:, 0, 0:3]
pelvis_yaw_reward = self._compute_heading_reward(pelvis_forward, target_dir, bounds=(0.9, 1.0), margin=0.3)
pelvis_up = np.asarray(pelvis_rot[:, 2, 2], dtype=np.float32)
pelvis_level_reward = (
reward.tolerance(
pelvis_up,
bounds=(0.9, 1.0),
margin=0.3,
sigmoid="linear",
value_at_margin=0.0,
)
.astype(np.float32)
.flatten()
)
pelvis_up = pelvis_rot[:, 2, 2]
pelvis_level_reward = reward.tolerance(
pelvis_up,
bounds=(0.9, 1.0),
margin=0.3,
sigmoid="linear",
value_at_margin=0.0,
).flatten()
left_foot_pos = self._left_foot.get_position(data)
right_foot_pos = self._right_foot.get_position(data)
max_foot_h = np.maximum(
np.asarray(left_foot_pos[:, 2], dtype=np.float32),
np.asarray(right_foot_pos[:, 2], dtype=np.float32),
)
feet_height_reward = (
reward.tolerance(
max_foot_h,
bounds=(0.0, 0.3),
margin=0.5,
sigmoid="quadratic",
value_at_margin=0.0,
)
.astype(np.float32)
.flatten()
)
max_foot_h = np.maximum(left_foot_pos[:, 2], right_foot_pos[:, 2])
feet_height_reward = reward.tolerance(
max_foot_h,
bounds=(0.0, 0.3),
margin=0.5,
sigmoid="quadratic",
value_at_margin=0.0,
).flatten()
return (
torso_heading_reward * head_heading_reward * pelvis_yaw_reward * pelvis_level_reward * feet_height_reward
).astype(np.float32)
return torso_heading_reward * head_heading_reward * pelvis_yaw_reward * pelvis_level_reward * feet_height_reward
def _compute_terminated(
self,
@@ -415,13 +371,13 @@ class Humanoid3DEnv(NpEnv):
head_height: np.ndarray,
torso_upright: np.ndarray,
) -> np.ndarray:
qpos = np.asarray(data.dof_pos, dtype=np.float32)
qvel = np.asarray(data.dof_vel, dtype=np.float32)
qpos = data.dof_pos
qvel = data.dof_vel
bad = ~np.isfinite(qpos).all(axis=-1) | ~np.isfinite(qvel).all(axis=-1)
too_low = head_height < self._term_head_height_min
too_tilted = torso_upright < self._term_torso_upright_threshold
extreme_vel = np.abs(qvel).max(axis=-1) > self._term_extreme_vel_threshold
return (bad | too_low | too_tilted | extreme_vel).astype(bool)
return bad | too_low | too_tilted | extreme_vel
def _init_joint_randomization_config(self, cfg: HumanoidWalkCfg) -> None:
init_cfg = cfg.init_state

View File

@@ -0,0 +1,20 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from . import lqr_np # noqa: F401
from .cfg import Lqr21Cfg, Lqr62Cfg
from .lqr_np import LqrEnv
__all__ = ["Lqr21Cfg", "Lqr62Cfg", "LqrEnv"]

View File

@@ -0,0 +1,73 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import os
from dataclasses import dataclass
from motrix_envs import registry
from motrix_envs.base import EnvCfg
_DIR = os.path.dirname(__file__)
@dataclass
class LqrBaseCfg(EnvCfg):
sim_dt: float = 0.01
ctrl_dt: float = 0.03
max_episode_seconds: float = None
control_cost_coef: float = 0.1
velocity_cost_coef: float = 0.05
reset_position_norm: float = 2.0**0.5
boundary_position_limit: float = 1.2
boundary_velocity_limit: float = 8.0
success_position_tol: float = 0.06
success_velocity_tol: float = 0.05
success_bonus: float = 3.0
out_of_bounds_penalty: float = 2.0
expected_nq: int = 0
expected_nu: int = 0
@registry.envcfg("dm-lqr-2-1")
@dataclass
class Lqr21Cfg(LqrBaseCfg):
model_file: str = os.path.join(_DIR, "lqr_2_1.xml")
reset_position_norm: float = 0.8
control_cost_coef: float = 0.15
velocity_cost_coef: float = 0.15
boundary_position_limit: float = 1.15
boundary_velocity_limit: float = 6.0
success_position_tol: float = 0.04
success_velocity_tol: float = 0.03
success_bonus: float = 4.0
out_of_bounds_penalty: float = 3.0
expected_nq: int = 2
expected_nu: int = 1
@registry.envcfg("dm-lqr-6-2")
@dataclass
class Lqr62Cfg(LqrBaseCfg):
model_file: str = os.path.join(_DIR, "lqr_6_2.xml")
reset_position_norm: float = 1.0
velocity_cost_coef: float = 0.08
boundary_position_limit: float = 1.2
boundary_velocity_limit: float = 8.0
success_position_tol: float = 0.1
success_velocity_tol: float = 0.06
success_bonus: float = 5.0
out_of_bounds_penalty: float = 3.0
expected_nq: int = 6
expected_nu: int = 2

View File

@@ -0,0 +1,70 @@
<mujoco model="dm-lqr-2-1">
<include file="../../common/materials.xml"/>
<compiler angle="radian" inertiafromgeom="true"/>
<option timestep="0.01" integrator="RK4" gravity="0 0 -9.81"/>
<statistic center="0 0 0.12" extent="1.8" />
<default>
<geom type="sphere" size="0.04" density="300" material="self" contype="0" conaffinity="0"/>
<joint type="slide" axis="1 0 0" damping="0.3" limited="true" range="-1.5 1.5"/>
<motor ctrlrange="-1 1" ctrllimited="true" gear="1"/>
</default>
<asset>
<texture name="skybox" type="skybox" builtin="gradient" rgb1="0.4 0.4 0.4" rgb2="0 0 0"
width="512"
height="512" />
<texture name="motphys-ground" type="2d" file="../../common/motphys-ground.png" />
<material name="motphys-ground" texture="motphys-ground" texuniform="true"
texrepeat="0.4 0.4" />
</asset>
<worldbody>
<light name="light" dir="0 1 -1" directional="true" />
<camera name="side" pos="0 -2.8 0" quat="0.707 0.707 0 0" mode="trackcom" />
<camera name="back" pos="-1.2 -1.8 1.1" xyaxes="0.55 -0.84 0 0.28 0.18 0.94" />
<geom name="ground" type="plane" pos="0 0 -0.02" size="0 0 0.01"
material="motphys-ground"
contype="0"
conaffinity="0" />
<geom
name="origin"
type="capsule"
fromto="0 -0.6 0.05 0 0.6 0.05"
size="0.01"
rgba="1 0.8 0.2 1"
contype="0"
conaffinity="0"/>
<body name="m0" pos="0 -0.15 0.1">
<joint name="q0"/>
<geom name="geom_0"/>
</body>
<body name="m1" pos="0 0.15 0.1">
<joint name="q1"/>
<geom name="geom_1"/>
</body>
</worldbody>
<tendon>
<fixed
name="rope_01"
limited="false"
width="0.016"
rgba="0.9 0.82 0.74 1"
stiffness="50"
damping="2"
springlength="0">
<joint joint="q0" coef="-1"/>
<joint joint="q1" coef="1"/>
</fixed>
</tendon>
<actuator>
<motor name="motor_1" joint="q1"/>
</actuator>
</mujoco>

View File

@@ -0,0 +1,100 @@
<mujoco model="dm-lqr-6-2">
<include file="../../common/materials.xml"/>
<compiler angle="radian" inertiafromgeom="true"/>
<option timestep="0.01" integrator="RK4" gravity="0 0 -9.81"/>
<statistic center="0 0 0.12" extent="2.8" />
<default>
<geom type="sphere" size="0.04" density="300" material="self" contype="0" conaffinity="0"/>
<joint type="slide" axis="1 0 0" damping="0.3" limited="true" range="-1.5 1.5"/>
<motor ctrlrange="-1 1" ctrllimited="true" gear="1"/>
</default>
<asset>
<texture name="skybox" type="skybox" builtin="gradient" rgb1="0.4 0.4 0.4" rgb2="0 0 0"
width="512"
height="512" />
<texture name="motphys-ground" type="2d" file="../../common/motphys-ground.png" />
<material name="motphys-ground" texture="motphys-ground" texuniform="true"
texrepeat="0.4 0.4" />
</asset>
<worldbody>
<light name="light" dir="0 1 -1" directional="true" />
<camera name="side" pos="0 -4.2 0" quat="0.707 0.707 0 0" mode="trackcom" />
<camera name="back" pos="-1.0 -2.6 1.4" xyaxes="0.55 -0.84 0 0.24 0.16 0.96" />
<geom name="ground" type="plane" pos="0 0 -0.02" size="0 0 0.01"
material="motphys-ground"
contype="0"
conaffinity="0" />
<geom
name="origin"
type="capsule"
fromto="0 -1.0 0.05 0 1.0 0.05"
size="0.01"
rgba="1 0.8 0.2 1"
contype="0"
conaffinity="0"/>
<body name="m0" pos="0 -0.5 0.1">
<joint name="q0"/>
<geom name="geom_0"/>
</body>
<body name="m1" pos="0 -0.3 0.1">
<joint name="q1"/>
<geom name="geom_1"/>
</body>
<body name="m2" pos="0 -0.1 0.1">
<joint name="q2"/>
<geom name="geom_2"/>
</body>
<body name="m3" pos="0 0.1 0.1">
<joint name="q3"/>
<geom name="geom_3"/>
</body>
<body name="m4" pos="0 0.3 0.1">
<joint name="q4"/>
<geom name="geom_4"/>
</body>
<body name="m5" pos="0 0.5 0.1">
<joint name="q5"/>
<geom name="geom_5"/>
</body>
</worldbody>
<tendon>
<fixed name="rope_01" limited="false" width="0.016" rgba="0.9 0.82 0.74 1" stiffness="50" damping="2" springlength="0">
<joint joint="q0" coef="-1"/>
<joint joint="q1" coef="1"/>
</fixed>
<fixed name="rope_12" stiffness="50" damping="2" springlength="0" width="0.016" rgba="0.9 0.82 0.74 1">
<joint joint="q1" coef="-1"/>
<joint joint="q2" coef="1"/>
</fixed>
<fixed name="rope_23" stiffness="50" damping="2" springlength="0" width="0.016" rgba="0.9 0.82 0.74 1">
<joint joint="q2" coef="-1"/>
<joint joint="q3" coef="1"/>
</fixed>
<fixed name="rope_34" stiffness="50" damping="2" springlength="0" width="0.016" rgba="0.9 0.82 0.74 1">
<joint joint="q3" coef="-1"/>
<joint joint="q4" coef="1"/>
</fixed>
<fixed name="rope_45" stiffness="50" damping="2" springlength="0" width="0.016" rgba="0.9 0.82 0.74 1">
<joint joint="q4" coef="-1"/>
<joint joint="q5" coef="1"/>
</fixed>
</tendon>
<actuator>
<motor name="motor_4" joint="q4"/>
<motor name="motor_5" joint="q5"/>
</actuator>
</mujoco>

View File

@@ -0,0 +1,162 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import gymnasium as gym
import motrixsim as mtx
import numpy as np
from motrixsim.render import Color
from motrix_envs import registry
from motrix_envs.np.env import NpEnv, NpEnvState
from .cfg import LqrBaseCfg
def _normalize_actions(actions: np.ndarray, num_envs: int, num_actuators: int) -> np.ndarray:
actions = np.asarray(actions, dtype=np.float32)
if actions.ndim == 1:
if num_envs != 1 or actions.shape[0] != num_actuators:
raise ValueError(f"Expected action shape ({num_envs}, {num_actuators}) or ({num_actuators},).")
actions = actions.reshape(1, num_actuators)
if actions.shape != (num_envs, num_actuators):
raise ValueError(f"Expected action shape ({num_envs}, {num_actuators}), got {actions.shape}.")
return np.ascontiguousarray(actions)
@registry.env("dm-lqr-2-1", "np")
@registry.env("dm-lqr-6-2", "np")
class LqrEnv(NpEnv):
_cfg: LqrBaseCfg
def __init__(self, cfg: LqrBaseCfg, num_envs: int = 1):
super().__init__(cfg, num_envs=num_envs)
self._nq = int(self._model.num_dof_pos)
self._nv = int(self._model.num_dof_vel)
self._nu = int(self._model.num_actuators)
if self._nq != cfg.expected_nq or self._nv != cfg.expected_nq:
raise ValueError(f"LQR model mismatch: expected nq=nv={cfg.expected_nq}, got nq={self._nq}, nv={self._nv}.")
if self._nu != cfg.expected_nu:
raise ValueError(f"LQR model mismatch: expected nu={cfg.expected_nu}, got nu={self._nu}.")
obs_dim = self._nq + self._nv
self._action_low = np.asarray(self._model.actuator_ctrl_limits[0], dtype=np.float32)
self._action_high = np.asarray(self._model.actuator_ctrl_limits[1], dtype=np.float32)
self._observation_space = gym.spaces.Box(-np.inf, np.inf, (obs_dim,), dtype=np.float32)
self._action_space = gym.spaces.Box(self._action_low, self._action_high, (self._nu,), dtype=np.float32)
self._rope_geom_pairs = [
(self._model.get_geom(f"geom_{i}"), self._model.get_geom(f"geom_{i + 1}")) for i in range(self._nq - 1)
]
self._rope_color = Color.rgb(0.85, 0.75, 0.65)
@property
def observation_space(self):
return self._observation_space
@property
def action_space(self):
return self._action_space
def apply_action(self, actions: np.ndarray, state: NpEnvState) -> NpEnvState:
actions = _normalize_actions(actions, self._num_envs, self._nu)
state.data.actuator_ctrls = np.clip(actions, self._action_low, self._action_high)
return state
def _get_obs(self, data: mtx.SceneData) -> np.ndarray:
qpos = np.asarray(data.dof_pos, dtype=np.float32)
qvel = np.asarray(data.dof_vel, dtype=np.float32)
return np.concatenate([qpos, qvel], axis=-1)
def draw_gizmos(self, gizmos, render_offsets: np.ndarray) -> None:
if self.state is None:
return
offsets = np.asarray(render_offsets, dtype=np.float32)
data = self.state.data
gizmos.line_width = 6.0
for geom_a, geom_b in self._rope_geom_pairs:
start = np.asarray(geom_a.get_pose(data), dtype=np.float32)[..., :3]
end = np.asarray(geom_b.get_pose(data), dtype=np.float32)[..., :3]
for env_i in range(self._num_envs):
gizmos.draw_line(
start[env_i] + offsets[env_i],
end[env_i] + offsets[env_i],
color=self._rope_color,
)
def update_state(self, state: NpEnvState) -> NpEnvState:
data = state.data
qpos = np.asarray(data.dof_pos, dtype=np.float32)
qvel = np.asarray(data.dof_vel, dtype=np.float32)
ctrl = np.asarray(data.actuator_ctrls, dtype=np.float32)
obs = self._get_obs(data)
out_of_bounds = np.any(np.abs(qpos) > self._cfg.boundary_position_limit, axis=-1)
out_of_bounds |= np.any(np.abs(qvel) > self._cfg.boundary_velocity_limit, axis=-1)
position_norm = np.linalg.norm(qpos, axis=-1)
velocity_norm = np.linalg.norm(qvel, axis=-1)
state_cost = 0.5 * np.sum(np.square(qpos), axis=-1)
velocity_cost = 0.5 * self._cfg.velocity_cost_coef * np.sum(np.square(qvel), axis=-1)
control_cost = 0.5 * self._cfg.control_cost_coef * np.sum(np.square(ctrl), axis=-1)
success = (position_norm <= self._cfg.success_position_tol) & (velocity_norm <= self._cfg.success_velocity_tol)
success &= ~out_of_bounds
success_reward = self._cfg.success_bonus * success.astype(np.float32)
boundary_penalty = self._cfg.out_of_bounds_penalty * out_of_bounds.astype(np.float32)
reward = 1.0 - (state_cost + velocity_cost + control_cost) + success_reward - boundary_penalty
terminated = success | out_of_bounds
terminated |= np.isnan(obs).any(axis=-1)
terminated |= np.isnan(ctrl).any(axis=-1)
state.info["metrics"] = {
"position_norm": position_norm.astype(np.float32),
"velocity_norm": velocity_norm.astype(np.float32),
"success": success.astype(np.float32),
"out_of_bounds": out_of_bounds.astype(np.float32),
}
state.info["Reward"] = {
"state_cost": (-state_cost).astype(np.float32),
"velocity_cost": (-velocity_cost).astype(np.float32),
"control_cost": (-control_cost).astype(np.float32),
"success_bonus": success_reward.astype(np.float32),
"out_of_bounds_penalty": (-boundary_penalty).astype(np.float32),
}
return state.replace(
obs=obs,
reward=reward.astype(np.float32),
terminated=terminated,
)
def reset(self, data: mtx.SceneData) -> tuple[np.ndarray, dict]:
data.reset(self._model)
num_envs = int(data.shape[0])
qpos = np.random.standard_normal((num_envs, self._nq)).astype(np.float32)
norms = np.linalg.norm(qpos, axis=-1, keepdims=True)
zero_norm = norms[:, 0] < 1e-8
if np.any(zero_norm):
qpos[zero_norm, 0] = 1.0
norms = np.linalg.norm(qpos, axis=-1, keepdims=True)
qpos *= self._cfg.reset_position_norm / np.clip(norms, 1e-8, None)
qvel = np.zeros((num_envs, self._nv), dtype=np.float32)
data.set_dof_pos(qpos, self._model)
data.set_dof_vel(qvel)
self._model.forward_kinematic(data)
return np.concatenate([qpos, qvel], axis=-1), {}

View File

@@ -28,7 +28,7 @@ class BringBallCfg(EnvCfg):
# Simulation
model_file: str = bring_ball_model_file
max_episode_seconds: float = 10.0
sim_dt: float = 0.001
sim_dt: float = 0.01
ctrl_dt: float = 0.01
render_spacing: float = 2.5

View File

@@ -24,6 +24,7 @@ from motrix_envs.base import EnvCfg
model_file = os.path.dirname(__file__) + "/pendulum.xml"
# -- docs-tag-start: pendulum-env-cfg --
@registry.envcfg("pendulum")
@dataclass
class PendulumEnvCfg(EnvCfg):
@@ -34,6 +35,7 @@ class PendulumEnvCfg(EnvCfg):
angle_bound: float = 8.0
cosing_bound: float = 0.0
# reset_noise_scale: float = 0.01
# -- docs-tag-end: pendulum-env-cfg --
def __post_init__(self):
self.cosing_bound = float(np.cos(np.deg2rad(self.angle_bound)))

View File

@@ -0,0 +1,16 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from . import point_mass_np # noqa: F401

View File

@@ -0,0 +1,32 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import os
from dataclasses import dataclass
from motrix_envs import registry
from motrix_envs.base import EnvCfg
model_file = os.path.dirname(__file__) + "/point_mass.xml"
@registry.envcfg("point_mass")
@dataclass
class PointMassEnvCfg(EnvCfg):
model_file: str = model_file
reset_noise_scale: float = 0.01
max_episode_seconds: float = 10
render_spacing: float = 2.0
target_radius: float = 0.1

View File

@@ -0,0 +1,43 @@
<mujoco model="point_mass">
<compiler inertiafromgeom="true" />
<option gravity="0 0 0" timestep="0.01" />
<default>
<joint armature="0" damping="0.1" />
<geom contype="0" conaffinity="0" friction="1 0.1 0.1" />
<motor ctrlrange="-1 1" gear="10" />
</default>
<asset>
<texture name="skybox" type="skybox" builtin="gradient" rgb1="0.4 0.4 0.4" rgb2="0 0 0"
width="512"
height="512" />
<texture name="motphys-ground" type="2d" file="../../common/motphys-ground.png" />
<material name="motphys-ground" texture="motphys-ground" texuniform="true"
texrepeat="0.4 0.4" />
</asset>
<worldbody>
<light pos="0 0 1.5" dir="0 0 -1" directional="true" />
<geom name="floor" size="0 0 0.01" type="plane" material="motphys-ground" pos="0 0 0" />
</worldbody>
<worldbody>
<!-- Point mass -->
<body name="point_mass" pos="0 0 0.1">
<joint name="point_mass_x" type="slide" axis="1 0 0" />
<joint name="point_mass_y" type="slide" axis="0 1 0" />
<geom name="mass" type="sphere" size="0.05" rgba="0.5 0.5 1 1" mass="1" />
</body>
<!-- Target -->
<body name="target" pos="0 0 0.1" mocap="true">
<joint name="target_x" type="slide" axis="1 0 0" />
<joint name="target_y" type="slide" axis="0 1 0" />
<geom name="target_geom" type="sphere" size="0.1" rgba="1 0 0 0.8" contype="0" conaffinity="0" />
</body>
</worldbody>
<actuator>
<motor name="x_force" joint="point_mass_x" />
<motor name="y_force" joint="point_mass_y" />
</actuator>
</mujoco>

View File

@@ -0,0 +1,174 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import gymnasium as gym
import motrixsim as mtx
import numpy as np
from motrix_envs import registry
from motrix_envs.np.env import NpEnv, NpEnvState
from .cfg import PointMassEnvCfg
@registry.env("point_mass", "np")
class PointMassEnv(NpEnv):
_cfg: PointMassEnvCfg
def __init__(self, cfg: PointMassEnvCfg, num_envs: int = 1):
super().__init__(cfg, num_envs=num_envs)
self._action_space = gym.spaces.Box(-1.0, 1.0, (2,), dtype=np.float32)
self._observation_space = gym.spaces.Box(-np.inf, np.inf, (9,), dtype=np.float32)
self._num_dof_pos = self._model.num_dof_pos
self._num_dof_vel = self._model.num_dof_vel
self._point_mass = self._model.get_body("point_mass")
self._target = self._model.get_body("target")
self._target_radius = cfg.target_radius
# Target stay counter, used to control reset after 0.5 seconds of overlap
self._in_target_steps = np.zeros(self._num_envs, dtype=np.int32)
self._required_in_target_steps = int(0.5 / cfg.ctrl_dt)
@property
def observation_space(self):
return self._observation_space
@property
def action_space(self):
return self._action_space
def apply_action(self, actions: np.ndarray, state: NpEnvState):
actions = np.clip(actions, -1.0, 1.0)
state.data.actuator_ctrls = actions
return state
def _get_obs(self, data: mtx.SceneData) -> np.ndarray:
dof_pos = data.dof_pos[:, :2] # Only x and y positions
dof_vel = data.dof_vel[:, :2] # Only x and y velocities
# Get target position
target_pos = self._target.get_pose(data)[:, :2]
# Calculate distance and direction to target
delta = target_pos - dof_pos
distance = np.linalg.norm(delta, axis=-1, keepdims=True)
obs = np.concatenate([dof_pos, dof_vel, target_pos, delta, distance], axis=-1)
return obs
def update_state(self, state: NpEnvState) -> NpEnvState:
data = state.data
obs = self._get_obs(data)
# Get positions of point mass and target
point_pos = self._point_mass.get_pose(data)[:, :2]
target_pos = self._target.get_pose(data)[:, :2]
dist_to_target = np.linalg.norm(point_pos - target_pos, axis=-1)
# Calculate effective target radius for complete overlap
# Blue ball radius is 0.05, red ball radius is 0.1
# For complete overlap, center distance should be very small
effective_target_radius = 0.02 # Smaller radius for complete overlap
# Fine-grained distance reward - exponential function, reward grows faster as distance decreases
distance_reward = np.exp(-10 * dist_to_target) # Stronger exponential reward
# Large bonus for complete target entry
in_target = dist_to_target < effective_target_radius
target_bonus = 100.0 * in_target # Significantly increased reward
# Continuous stay reward
continuous_reward = 30.0 * in_target # Increased continuous reward
# Penalty for distance from target center - encourages complete overlap
# When inside target, penalty increases with distance from center
center_penalty = np.where(in_target, 10.0 * dist_to_target, 0.0)
# Control penalty - increased penalty to encourage smoother movement
dof_vel = data.dof_vel[:, :2]
vel_magnitude = np.linalg.norm(dof_vel, axis=-1)
control_penalty = 0.1 * vel_magnitude # Increased penalty to reduce excessive movement
# Path optimization reward - encourages straight-line movement
# Calculate alignment between velocity direction and target direction
if dist_to_target.max() > 0:
delta = target_pos - point_pos
delta_norm = np.linalg.norm(delta, axis=-1, keepdims=True)
delta_normalized = delta / delta_norm
vel_normalized = dof_vel / (np.linalg.norm(dof_vel, axis=-1, keepdims=True) + 1e-6)
direction_alignment = np.sum(delta_normalized * vel_normalized, axis=-1)
path_reward = 0.5 * direction_alignment
else:
path_reward = 0.0
# Total reward
rwd = distance_reward + target_bonus + continuous_reward + path_reward - center_penalty - control_penalty
# Update target stay steps
self._in_target_steps = np.where(in_target, self._in_target_steps + 1, 0)
# Check if stayed in target long enough
in_target_long_enough = self._in_target_steps >= self._required_in_target_steps
# Check termination conditions - terminate when reaching target for 0.5 seconds or when NaN encountered
terminated = np.zeros((self._num_envs,), dtype=bool)
terminated = np.logical_or(in_target_long_enough, terminated)
terminated = np.logical_or(np.isnan(obs).any(axis=-1), terminated)
state.obs = obs
state.reward = rwd
state.terminated = terminated
return state
def reset(self, data: mtx.SceneData) -> tuple[np.ndarray, dict]:
data.reset(self._model)
num_reset = data.shape[0]
# Get the actual number of DOF from the model
num_dof_pos = self._model.num_dof_pos
num_dof_vel = self._model.num_dof_vel
# Random initial position within a range for the point mass (only x, y)
x_pos = np.random.uniform(-1.0, 1.0, size=num_reset).astype(np.float32)
y_pos = np.random.uniform(-1.0, 1.0, size=num_reset).astype(np.float32)
# Create dof_pos with the correct length (point mass x, y and target x, y)
dof_pos = np.zeros((num_reset, num_dof_pos), dtype=np.float32)
dof_pos[:, 0] = x_pos # point_mass_x
dof_pos[:, 1] = y_pos # point_mass_y
dof_vel = np.zeros((num_reset, num_dof_vel), dtype=np.float32)
data.set_dof_vel(dof_vel)
data.set_dof_pos(dof_pos, self._model)
# Randomize target position using its slide joints
target_x = np.random.uniform(-1.5, 1.5, size=num_reset).astype(np.float32)
target_y = np.random.uniform(-1.5, 1.5, size=num_reset).astype(np.float32)
# Set target position via its slide joints (indices 2 and 3)
dof_pos[:, 2] = target_x # target_x
dof_pos[:, 3] = target_y # target_y
data.set_dof_pos(dof_pos, self._model)
self._model.forward_kinematic(data)
# Reset target stay counter for the environments being reset
self._in_target_steps[:num_reset] = 0
obs = self._get_obs(data)
return obs, {}

View File

@@ -0,0 +1,23 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from . import quadruped_np # noqa: F401
from .cfg import ( # noqa: F401
QuadrupedBaseCfg,
QuadrupedEscapeCfg,
QuadrupedFetchCfg,
QuadrupedRunCfg,
QuadrupedWalkCfg,
)

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:775bf911a0d5ce8703f1a1f766da870a1dd717a3b9366c118bad91474bbeebf0
size 13996

View File

@@ -0,0 +1,149 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import os
from dataclasses import dataclass
from motrix_envs import registry
from motrix_envs.base import EnvCfg
_DIR = os.path.dirname(__file__)
_WALK_MODEL = os.path.join(_DIR, "quadruped_walk.xml")
_ESCAPE_MODEL = os.path.join(_DIR, "quadruped_escape.xml")
_FETCH_MODEL = os.path.join(_DIR, "quadruped_fetch.xml")
@dataclass
class QuadrupedBaseCfg(EnvCfg):
model_file: str = _WALK_MODEL
max_episode_seconds: float = 20.0
sim_dt: float = 0.01
ctrl_dt: float = 0.01
render_spacing: float = 2.0
# Task parameters
desired_speed: float = 0.0
deviation_angle: float = 0.0
fix_heading: bool = False
clip_env_actions: bool = True
# Observation toggles
include_origin: bool = False
include_rangefinder: bool = False
include_ball: bool = False
include_target: bool = False
# Task geometry (fallbacks when sites/geom metadata are unavailable)
target_radius: float = 0.7
terrain_size: float = 30.0
# Gait shaping (walk/run)
stand_height: float = 0.55
stand_height_margin: float = 0.25
height_reward_weight: float = 0.1
lateral_velocity_limit: float = 0.2
lateral_velocity_margin: float = 0.5
lateral_reward_weight: float = 0.05
heading_reward_margin: float = 1.0
heading_reward_weight: float = 0.0
action_smoothness_margin: float = 5.0
action_smoothness_weight: float = 0.08
lin_vel_z_weight: float = 0.05
ang_vel_xy_weight: float = 0.02
similar_to_default_weight: float = 0.025
# Forward motion shaping (walk/run)
backward_penalty_weight: float = 0.2
# Radial motion shaping (escape)
radial_velocity_weight: float = 0.2
# Fetch shaping
fetch_reward_margin: float = 10.0
fetch_reward_weight: float = 1.0
fetch_behind_distance: float = 0.7
fetch_ahead_distance: float = 0.2
fetch_side_stage_offset: float = 0.6
fetch_side_stage_ball_distance: float = 1.0
fetch_side_stage_gate_threshold: float = 0.5
fetch_side_stage_align_threshold: float = 0.8
fetch_stage_radius: float = 0.5
fetch_stage_speed: float = 0.5
fetch_stage_reward_weight: float = 0.5
fetch_corridor_width: float = 0.3
fetch_behind_align_margin: float = 1.0
fetch_heading_margin: float = 1.0
fetch_heading_weight: float = 0.2
fetch_ready_ball_distance: float = 0.5
fetch_ready_weight: float = 0.3
fetch_ready_threshold: float = 0.7
fetch_push_speed: float = 0.2
fetch_push_reward_weight: float = 0.3
fetch_backward_penalty_weight: float = 0.2
fetch_away_penalty_weight: float = 0.4
fetch_leg_ball_penalty_weight: float = 0.1
fetch_leg_ball_penalty_margin = 0.03
fetch_stability_upright_min: float = 0.8
fetch_stability_upright_margin: float = 0.5
fetch_stability_height_min: float = 0.45
fetch_stability_height_margin: float = 0.2
fetch_fall_upright_min: float = 0.2
fetch_fall_height_min: float = 0.25
@registry.envcfg("dm-quadruped-walk")
@dataclass
class QuadrupedWalkCfg(QuadrupedBaseCfg):
model_file: str = _WALK_MODEL
desired_speed: float = 0.5
fix_heading: bool = True
heading_reward_weight: float = 0.2
@registry.envcfg("dm-quadruped-run")
@dataclass
class QuadrupedRunCfg(QuadrupedBaseCfg):
model_file: str = _WALK_MODEL
desired_speed: float = 5.0
fix_heading: bool = True
heading_reward_weight: float = 0.2
@registry.envcfg("dm-quadruped-escape")
@dataclass
class QuadrupedEscapeCfg(QuadrupedBaseCfg):
model_file: str = _ESCAPE_MODEL
render_camera_name: str = "global"
desired_speed: float = 3.0
include_origin: bool = True
include_rangefinder: bool = False
deviation_angle: float = 20.0
fix_heading: bool = True
heading_reward_weight: float = 0.2
radial_velocity_weight: float = 0.5
similar_to_default_weight: float = 0.01
@registry.envcfg("dm-quadruped-fetch")
@dataclass
class QuadrupedFetchCfg(QuadrupedBaseCfg):
model_file: str = _FETCH_MODEL
desired_speed: float = 2.0
include_ball: bool = True
include_target: bool = True

View File

@@ -0,0 +1,327 @@
<mujoco model="quadruped">
<include file="../../common/skybox.xml"/>
<include file="../../common/visual.xml"/>
<include file="./quadruped_materials.xml"/>
<visual>
<rgba rangefinder="1 1 0.1 0.1"/>
<map znear=".005" zfar="20"/>
</visual>
<asset>
<hfield name="terrain" ncol="201" nrow="201" size="30 30 5 .1"/>
</asset>
<option timestep=".005"/>
<default>
<geom solimp=".9 .99 .003" solref=".01 1"/>
<default class="body">
<geom type="capsule" size=".08" condim="1" material="self" density="500"/>
<joint type="hinge" damping="30" armature=".01"
limited="true" solimplimit="0 .99 .01"/>
<default class="hip">
<default class="yaw">
<joint axis="0 0 1" range="-50 50"/>
</default>
<default class="pitch">
<joint axis="0 1 0" range="-20 60"/>
</default>
<geom fromto="0 0 0 .3 0 .11"/>
</default>
<default class="knee">
<joint axis="0 1 0" range="-60 50"/>
<geom size=".065" fromto="0 0 0 .25 0 -.25"/>
</default>
<default class="ankle">
<joint axis="0 1 0" range="-45 55"/>
<geom size=".055" fromto="0 0 0 0 0 -.25"/>
</default>
<default class="toe">
<geom type="sphere" size=".08" material="effector" friction="1.5"/>
<site type="sphere" size=".084" material="site" group="4"/>
</default>
</default>
<default class="rangefinder">
<site type="capsule" size=".005 .1" material="site" group="4"/>
</default>
<default class="wall">
<geom type="plane" material="decoration"/>
</default>
<default class="coupling">
<equality solimp="0.95 0.99 0.01" solref=".005 .5"/>
</default>
<general ctrllimited="true" gainprm="1000" biasprm="0 -1000" biastype="affine" dyntype="filter" dynprm=".1"/>
<default class="yaw_act">
<general ctrlrange="-1 1"/>
</default>
<default class="lift_act">
<general ctrlrange="-1 1.1"/>
</default>
<default class="extend_act">
<general ctrlrange="-.8 .8"/>
</default>
</default>
<asset>
<texture name="ball" builtin="checker" mark="cross" width="151" height="151"
rgb1="0.1 0.1 0.1" rgb2="0.9 0.9 0.9" markrgb="1 1 1"/>
<material name="ball" texture="ball" />
</asset>
<worldbody>
<geom name="floor" type="plane" size="0 0 0.01" material="motphys-ground"/>
<light pos="0 0 1.5" dir="0 0 -1" directional="true"/>
<geom name="wall_px" class="wall" pos="-15.7 0 .7" zaxis="1 0 1" size="1 15 .5"/>
<geom name="wall_py" class="wall" pos="0 -15.7 .7" zaxis="0 1 1" size="15 1 .5"/>
<geom name="wall_nx" class="wall" pos="15.7 0 .7" zaxis="-1 0 1" size="1 15 .5"/>
<geom name="wall_ny" class="wall" pos="0 15.7 .7" zaxis="0 -1 1" size="15 1 .5"/>
<site name="target" type="cylinder" size=".4 .06" pos="0 0 .05" material="target"/>
<geom name="terrain" type="hfield" hfield="terrain" rgba=".2 .3 .4 1" pos="0 0 -.01"/>
<camera name="global" pos="-10 10 10" xyaxes="-1 -1 0 1 0 1" mode="trackcom"/>
<body name="torso" childclass="body" pos="0 0 .57">
<freejoint name="root"/>
<camera name="x" pos="-1.7 0 1" xyaxes="0 -1 0 .75 0 1" mode="trackcom"/>
<camera name="y" pos="0 4 2" xyaxes="-1 0 0 0 -.5 1" mode="trackcom"/>
<camera name="egocentric" pos=".3 0 .11" xyaxes="0 -1 0 .4 0 1" fovy="60"/>
<geom name="eye_r" type="cylinder" size=".05" fromto=".1 -.07 .12 .31 -.07 .08" mass="0"/>
<site name="pupil_r" type="sphere" size=".033" pos=".3 -.07 .08" zaxis="1 0 0" material="eye"/>
<geom name="eye_l" type="cylinder" size=".05" fromto=".1 .07 .12 .31 .07 .08" mass="0"/>
<site name="pupil_l" type="sphere" size=".033" pos=".3 .07 .08" zaxis="1 0 0" material="eye"/>
<site name="workspace" type="sphere" size=".3 .3 .3" material="site" pos=".8 0 -.2" group="3"/>
<site name="rf_00" class="rangefinder" fromto=".41 -.02 .11 .34 0 .115"/>
<site name="rf_01" class="rangefinder" fromto=".41 -.01 .11 .34 0 .115"/>
<site name="rf_02" class="rangefinder" fromto=".41 0 .11 .34 0 .115"/>
<site name="rf_03" class="rangefinder" fromto=".41 .01 .11 .34 0 .115"/>
<site name="rf_04" class="rangefinder" fromto=".41 .02 .11 .34 0 .115"/>
<site name="rf_10" class="rangefinder" fromto=".41 -.02 .1 .36 0 .11"/>
<site name="rf_11" class="rangefinder" fromto=".41 -.02 .1 .36 0 .11"/>
<site name="rf_12" class="rangefinder" fromto=".41 0 .1 .36 0 .11"/>
<site name="rf_13" class="rangefinder" fromto=".41 .01 .1 .36 0 .11"/>
<site name="rf_14" class="rangefinder" fromto=".41 .02 .1 .36 0 .11"/>
<site name="rf_20" class="rangefinder" fromto=".41 -.02 .09 .38 0 .105"/>
<site name="rf_21" class="rangefinder" fromto=".41 -.01 .09 .38 0 .105"/>
<site name="rf_22" class="rangefinder" fromto=".41 0 .09 .38 0 .105"/>
<site name="rf_23" class="rangefinder" fromto=".41 .01 .09 .38 0 .105"/>
<site name="rf_24" class="rangefinder" fromto=".41 .02 .09 .38 0 .105"/>
<site name="rf_30" class="rangefinder" fromto=".41 -.02 .08 .4 0 .1"/>
<site name="rf_31" class="rangefinder" fromto=".41 -.01 .08 .4 0 .1"/>
<site name="rf_32" class="rangefinder" fromto=".41 0 .08 .4 0 .1"/>
<site name="rf_33" class="rangefinder" fromto=".41 .01 .08 .4 0 .1"/>
<site name="rf_34" class="rangefinder" fromto=".41 .02 .08 .4 0 .1"/>
<geom name="torso" type="ellipsoid" size=".3 .27 .2" density="1000"/>
<site name="torso_touch" type="box" size=".26 .26 .26" rgba="0 0 1 0"/>
<site name="torso" size=".05" rgba="1 0 0 1" />
<body name="hip_front_left" pos=".2 .2 0" euler="0 0 45" childclass="hip">
<joint name="yaw_front_left" class="yaw"/>
<joint name="pitch_front_left" class="pitch"/>
<geom name="thigh_front_left"/>
<body name="knee_front_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_left"/>
<geom name="shin_front_left"/>
<body name="ankle_front_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_left"/>
<geom name="foot_front_left"/>
<body name="toe_front_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_left"/>
<site name="toe_front_left"/>
</body>
</body>
</body>
</body>
<body name="hip_front_right" pos=".2 -.2 0" euler="0 0 -45" childclass="hip">
<joint name="yaw_front_right" class="yaw"/>
<joint name="pitch_front_right" class="pitch"/>
<geom name="thigh_front_right"/>
<body name="knee_front_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_right"/>
<geom name="shin_front_right"/>
<body name="ankle_front_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_right"/>
<geom name="foot_front_right"/>
<body name="toe_front_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_right"/>
<site name="toe_front_right"/>
</body>
</body>
</body>
</body>
<body name="hip_back_right" pos="-.2 -.2 0" euler="0 0 -135" childclass="hip">
<joint name="yaw_back_right" class="yaw"/>
<joint name="pitch_back_right" class="pitch"/>
<geom name="thigh_back_right"/>
<body name="knee_back_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_right"/>
<geom name="shin_back_right"/>
<body name="ankle_back_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_right"/>
<geom name="foot_back_right"/>
<body name="toe_back_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_right"/>
<site name="toe_back_right"/>
</body>
</body>
</body>
</body>
<body name="hip_back_left" pos="-.2 .2 0" euler="0 0 135" childclass="hip">
<joint name="yaw_back_left" class="yaw"/>
<joint name="pitch_back_left" class="pitch"/>
<geom name="thigh_back_left"/>
<body name="knee_back_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_left"/>
<geom name="shin_back_left"/>
<body name="ankle_back_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_left"/>
<geom name="foot_back_left"/>
<body name="toe_back_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_left"/>
<site name="toe_back_left"/>
</body>
</body>
</body>
</body>
</body>
<body name="ball" pos="0 0 3">
<freejoint name="ball_root"/>
<geom name="ball" size=".15" material="ball" priority="1" condim="6" friction=".7 .005 .005"
solref="-10000 -30"/>
</body>
</worldbody>
<tendon>
<fixed name="coupling_front_left">
<joint joint="pitch_front_left" coef=".333"/>
<joint joint="knee_front_left" coef=".333"/>
<joint joint="ankle_front_left" coef=".333"/>
</fixed>
<fixed name="coupling_front_right">
<joint joint="pitch_front_right" coef=".333"/>
<joint joint="knee_front_right" coef=".333"/>
<joint joint="ankle_front_right" coef=".333"/>
</fixed>
<fixed name="coupling_back_right">
<joint joint="pitch_back_right" coef=".333"/>
<joint joint="knee_back_right" coef=".333"/>
<joint joint="ankle_back_right" coef=".333"/>
</fixed>
<fixed name="coupling_back_left">
<joint joint="pitch_back_left" coef=".333"/>
<joint joint="knee_back_left" coef=".333"/>
<joint joint="ankle_back_left" coef=".333"/>
</fixed>
<fixed name="extend_front_left">
<joint joint="pitch_front_left" coef=".25"/>
<joint joint="knee_front_left" coef="-.5"/>
<joint joint="ankle_front_left" coef=".25"/>
</fixed>
<fixed name="lift_front_left">
<joint joint="pitch_front_left" coef=".5"/>
<joint joint="ankle_front_left" coef="-.5"/>
</fixed>
<fixed name="extend_front_right">
<joint joint="pitch_front_right" coef=".25"/>
<joint joint="knee_front_right" coef="-.5"/>
<joint joint="ankle_front_right" coef=".25"/>
</fixed>
<fixed name="lift_front_right">
<joint joint="pitch_front_right" coef=".5"/>
<joint joint="ankle_front_right" coef="-.5"/>
</fixed>
<fixed name="extend_back_right">
<joint joint="pitch_back_right" coef=".25"/>
<joint joint="knee_back_right" coef="-.5"/>
<joint joint="ankle_back_right" coef=".25"/>
</fixed>
<fixed name="lift_back_right">
<joint joint="pitch_back_right" coef=".5"/>
<joint joint="ankle_back_right" coef="-.5"/>
</fixed>
<fixed name="extend_back_left">
<joint joint="pitch_back_left" coef=".25"/>
<joint joint="knee_back_left" coef="-.5"/>
<joint joint="ankle_back_left" coef=".25"/>
</fixed>
<fixed name="lift_back_left">
<joint joint="pitch_back_left" coef=".5"/>
<joint joint="ankle_back_left" coef="-.5"/>
</fixed>
</tendon>
<equality>
<tendon name="coupling_front_left" tendon1="coupling_front_left" class="coupling"/>
<tendon name="coupling_front_right" tendon1="coupling_front_right" class="coupling"/>
<tendon name="coupling_back_right" tendon1="coupling_back_right" class="coupling"/>
<tendon name="coupling_back_left" tendon1="coupling_back_left" class="coupling"/>
</equality>
<actuator>
<general name="yaw_front_left" class="yaw_act" joint="yaw_front_left"/>
<general name="lift_front_left" class="lift_act" tendon="lift_front_left"/>
<general name="extend_front_left" class="extend_act" tendon="extend_front_left"/>
<general name="yaw_front_right" class="yaw_act" joint="yaw_front_right"/>
<general name="lift_front_right" class="lift_act" tendon="lift_front_right"/>
<general name="extend_front_right" class="extend_act" tendon="extend_front_right"/>
<general name="yaw_back_right" class="yaw_act" joint="yaw_back_right"/>
<general name="lift_back_right" class="lift_act" tendon="lift_back_right"/>
<general name="extend_back_right" class="extend_act" tendon="extend_back_right"/>
<general name="yaw_back_left" class="yaw_act" joint="yaw_back_left"/>
<general name="lift_back_left" class="lift_act" tendon="lift_back_left"/>
<general name="extend_back_left" class="extend_act" tendon="extend_back_left"/>
</actuator>
<sensor>
<accelerometer name="imu_accel" site="torso"/>
<gyro name="imu_gyro" site="torso"/>
<velocimeter name="velocimeter" site="torso"/>
<force name="force_toe_front_left" site="toe_front_left"/>
<force name="force_toe_front_right" site="toe_front_right"/>
<force name="force_toe_back_right" site="toe_back_right"/>
<force name="force_toe_back_left" site="toe_back_left"/>
<torque name="torque_toe_front_left" site="toe_front_left"/>
<torque name="torque_toe_front_right" site="toe_front_right"/>
<torque name="torque_toe_back_right" site="toe_back_right"/>
<torque name="torque_toe_back_left" site="toe_back_left"/>
<subtreecom name="center_of_mass" body="torso"/>
<rangefinder name="rf_00" site="rf_00"/>
<rangefinder name="rf_01" site="rf_01"/>
<rangefinder name="rf_02" site="rf_02"/>
<rangefinder name="rf_03" site="rf_03"/>
<rangefinder name="rf_04" site="rf_04"/>
<rangefinder name="rf_10" site="rf_10"/>
<rangefinder name="rf_11" site="rf_11"/>
<rangefinder name="rf_12" site="rf_12"/>
<rangefinder name="rf_13" site="rf_13"/>
<rangefinder name="rf_14" site="rf_14"/>
<rangefinder name="rf_20" site="rf_20"/>
<rangefinder name="rf_21" site="rf_21"/>
<rangefinder name="rf_22" site="rf_22"/>
<rangefinder name="rf_23" site="rf_23"/>
<rangefinder name="rf_24" site="rf_24"/>
<rangefinder name="rf_30" site="rf_30"/>
<rangefinder name="rf_31" site="rf_31"/>
<rangefinder name="rf_32" site="rf_32"/>
<rangefinder name="rf_33" site="rf_33"/>
<rangefinder name="rf_34" site="rf_34"/>
</sensor>
</mujoco>

View File

@@ -0,0 +1,272 @@
<mujoco model="quadruped">
<include file="../../common/skybox.xml" />
<include file="../../common/visual.xml" />
<include file="./quadruped_materials.xml" />
<visual>
<rgba rangefinder="1 1 0.1 0.1" />
<map znear=".005" zfar="20" />
</visual>
<asset>
<hfield name="terrain" ncol="201" nrow="201" size="30 30 4.0 .1" file="assets/quadruped_escape_heightfield.png" />
</asset>
<option timestep=".005" />
<default>
<geom solimp=".9 .99 .003" solref=".01 1" />
<default class="body">
<geom type="capsule" size=".08" condim="1" material="self" density="500" />
<joint type="hinge" damping="30" armature=".01" limited="true" solimplimit="0 .99 .01" />
<default class="hip">
<default class="yaw">
<joint axis="0 0 1" range="-50 50" />
</default>
<default class="pitch">
<joint axis="0 1 0" range="-20 60" />
</default>
<geom fromto="0 0 0 .3 0 .11" />
</default>
<default class="knee">
<joint axis="0 1 0" range="-60 50" />
<geom size=".065" fromto="0 0 0 .25 0 -.25" />
</default>
<default class="ankle">
<joint axis="0 1 0" range="-45 55" />
<geom size=".055" fromto="0 0 0 0 0 -.25" />
</default>
<default class="toe">
<geom type="sphere" size=".08" material="effector" friction="2.0" />
<site type="sphere" size=".084" material="site" group="4" />
</default>
</default>
<default class="rangefinder">
<site type="capsule" size=".005 .1" material="site" group="4" />
</default>
<default class="wall">
<geom type="plane" material="decoration" />
</default>
<default class="coupling">
<equality solimp="0.95 0.99 0.01" solref=".005 .5" />
</default>
<general ctrllimited="true" gainprm="1500" biasprm="0 -1500" biastype="affine" dyntype="filter" dynprm=".1" />
<default class="yaw_act">
<general ctrlrange="-1 1" />
</default>
<default class="lift_act">
<general ctrlrange="-1 1.1" />
</default>
<default class="extend_act">
<general ctrlrange="-.8 .8" />
</default>
</default>
<asset>
<texture name="ball" builtin="checker" mark="cross" width="151" height="151" rgb1="0.1 0.1 0.1" rgb2="0.9 0.9 0.9" markrgb="1 1 1" />
<material name="ball" texture="ball" />
</asset>
<worldbody>
<geom name="floor" type="plane" size="0 0 0.01" material="motphys-ground" />
<geom name="terrain" type="hfield" hfield="terrain" rgba=".2 .3 .4 1" pos="0 0 -.0" />
<light pos="0 0 1.5" dir="0 0 -1" directional="true" />
<camera name="global" pos="-10 10 10" xyaxes="-1 -1 0 1 0 1" mode="trackcom" />
<body name="torso" childclass="body" pos="0 0 .57">
<freejoint name="root" />
<camera name="x" pos="-1.7 0 1" xyaxes="0 -1 0 .75 0 1" mode="trackcom" />
<camera name="y" pos="0 4 2" xyaxes="-1 0 0 0 -.5 1" mode="trackcom" />
<camera name="egocentric" pos=".3 0 .11" xyaxes="0 -1 0 .4 0 1" fovy="60" />
<geom name="eye_r" type="cylinder" size=".05" fromto=".1 -.07 .12 .31 -.07 .08" mass="0" />
<site name="pupil_r" type="sphere" size=".033" pos=".3 -.07 .08" zaxis="1 0 0" material="eye" />
<geom name="eye_l" type="cylinder" size=".05" fromto=".1 .07 .12 .31 .07 .08" mass="0" />
<site name="pupil_l" type="sphere" size=".033" pos=".3 .07 .08" zaxis="1 0 0" material="eye" />
<site name="workspace" type="sphere" size=".3 .3 .3" material="site" pos=".8 0 -.2" group="3" />
<geom name="torso" type="box" size=".3 .27 .2" density="1000" />
<site name="torso_touch" type="box" size=".26 .26 .26" rgba="0 0 1 0" />
<site name="torso" size=".05" rgba="1 0 0 1" />
<body name="hip_front_left" pos=".2 .2 0" euler="0 0 45" childclass="hip">
<joint name="yaw_front_left" class="yaw" />
<joint name="pitch_front_left" class="pitch" />
<geom name="thigh_front_left" />
<body name="knee_front_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_left" />
<geom name="shin_front_left" />
<body name="ankle_front_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_left" />
<geom name="foot_front_left" />
<body name="toe_front_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_left" />
<site name="toe_front_left" />
</body>
</body>
</body>
</body>
<body name="hip_front_right" pos=".2 -.2 0" euler="0 0 -45" childclass="hip">
<joint name="yaw_front_right" class="yaw" />
<joint name="pitch_front_right" class="pitch" />
<geom name="thigh_front_right" />
<body name="knee_front_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_right" />
<geom name="shin_front_right" />
<body name="ankle_front_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_right" />
<geom name="foot_front_right" />
<body name="toe_front_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_right" />
<site name="toe_front_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_right" pos="-.2 -.2 0" euler="0 0 -135" childclass="hip">
<joint name="yaw_back_right" class="yaw" />
<joint name="pitch_back_right" class="pitch" />
<geom name="thigh_back_right" />
<body name="knee_back_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_right" />
<geom name="shin_back_right" />
<body name="ankle_back_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_right" />
<geom name="foot_back_right" />
<body name="toe_back_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_right" />
<site name="toe_back_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_left" pos="-.2 .2 0" euler="0 0 135" childclass="hip">
<joint name="yaw_back_left" class="yaw" />
<joint name="pitch_back_left" class="pitch" />
<geom name="thigh_back_left" />
<body name="knee_back_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_left" />
<geom name="shin_back_left" />
<body name="ankle_back_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_left" />
<geom name="foot_back_left" />
<body name="toe_back_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_left" />
<site name="toe_back_left" />
</body>
</body>
</body>
</body>
</body>
</worldbody>
<tendon>
<fixed name="coupling_front_left">
<joint joint="pitch_front_left" coef=".333" />
<joint joint="knee_front_left" coef=".333" />
<joint joint="ankle_front_left" coef=".333" />
</fixed>
<fixed name="coupling_front_right">
<joint joint="pitch_front_right" coef=".333" />
<joint joint="knee_front_right" coef=".333" />
<joint joint="ankle_front_right" coef=".333" />
</fixed>
<fixed name="coupling_back_right">
<joint joint="pitch_back_right" coef=".333" />
<joint joint="knee_back_right" coef=".333" />
<joint joint="ankle_back_right" coef=".333" />
</fixed>
<fixed name="coupling_back_left">
<joint joint="pitch_back_left" coef=".333" />
<joint joint="knee_back_left" coef=".333" />
<joint joint="ankle_back_left" coef=".333" />
</fixed>
<fixed name="extend_front_left">
<joint joint="pitch_front_left" coef=".25" />
<joint joint="knee_front_left" coef="-.5" />
<joint joint="ankle_front_left" coef=".25" />
</fixed>
<fixed name="lift_front_left">
<joint joint="pitch_front_left" coef=".5" />
<joint joint="ankle_front_left" coef="-.5" />
</fixed>
<fixed name="extend_front_right">
<joint joint="pitch_front_right" coef=".25" />
<joint joint="knee_front_right" coef="-.5" />
<joint joint="ankle_front_right" coef=".25" />
</fixed>
<fixed name="lift_front_right">
<joint joint="pitch_front_right" coef=".5" />
<joint joint="ankle_front_right" coef="-.5" />
</fixed>
<fixed name="extend_back_right">
<joint joint="pitch_back_right" coef=".25" />
<joint joint="knee_back_right" coef="-.5" />
<joint joint="ankle_back_right" coef=".25" />
</fixed>
<fixed name="lift_back_right">
<joint joint="pitch_back_right" coef=".5" />
<joint joint="ankle_back_right" coef="-.5" />
</fixed>
<fixed name="extend_back_left">
<joint joint="pitch_back_left" coef=".25" />
<joint joint="knee_back_left" coef="-.5" />
<joint joint="ankle_back_left" coef=".25" />
</fixed>
<fixed name="lift_back_left">
<joint joint="pitch_back_left" coef=".5" />
<joint joint="ankle_back_left" coef="-.5" />
</fixed>
</tendon>
<equality>
<tendon name="coupling_front_left" tendon1="coupling_front_left" class="coupling" />
<tendon name="coupling_front_right" tendon1="coupling_front_right" class="coupling" />
<tendon name="coupling_back_right" tendon1="coupling_back_right" class="coupling" />
<tendon name="coupling_back_left" tendon1="coupling_back_left" class="coupling" />
</equality>
<actuator>
<general name="yaw_front_left" class="yaw_act" joint="yaw_front_left" />
<general name="lift_front_left" class="lift_act" tendon="lift_front_left" />
<general name="extend_front_left" class="extend_act" tendon="extend_front_left" />
<general name="yaw_front_right" class="yaw_act" joint="yaw_front_right" />
<general name="lift_front_right" class="lift_act" tendon="lift_front_right" />
<general name="extend_front_right" class="extend_act" tendon="extend_front_right" />
<general name="yaw_back_right" class="yaw_act" joint="yaw_back_right" />
<general name="lift_back_right" class="lift_act" tendon="lift_back_right" />
<general name="extend_back_right" class="extend_act" tendon="extend_back_right" />
<general name="yaw_back_left" class="yaw_act" joint="yaw_back_left" />
<general name="lift_back_left" class="lift_act" tendon="lift_back_left" />
<general name="extend_back_left" class="extend_act" tendon="extend_back_left" />
</actuator>
<sensor>
<accelerometer name="imu_accel" site="torso" />
<gyro name="imu_gyro" site="torso" />
<velocimeter name="velocimeter" site="torso" />
<force name="force_toe_front_left" site="toe_front_left" />
<force name="force_toe_front_right" site="toe_front_right" />
<force name="force_toe_back_right" site="toe_back_right" />
<force name="force_toe_back_left" site="toe_back_left" />
<torque name="torque_toe_front_left" site="toe_front_left" />
<torque name="torque_toe_front_right" site="toe_front_right" />
<torque name="torque_toe_back_right" site="toe_back_right" />
<torque name="torque_toe_back_left" site="toe_back_left" />
<subtreecom name="center_of_mass" body="torso" />
</sensor>
</mujoco>

View File

@@ -0,0 +1,274 @@
<mujoco model="quadruped">
<include file="../../common/skybox.xml" />
<include file="../../common/visual.xml" />
<include file="./quadruped_materials.xml" />
<visual>
<rgba rangefinder="1 1 0.1 0.1" />
<map znear=".005" zfar="20" />
</visual>
<asset>
</asset>
<option timestep=".005" />
<default>
<geom solimp=".9 .99 .003" solref=".01 1" />
<default class="body">
<geom type="capsule" size=".08" condim="1" material="self" density="500" contype="1" conaffinity="1" />
<joint type="hinge" damping="30" armature=".01" limited="true" solimplimit="0 .99 .01" />
<default class="hip">
<default class="yaw">
<joint axis="0 0 1" range="-50 50" />
</default>
<default class="pitch">
<joint axis="0 1 0" range="-20 60" />
</default>
<geom fromto="0 0 0 .3 0 .11" />
</default>
<default class="knee">
<joint axis="0 1 0" range="-60 25" />
<geom size=".065" fromto="0 0 0 .25 0 -.25" />
</default>
<default class="ankle">
<joint axis="0 1 0" range="-45 45" />
<geom size=".055" fromto="0 0 0 0 0 -.25" />
</default>
<default class="toe">
<geom type="sphere" size=".08" material="effector" friction="1.5" />
<site type="sphere" size=".084" material="site" group="4" />
</default>
</default>
<default class="rangefinder">
<site type="capsule" size=".005 .1" material="site" group="4" />
</default>
<default class="wall">
<geom type="plane" material="decoration" contype="3" conaffinity="3" />
</default>
<default class="coupling">
<equality solimp="0.95 0.99 0.01" solref=".005 .5" />
</default>
<general ctrllimited="true" gainprm="1000" biasprm="0 -1000" biastype="affine" dyntype="filter" dynprm=".1" />
<default class="yaw_act">
<general ctrlrange="-1 1" />
</default>
<default class="lift_act">
<general ctrlrange="-1 1.1" />
</default>
<default class="extend_act">
<general ctrlrange="-.8 .8" />
</default>
</default>
<asset>
<texture name="ball" builtin="checker" mark="cross" width="151" height="151" rgb1="0.1 0.1 0.1" rgb2="0.9 0.9 0.9" markrgb="1 1 1" />
<material name="ball" texture="ball" />
</asset>
<worldbody>
<geom name="floor" type="plane" size="0 0 0.01" material="motphys-ground" contype="3" conaffinity="3" />
<light pos="0 0 1.5" dir="0 0 -1" directional="true" />
<geom name="wall_px" class="wall" pos="-15.7 0 .7" zaxis="1 0 1" size="1 15 .5" />
<geom name="wall_py" class="wall" pos="0 -15.7 .7" zaxis="0 1 1" size="15 1 .5" />
<geom name="wall_nx" class="wall" pos="15.7 0 .7" zaxis="-1 0 1" size="1 15 .5" />
<geom name="wall_ny" class="wall" pos="0 15.7 .7" zaxis="0 -1 1" size="15 1 .5" />
<site name="target" type="cylinder" size=".4 .06" pos="0 0 .05" material="target" />
<geom name="target_marker" type="cylinder" size=".4 .005" pos="0 0 .005" rgba=".9 .2 .2 0.4" />
<camera name="global" pos="-10 10 10" xyaxes="-1 -1 0 1 0 1" mode="trackcom" />
<body name="torso" childclass="body" pos="0 0 .57">
<freejoint name="root" />
<camera name="x" pos="-1.7 0 1" xyaxes="0 -1 0 .75 0 1" mode="trackcom" />
<camera name="y" pos="0 4 2" xyaxes="-1 0 0 0 -.5 1" mode="trackcom" />
<camera name="egocentric" pos=".3 0 .11" xyaxes="0 -1 0 .4 0 1" fovy="60" />
<geom name="eye_r" type="cylinder" size=".05" fromto=".1 -.07 .12 .31 -.07 .08" mass="0" />
<site name="pupil_r" type="sphere" size=".033" pos=".3 -.07 .08" zaxis="1 0 0" material="eye" />
<geom name="eye_l" type="cylinder" size=".05" fromto=".1 .07 .12 .31 .07 .08" mass="0" />
<site name="pupil_l" type="sphere" size=".033" pos=".3 .07 .08" zaxis="1 0 0" material="eye" />
<site name="workspace" type="sphere" size=".3 .3 .3" material="site" pos=".8 0 -.2" group="3" />
<geom name="torso" type="box" size=".3 .27 .2" density="1000" contype="3" conaffinity="3" />
<geom name="torso_belly" type="box" size=".3 .27 .2" pos="0 0 -.12" mass="0" contype="2" conaffinity="2" />
<site name="torso_touch" type="box" size=".26 .26 .26" rgba="0 0 1 0" />
<site name="torso" size=".05" rgba="1 0 0 1" />
<body name="hip_front_left" pos=".2 .2 0" euler="0 0 45" childclass="hip">
<joint name="yaw_front_left" class="yaw" />
<joint name="pitch_front_left" class="pitch" />
<geom name="thigh_front_left" />
<body name="knee_front_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_left" />
<geom name="shin_front_left" />
<body name="ankle_front_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_left" />
<geom name="foot_front_left" />
<body name="toe_front_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_left" />
<site name="toe_front_left" />
</body>
</body>
</body>
</body>
<body name="hip_front_right" pos=".2 -.2 0" euler="0 0 -45" childclass="hip">
<joint name="yaw_front_right" class="yaw" />
<joint name="pitch_front_right" class="pitch" />
<geom name="thigh_front_right" />
<body name="knee_front_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_right" />
<geom name="shin_front_right" />
<body name="ankle_front_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_right" />
<geom name="foot_front_right" />
<body name="toe_front_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_right" />
<site name="toe_front_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_right" pos="-.2 -.2 0" euler="0 0 -135" childclass="hip">
<joint name="yaw_back_right" class="yaw" />
<joint name="pitch_back_right" class="pitch" />
<geom name="thigh_back_right" />
<body name="knee_back_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_right" />
<geom name="shin_back_right" />
<body name="ankle_back_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_right" />
<geom name="foot_back_right" />
<body name="toe_back_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_right" />
<site name="toe_back_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_left" pos="-.2 .2 0" euler="0 0 135" childclass="hip">
<joint name="yaw_back_left" class="yaw" />
<joint name="pitch_back_left" class="pitch" />
<geom name="thigh_back_left" />
<body name="knee_back_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_left" />
<geom name="shin_back_left" />
<body name="ankle_back_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_left" />
<geom name="foot_back_left" />
<body name="toe_back_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_left" />
<site name="toe_back_left" />
</body>
</body>
</body>
</body>
</body>
<body name="ball" pos="0 0 3">
<freejoint name="ball_root" />
<geom name="ball" size=".3" material="ball" priority="1" condim="6" friction="0.6 .02 .02" mass="1.0" solref="0.02 1" contype="2" conaffinity="2" />
</body>
</worldbody>
<tendon>
<fixed name="coupling_front_left">
<joint joint="pitch_front_left" coef=".333" />
<joint joint="knee_front_left" coef=".333" />
<joint joint="ankle_front_left" coef=".333" />
</fixed>
<fixed name="coupling_front_right">
<joint joint="pitch_front_right" coef=".333" />
<joint joint="knee_front_right" coef=".333" />
<joint joint="ankle_front_right" coef=".333" />
</fixed>
<fixed name="coupling_back_right">
<joint joint="pitch_back_right" coef=".333" />
<joint joint="knee_back_right" coef=".333" />
<joint joint="ankle_back_right" coef=".333" />
</fixed>
<fixed name="coupling_back_left">
<joint joint="pitch_back_left" coef=".333" />
<joint joint="knee_back_left" coef=".333" />
<joint joint="ankle_back_left" coef=".333" />
</fixed>
<fixed name="extend_front_left">
<joint joint="pitch_front_left" coef=".25" />
<joint joint="knee_front_left" coef="-.5" />
<joint joint="ankle_front_left" coef=".25" />
</fixed>
<fixed name="lift_front_left">
<joint joint="pitch_front_left" coef=".5" />
<joint joint="ankle_front_left" coef="-.5" />
</fixed>
<fixed name="extend_front_right">
<joint joint="pitch_front_right" coef=".25" />
<joint joint="knee_front_right" coef="-.5" />
<joint joint="ankle_front_right" coef=".25" />
</fixed>
<fixed name="lift_front_right">
<joint joint="pitch_front_right" coef=".5" />
<joint joint="ankle_front_right" coef="-.5" />
</fixed>
<fixed name="extend_back_right">
<joint joint="pitch_back_right" coef=".25" />
<joint joint="knee_back_right" coef="-.5" />
<joint joint="ankle_back_right" coef=".25" />
</fixed>
<fixed name="lift_back_right">
<joint joint="pitch_back_right" coef=".5" />
<joint joint="ankle_back_right" coef="-.5" />
</fixed>
<fixed name="extend_back_left">
<joint joint="pitch_back_left" coef=".25" />
<joint joint="knee_back_left" coef="-.5" />
<joint joint="ankle_back_left" coef=".25" />
</fixed>
<fixed name="lift_back_left">
<joint joint="pitch_back_left" coef=".5" />
<joint joint="ankle_back_left" coef="-.5" />
</fixed>
</tendon>
<equality>
<tendon name="coupling_front_left" tendon1="coupling_front_left" class="coupling" />
<tendon name="coupling_front_right" tendon1="coupling_front_right" class="coupling" />
<tendon name="coupling_back_right" tendon1="coupling_back_right" class="coupling" />
<tendon name="coupling_back_left" tendon1="coupling_back_left" class="coupling" />
</equality>
<actuator>
<general name="yaw_front_left" class="yaw_act" joint="yaw_front_left" />
<general name="lift_front_left" class="lift_act" tendon="lift_front_left" />
<general name="extend_front_left" class="extend_act" tendon="extend_front_left" />
<general name="yaw_front_right" class="yaw_act" joint="yaw_front_right" />
<general name="lift_front_right" class="lift_act" tendon="lift_front_right" />
<general name="extend_front_right" class="extend_act" tendon="extend_front_right" />
<general name="yaw_back_right" class="yaw_act" joint="yaw_back_right" />
<general name="lift_back_right" class="lift_act" tendon="lift_back_right" />
<general name="extend_back_right" class="extend_act" tendon="extend_back_right" />
<general name="yaw_back_left" class="yaw_act" joint="yaw_back_left" />
<general name="lift_back_left" class="lift_act" tendon="lift_back_left" />
<general name="extend_back_left" class="extend_act" tendon="extend_back_left" />
</actuator>
<sensor>
<framequat name="orientation" objtype="xbody" objname="torso" />
<velocimeter name="velocimeter" site="torso" />
<gyro name="imu_gyro" site="torso" />
<accelerometer name="imu_accel" site="torso" />
</sensor>
</mujoco>

View File

@@ -0,0 +1,21 @@
<!-- Quadruped-specific materials that extend the shared env visuals. -->
<mujoco>
<asset>
<texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3" rgb2=".2 .3 .4" width="300" height="300" mark="edge" markrgb=".2 .3 .4"/>
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
<texture name="motphys-ground" type="2d" file="../../common/motphys-ground.png"/>
<material name="motphys-ground" texture="motphys-ground" texuniform="true" texrepeat="0.4 0.4"/>
<material name="self" rgba=".7 .5 .3 1"/>
<material name="self_default" rgba=".7 .5 .3 1"/>
<material name="self_highlight" rgba="0 .5 .3 1"/>
<material name="effector" rgba=".7 .4 .2 1"/>
<material name="effector_default" rgba=".7 .4 .2 1"/>
<material name="effector_highlight" rgba="0 .5 .3 1"/>
<material name="decoration" rgba=".3 .5 .7 1"/>
<material name="eye" rgba="0 .2 1 1"/>
<material name="target" rgba=".6 .3 .3 1"/>
<material name="target_default" rgba=".6 .3 .3 1"/>
<material name="target_highlight" rgba=".6 .3 .3 .4"/>
<material name="site" rgba=".5 .5 .5 .3"/>
</asset>
</mujoco>

View File

@@ -0,0 +1,893 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import gymnasium as gym
import motrixsim as mtx
import numpy as np
from motrix_envs import registry
from motrix_envs.basic.quadruped.cfg import QuadrupedBaseCfg
from motrix_envs.math import quaternion
from motrix_envs.np import reward
from motrix_envs.np.env import NpEnv, NpEnvState
_RANGEFINDER_SENSORS = [f"rf_{row}{col}" for row in range(4) for col in range(5)]
class QuadrupedEnv(NpEnv):
_cfg: QuadrupedBaseCfg
_observation_space: gym.spaces.Box
_action_space: gym.spaces.Box
def __init__(self, cfg: QuadrupedBaseCfg, num_envs: int = 1):
super().__init__(cfg, num_envs)
self._cfg = cfg
self._torso = self._model.get_link("torso")
self._floor_geom = self._model.get_geom("floor")
self._workspace_site = None
if cfg.include_origin:
self._workspace_site = self._model.get_site("workspace")
self._target_site = None
if cfg.include_target:
self._target_site = self._model.get_site("target")
self._ball_body = None
self._ball_geom = None
if cfg.include_ball:
self._ball_body = self._model.get_body("ball")
self._ball_geom = self._model.get_geom("ball")
self._leg_ball_geoms = []
self._leg_ball_geom_count = 0
self._leg_ball_geom_slices = []
if cfg.include_ball:
try:
leg_body_geom_names = [
["thigh_front_left", "shin_front_left", "foot_front_left", "toe_front_left"],
["thigh_front_right", "shin_front_right", "foot_front_right", "toe_front_right"],
["thigh_back_right", "shin_back_right", "foot_back_right", "toe_back_right"],
["thigh_back_left", "shin_back_left", "foot_back_left", "toe_back_left"],
]
leg_geoms = []
start = 0
for geom_names in leg_body_geom_names:
stop = start
for name in geom_names:
try:
geom = self._model.get_geom(name)
except Exception:
continue
leg_geoms.append(geom)
stop += 1
self._leg_ball_geom_slices.append(slice(start, stop))
start = stop
if leg_geoms:
self._leg_ball_geoms = leg_geoms
self._leg_ball_geom_count = len(leg_geoms)
except Exception:
self._leg_ball_geom_slices = []
self._body_dof_pos = self._model.num_dof_pos - 7 - (7 if cfg.include_ball else 0)
self._body_dof_vel = self._model.num_dof_vel - 6 - (6 if cfg.include_ball else 0)
self._dof_pos_slice = slice(7, 7 + self._body_dof_pos)
self._dof_vel_slice = slice(6, 6 + self._body_dof_vel)
self._ball_pos_slice = None
self._ball_vel_slice = None
if cfg.include_ball:
self._ball_pos_slice = slice(self._model.num_dof_pos - 7, self._model.num_dof_pos)
self._ball_vel_slice = slice(self._model.num_dof_vel - 6, self._model.num_dof_vel)
self._init_dof_pos = self._model.compute_init_dof_pos().astype(np.float32)
self._default_body_dof_pos = self._init_dof_pos[self._dof_pos_slice].copy()
self._terrain_size = float(cfg.terrain_size)
try:
if self._model.num_hfields:
hfield = self._model.get_hfield(0)
self._terrain_size = max(self._terrain_size, float(abs(hfield.bound[3])))
except Exception:
pass
self._init_obs_space()
self._init_action_space()
def _init_obs_space(self):
num_obs = self._body_dof_pos + self._body_dof_vel + self._model.num_actuators
num_obs += 3 # torso velocity
num_obs += 1 # torso upright
num_obs += 6 # imu accel + gyro
if self._cfg.include_origin:
num_obs += 3
if self._cfg.include_rangefinder:
num_obs += len(_RANGEFINDER_SENSORS)
if self._cfg.include_ball:
num_obs += 9
if self._cfg.include_target:
num_obs += 3
self._observation_space = gym.spaces.Box(-np.inf, np.inf, (num_obs,), dtype=np.float32)
def _init_action_space(self):
low, high = self._model.actuator_ctrl_limits
self._action_space = gym.spaces.Box(low, high, (self._model.num_actuators,), dtype=np.float32)
@property
def observation_space(self) -> gym.spaces.Box:
return self._observation_space
@property
def action_space(self) -> gym.spaces.Box:
return self._action_space
def apply_action(self, actions: np.ndarray, state: NpEnvState) -> NpEnvState:
if self._cfg.clip_env_actions:
actions = np.clip(actions, self._action_space.low, self._action_space.high)
actions = actions.astype(np.float32)
if "actions" not in state.info:
state.info["actions"] = np.zeros_like(actions, dtype=np.float32)
if "last_actions" not in state.info:
state.info["last_actions"] = np.zeros_like(actions, dtype=np.float32)
state.info["last_actions"] = state.info["actions"]
state.info["actions"] = actions
state.data.actuator_ctrls = actions
return state
def _sensor_value(self, data: mtx.SceneData, name: str) -> np.ndarray:
value = np.asarray(self._model.get_sensor_value(name, data))
return value.reshape(data.shape[0], -1)
def _sensor_vector(self, data: mtx.SceneData, names: list[str]) -> np.ndarray:
if not names:
return np.zeros((data.shape[0], 0), dtype=np.float32)
values = [self._sensor_value(data, name) for name in names]
return np.concatenate(values, axis=-1)
def _egocentric_state(self, data: mtx.SceneData) -> np.ndarray:
dof_pos = data.dof_pos[:, self._dof_pos_slice]
dof_vel = data.dof_vel[:, self._dof_vel_slice]
act = data.actuator_ctrls
return np.concatenate([dof_pos, dof_vel, act], axis=-1)
def _torso_upright(self, data: mtx.SceneData) -> np.ndarray:
return self._torso.get_rotation_mat(data)[:, 2, 2]
def _torso_velocity(self, data: mtx.SceneData) -> np.ndarray:
return self._sensor_value(data, "velocimeter")
def _imu(self, data: mtx.SceneData) -> np.ndarray:
accel = self._sensor_value(data, "imu_accel")
gyro = self._sensor_value(data, "imu_gyro")
return np.concatenate([accel, gyro], axis=-1)
def _rangefinder(self, data: mtx.SceneData) -> np.ndarray:
readings = self._sensor_vector(data, _RANGEFINDER_SENSORS)
no_intersection = -1.0
return np.where(readings == no_intersection, 1.0, np.tanh(readings))
def _origin(self, data: mtx.SceneData) -> np.ndarray:
torso_pos = self._torso.get_position(data)
torso_frame = self._torso.get_rotation_mat(data)
return -np.einsum("ni,nij->nj", torso_pos, torso_frame)
def _origin_distance(self, data: mtx.SceneData) -> np.ndarray:
workspace_pos = self._workspace_site.get_position(data)
return np.linalg.norm(workspace_pos, axis=-1)
def _ball_state(self, data: mtx.SceneData) -> np.ndarray:
ball_pose = self._ball_body.get_pose(data)
ball_pos = ball_pose[:, :3]
torso_pos = self._torso.get_position(data)
torso_frame = self._torso.get_rotation_mat(data)
ball_rel_pos = ball_pos - torso_pos
root_linvel = data.dof_vel[:, :3]
ball_vel = data.dof_vel[:, self._ball_vel_slice]
ball_rel_vel = ball_vel[:, :3] - root_linvel
ball_rot_vel = ball_vel[:, 3:]
stacked = np.stack([ball_rel_pos, ball_rel_vel, ball_rot_vel], axis=1)
local = np.einsum("nij,njk->nik", stacked, torso_frame)
return local.reshape(data.shape[0], -1)
def _target_position(self, data: mtx.SceneData) -> np.ndarray:
torso_pos = self._torso.get_position(data)
torso_frame = self._torso.get_rotation_mat(data)
to_target = self._target_site.get_position(data) - torso_pos
return np.einsum("ni,nij->nj", to_target, torso_frame)
def _ball_to_target_distance(self, data: mtx.SceneData) -> np.ndarray:
ball_pos = self._ball_body.get_pose(data)[:, :3]
target_pos = self._target_site.get_position(data)
return np.linalg.norm((target_pos - ball_pos)[:, :2], axis=-1)
def _aggregate_leg_ball_proximity(self, geom_penalties: np.ndarray) -> np.ndarray:
num_legs = len(self._leg_ball_geom_slices)
if num_legs == 0:
return np.zeros((geom_penalties.shape[0], 0), dtype=np.float32)
leg_penalties = []
for geom_slice in self._leg_ball_geom_slices:
if geom_slice.start == geom_slice.stop:
leg_penalties.append(np.zeros((geom_penalties.shape[0],), dtype=np.float32))
else:
leg_penalties.append(geom_penalties[:, geom_slice].max(axis=-1))
return np.stack(leg_penalties, axis=-1)
def _point_to_segment_distance(self, point: np.ndarray, start: np.ndarray, end: np.ndarray) -> np.ndarray:
segment = end - start
segment_sq_norm = np.sum(segment * segment, axis=-1)
safe_norm = np.where(segment_sq_norm > 1e-8, segment_sq_norm, 1.0)
t = np.sum((point - start) * segment, axis=-1) / safe_norm
t = np.where(segment_sq_norm > 1e-8, np.clip(t, 0.0, 1.0), 0.0)
closest = start + t[:, None] * segment
return np.linalg.norm(point - closest, axis=-1)
def _geom_ball_surface_clearance(
self, geom: mtx.Geom, ball_pos: np.ndarray, ball_radius: float, data: mtx.SceneData
) -> np.ndarray:
geom_pose = geom.get_pose(data)
geom_pos = geom_pose[:, :3]
geom_quat = geom_pose[:, 3:]
geom_size = np.atleast_1d(np.asarray(geom.size, dtype=np.float32))
geom_radius = float(geom_size[0])
if getattr(geom, "shape", None) == mtx.Shape.Capsule and geom_size.shape[0] > 1 and geom_size[1] > 0.0:
half_length = float(geom_size[1])
axis = quaternion.rotate_vector(geom_quat, np.array([0.0, 0.0, 1.0], dtype=np.float32))
start = geom_pos - axis * half_length
end = geom_pos + axis * half_length
center_distance = self._point_to_segment_distance(ball_pos, start, end)
else:
center_distance = np.linalg.norm(ball_pos - geom_pos, axis=-1)
return center_distance - (ball_radius + geom_radius)
def _leg_body_ball_penalty(self, data: mtx.SceneData) -> np.ndarray:
num_legs = len(self._leg_ball_geom_slices)
if self._ball_geom is None or self._leg_ball_geom_count == 0 or num_legs == 0:
return np.zeros((data.shape[0],), dtype=np.float32)
ball_pos = self._ball_geom.get_pose(data)[:, :3]
ball_radius = float(np.atleast_1d(self._ball_geom.size)[0])
geom_penalties = []
for geom in self._leg_ball_geoms:
clearance = self._geom_ball_surface_clearance(geom, ball_pos, ball_radius, data)
geom_penalties.append(
reward.tolerance(
-clearance,
bounds=(0.0, float("inf")),
margin=self._cfg.fetch_leg_ball_penalty_margin,
value_at_margin=0.0,
sigmoid="linear",
)
)
proximity = np.stack(geom_penalties, axis=-1).astype(np.float32)
leg_penalties = self._aggregate_leg_ball_proximity(proximity)
return leg_penalties.sum(axis=-1).astype(np.float32)
def _fetch_stability_gate(self, torso_upright: np.ndarray, torso_height: np.ndarray) -> np.ndarray:
upright_gate = reward.tolerance(
torso_upright,
bounds=(self._cfg.fetch_stability_upright_min, float("inf")),
margin=self._cfg.fetch_stability_upright_margin,
value_at_margin=0.0,
sigmoid="linear",
)
height_gate = reward.tolerance(
torso_height,
bounds=(self._cfg.fetch_stability_height_min, float("inf")),
margin=self._cfg.fetch_stability_height_margin,
value_at_margin=0.0,
sigmoid="linear",
)
return upright_gate * height_gate
def _fetch_fall_terminated(self, torso_upright: np.ndarray, torso_height: np.ndarray) -> np.ndarray:
return (torso_upright < self._cfg.fetch_fall_upright_min) | (torso_height < self._cfg.fetch_fall_height_min)
def _upright_reward(self, torso_upright: np.ndarray) -> np.ndarray:
deviation = float(np.cos(np.deg2rad(self._cfg.deviation_angle)))
return reward.tolerance(
torso_upright,
bounds=(deviation, float("inf")),
margin=1 + deviation,
value_at_margin=0.0,
sigmoid="linear",
)
def _move_reward(self, torso_vel: np.ndarray) -> np.ndarray:
return reward.tolerance(
torso_vel[:, 0],
bounds=(self._cfg.desired_speed, float("inf")),
margin=self._cfg.desired_speed,
value_at_margin=0.5,
sigmoid="linear",
)
def _backward_penalty(self, torso_vel: np.ndarray) -> np.ndarray:
return np.maximum(0.0, -torso_vel[:, 0])
def _escape_reward(self, data: mtx.SceneData) -> np.ndarray:
return reward.tolerance(
self._origin_distance(data),
bounds=(self._terrain_size, float("inf")),
margin=self._terrain_size,
value_at_margin=0.0,
sigmoid="linear",
)
def _radial_speed_reward(self, data: mtx.SceneData) -> np.ndarray:
radial_speed_reward = np.zeros((data.shape[0],), dtype=np.float32)
if not self._cfg.include_origin:
return radial_speed_reward
torso_pos = self._torso.get_position(data)
radial_vec = torso_pos[:, :2]
radial_norm = np.linalg.norm(radial_vec, axis=-1, keepdims=True)
radial_dir = np.divide(radial_vec, radial_norm, out=np.zeros_like(radial_vec), where=radial_norm > 1e-6)
radial_speed = np.sum(data.dof_vel[:, :2] * radial_dir, axis=-1)
radial_speed = np.maximum(0.0, radial_speed)
return reward.tolerance(
radial_speed,
bounds=(self._cfg.desired_speed, float("inf")),
margin=self._cfg.desired_speed,
value_at_margin=0.5,
sigmoid="linear",
)
def _heading_reward(self, data: mtx.SceneData) -> np.ndarray:
heading_reward = np.zeros((data.shape[0],), dtype=np.float32)
if self._cfg.heading_reward_weight <= 0.0:
return heading_reward
torso_frame = self._torso.get_rotation_mat(data)
heading_xy = torso_frame[:, 0, :2]
heading_norm = np.linalg.norm(heading_xy, axis=-1, keepdims=True)
heading_dir = np.divide(heading_xy, heading_norm, out=np.zeros_like(heading_xy), where=heading_norm > 1e-6)
heading_align = heading_dir[:, 0]
return reward.tolerance(
heading_align,
bounds=(1.0, 1.0),
margin=self._cfg.heading_reward_margin,
value_at_margin=0.0,
sigmoid="linear",
)
def _height_reward(self, data: mtx.SceneData) -> np.ndarray:
torso_height = self._torso.get_position(data)[:, 2]
return reward.tolerance(
torso_height,
bounds=(self._cfg.stand_height, float("inf")),
margin=self._cfg.stand_height_margin,
value_at_margin=0.0,
sigmoid="linear",
)
def _lateral_reward(self, torso_vel: np.ndarray) -> np.ndarray:
return reward.tolerance(
np.abs(torso_vel[:, 1]),
bounds=(0.0, self._cfg.lateral_velocity_limit),
margin=self._cfg.lateral_velocity_margin,
value_at_margin=0.0,
sigmoid="linear",
)
def _smooth_reward(self, state: NpEnvState) -> np.ndarray:
smooth_reward = np.zeros((state.data.shape[0],), dtype=np.float32)
if "actions" not in state.info or "last_actions" not in state.info:
return smooth_reward
delta = state.info["actions"] - state.info["last_actions"]
delta_norm = np.linalg.norm(delta, axis=-1)
return reward.tolerance(
delta_norm,
bounds=(0.0, 0.0),
margin=self._cfg.action_smoothness_margin,
value_at_margin=0.0,
sigmoid="linear",
)
def _lin_vel_z_penalty(self, torso_vel: np.ndarray) -> np.ndarray:
return np.square(torso_vel[:, 2]).astype(np.float32)
def _ang_vel_xy_penalty(self, data: mtx.SceneData) -> np.ndarray:
imu = self._imu(data)
return np.sum(np.square(imu[:, 3:5]), axis=1).astype(np.float32)
def _similar_to_default_penalty(self, data: mtx.SceneData) -> np.ndarray:
body_dof_pos = data.dof_pos[:, self._dof_pos_slice]
return np.sum(np.abs(body_dof_pos - self._default_body_dof_pos), axis=1).astype(np.float32)
def _locomotion_reward_terms(
self,
upright_reward: np.ndarray,
move_reward: np.ndarray,
backward_penalty: np.ndarray,
height_reward: np.ndarray,
lateral_reward: np.ndarray,
heading_reward: np.ndarray,
smooth_reward: np.ndarray,
lin_vel_z_penalty: np.ndarray,
ang_vel_xy_penalty: np.ndarray,
similar_to_default_penalty: np.ndarray,
) -> dict[str, np.ndarray]:
return {
"move": upright_reward * move_reward,
"backward": backward_penalty,
"height": height_reward,
"lateral": lateral_reward,
"heading": heading_reward,
"smooth": smooth_reward,
"lin_vel_z": lin_vel_z_penalty,
"ang_vel_xy": ang_vel_xy_penalty,
"similar_to_default": similar_to_default_penalty,
}
def _locomotion_reward_scales(self) -> dict[str, float]:
return {
"move": 1.0,
"backward": -self._cfg.backward_penalty_weight,
"height": self._cfg.height_reward_weight,
"lateral": self._cfg.lateral_reward_weight,
"heading": self._cfg.heading_reward_weight,
"smooth": self._cfg.action_smoothness_weight,
"lin_vel_z": -self._cfg.lin_vel_z_weight,
"ang_vel_xy": -self._cfg.ang_vel_xy_weight,
"similar_to_default": -self._cfg.similar_to_default_weight,
}
def _escape_reward_terms(
self, upright_reward: np.ndarray, escape_reward: np.ndarray, radial_speed_reward: np.ndarray
) -> dict[str, np.ndarray]:
return {
"escape": upright_reward * escape_reward,
"radial": radial_speed_reward,
}
def _escape_reward_scales(self) -> dict[str, float]:
return {
"escape": 1.0,
"radial": self._cfg.radial_velocity_weight,
}
def _sum_scaled_rewards(self, reward_terms: dict[str, np.ndarray], reward_scales: dict[str, float]) -> np.ndarray:
rewards = {name: value * reward_scales[name] for name, value in reward_terms.items()}
return sum(rewards.values())
def _get_obs(self, data: mtx.SceneData) -> np.ndarray:
parts = [
self._egocentric_state(data),
self._torso_velocity(data),
self._torso_upright(data).reshape(data.shape[0], 1),
self._imu(data),
]
if self._cfg.include_origin:
parts.append(self._origin(data))
if self._cfg.include_rangefinder:
parts.append(self._rangefinder(data))
if self._cfg.include_ball:
parts.append(self._ball_state(data))
if self._cfg.include_target:
parts.append(self._target_position(data))
return np.concatenate(parts, axis=-1).astype(np.float32)
def _locomotion_reward_info(self, num_envs: int) -> dict:
return {
"upright": np.zeros((num_envs,), dtype=np.float32),
"move": np.zeros((num_envs,), dtype=np.float32),
"backward": np.zeros((num_envs,), dtype=np.float32),
"height": np.zeros((num_envs,), dtype=np.float32),
"lateral": np.zeros((num_envs,), dtype=np.float32),
"heading": np.zeros((num_envs,), dtype=np.float32),
"smooth": np.zeros((num_envs,), dtype=np.float32),
"lin_vel_z": np.zeros((num_envs,), dtype=np.float32),
"ang_vel_xy": np.zeros((num_envs,), dtype=np.float32),
"similar_to_default": np.zeros((num_envs,), dtype=np.float32),
"total": np.zeros((num_envs,), dtype=np.float32),
}
def _escape_reward_info(self, num_envs: int) -> dict:
info = self._locomotion_reward_info(num_envs)
info.update(
{
"escape": np.zeros((num_envs,), dtype=np.float32),
"radial": np.zeros((num_envs,), dtype=np.float32),
}
)
return info
def _fetch_reward_info(self, num_envs: int) -> dict:
return {
"upright": np.zeros((num_envs,), dtype=np.float32),
"stage_move": np.zeros((num_envs,), dtype=np.float32),
"stage_reach": np.zeros((num_envs,), dtype=np.float32),
"stability": np.zeros((num_envs,), dtype=np.float32),
"behind_align": np.zeros((num_envs,), dtype=np.float32),
"face_ball": np.zeros((num_envs,), dtype=np.float32),
"near_ball": np.zeros((num_envs,), dtype=np.float32),
"ready": np.zeros((num_envs,), dtype=np.float32),
"ready_gate": np.zeros((num_envs,), dtype=np.float32),
"fetch": np.zeros((num_envs,), dtype=np.float32),
"push": np.zeros((num_envs,), dtype=np.float32),
"away": np.zeros((num_envs,), dtype=np.float32),
"leg_ball": np.zeros((num_envs,), dtype=np.float32),
"backward": np.zeros((num_envs,), dtype=np.float32),
"total": np.zeros((num_envs,), dtype=np.float32),
}
def _base_locomotion_components(self, data: mtx.SceneData, state: NpEnvState) -> dict[str, np.ndarray]:
torso_vel = self._torso_velocity(data)
return {
"move": self._move_reward(torso_vel),
"backward": self._backward_penalty(torso_vel),
"height": self._height_reward(data),
"lateral": self._lateral_reward(torso_vel),
"heading": self._heading_reward(data),
"smooth": self._smooth_reward(state),
"lin_vel_z": self._lin_vel_z_penalty(torso_vel),
"ang_vel_xy": self._ang_vel_xy_penalty(data),
"similar_to_default": self._similar_to_default_penalty(data),
}
def _locomotion_reward(self, upright_reward: np.ndarray, components: dict[str, np.ndarray]) -> np.ndarray:
reward_terms = self._locomotion_reward_terms(
upright_reward,
components["move"],
components["backward"],
components["height"],
components["lateral"],
components["heading"],
components["smooth"],
components["lin_vel_z"],
components["ang_vel_xy"],
components["similar_to_default"],
)
return self._sum_scaled_rewards(reward_terms, self._locomotion_reward_scales())
def _build_reset_info(self, num_envs: int) -> dict:
return {
"Reward": self._init_reward_info(num_envs),
"actions": np.zeros((num_envs, self._model.num_actuators), dtype=np.float32),
"last_actions": np.zeros((num_envs, self._model.num_actuators), dtype=np.float32),
}
def _random_quaternion(self, num: int) -> np.ndarray:
q = np.random.randn(num, 4).astype(np.float32)
q /= np.linalg.norm(q, axis=-1, keepdims=True)
return q
def _yaw_quaternion(self, yaw: np.ndarray) -> np.ndarray:
zeros = np.zeros_like(yaw)
half = yaw * 0.5
return np.stack([zeros, zeros, np.sin(half), np.cos(half)], axis=-1).astype(np.float32)
def _lift_non_contacting(self, data: mtx.SceneData, dof_pos: np.ndarray) -> np.ndarray:
z = dof_pos[:, 2].copy()
pending = np.ones((data.shape[0],), dtype=bool)
for _ in range(1000):
if not pending.any():
break
dof_pos[pending, 2] = z[pending]
data.set_dof_pos(dof_pos, self._model)
self._model.forward_kinematic(data)
num_contacts = self._model.get_contact_query(data).num_contacts
pending = num_contacts > 0
z[pending] += 0.01
return dof_pos
def _finish_reset(self, data: mtx.SceneData, dof_pos: np.ndarray, dof_vel: np.ndarray) -> tuple[np.ndarray, dict]:
dof_pos = self._lift_non_contacting(data, dof_pos)
data.set_dof_pos(dof_pos, self._model)
data.set_dof_vel(dof_vel)
self._model.forward_kinematic(data)
obs = self._get_obs(data)
info = self._build_reset_info(int(data.shape[0]))
return obs, info
@registry.env("dm-quadruped-walk", "np")
@registry.env("dm-quadruped-run", "np")
class QuadrupedLocomotionEnv(QuadrupedEnv):
def _init_reward_info(self, num_envs: int) -> dict:
return self._locomotion_reward_info(num_envs)
def update_state(self, state: NpEnvState) -> NpEnvState:
data = state.data
obs = self._get_obs(data)
torso_upright = self._torso_upright(data)
upright_reward = self._upright_reward(torso_upright)
locomotion_components = self._base_locomotion_components(data, state)
rwd = self._locomotion_reward(upright_reward, locomotion_components)
reward_components = {"upright": upright_reward}
reward_components.update(locomotion_components)
reward_components["total"] = rwd
terminated = np.isnan(obs).any(axis=-1)
rwd = np.where(terminated, 0.0, rwd).astype(np.float32)
state.info["Reward"] = reward_components
return state.replace(obs=obs, reward=rwd, terminated=terminated)
def reset(self, data: mtx.SceneData) -> tuple[np.ndarray, dict]:
data.reset(self._model)
num = int(data.shape[0])
dof_pos = np.tile(self._init_dof_pos, (num, 1))
dof_vel = np.zeros((num, self._model.num_dof_vel), dtype=np.float32)
if self._cfg.fix_heading:
dof_pos[:, 3:7] = np.tile(np.array([0.0, 0.0, 0.0, 1.0], dtype=np.float32), (num, 1))
else:
dof_pos[:, 3:7] = self._random_quaternion(num)
return self._finish_reset(data, dof_pos, dof_vel)
@registry.env("dm-quadruped-escape", "np")
class QuadrupedEscapeEnv(QuadrupedLocomotionEnv):
def _init_reward_info(self, num_envs: int) -> dict:
return self._escape_reward_info(num_envs)
def update_state(self, state: NpEnvState) -> NpEnvState:
data = state.data
obs = self._get_obs(data)
torso_upright = self._torso_upright(data)
upright_reward = self._upright_reward(torso_upright)
locomotion_components = self._base_locomotion_components(data, state)
escape_reward = self._escape_reward(data)
radial_speed_reward = self._radial_speed_reward(data)
reward_terms = self._locomotion_reward_terms(
upright_reward,
locomotion_components["move"],
locomotion_components["backward"],
locomotion_components["height"],
locomotion_components["lateral"],
locomotion_components["heading"],
locomotion_components["smooth"],
locomotion_components["lin_vel_z"],
locomotion_components["ang_vel_xy"],
locomotion_components["similar_to_default"],
)
reward_scales = self._locomotion_reward_scales()
reward_terms.update(self._escape_reward_terms(upright_reward, escape_reward, radial_speed_reward))
reward_scales.update(self._escape_reward_scales())
rwd = self._sum_scaled_rewards(reward_terms, reward_scales)
reward_components = {"upright": upright_reward}
reward_components.update(locomotion_components)
reward_components.update(
{
"escape": escape_reward,
"radial": radial_speed_reward,
"total": rwd,
}
)
terminated = np.isnan(obs).any(axis=-1)
rwd = np.where(terminated, 0.0, rwd).astype(np.float32)
state.info["Reward"] = reward_components
return state.replace(obs=obs, reward=rwd, terminated=terminated)
@registry.env("dm-quadruped-fetch", "np")
class QuadrupedFetchEnv(QuadrupedEnv):
def _init_reward_info(self, num_envs: int) -> dict:
return self._fetch_reward_info(num_envs)
def update_state(self, state: NpEnvState) -> NpEnvState:
data = state.data
obs = self._get_obs(data)
torso_upright = self._torso_upright(data)
upright_reward = self._upright_reward(torso_upright)
torso_height = self._torso.get_position(data)[:, 2]
stability_gate = self._fetch_stability_gate(torso_upright, torso_height)
target_radius = float(self._cfg.target_radius)
if self._target_site is not None:
try:
target_radius = float(np.atleast_1d(self._target_site.size)[0])
except Exception:
pass
ball_pos = self._ball_body.get_pose(data)[:, :3]
target_pos = self._target_site.get_position(data)
torso_pos = self._torso.get_position(data)
to_target = target_pos[:, :2] - ball_pos[:, :2]
to_target_norm = np.linalg.norm(to_target, axis=-1, keepdims=True)
to_target_dir = np.where(to_target_norm > 1e-6, to_target / to_target_norm, 0.0)
torso_frame = self._torso.get_rotation_mat(data)
heading_xy = torso_frame[:, 0, :2]
heading_norm = np.linalg.norm(heading_xy, axis=-1, keepdims=True)
heading_dir = np.where(heading_norm > 1e-6, heading_xy / heading_norm, 0.0)
to_ball = ball_pos[:, :2] - torso_pos[:, :2]
to_ball_norm = np.linalg.norm(to_ball, axis=-1, keepdims=True)
to_ball_dir = np.where(to_ball_norm > 1e-6, to_ball / to_ball_norm, 0.0)
behind_align = np.sum(to_ball_dir * to_target_dir, axis=-1)
behind_align_reward = reward.tolerance(
behind_align,
bounds=(1.0, 1.0),
margin=self._cfg.fetch_behind_align_margin,
value_at_margin=0.0,
sigmoid="linear",
)
heading_align = np.sum(heading_dir * to_ball_dir, axis=-1)
face_ball_reward = reward.tolerance(
heading_align,
bounds=(1.0, 1.0),
margin=self._cfg.fetch_heading_margin,
value_at_margin=0.0,
sigmoid="linear",
)
ball_to_robot = torso_pos[:, :2] - ball_pos[:, :2]
back_dir = -to_target_dir
corridor_lat = np.linalg.norm(
ball_to_robot - np.sum(ball_to_robot * back_dir, axis=-1, keepdims=True) * back_dir,
axis=-1,
)
corridor_reward = reward.tolerance(
corridor_lat,
bounds=(0.0, self._cfg.fetch_corridor_width),
margin=self._cfg.fetch_corridor_width,
value_at_margin=0.0,
sigmoid="linear",
)
ball_dist = np.linalg.norm(to_ball, axis=-1)
near_ball_reward = reward.tolerance(
ball_dist,
bounds=(0.0, self._cfg.fetch_ready_ball_distance),
margin=self._cfg.fetch_ready_ball_distance,
value_at_margin=0.0,
sigmoid="linear",
)
ready = behind_align_reward * face_ball_reward * corridor_reward * near_ball_reward
ready_gate = reward.tolerance(
ready,
bounds=(self._cfg.fetch_ready_threshold, 1.0),
margin=1.0 - self._cfg.fetch_ready_threshold,
value_at_margin=0.0,
sigmoid="linear",
)
behind_pos = ball_pos[:, :2] + back_dir * self._cfg.fetch_behind_distance
ahead_pos = ball_pos[:, :2] + to_target_dir * self._cfg.fetch_ahead_distance
stage_pos = (1.0 - ready_gate)[:, None] * behind_pos + ready_gate[:, None] * ahead_pos
if self._cfg.fetch_side_stage_offset > 0.0:
side_dir = np.stack([-back_dir[:, 1], back_dir[:, 0]], axis=-1)
ball_to_robot_side = np.sum(ball_to_robot * side_dir, axis=-1)
side_sign = np.where(ball_to_robot_side >= 0.0, 1.0, -1.0)
side_pos = behind_pos + (side_sign[:, None] * side_dir * self._cfg.fetch_side_stage_offset)
use_side_stage = (
(ready_gate < self._cfg.fetch_side_stage_gate_threshold)
& (ball_dist < self._cfg.fetch_side_stage_ball_distance)
& (behind_align < self._cfg.fetch_side_stage_align_threshold)
)
stage_pos = np.where(use_side_stage[:, None], side_pos, stage_pos)
to_stage = stage_pos - torso_pos[:, :2]
stage_dist = np.linalg.norm(to_stage, axis=-1)
stage_dir = np.where(stage_dist[:, None] > 1e-6, to_stage / stage_dist[:, None], 0.0)
speed_to_stage = np.sum(data.dof_vel[:, :2] * stage_dir, axis=-1)
stage_move = reward.tolerance(
speed_to_stage,
bounds=(self._cfg.fetch_stage_speed, float("inf")),
margin=self._cfg.fetch_stage_speed,
value_at_margin=0.0,
sigmoid="linear",
)
backward_penalty = np.maximum(0.0, -speed_to_stage)
stage_reach = reward.tolerance(
stage_dist,
bounds=(0.0, self._cfg.fetch_stage_radius),
margin=self._cfg.fetch_stage_radius,
value_at_margin=0.0,
sigmoid="linear",
)
fetch_reward = reward.tolerance(
self._ball_to_target_distance(data),
bounds=(0.0, target_radius),
margin=self._cfg.fetch_reward_margin,
value_at_margin=0.0,
sigmoid="linear",
)
ball_vel = data.dof_vel[:, self._ball_vel_slice][:, :2]
ball_speed_to_target = np.sum(ball_vel * to_target_dir, axis=-1)
push_reward = reward.tolerance(
np.maximum(0.0, ball_speed_to_target),
bounds=(self._cfg.fetch_push_speed, float("inf")),
margin=self._cfg.fetch_push_speed,
value_at_margin=0.0,
sigmoid="linear",
)
away_penalty = (1.0 - ready_gate) * np.maximum(0.0, -ball_speed_to_target)
leg_ball_penalty = self._leg_body_ball_penalty(data)
rwd = stability_gate * upright_reward * stage_move
rwd -= self._cfg.fetch_backward_penalty_weight * backward_penalty
rwd += self._cfg.fetch_stage_reward_weight * (stability_gate * stage_reach)
rwd += self._cfg.fetch_heading_weight * (stability_gate * face_ball_reward)
rwd += self._cfg.fetch_ready_weight * (stability_gate * ready)
rwd += self._cfg.fetch_reward_weight * (stability_gate * ready_gate * fetch_reward)
rwd += self._cfg.fetch_push_reward_weight * (stability_gate * ready_gate * push_reward)
rwd -= self._cfg.fetch_away_penalty_weight * away_penalty
rwd -= self._cfg.fetch_leg_ball_penalty_weight * leg_ball_penalty
reward_components = {
"upright": upright_reward,
"stage_move": stage_move,
"stage_reach": stage_reach,
"stability": stability_gate,
"behind_align": behind_align_reward,
"face_ball": face_ball_reward,
"near_ball": near_ball_reward,
"ready": ready,
"ready_gate": ready_gate,
"fetch": fetch_reward,
"push": push_reward,
"away": away_penalty,
"leg_ball": leg_ball_penalty,
"backward": backward_penalty,
"total": rwd,
}
terminated = np.isnan(obs).any(axis=-1)
terminated |= self._fetch_fall_terminated(torso_upright, torso_height)
rwd = np.where(terminated, 0.0, rwd).astype(np.float32)
for key, value in reward_components.items():
reward_components[key] = np.where(terminated, 0.0, value).astype(np.float32)
state.info["Reward"] = reward_components
return state.replace(obs=obs, reward=rwd, terminated=terminated)
def reset(self, data: mtx.SceneData) -> tuple[np.ndarray, dict]:
data.reset(self._model)
num = int(data.shape[0])
dof_pos = np.tile(self._init_dof_pos, (num, 1))
dof_vel = np.zeros((num, self._model.num_dof_vel), dtype=np.float32)
floor_radius = float(self._floor_geom.size[0])
if floor_radius <= 0.0:
floor_radius = self._terrain_size
spawn_radius = 0.12 * floor_radius
yaw = np.random.uniform(0.0, 2 * np.pi, size=(num,))
dof_pos[:, 0] = np.random.uniform(-spawn_radius, spawn_radius, size=(num,))
dof_pos[:, 1] = np.random.uniform(-spawn_radius, spawn_radius, size=(num,))
dof_pos[:, 3:7] = self._yaw_quaternion(yaw)
ball_xy = np.random.uniform(-spawn_radius, spawn_radius, size=(num, 2))
ball_qpos = self._ball_pos_slice
dof_pos[:, ball_qpos.start : ball_qpos.start + 2] = ball_xy
ball_radius = float(self._ball_geom.size[0]) if self._ball_geom is not None else 0.15
dof_pos[:, ball_qpos.start + 2] = ball_radius
dof_pos[:, ball_qpos.start + 3 : ball_qpos.stop] = np.tile(
np.array([0.0, 0.0, 0.0, 1.0], dtype=np.float32), (num, 1)
)
ball_qvel = self._ball_vel_slice
dof_vel[:, ball_qvel.start : ball_qvel.stop] = 0.0
return self._finish_reset(data, dof_pos, dof_vel)

View File

@@ -0,0 +1,269 @@
<mujoco model="quadruped">
<include file="../../common/skybox.xml" />
<include file="../../common/visual.xml" />
<include file="./quadruped_materials.xml" />
<visual>
<rgba rangefinder="1 1 0.1 0.1" />
<map znear=".005" zfar="20" />
</visual>
<asset>
</asset>
<option timestep=".005" />
<default>
<geom solimp=".9 .99 .003" solref=".01 1" />
<default class="body">
<geom type="capsule" size=".08" condim="1" material="self" density="500" />
<joint type="hinge" damping="30" armature=".01" limited="true" solimplimit="0 .99 .01" />
<default class="hip">
<default class="yaw">
<joint axis="0 0 1" range="-50 50" />
</default>
<default class="pitch">
<joint axis="0 1 0" range="-20 60" />
</default>
<geom fromto="0 0 0 .3 0 .11" />
</default>
<default class="knee">
<joint axis="0 1 0" range="-60 25" />
<geom size=".065" fromto="0 0 0 .25 0 -.25" />
</default>
<default class="ankle">
<joint axis="0 1 0" range="-45 45" />
<geom size=".055" fromto="0 0 0 0 0 -.25" />
</default>
<default class="toe">
<geom type="sphere" size=".08" material="effector" friction="1.5" />
<site type="sphere" size=".084" material="site" group="4" />
</default>
</default>
<default class="rangefinder">
<site type="capsule" size=".005 .1" material="site" group="4" />
</default>
<default class="wall">
<geom type="plane" material="decoration" />
</default>
<default class="coupling">
<equality solimp="0.95 0.99 0.01" solref=".005 .5" />
</default>
<general ctrllimited="true" gainprm="1000" biasprm="0 -1000" biastype="affine" dyntype="filter" dynprm=".1" />
<default class="yaw_act">
<general ctrlrange="-1 1" />
</default>
<default class="lift_act">
<general ctrlrange="-1 1.1" />
</default>
<default class="extend_act">
<general ctrlrange="-.8 .8" />
</default>
</default>
<asset>
<texture name="ball" builtin="checker" mark="cross" width="151" height="151" rgb1="0.1 0.1 0.1" rgb2="0.9 0.9 0.9" markrgb="1 1 1" />
<material name="ball" texture="ball" />
</asset>
<worldbody>
<geom name="floor" type="plane" size="0 0 0.01" material="motphys-ground" />
<light pos="0 0 1.5" dir="0 0 -1" directional="true" />
<camera name="global" pos="-10 10 10" xyaxes="-1 -1 0 1 0 1" mode="trackcom" />
<body name="torso" childclass="body" pos="0 0 .57">
<freejoint name="root" />
<camera name="x" pos="-1.7 0 1" xyaxes="0 -1 0 .75 0 1" mode="trackcom" />
<camera name="y" pos="0 4 2" xyaxes="-1 0 0 0 -.5 1" mode="trackcom" />
<camera name="egocentric" pos=".3 0 .11" xyaxes="0 -1 0 .4 0 1" fovy="60" />
<geom name="eye_r" type="cylinder" size=".05" fromto=".1 -.07 .12 .31 -.07 .08" mass="0" />
<site name="pupil_r" type="sphere" size=".033" pos=".3 -.07 .08" zaxis="1 0 0" material="eye" />
<geom name="eye_l" type="cylinder" size=".05" fromto=".1 .07 .12 .31 .07 .08" mass="0" />
<site name="pupil_l" type="sphere" size=".033" pos=".3 .07 .08" zaxis="1 0 0" material="eye" />
<site name="workspace" type="sphere" size=".3 .3 .3" material="site" pos=".8 0 -.2" group="3" />
<geom name="torso" type="box" size=".3 .27 .2" density="1000" />
<site name="torso_touch" type="box" size=".26 .26 .26" rgba="0 0 1 0" />
<site name="torso" size=".05" rgba="1 0 0 1" />
<body name="hip_front_left" pos=".2 .2 0" euler="0 0 45" childclass="hip">
<joint name="yaw_front_left" class="yaw" />
<joint name="pitch_front_left" class="pitch" />
<geom name="thigh_front_left" />
<body name="knee_front_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_left" />
<geom name="shin_front_left" />
<body name="ankle_front_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_left" />
<geom name="foot_front_left" />
<body name="toe_front_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_left" />
<site name="toe_front_left" />
</body>
</body>
</body>
</body>
<body name="hip_front_right" pos=".2 -.2 0" euler="0 0 -45" childclass="hip">
<joint name="yaw_front_right" class="yaw" />
<joint name="pitch_front_right" class="pitch" />
<geom name="thigh_front_right" />
<body name="knee_front_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_front_right" />
<geom name="shin_front_right" />
<body name="ankle_front_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_front_right" />
<geom name="foot_front_right" />
<body name="toe_front_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_front_right" />
<site name="toe_front_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_right" pos="-.2 -.2 0" euler="0 0 -135" childclass="hip">
<joint name="yaw_back_right" class="yaw" />
<joint name="pitch_back_right" class="pitch" />
<geom name="thigh_back_right" />
<body name="knee_back_right" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_right" />
<geom name="shin_back_right" />
<body name="ankle_back_right" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_right" />
<geom name="foot_back_right" />
<body name="toe_back_right" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_right" />
<site name="toe_back_right" />
</body>
</body>
</body>
</body>
<body name="hip_back_left" pos="-.2 .2 0" euler="0 0 135" childclass="hip">
<joint name="yaw_back_left" class="yaw" />
<joint name="pitch_back_left" class="pitch" />
<geom name="thigh_back_left" />
<body name="knee_back_left" pos=".3 0 .11" childclass="knee">
<joint name="knee_back_left" />
<geom name="shin_back_left" />
<body name="ankle_back_left" pos=".25 0 -.25" childclass="ankle">
<joint name="ankle_back_left" />
<geom name="foot_back_left" />
<body name="toe_back_left" pos="0 0 -.3" childclass="toe">
<geom name="toe_back_left" />
<site name="toe_back_left" />
</body>
</body>
</body>
</body>
</body>
</worldbody>
<tendon>
<fixed name="coupling_front_left">
<joint joint="pitch_front_left" coef=".333" />
<joint joint="knee_front_left" coef=".333" />
<joint joint="ankle_front_left" coef=".333" />
</fixed>
<fixed name="coupling_front_right">
<joint joint="pitch_front_right" coef=".333" />
<joint joint="knee_front_right" coef=".333" />
<joint joint="ankle_front_right" coef=".333" />
</fixed>
<fixed name="coupling_back_right">
<joint joint="pitch_back_right" coef=".333" />
<joint joint="knee_back_right" coef=".333" />
<joint joint="ankle_back_right" coef=".333" />
</fixed>
<fixed name="coupling_back_left">
<joint joint="pitch_back_left" coef=".333" />
<joint joint="knee_back_left" coef=".333" />
<joint joint="ankle_back_left" coef=".333" />
</fixed>
<fixed name="extend_front_left">
<joint joint="pitch_front_left" coef=".25" />
<joint joint="knee_front_left" coef="-.5" />
<joint joint="ankle_front_left" coef=".25" />
</fixed>
<fixed name="lift_front_left">
<joint joint="pitch_front_left" coef=".5" />
<joint joint="ankle_front_left" coef="-.5" />
</fixed>
<fixed name="extend_front_right">
<joint joint="pitch_front_right" coef=".25" />
<joint joint="knee_front_right" coef="-.5" />
<joint joint="ankle_front_right" coef=".25" />
</fixed>
<fixed name="lift_front_right">
<joint joint="pitch_front_right" coef=".5" />
<joint joint="ankle_front_right" coef="-.5" />
</fixed>
<fixed name="extend_back_right">
<joint joint="pitch_back_right" coef=".25" />
<joint joint="knee_back_right" coef="-.5" />
<joint joint="ankle_back_right" coef=".25" />
</fixed>
<fixed name="lift_back_right">
<joint joint="pitch_back_right" coef=".5" />
<joint joint="ankle_back_right" coef="-.5" />
</fixed>
<fixed name="extend_back_left">
<joint joint="pitch_back_left" coef=".25" />
<joint joint="knee_back_left" coef="-.5" />
<joint joint="ankle_back_left" coef=".25" />
</fixed>
<fixed name="lift_back_left">
<joint joint="pitch_back_left" coef=".5" />
<joint joint="ankle_back_left" coef="-.5" />
</fixed>
</tendon>
<equality>
<tendon name="coupling_front_left" tendon1="coupling_front_left" class="coupling" />
<tendon name="coupling_front_right" tendon1="coupling_front_right" class="coupling" />
<tendon name="coupling_back_right" tendon1="coupling_back_right" class="coupling" />
<tendon name="coupling_back_left" tendon1="coupling_back_left" class="coupling" />
</equality>
<actuator>
<general name="yaw_front_left" class="yaw_act" joint="yaw_front_left" />
<general name="lift_front_left" class="lift_act" tendon="lift_front_left" />
<general name="extend_front_left" class="extend_act" tendon="extend_front_left" />
<general name="yaw_front_right" class="yaw_act" joint="yaw_front_right" />
<general name="lift_front_right" class="lift_act" tendon="lift_front_right" />
<general name="extend_front_right" class="extend_act" tendon="extend_front_right" />
<general name="yaw_back_right" class="yaw_act" joint="yaw_back_right" />
<general name="lift_back_right" class="lift_act" tendon="lift_back_right" />
<general name="extend_back_right" class="extend_act" tendon="extend_back_right" />
<general name="yaw_back_left" class="yaw_act" joint="yaw_back_left" />
<general name="lift_back_left" class="lift_act" tendon="lift_back_left" />
<general name="extend_back_left" class="extend_act" tendon="extend_back_left" />
</actuator>
<sensor>
<accelerometer name="imu_accel" site="torso" />
<gyro name="imu_gyro" site="torso" />
<velocimeter name="velocimeter" site="torso" />
<force name="force_toe_front_left" site="toe_front_left" />
<force name="force_toe_front_right" site="toe_front_right" />
<force name="force_toe_back_right" site="toe_back_right" />
<force name="force_toe_back_left" site="toe_back_left" />
<torque name="torque_toe_front_left" site="toe_front_left" />
<torque name="torque_toe_front_right" site="toe_front_right" />
<torque name="torque_toe_back_right" site="toe_back_right" />
<torque name="torque_toe_back_left" site="toe_back_left" />
<subtreecom name="center_of_mass" body="torso" />
</sensor>
</mujoco>

View File

@@ -79,7 +79,6 @@ class Reacher2DEnv(NpEnv):
terminated = np.isnan(obs).any(axis=-1)
rwd[terminated] = 0.0
state.info["target_info"] = {"positions": self._target_xyz.copy(), "size": self._target_size}
state.info["Reward"] = {"distance": dist, "tolerance": rwd.copy()}
return state.replace(obs=obs, reward=rwd, terminated=terminated)
@@ -110,6 +109,8 @@ class Reacher2DEnv(NpEnv):
obs = self._get_obs(data)
rewards = {"distance": np.zeros((num_reset,)), "tolerance": np.zeros((num_reset,))}
info = {"Reward": rewards, "target_info": {"positions": self._target_xyz.copy(), "size": self._target_size}}
info = {
"Reward": rewards,
}
return obs, info

View File

@@ -500,25 +500,25 @@ class AnymalCEnv(NpEnv):
pos_range[0],
pos_range[2], # x_min, x_max
num_envs,
)
).astype(np.float32)
robot_init_y = np.random.uniform(
pos_range[1],
pos_range[3], # y_min, y_max
num_envs,
)
).astype(np.float32)
robot_init_pos = np.stack([robot_init_x, robot_init_y], axis=1) # [num_envs, 2]
# Generate target position: offset relative to robot initial position
# pose_command_range now represents offset range relative to robot
target_offset = np.random.uniform(
low=cfg.commands.pose_command_range[:2], high=cfg.commands.pose_command_range[3:5], size=(num_envs, 2)
)
).astype(np.float32)
target_positions = robot_init_pos + target_offset # Target position in world coordinates
# Generate target heading (absolute heading, random in horizontal direction)
target_headings = np.random.uniform(
low=cfg.commands.pose_command_range[2], high=cfg.commands.pose_command_range[5], size=(num_envs, 1)
)
).astype(np.float32)
pose_commands = np.concatenate([target_positions, target_headings], axis=1)

View File

@@ -92,6 +92,7 @@ class Sensor:
feet = ["FR", "FL", "RR", "RL"]
# -- docs-tag-start: go1-reward-config --
@dataclass
class RewardConfig:
scales: dict[str, float] = field(
@@ -119,6 +120,9 @@ class RewardConfig:
max_foot_height: float = 0.1
# -- docs-tag-end: go1-reward-config --
@registry.envcfg("go1-flat-terrain-walk")
@dataclass
class Go1WalkNpEnvCfg(EnvCfg):

View File

@@ -244,7 +244,7 @@ class Go1WalkTask(NpEnv):
high=self.cfg.commands.vel_limit[1],
size=(num_envs, 3),
)
return commands
return commands.astype(np.float32)
def update_reward(self, state: NpEnvState) -> NpEnvState:
data = state.data
@@ -266,12 +266,9 @@ class Go1WalkTask(NpEnv):
def reset(self, data) -> tuple[np.ndarray, dict]:
num_reset = data.shape[0]
dof_pos = np.tile(self._init_dof_pos, (num_reset, 1))
dof_vel = np.tile(self._init_dof_vel, (num_reset, 1))
data.reset(self._model)
data.set_dof_vel(dof_vel)
data.set_dof_pos(dof_pos, self._model)
data.set_dof_vel(self._init_dof_vel)
data.set_dof_pos(self._init_dof_pos, self._model)
self._model.forward_kinematic(data)
info = {

View File

@@ -271,7 +271,7 @@ class Go1WalkRoughTask(NpEnv):
size=(num_envs, 3),
)
# commands[:, 2] = 0
return commands
return commands.astype(np.float32)
def update_reward(self, state: NpEnvState) -> NpEnvState:
data = state.data

View File

@@ -287,7 +287,7 @@ class Go1WalkStairsTask(NpEnv):
high=self.cfg.commands.vel_limit[1],
size=(num_envs, 3),
)
return commands
return commands.astype(np.float32)
def update_reward(self, state: NpEnvState) -> NpEnvState:
data = state.data

View File

@@ -234,7 +234,7 @@ class Go2WalkTask(NpEnv):
high=self.cfg.commands.vel_limit[1],
size=(num_envs, 3),
)
return commands
return commands.astype(np.float32)
def update_reward(self, state: NpEnvState) -> NpEnvState:
data = state.data

View File

@@ -13,4 +13,9 @@
# limitations under the License.
# ==============================================================================
from . import franka_lift_cube, franka_open_cabinet, shadow_hand # noqa: F401 import to register envs
from . import (
franka_lift_cube,
franka_open_cabinet,
rm65_open_cabinet,
shadow_hand,
)

View File

@@ -117,8 +117,7 @@
<worldbody>
<body name="link0" childclass="panda">
<inertial mass="0.629769" pos="-0.041018 -0.00014 0.049974"
fullinertia="0.00315 0.00388 0.004285 8.2904e-7 0.00015 8.2299e-6"/>
<inertial mass="0.629769" pos="-0.041018 -0.00014 0.049974" fullinertia="0.00315 0.00388 0.004285 8.2904e-7 0.00015 8.2299e-6"/>
<geom mesh="link0_0" material="off_white" class="visual"/>
<geom mesh="link0_1" material="black" class="visual"/>
<geom mesh="link0_2" material="off_white" class="visual"/>
@@ -132,29 +131,25 @@
<geom mesh="link0_11" material="white" class="visual"/>
<geom mesh="link0_c" class="collision"/>
<body name="link1" pos="0 0 0.333">
<inertial mass="4.970684" pos="0.003875 0.002081 -0.04762"
fullinertia="0.70337 0.70661 0.0091170 -0.00013900 0.0067720 0.019169"/>
<inertial mass="4.970684" pos="0.003875 0.002081 -0.04762" fullinertia="0.70337 0.70661 0.0091170 -0.00013900 0.0067720 0.019169"/>
<joint name="joint1" damping="40"/>
<geom material="white" mesh="link1" class="visual"/>
<geom mesh="link1_c" class="collision"/>
<body name="link2" quat="1 -1 0 0">
<inertial mass="0.646926" pos="-0.003141 -0.02872 0.003495"
fullinertia="0.0079620 2.8110e-2 2.5995e-2 -3.925e-3 1.0254e-2 7.04e-4"/>
<inertial mass="0.646926" pos="-0.003141 -0.02872 0.003495" fullinertia="0.0079620 2.8110e-2 2.5995e-2 -3.925e-3 1.0254e-2 7.04e-4"/>
<joint name="joint2" range="-1.7628 1.7628" damping="40"/>
<geom material="white" mesh="link2" class="visual"/>
<geom mesh="link2_c" class="collision"/>
<body name="link3" pos="0 -0.316 0" quat="1 1 0 0">
<joint name="joint3" damping="40"/>
<inertial mass="3.228604" pos="2.7518e-2 3.9252e-2 -6.6502e-2"
fullinertia="3.7242e-2 3.6155e-2 1.083e-2 -4.761e-3 -1.1396e-2 -1.2805e-2"/>
<inertial mass="3.228604" pos="2.7518e-2 3.9252e-2 -6.6502e-2" fullinertia="3.7242e-2 3.6155e-2 1.083e-2 -4.761e-3 -1.1396e-2 -1.2805e-2"/>
<geom mesh="link3_0" material="white" class="visual"/>
<geom mesh="link3_1" material="white" class="visual"/>
<geom mesh="link3_2" material="white" class="visual"/>
<geom mesh="link3_3" material="black" class="visual"/>
<geom mesh="link3_c" class="collision"/>
<body name="link4" pos="0.0825 0 0" quat="1 1 0 0">
<inertial mass="3.587895" pos="-5.317e-2 1.04419e-1 2.7454e-2"
fullinertia="2.5853e-2 1.9552e-2 2.8323e-2 7.796e-3 -1.332e-3 8.641e-3"/>
<inertial mass="3.587895" pos="-5.317e-2 1.04419e-1 2.7454e-2" fullinertia="2.5853e-2 1.9552e-2 2.8323e-2 7.796e-3 -1.332e-3 8.641e-3"/>
<joint name="joint4" range="-3.0718 -0.0698" damping="40"/>
<geom mesh="link4_0" material="white" class="visual"/>
<geom mesh="link4_1" material="white" class="visual"/>
@@ -162,8 +157,7 @@
<geom mesh="link4_3" material="white" class="visual"/>
<geom mesh="link4_c" class="collision"/>
<body name="link5" pos="-0.0825 0.384 0" quat="1 -1 0 0">
<inertial mass="1.225946" pos="-1.1953e-2 4.1065e-2 -3.8437e-2"
fullinertia="3.5549e-2 2.9474e-2 8.627e-3 -2.117e-3 -4.037e-3 2.29e-4"/>
<inertial mass="1.225946" pos="-1.1953e-2 4.1065e-2 -3.8437e-2" fullinertia="3.5549e-2 2.9474e-2 8.627e-3 -2.117e-3 -4.037e-3 2.29e-4"/>
<joint name="joint5" damping="2"/>
<geom mesh="link5_0" material="black" class="visual"/>
<geom mesh="link5_1" material="white" class="visual"/>
@@ -172,8 +166,7 @@
<geom mesh="link5_c1" class="collision"/>
<geom mesh="link5_c2" class="collision"/>
<body name="link6" quat="1 1 0 0">
<inertial mass="1.666555" pos="6.0149e-2 -1.4117e-2 -1.0517e-2"
fullinertia="1.964e-3 4.354e-3 5.433e-3 1.09e-4 -1.158e-3 3.41e-4"/>
<inertial mass="1.666555" pos="6.0149e-2 -1.4117e-2 -1.0517e-2" fullinertia="1.964e-3 4.354e-3 5.433e-3 1.09e-4 -1.158e-3 3.41e-4"/>
<joint name="joint6" range="-0.0175 3.7525" damping="2"/>
<geom mesh="link6_0" material="off_white" class="visual"/>
<geom mesh="link6_1" material="white" class="visual"/>
@@ -194,8 +187,7 @@
<geom mesh="link6_16" material="white" class="visual"/>
<geom mesh="link6_c" class="collision"/>
<body name="link7" pos="0.088 0 0" quat="1 1 0 0">
<inertial mass="7.35522e-01" pos="1.0517e-2 -4.252e-3 6.1597e-2"
fullinertia="1.2516e-2 1.0027e-2 4.815e-3 -4.28e-4 -1.196e-3 -7.41e-4"/>
<inertial mass="7.35522e-01" pos="1.0517e-2 -4.252e-3 6.1597e-2" fullinertia="1.2516e-2 1.0027e-2 4.815e-3 -4.28e-4 -1.196e-3 -7.41e-4"/>
<joint name="joint7" damping="2"/>
<geom mesh="link7_0" material="white" class="visual"/>
<geom mesh="link7_1" material="black" class="visual"/>
@@ -214,9 +206,7 @@
<geom mesh="hand_3" material="white" class="visual"/>
<geom mesh="hand_4" material="off_white" class="visual"/>
<geom mesh="hand_c" class="collision"/>
<geom name="hand_capsule" type="capsule"
class="collision" conaffinity="1" size="0.04 0.06"
quat="1 1 0 0" pos="0 0 0.03"/>
<geom name="hand_capsule" type="capsule" class="collision" conaffinity="1" size="0.04 0.06" quat="1 1 0 0" pos="0 0 0.03"/>
<site name="gripper" pos="0 0 0.1"/>
<body name="left_finger" pos="0 0 0.0584">
<inertial mass="0.015" pos="0 0 0" diaginertia="2.375e-6 2.375e-6 7.5e-7"/>
@@ -258,21 +248,14 @@
</equality>
<actuator>
<position class="panda" name="actuator1" joint="joint1" kp="1000" kv="20"
ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator2" joint="joint2" kp="1000" kv="20"
ctrlrange="-1.7628 1.7628"/>
<position class="panda" name="actuator3" joint="joint3" kp="750" kv="4"
ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator4" joint="joint4" kp="750" kv="4"
ctrlrange="-3.0718 -0.0698"/>
<position class="panda" name="actuator5" joint="joint5" kp="300" kv="2"
forcerange="-12 12" ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator6" joint="joint6" kp="300" kv="2" forcerange="-12 12"
ctrlrange="-0.0175 3.7525"/>
<position class="panda" name="actuator1" joint="joint1" kp="1000" kv="20" ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator2" joint="joint2" kp="1000" kv="20" ctrlrange="-1.7628 1.7628"/>
<position class="panda" name="actuator3" joint="joint3" kp="750" kv="4" ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator4" joint="joint4" kp="750" kv="4" ctrlrange="-3.0718 -0.0698"/>
<position class="panda" name="actuator5" joint="joint5" kp="300" kv="2" forcerange="-12 12" ctrlrange="-2.8973 2.8973"/>
<position class="panda" name="actuator6" joint="joint6" kp="300" kv="2" forcerange="-12 12" ctrlrange="-0.0175 3.7525"/>
<position class="panda" name="actuator7" joint="joint7" kp="300" kv="2" forcerange="-12 12"/>
<general class="panda" name="actuator8" joint="finger_joint1"
ctrlrange="0 0.04" gainprm="350 0 0" biasprm="0 -350 -10" forcerange="-200 200"/>
<general class="panda" name="actuator8" joint="finger_joint1" ctrlrange="0 0.04" gainprm="350 0 0" biasprm="0 -350 -10" forcerange="-200 200"/>
</actuator>
<contact>

View File

@@ -15,43 +15,33 @@
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3" specular="0 0 0" />
<rgba haze="0.15 0.25 0.35 1" />
<global azimuth="120" elevation="-20" />
<scale contactwidth="0.075" contactheight="0.025" forcewidth="0.05" com="0.05" framewidth="0.01"
framelength="0.2" />
<scale contactwidth="0.075" contactheight="0.025" forcewidth="0.05" com="0.05" framewidth="0.01" framelength="0.2" />
</visual>
<asset>
<material name="Transport" rgba="0 1 0 0" reflectance="0.5" metallic="0.0" roughness="0.5" />
<texture type="2d" colorspace="sRGB" name="small_meta_table_diffuse"
file="small_meta_table_diffuse.png" />
<texture type="2d" colorspace="linear" name="small_meta_table_nrm"
file="small_meta_table_nrm.png" />
<texture type="2d" colorspace="linear" name="small_meta_table_orm"
file="small_meta_table_orm.png" />
<texture type="2d" colorspace="sRGB" name="small_meta_table_diffuse" file="small_meta_table_diffuse.png" />
<texture type="2d" colorspace="linear" name="small_meta_table_nrm" file="small_meta_table_nrm.png" />
<texture type="2d" colorspace="linear" name="small_meta_table_orm" file="small_meta_table_orm.png" />
<material name="wood" rgba="0.8 0.8 0.8 1" reflectance="0.25" metallic="0.0" roughness=".95">
<layer texture="small_meta_table_diffuse" role="rgb" />
<layer texture="small_meta_table_nrm" role="normal" />
<layer texture="small_meta_table_orm" role="orm" />
</material>
<!-- Table dimensions (length x width x height in meters): 1.21x0.76x0.75 -->
<material name="chrome" rgba="0.8 0.8 0.8 1" reflectance="0.5" metallic="1.0"
roughness="0.44999998807907104" />
<material name="chrome" rgba="0.8 0.8 0.8 1" reflectance="0.5" metallic="1.0" roughness="0.44999998807907104" />
<mesh file="tablelegs.obj" />
<mesh file="tabletop.obj" />
<texture name="skybox" type="skybox" builtin="gradient" rgb1="0.4 0.4 0.4" rgb2="0 0 0"
width="512"
height="512" />
<texture name="skybox" type="skybox" builtin="gradient" rgb1="0.4 0.4 0.4" rgb2="0 0 0" width="512" height="512" />
<texture name="motphys-ground" type="2d" file="../../../common/motphys-ground.png" />
<material name="motphys-ground" texture="motphys-ground" texuniform="true"
texrepeat="0.4 0.4" />
<material name="motphys-ground" texture="motphys-ground" texuniform="true" texrepeat="0.4 0.4" />
</asset>
<worldbody>
<light diffuse="0.6 0.6 0.6" pos="0 0 1.5"
dir="-0.49835488200187683 0.2925136387348175 -0.8161361217498779" directional="true" />
<geom name="floor" size="0 0 0.05" pos="0 0 -0.75" type="plane" material="motphys-ground"
contype="1" />
<light diffuse="0.6 0.6 0.6" pos="0 0 1.5" dir="-0.49835488200187683 0.2925136387348175 -0.8161361217498779" directional="true" />
<geom name="floor" size="0 0 0.05" pos="0 0 -0.75" type="plane" material="motphys-ground" contype="1" />
<geom mesh="tabletop" material="wood" class="visual" pos="0.3 0 -0.75" quat="1 0 0 1" />
<geom mesh="tablelegs" material="chrome" class="visual" pos="0.3 0 -0.75" quat="1 0 0 1" />

View File

@@ -0,0 +1,16 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from . import rm65_open_cabinet_np # noqa: F401

View File

@@ -0,0 +1,153 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
import os
from dataclasses import dataclass, field
from motrix_envs import registry
from motrix_envs.base import EnvCfg
model_file = os.path.dirname(__file__) + "/xmls/scene.xml"
@dataclass
class ResetConfig:
joint_pos_noise_scale: float = 0
@dataclass
class ArmControlConfig:
action_mode: str = "joint_target"
action_in_degrees: bool = False
target_action_normalized: bool = True
max_joint_speed: float = 1.15
max_joint_acc: float = 10.47
use_speed_limit: bool = True
use_acc_limit: bool = True
target_smoothing_alpha: float = 0.0
action_delay_steps: int = 6
actuator_lag_alpha: float = 0.062
delay_lag_randomization_enabled: bool = True
action_delay_steps_min: int = 6
action_delay_steps_max: int = 7
actuator_lag_alpha_min: float = 0.059
actuator_lag_alpha_max: float = 0.064
speed_acc_randomization_enabled: bool = True
max_joint_speed_min: float = 0.95
max_joint_speed_max: float = 1.35
max_joint_acc_min: float = 8.5
max_joint_acc_max: float = 12.0
@dataclass
class GripperControlConfig:
action_mode: str = "binary"
use_sigmoid: bool = True
close_threshold: float = 0.7
close_on_threshold: float = 0.78
open_off_threshold: float = 0.62
min_switch_interval_s: float = 0.25
max_speed: float = 4.0
use_speed_limit: bool = True
actuator_lag_alpha: float = 0.062
@dataclass
class RewardConfig:
dist_std: float = 0.4
dist_scale: float = 15.0
gripper_close_dist: float = 0.035
gripper_close_reward: float = 140.0
gripper_close_penalty: float = -8.0
grasp_dist: float = 0.03
grasp_close_ratio: float = 0.7
grasp_hold_steps: int = 6
open_reward_scale: float = 420.0
open_delta_reward_scale: float = 260.0
open_reward_strict_dist: float = 0.08
grasp_hold_reward_scale: float = 8.0
grasp_hold_open_scale: float = 10.0
open_bonus_dist_1: float = 0.15
open_bonus_reward_1: float = 35.0
open_bonus_dist_2: float = 0.22
open_bonus_reward_2: float = 70.0
slip_penalty: float = 20.0
slip_penalty_open_scale: float = 65.0
slip_open_dist_thresh: float = 0.002
action_penalty_rate_late: float = 4e-3
finger_penalty_weight: float = 6.0
finger_penalty_dist: float = 0.6
finger_align_reward: float = 8.0
finger_align_close_amount_thresh: float = 0.05
gripper_switch_penalty: float = 0.8
gripper_switch_penalty_dist: float = 0.10
quat_reward_scale: float = 12
quat_reward_dist_thresh: float = 0.5
wrong_open_dist: float = 0.032
action_penalty_switch_step: int = 12000
action_penalty_rate_early: float = 8e-4
joint_vel_penalty_rate_early: float = 0.0
joint_vel_penalty_rate_late: float = 5e-3
truncation_penalty: float = 10.0
@dataclass
class TerminationConfig:
tcp_behind_handle_threshold: float = -0.02
max_joint_vel: float = 3.93
@dataclass
class ObservationNoiseConfig:
enabled: bool = True
joint_noise_enabled: bool = True
handle_pose_noise_enabled: bool = True
joint_pos_std: float = 2e-5
joint_vel_std: float = 1e-4
target_pos_std: float = 0.01
target_rot_std: float = 0.017
target_pos_bias_std: float = 0.015
target_rot_bias_std: float = 0.03
bias_resample_prob: float = 0.0
dropout_prob: float = 0.091
latency_steps: int = 0
hold_last_on_dropout: bool = True
@registry.envcfg("rm65-open-cabinet")
@dataclass
class RM65OpenCabinetEnvCfg(EnvCfg):
model_file: str = model_file
max_episode_seconds: float = 30.0
sim_dt: float = 0.005
ctrl_dt: float = 0.025
render_spacing: float = 2.0
action_scale = (0.05, 0.05, 0.05, 0.05, 0.05, 0.05)
action_history_len: int = 9
reset: ResetConfig = field(default_factory=ResetConfig)
reward: RewardConfig = field(default_factory=RewardConfig)
termination: TerminationConfig = field(default_factory=TerminationConfig)
arm_control: ArmControlConfig = field(default_factory=ArmControlConfig)
gripper_control: GripperControlConfig = field(default_factory=GripperControlConfig)
observation_noise: ObservationNoiseConfig = field(default_factory=ObservationNoiseConfig)

View File

@@ -0,0 +1,62 @@
# Copyright (C) 2020-2025 Motphys Technology Co., Ltd. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from __future__ import annotations
import numpy as np
def raw_action_to_close_ratio(raw_gripper_action: np.ndarray, use_sigmoid: bool) -> np.ndarray:
raw = np.asarray(raw_gripper_action, dtype=np.float32)
if bool(use_sigmoid):
return 1.0 / (1.0 + np.exp(-raw))
return np.clip((raw + 1.0) * 0.5, 0.0, 1.0)
def binary_hysteresis_step(
*,
close_ratio: np.ndarray,
prev_closed: np.ndarray,
steps_since_switch: np.ndarray,
close_on_threshold: float,
open_off_threshold: float,
min_switch_interval_steps: int,
) -> tuple[np.ndarray, np.ndarray]:
close_ratio = np.asarray(close_ratio, dtype=np.float32)
prev_closed = np.asarray(prev_closed, dtype=bool)
steps_since_switch = np.asarray(steps_since_switch, dtype=np.int32)
close_on = float(np.clip(close_on_threshold, 0.0, 1.0))
open_off = float(np.clip(open_off_threshold, 0.0, 1.0))
if open_off > close_on:
open_off = close_on
min_steps = max(int(min_switch_interval_steps), 0)
can_switch = steps_since_switch >= min_steps
want_close = close_ratio > close_on
want_open = close_ratio < open_off
next_closed = prev_closed.copy()
next_closed = np.where(
np.logical_and(np.logical_not(prev_closed), np.logical_and(can_switch, want_close)),
True,
next_closed,
)
next_closed = np.where(
np.logical_and(prev_closed, np.logical_and(can_switch, want_open)),
False,
next_closed,
)
switched = next_closed != prev_closed
return next_closed.astype(bool), switched.astype(bool)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,176 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e9d29e9a8cd2187d4cc54c17d261a8f0dba4fd75f43c3913194b1d4ad87c74b4
size 444

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d2416faaf6f93732f15dc8748a830621ceef393822f388a2f1e5335f05128a35
size 16120

View File

@@ -0,0 +1,13 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material.001
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.840000 0.80000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
# map_Kd WoodFine0035_1_S.jpg

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:faac6910a79c21389ed9ad3cb4177c51bb674b77b30b1717bdbbf6ca2ee23227
size 65480

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5883b7c6f94df7ec293b4f56f9cdbf1cb78cde84b7ffc8d20154e1d8f0c8cf93
size 17184

View File

@@ -0,0 +1,553 @@
#VRML V2.0 utf8
Group {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.975 0.486 0.975
specularColor 0.7 0.7 1.0
}
}
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
-0.010282 -0.189491 0.188934,
-0.008882 -0.190891 0.188934,
-0.006123 -0.190891 0.188934,
-0.010282 -0.184131 0.188934,
-0.006123 -0.190891 0.210934,
-0.010282 -0.184131 0.210934,
-0.006123 -0.184131 0.210934,
-0.010282 -0.189491 -0.189757,
-0.010282 -0.184131 -0.189757,
-0.006123 -0.190891 -0.189757,
-0.008882 -0.190891 -0.189757,
-0.006123 -0.190891 -0.211757,
-0.010282 -0.184131 -0.211757,
-0.010282 -0.189491 -0.211757,
-0.008882 -0.190891 -0.211757,
-0.008882 -0.190891 0.210934,
-0.010282 -0.189491 0.210934,
-0.006123 -0.184131 0.188934,
-0.006123 -0.184131 -0.189757,
-0.006123 -0.184131 -0.211757,
0.009747 -0.106958 -0.165943,
0.009747 0.104562 -0.165943,
0.009747 0.104562 0.165120,
0.009747 -0.106958 0.165120,
-0.010282 -0.139733 0.195593,
-0.010282 0.137337 0.195593,
-0.010282 0.137337 -0.196416,
-0.010282 -0.139733 -0.196416,
0.003847 -0.139733 0.195593,
0.003847 0.137337 0.195593,
0.003847 0.137337 -0.196416,
0.003847 -0.139733 -0.196416,
0.003847 -0.116058 0.175151,
0.009324 -0.107677 0.166763,
0.009324 0.105281 0.166763,
0.003847 0.113662 0.175151,
0.003847 -0.119309 -0.172721,
0.009324 -0.110927 -0.164332,
0.009324 -0.110927 0.163509,
0.003847 -0.119309 0.171898,
0.003847 0.113662 -0.175974,
0.009324 0.105281 -0.167586,
0.009324 -0.107677 -0.167586,
0.003847 -0.116058 -0.175974,
0.003847 0.116913 0.171898,
0.009324 0.108531 0.163509,
0.009324 0.108531 -0.164332,
0.003847 0.116913 -0.172721,
0.003847 -0.117480 0.174948,
0.009324 -0.109099 0.166560,
0.003847 -0.118496 0.174338,
0.009324 -0.110115 0.165949,
0.009324 0.106703 0.166560,
0.003847 0.115084 0.174948,
0.009324 0.107719 0.165949,
0.003847 0.116100 0.174338,
0.003847 -0.119106 -0.174144,
0.009324 -0.110724 -0.165755,
0.003847 -0.118496 -0.175161,
0.009324 -0.110115 -0.166772,
0.009324 -0.110724 0.164933,
0.003847 -0.119106 0.173321,
0.003847 0.115084 -0.175771,
0.009324 0.106703 -0.167382,
0.003847 0.116100 -0.175161,
0.009324 0.107719 -0.166772,
0.009324 -0.109099 -0.167382,
0.003847 -0.117480 -0.175771,
0.003847 0.116710 0.173321,
0.009324 0.108328 0.164933,
0.009324 0.108328 -0.165755,
0.003847 0.116710 -0.174144,
0.009747 -0.108112 0.164955,
0.009747 -0.108742 0.164576,
0.009747 -0.109121 0.163945,
0.009747 -0.109286 0.162790,
0.009747 -0.108743 -0.165399,
0.009747 -0.109121 -0.164767,
0.009747 -0.108112 -0.165778,
0.009747 0.105716 -0.165778,
0.009747 0.106347 -0.165399,
0.009747 0.106725 -0.164767,
0.009747 0.106890 -0.163613,
0.009747 0.106890 0.162790,
0.009747 0.106725 0.163945,
0.009747 0.106347 0.164576,
0.009747 0.105716 0.164955,
0.008363 0.136073 0.253550,
-0.008882 0.136073 0.253550,
-0.008882 -0.138469 0.253550,
0.008363 -0.138469 0.253550,
-0.008882 0.136073 -0.254373,
0.008363 0.136073 -0.254373,
0.008363 -0.138469 -0.254373,
-0.008882 -0.138469 -0.254373,
0.009763 -0.138469 -0.252973,
0.009763 0.136073 -0.252973,
0.009763 0.136073 -0.197681,
0.009763 -0.138469 -0.197681,
-0.010282 -0.138469 -0.252973,
-0.010282 -0.138469 -0.197681,
-0.010282 0.136073 -0.197681,
-0.010282 0.136073 -0.252973,
0.009763 0.136073 0.252150,
0.009763 -0.138469 0.252150,
0.009763 -0.138469 0.196858,
0.009763 0.136073 0.196858,
-0.010282 0.136073 0.252150,
-0.010282 0.136073 0.196858,
-0.010282 -0.138469 0.196858,
-0.010282 -0.138469 0.252150,
0.008363 -0.139733 0.252150,
-0.008882 -0.139733 0.252150,
-0.008882 -0.139733 0.196858,
0.008363 -0.139733 0.196858,
-0.008882 0.137337 0.252150,
0.008363 0.137337 0.252150,
0.008363 0.137337 0.196858,
-0.008882 0.137337 0.196858,
-0.008882 0.136073 0.195593,
0.008363 0.136073 0.195593,
0.008363 -0.138469 0.195593,
-0.008882 -0.138469 0.195593,
0.008363 0.137337 -0.252973,
-0.008882 0.137337 -0.252973,
-0.008882 0.137337 -0.197681,
0.008363 0.137337 -0.197681,
-0.008882 -0.139733 -0.252973,
0.008363 -0.139733 -0.252973,
0.008363 -0.139733 -0.197681,
-0.008882 -0.139733 -0.197681,
-0.008882 -0.138469 -0.196416,
0.008363 -0.138469 -0.196416,
0.008363 0.136073 -0.196416,
-0.008882 0.136073 -0.196416,
0.008363 0.190111 0.252150,
0.008363 0.190111 -0.252973,
-0.008882 0.190111 -0.252973,
-0.008882 0.190111 0.252150,
0.008363 0.188711 0.253550,
-0.008882 0.188711 0.253550,
-0.008882 0.138601 0.253550,
0.008363 0.138601 0.253550,
-0.008882 0.188711 -0.254373,
0.008363 0.188711 -0.254373,
0.008363 0.138601 -0.254373,
-0.008882 0.138601 -0.254373,
0.009763 0.138601 -0.252973,
0.009763 0.188711 -0.252973,
0.009763 0.188711 0.252150,
0.009763 0.138601 0.252150,
-0.010282 0.138601 0.252150,
-0.010282 0.188711 0.252150,
-0.010282 0.188711 -0.252973,
-0.010282 0.138601 -0.252973,
0.009763 -0.189491 0.252150,
0.008363 -0.189491 0.253550,
0.008363 -0.190891 0.252150,
-0.008882 -0.189491 0.253550,
-0.010282 -0.189491 0.252150,
-0.008882 -0.190891 0.252150,
0.009763 -0.140997 0.252150,
0.008363 -0.140997 0.253550,
-0.008882 -0.140997 0.253550,
-0.010282 -0.140997 0.252150,
0.008363 -0.190891 0.188934,
0.009763 -0.189491 0.188934,
0.009763 -0.140997 0.188934,
0.008363 -0.139733 0.188934,
-0.008882 -0.139733 0.188934,
-0.010282 -0.140997 0.188934,
0.009763 -0.140997 -0.189757,
0.008363 -0.139733 -0.189757,
0.009763 -0.189491 -0.189757,
0.009763 -0.189491 -0.252973,
0.008363 -0.190891 -0.252973,
0.008363 -0.189491 -0.254373,
-0.008882 -0.189491 -0.254373,
-0.008882 -0.190891 -0.252973,
-0.010282 -0.189491 -0.252973,
0.009763 -0.140997 -0.252973,
0.008363 -0.140997 -0.254373,
-0.008882 -0.140997 -0.254373,
-0.010282 -0.140997 -0.252973,
0.008363 -0.190891 -0.189757,
-0.008882 -0.139733 -0.189757,
-0.010282 -0.140997 -0.189757,
]
}
coordIndex [
0, 1, 2, -1,
0, 2, 3, -1,
4, 5, 6, -1,
7, 8, 9, -1,
7, 9, 10, -1,
11, 12, 13, -1,
11, 13, 14, -1,
4, 15, 16, -1,
4, 16, 5, -1,
2, 17, 3, -1,
8, 18, 9, -1,
11, 19, 12, -1,
20, 21, 22, -1,
20, 22, 23, -1,
24, 25, 26, -1,
24, 26, 27, -1,
24, 28, 29, -1,
24, 29, 25, -1,
25, 29, 30, -1,
25, 30, 26, -1,
26, 30, 31, -1,
26, 31, 27, -1,
27, 31, 28, -1,
27, 28, 24, -1,
29, 28, 31, -1,
29, 31, 30, -1,
32, 33, 34, -1,
32, 34, 35, -1,
36, 37, 38, -1,
36, 38, 39, -1,
40, 41, 42, -1,
40, 42, 43, -1,
44, 45, 46, -1,
44, 46, 47, -1,
32, 48, 49, -1,
32, 49, 33, -1,
48, 50, 51, -1,
48, 51, 49, -1,
35, 34, 52, -1,
35, 52, 53, -1,
53, 52, 54, -1,
53, 54, 55, -1,
36, 56, 57, -1,
36, 57, 37, -1,
56, 58, 59, -1,
56, 59, 57, -1,
39, 38, 60, -1,
39, 60, 61, -1,
61, 60, 51, -1,
61, 51, 50, -1,
40, 62, 63, -1,
40, 63, 41, -1,
62, 64, 65, -1,
62, 65, 63, -1,
43, 42, 66, -1,
43, 66, 67, -1,
67, 66, 59, -1,
67, 59, 58, -1,
44, 68, 69, -1,
44, 69, 45, -1,
68, 55, 54, -1,
68, 54, 69, -1,
47, 46, 70, -1,
47, 70, 71, -1,
71, 70, 65, -1,
71, 65, 64, -1,
72, 23, 33, -1,
72, 33, 49, -1,
73, 72, 49, -1,
73, 49, 51, -1,
74, 73, 51, -1,
74, 51, 60, -1,
75, 74, 60, -1,
75, 60, 38, -1,
76, 77, 57, -1,
76, 57, 59, -1,
78, 76, 59, -1,
78, 59, 66, -1,
20, 78, 66, -1,
20, 66, 42, -1,
21, 20, 42, -1,
21, 42, 41, -1,
79, 21, 41, -1,
79, 41, 63, -1,
80, 79, 63, -1,
80, 63, 65, -1,
81, 80, 65, -1,
81, 65, 70, -1,
82, 81, 70, -1,
82, 70, 46, -1,
83, 82, 46, -1,
83, 46, 45, -1,
84, 83, 45, -1,
84, 45, 69, -1,
85, 84, 69, -1,
85, 69, 54, -1,
86, 85, 54, -1,
86, 54, 52, -1,
86, 52, 34, -1,
86, 34, 22, -1,
23, 22, 34, -1,
23, 34, 33, -1,
84, 86, 22, -1,
84, 22, 83, -1,
79, 81, 82, -1,
79, 82, 21, -1,
82, 83, 22, -1,
82, 22, 21, -1,
72, 74, 75, -1,
72, 75, 23, -1,
77, 76, 78, -1,
72, 73, 74, -1,
84, 85, 86, -1,
79, 80, 81, -1,
87, 88, 89, -1,
87, 89, 90, -1,
91, 92, 93, -1,
91, 93, 94, -1,
95, 96, 97, -1,
95, 97, 98, -1,
99, 100, 101, -1,
99, 101, 102, -1,
103, 104, 105, -1,
103, 105, 106, -1,
107, 108, 109, -1,
107, 109, 110, -1,
111, 112, 113, -1,
111, 113, 114, -1,
115, 116, 117, -1,
115, 117, 118, -1,
119, 120, 121, -1,
119, 121, 122, -1,
123, 124, 125, -1,
123, 125, 126, -1,
127, 128, 129, -1,
127, 129, 130, -1,
131, 132, 133, -1,
131, 133, 134, -1,
97, 126, 133, -1,
120, 117, 106, -1,
105, 114, 121, -1,
132, 129, 98, -1,
131, 100, 130, -1,
113, 109, 122, -1,
119, 108, 118, -1,
125, 101, 134, -1,
116, 87, 103, -1,
104, 90, 111, -1,
112, 89, 110, -1,
107, 88, 115, -1,
128, 93, 95, -1,
96, 92, 123, -1,
124, 91, 102, -1,
99, 94, 127, -1,
103, 87, 90, -1,
103, 90, 104, -1,
110, 89, 88, -1,
110, 88, 107, -1,
95, 93, 92, -1,
95, 92, 96, -1,
102, 91, 94, -1,
102, 94, 99, -1,
105, 121, 120, -1,
105, 120, 106, -1,
97, 133, 132, -1,
97, 132, 98, -1,
108, 119, 122, -1,
108, 122, 109, -1,
100, 131, 134, -1,
100, 134, 101, -1,
87, 116, 115, -1,
87, 115, 88, -1,
89, 112, 111, -1,
89, 111, 90, -1,
91, 124, 123, -1,
91, 123, 92, -1,
93, 128, 127, -1,
93, 127, 94, -1,
98, 129, 128, -1,
98, 128, 95, -1,
99, 127, 130, -1,
99, 130, 100, -1,
101, 125, 124, -1,
101, 124, 102, -1,
96, 123, 126, -1,
96, 126, 97, -1,
106, 117, 116, -1,
106, 116, 103, -1,
107, 115, 118, -1,
107, 118, 108, -1,
109, 113, 112, -1,
109, 112, 110, -1,
104, 111, 114, -1,
104, 114, 105, -1,
113, 122, 121, -1,
113, 121, 114, -1,
117, 120, 119, -1,
117, 119, 118, -1,
125, 134, 133, -1,
125, 133, 126, -1,
129, 132, 131, -1,
129, 131, 130, -1,
135, 136, 137, -1,
135, 137, 138, -1,
139, 140, 141, -1,
139, 141, 142, -1,
143, 144, 145, -1,
143, 145, 146, -1,
147, 148, 149, -1,
147, 149, 150, -1,
151, 152, 153, -1,
151, 153, 154, -1,
116, 115, 124, -1,
116, 124, 123, -1,
148, 144, 136, -1,
135, 139, 149, -1,
138, 152, 140, -1,
143, 153, 137, -1,
142, 116, 150, -1,
151, 115, 141, -1,
147, 123, 145, -1,
146, 124, 154, -1,
143, 137, 136, -1,
143, 136, 144, -1,
148, 136, 135, -1,
148, 135, 149, -1,
152, 138, 137, -1,
152, 137, 153, -1,
139, 135, 138, -1,
139, 138, 140, -1,
149, 139, 142, -1,
149, 142, 150, -1,
153, 143, 146, -1,
153, 146, 154, -1,
151, 141, 140, -1,
151, 140, 152, -1,
141, 115, 116, -1,
141, 116, 142, -1,
147, 145, 144, -1,
147, 144, 148, -1,
145, 123, 124, -1,
145, 124, 146, -1,
154, 124, 115, -1,
154, 115, 151, -1,
150, 116, 123, -1,
150, 123, 147, -1,
155, 156, 157, -1,
158, 159, 160, -1,
161, 111, 162, -1,
163, 112, 164, -1,
155, 157, 165, -1,
155, 165, 166, -1,
160, 159, 16, -1,
160, 16, 15, -1,
111, 161, 167, -1,
111, 167, 168, -1,
164, 112, 169, -1,
164, 169, 170, -1,
160, 157, 156, -1,
160, 156, 158, -1,
162, 111, 112, -1,
162, 112, 163, -1,
160, 15, 4, -1,
160, 4, 157, -1,
168, 169, 112, -1,
168, 112, 111, -1,
163, 164, 159, -1,
163, 159, 158, -1,
156, 155, 161, -1,
156, 161, 162, -1,
164, 5, 16, -1,
164, 16, 159, -1,
166, 167, 161, -1,
166, 161, 155, -1,
163, 158, 156, -1,
163, 156, 162, -1,
3, 17, 6, -1,
3, 6, 5, -1,
6, 17, 2, -1,
6, 2, 4, -1,
1, 0, 7, -1,
1, 7, 10, -1,
167, 171, 172, -1,
167, 172, 168, -1,
2, 1, 10, -1,
2, 10, 9, -1,
167, 166, 173, -1,
167, 173, 171, -1,
174, 175, 176, -1,
177, 178, 179, -1,
180, 181, 128, -1,
182, 183, 127, -1,
184, 175, 174, -1,
184, 174, 173, -1,
13, 179, 178, -1,
13, 178, 14, -1,
171, 180, 128, -1,
171, 128, 172, -1,
185, 127, 183, -1,
185, 183, 186, -1,
176, 175, 178, -1,
176, 178, 177, -1,
127, 128, 181, -1,
127, 181, 182, -1,
11, 14, 178, -1,
11, 178, 175, -1,
11, 175, 184, -1,
11, 184, 9, -1,
127, 185, 172, -1,
127, 172, 128, -1,
179, 183, 182, -1,
179, 182, 177, -1,
180, 174, 176, -1,
180, 176, 181, -1,
13, 12, 183, -1,
13, 183, 179, -1,
180, 171, 173, -1,
180, 173, 174, -1,
176, 177, 182, -1,
176, 182, 181, -1,
19, 18, 8, -1,
19, 8, 12, -1,
9, 18, 19, -1,
9, 19, 11, -1,
166, 165, 184, -1,
166, 184, 173, -1,
169, 185, 186, -1,
169, 186, 170, -1,
2, 9, 184, -1,
2, 184, 165, -1,
172, 185, 169, -1,
172, 169, 168, -1,
3, 170, 186, -1,
3, 186, 8, -1,
3, 8, 7, -1,
3, 7, 0, -1,
4, 2, 165, -1,
4, 165, 157, -1,
170, 3, 5, -1,
170, 5, 164, -1,
12, 8, 186, -1,
12, 186, 183, -1
]
}
}
]
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c9f7a054ca51219b672cf78fcd3caa405b9e6b7cf77f2249f2b2e04452c7433c
size 25719

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2d67bb603014782235a64ae851089f7d867c64ba1fa4c699283d2e91a812bd8a
size 9984

View File

@@ -0,0 +1,331 @@
#VRML V2.0 utf8
Group {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.975 0.486 0.975
specularColor 0.7 0.7 1.0
}
}
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
0.010346 0.176606 0.184551,
0.010346 0.175985 0.188075,
0.016218 0.175985 0.188075,
0.016218 0.176606 0.184551,
0.010346 0.174195 0.191174,
0.016218 0.174195 0.191174,
0.010346 0.171454 0.193474,
0.016218 0.171454 0.193474,
0.010346 0.168092 0.194698,
0.016218 0.168092 0.194698,
0.010346 0.164514 0.194698,
0.016218 0.164514 0.194698,
0.010346 0.161151 0.193474,
0.016218 0.161151 0.193474,
0.010346 0.158410 0.191174,
0.016218 0.158410 0.191174,
0.010346 0.156621 0.188075,
0.016218 0.156621 0.188075,
0.010346 0.156000 0.184551,
0.016218 0.156000 0.184551,
0.010346 0.156621 0.181028,
0.016218 0.156621 0.181028,
0.010346 0.158410 0.177929,
0.016218 0.158410 0.177929,
0.010346 0.161151 0.175629,
0.016218 0.161151 0.175629,
0.010346 0.164514 0.174405,
0.016218 0.164514 0.174405,
0.010346 0.168092 0.174405,
0.016218 0.168092 0.174405,
0.010346 0.171454 0.175629,
0.016218 0.171454 0.175629,
0.010346 0.174195 0.177929,
0.016218 0.174195 0.177929,
0.010346 0.175985 0.181027,
0.016218 0.175985 0.181027,
0.021149 0.177090 0.188478,
0.021149 0.177782 0.184551,
0.021149 0.175097 0.191930,
0.021149 0.172043 0.194493,
0.021149 0.168296 0.195857,
0.021149 0.164309 0.195857,
0.021149 0.160563 0.194493,
0.021149 0.157509 0.191930,
0.021149 0.155515 0.188478,
0.021149 0.154823 0.184551,
0.021149 0.155515 0.180625,
0.021149 0.157509 0.177172,
0.021149 0.160563 0.174610,
0.021149 0.164309 0.173246,
0.021149 0.168296 0.173246,
0.021149 0.172043 0.174610,
0.021149 0.175097 0.177172,
0.021149 0.177090 0.180625,
0.026081 0.181180 0.184551,
0.026081 0.180283 0.189640,
0.036057 0.180283 0.189640,
0.036057 0.181180 0.184551,
0.026081 0.177700 0.194114,
0.036057 0.177700 0.194114,
0.026081 0.173742 0.197436,
0.036057 0.173742 0.197436,
0.026081 0.168886 0.199203,
0.036057 0.168886 0.199203,
0.026081 0.163719 0.199203,
0.036057 0.163719 0.199203,
0.026081 0.158864 0.197436,
0.036057 0.158864 0.197436,
0.026081 0.154906 0.194114,
0.036057 0.154906 0.194114,
0.026081 0.152322 0.189640,
0.036057 0.152322 0.189640,
0.026081 0.151425 0.184551,
0.036057 0.151425 0.184551,
0.026081 0.152322 0.179463,
0.036057 0.152322 0.179463,
0.026081 0.154906 0.174988,
0.036057 0.154906 0.174988,
0.026081 0.158864 0.171667,
0.036057 0.158864 0.171667,
0.026081 0.163719 0.169900,
0.036057 0.163719 0.169900,
0.026081 0.168886 0.169900,
0.036057 0.168886 0.169900,
0.026081 0.173741 0.171667,
0.036057 0.173741 0.171667,
0.026081 0.177700 0.174988,
0.036057 0.177700 0.174988,
0.026081 0.180283 0.179463,
0.036057 0.180283 0.179463,
0.036843 0.179751 0.189446,
0.036843 0.180614 0.184551,
0.036843 0.177266 0.193750,
0.036843 0.173458 0.196945,
0.036843 0.168788 0.198645,
0.036843 0.163818 0.198645,
0.036843 0.159147 0.196945,
0.036843 0.155340 0.193750,
0.036843 0.152855 0.189446,
0.036843 0.151992 0.184551,
0.036843 0.152855 0.179657,
0.036843 0.155340 0.175352,
0.036843 0.159147 0.172158,
0.036843 0.163818 0.170458,
0.036843 0.168788 0.170458,
0.036843 0.173458 0.172158,
0.036843 0.177266 0.175352,
0.036843 0.179751 0.179657,
0.036843 0.166303 0.184551,
]
}
coordIndex [
0, 1, 2, -1,
0, 2, 3, -1,
1, 4, 5, -1,
1, 5, 2, -1,
4, 6, 7, -1,
4, 7, 5, -1,
6, 8, 9, -1,
6, 9, 7, -1,
8, 10, 11, -1,
8, 11, 9, -1,
10, 12, 13, -1,
10, 13, 11, -1,
12, 14, 15, -1,
12, 15, 13, -1,
14, 16, 17, -1,
14, 17, 15, -1,
16, 18, 19, -1,
16, 19, 17, -1,
18, 20, 21, -1,
18, 21, 19, -1,
20, 22, 23, -1,
20, 23, 21, -1,
22, 24, 25, -1,
22, 25, 23, -1,
24, 26, 27, -1,
24, 27, 25, -1,
26, 28, 29, -1,
26, 29, 27, -1,
28, 30, 31, -1,
28, 31, 29, -1,
30, 32, 33, -1,
30, 33, 31, -1,
32, 34, 35, -1,
32, 35, 33, -1,
34, 0, 3, -1,
34, 3, 35, -1,
2, 36, 37, -1,
2, 37, 3, -1,
5, 38, 36, -1,
5, 36, 2, -1,
7, 39, 38, -1,
7, 38, 5, -1,
9, 40, 39, -1,
9, 39, 7, -1,
11, 41, 40, -1,
11, 40, 9, -1,
13, 42, 41, -1,
13, 41, 11, -1,
15, 43, 42, -1,
15, 42, 13, -1,
17, 44, 43, -1,
17, 43, 15, -1,
19, 45, 44, -1,
19, 44, 17, -1,
21, 46, 45, -1,
21, 45, 19, -1,
23, 47, 46, -1,
23, 46, 21, -1,
25, 48, 47, -1,
25, 47, 23, -1,
27, 49, 48, -1,
27, 48, 25, -1,
29, 50, 49, -1,
29, 49, 27, -1,
31, 51, 50, -1,
31, 50, 29, -1,
33, 52, 51, -1,
33, 51, 31, -1,
35, 53, 52, -1,
35, 52, 33, -1,
3, 37, 53, -1,
3, 53, 35, -1,
54, 55, 56, -1,
54, 56, 57, -1,
55, 58, 59, -1,
55, 59, 56, -1,
58, 60, 61, -1,
58, 61, 59, -1,
60, 62, 63, -1,
60, 63, 61, -1,
62, 64, 65, -1,
62, 65, 63, -1,
64, 66, 67, -1,
64, 67, 65, -1,
66, 68, 69, -1,
66, 69, 67, -1,
68, 70, 71, -1,
68, 71, 69, -1,
70, 72, 73, -1,
70, 73, 71, -1,
72, 74, 75, -1,
72, 75, 73, -1,
74, 76, 77, -1,
74, 77, 75, -1,
76, 78, 79, -1,
76, 79, 77, -1,
78, 80, 81, -1,
78, 81, 79, -1,
80, 82, 83, -1,
80, 83, 81, -1,
82, 84, 85, -1,
82, 85, 83, -1,
84, 86, 87, -1,
84, 87, 85, -1,
86, 88, 89, -1,
86, 89, 87, -1,
88, 54, 57, -1,
88, 57, 89, -1,
56, 90, 91, -1,
56, 91, 57, -1,
59, 92, 90, -1,
59, 90, 56, -1,
61, 93, 92, -1,
61, 92, 59, -1,
63, 94, 93, -1,
63, 93, 61, -1,
65, 95, 94, -1,
65, 94, 63, -1,
67, 96, 95, -1,
67, 95, 65, -1,
69, 97, 96, -1,
69, 96, 67, -1,
71, 98, 97, -1,
71, 97, 69, -1,
73, 99, 98, -1,
73, 98, 71, -1,
75, 100, 99, -1,
75, 99, 73, -1,
77, 101, 100, -1,
77, 100, 75, -1,
79, 102, 101, -1,
79, 101, 77, -1,
81, 103, 102, -1,
81, 102, 79, -1,
83, 104, 103, -1,
83, 103, 81, -1,
85, 105, 104, -1,
85, 104, 83, -1,
87, 106, 105, -1,
87, 105, 85, -1,
89, 107, 106, -1,
89, 106, 87, -1,
57, 91, 107, -1,
57, 107, 89, -1,
91, 90, 108, -1,
90, 92, 108, -1,
92, 93, 108, -1,
93, 94, 108, -1,
94, 95, 108, -1,
95, 96, 108, -1,
96, 97, 108, -1,
97, 98, 108, -1,
98, 99, 108, -1,
99, 100, 108, -1,
100, 101, 108, -1,
101, 102, 108, -1,
102, 103, 108, -1,
103, 104, 108, -1,
104, 105, 108, -1,
105, 106, 108, -1,
106, 107, 108, -1,
107, 91, 108, -1,
55, 54, 37, -1,
55, 37, 36, -1,
58, 55, 36, -1,
58, 36, 38, -1,
60, 58, 38, -1,
60, 38, 39, -1,
62, 60, 39, -1,
62, 39, 40, -1,
64, 62, 40, -1,
64, 40, 41, -1,
66, 64, 41, -1,
66, 41, 42, -1,
68, 66, 42, -1,
68, 42, 43, -1,
70, 68, 43, -1,
70, 43, 44, -1,
72, 70, 44, -1,
72, 44, 45, -1,
74, 72, 45, -1,
74, 45, 46, -1,
76, 74, 46, -1,
76, 46, 47, -1,
78, 76, 47, -1,
78, 47, 48, -1,
80, 78, 48, -1,
80, 48, 49, -1,
82, 80, 49, -1,
82, 49, 50, -1,
84, 82, 50, -1,
84, 50, 51, -1,
86, 84, 51, -1,
86, 51, 52, -1,
88, 86, 52, -1,
88, 52, 53, -1,
54, 88, 53, -1,
54, 53, 37, -1
]
}
}
]
}

View File

@@ -0,0 +1,13 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material.002
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.840000 0.80000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
# map_Kd WoodFine0035_1_S.jpg

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:acf69c4665732fbec4fd8c1fee1956575a645394fd6ed12070870e8f13249fd8
size 64676

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:57b5f8fda4f3e0249276794aeaf5f319071e00fb5cbf3df135f7f42cdbc1d999
size 17184

View File

@@ -0,0 +1,553 @@
#VRML V2.0 utf8
Group {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.975 0.486 0.975
specularColor 0.7 0.7 1.0
}
}
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
-0.010282 0.189491 -0.188934,
-0.008882 0.190891 -0.188934,
-0.006123 0.190891 -0.188934,
-0.010282 0.184131 -0.188934,
-0.006123 0.190891 -0.210934,
-0.010282 0.184131 -0.210934,
-0.006123 0.184131 -0.210934,
-0.010282 0.189491 0.189757,
-0.010282 0.184131 0.189757,
-0.006123 0.190891 0.189757,
-0.008882 0.190891 0.189757,
-0.006123 0.190891 0.211757,
-0.010282 0.184131 0.211757,
-0.010282 0.189491 0.211757,
-0.008882 0.190891 0.211757,
-0.008882 0.190891 -0.210934,
-0.010282 0.189491 -0.210934,
-0.006123 0.184131 -0.188934,
-0.006123 0.184131 0.189757,
-0.006123 0.184131 0.211757,
0.009747 0.106958 0.165943,
0.009747 -0.104562 0.165943,
0.009747 -0.104562 -0.165120,
0.009747 0.106958 -0.165120,
-0.010282 0.139733 -0.195593,
-0.010282 -0.137337 -0.195593,
-0.010282 -0.137337 0.196416,
-0.010282 0.139733 0.196416,
0.003847 0.139733 -0.195593,
0.003847 -0.137337 -0.195593,
0.003847 -0.137337 0.196416,
0.003847 0.139733 0.196416,
0.003847 0.116058 -0.175151,
0.009324 0.107677 -0.166763,
0.009324 -0.105281 -0.166763,
0.003847 -0.113662 -0.175151,
0.003847 0.119309 0.172721,
0.009324 0.110927 0.164332,
0.009324 0.110927 -0.163509,
0.003847 0.119309 -0.171898,
0.003847 -0.113662 0.175974,
0.009324 -0.105281 0.167586,
0.009324 0.107677 0.167586,
0.003847 0.116058 0.175974,
0.003847 -0.116913 -0.171898,
0.009324 -0.108531 -0.163509,
0.009324 -0.108531 0.164332,
0.003847 -0.116913 0.172721,
0.003847 0.117480 -0.174948,
0.009324 0.109099 -0.166560,
0.003847 0.118496 -0.174338,
0.009324 0.110115 -0.165949,
0.009324 -0.106703 -0.166560,
0.003847 -0.115084 -0.174948,
0.009324 -0.107719 -0.165949,
0.003847 -0.116100 -0.174338,
0.003847 0.119106 0.174144,
0.009324 0.110724 0.165755,
0.003847 0.118496 0.175161,
0.009324 0.110115 0.166772,
0.009324 0.110724 -0.164933,
0.003847 0.119106 -0.173321,
0.003847 -0.115084 0.175771,
0.009324 -0.106703 0.167382,
0.003847 -0.116100 0.175161,
0.009324 -0.107719 0.166772,
0.009324 0.109099 0.167382,
0.003847 0.117480 0.175771,
0.003847 -0.116710 -0.173321,
0.009324 -0.108328 -0.164933,
0.009324 -0.108328 0.165755,
0.003847 -0.116710 0.174144,
0.009747 0.108112 -0.164955,
0.009747 0.108742 -0.164576,
0.009747 0.109121 -0.163945,
0.009747 0.109286 -0.162790,
0.009747 0.108743 0.165399,
0.009747 0.109121 0.164767,
0.009747 0.108112 0.165778,
0.009747 -0.105716 0.165778,
0.009747 -0.106347 0.165399,
0.009747 -0.106725 0.164767,
0.009747 -0.106890 0.163613,
0.009747 -0.106890 -0.162790,
0.009747 -0.106725 -0.163945,
0.009747 -0.106347 -0.164576,
0.009747 -0.105716 -0.164955,
0.008363 -0.136073 -0.253550,
-0.008882 -0.136073 -0.253550,
-0.008882 0.138469 -0.253550,
0.008363 0.138469 -0.253550,
-0.008882 -0.136073 0.254373,
0.008363 -0.136073 0.254373,
0.008363 0.138469 0.254373,
-0.008882 0.138469 0.254373,
0.009763 0.138469 0.252973,
0.009763 -0.136073 0.252973,
0.009763 -0.136073 0.197681,
0.009763 0.138469 0.197681,
-0.010282 0.138469 0.252973,
-0.010282 0.138469 0.197681,
-0.010282 -0.136073 0.197681,
-0.010282 -0.136073 0.252973,
0.009763 -0.136073 -0.252150,
0.009763 0.138469 -0.252150,
0.009763 0.138469 -0.196858,
0.009763 -0.136073 -0.196858,
-0.010282 -0.136073 -0.252150,
-0.010282 -0.136073 -0.196858,
-0.010282 0.138469 -0.196858,
-0.010282 0.138469 -0.252150,
0.008363 0.139733 -0.252150,
-0.008882 0.139733 -0.252150,
-0.008882 0.139733 -0.196858,
0.008363 0.139733 -0.196858,
-0.008882 -0.137337 -0.252150,
0.008363 -0.137337 -0.252150,
0.008363 -0.137337 -0.196858,
-0.008882 -0.137337 -0.196858,
-0.008882 -0.136073 -0.195593,
0.008363 -0.136073 -0.195593,
0.008363 0.138469 -0.195593,
-0.008882 0.138469 -0.195593,
0.008363 -0.137337 0.252973,
-0.008882 -0.137337 0.252973,
-0.008882 -0.137337 0.197681,
0.008363 -0.137337 0.197681,
-0.008882 0.139733 0.252973,
0.008363 0.139733 0.252973,
0.008363 0.139733 0.197681,
-0.008882 0.139733 0.197681,
-0.008882 0.138469 0.196416,
0.008363 0.138469 0.196416,
0.008363 -0.136073 0.196416,
-0.008882 -0.136073 0.196416,
0.008363 -0.190111 -0.252150,
0.008363 -0.190111 0.252973,
-0.008882 -0.190111 0.252973,
-0.008882 -0.190111 -0.252150,
0.008363 -0.188711 -0.253550,
-0.008882 -0.188711 -0.253550,
-0.008882 -0.138601 -0.253550,
0.008363 -0.138601 -0.253550,
-0.008882 -0.188711 0.254373,
0.008363 -0.188711 0.254373,
0.008363 -0.138601 0.254373,
-0.008882 -0.138601 0.254373,
0.009763 -0.138601 0.252973,
0.009763 -0.188711 0.252973,
0.009763 -0.188711 -0.252150,
0.009763 -0.138601 -0.252150,
-0.010282 -0.138601 -0.252150,
-0.010282 -0.188711 -0.252150,
-0.010282 -0.188711 0.252973,
-0.010282 -0.138601 0.252973,
0.009763 0.189491 -0.252150,
0.008363 0.189491 -0.253550,
0.008363 0.190891 -0.252150,
-0.008882 0.189491 -0.253550,
-0.010282 0.189491 -0.252150,
-0.008882 0.190891 -0.252150,
0.009763 0.140997 -0.252150,
0.008363 0.140997 -0.253550,
-0.008882 0.140997 -0.253550,
-0.010282 0.140997 -0.252150,
0.008363 0.190891 -0.188934,
0.009763 0.189491 -0.188934,
0.009763 0.140997 -0.188934,
0.008363 0.139733 -0.188934,
-0.008882 0.139733 -0.188934,
-0.010282 0.140997 -0.188934,
0.009763 0.140997 0.189757,
0.008363 0.139733 0.189757,
0.009763 0.189491 0.189757,
0.009763 0.189491 0.252973,
0.008363 0.190891 0.252973,
0.008363 0.189491 0.254373,
-0.008882 0.189491 0.254373,
-0.008882 0.190891 0.252973,
-0.010282 0.189491 0.252973,
0.009763 0.140997 0.252973,
0.008363 0.140997 0.254373,
-0.008882 0.140997 0.254373,
-0.010282 0.140997 0.252973,
0.008363 0.190891 0.189757,
-0.008882 0.139733 0.189757,
-0.010282 0.140997 0.189757,
]
}
coordIndex [
0, 1, 2, -1,
0, 2, 3, -1,
4, 5, 6, -1,
7, 8, 9, -1,
7, 9, 10, -1,
11, 12, 13, -1,
11, 13, 14, -1,
4, 15, 16, -1,
4, 16, 5, -1,
2, 17, 3, -1,
8, 18, 9, -1,
11, 19, 12, -1,
20, 21, 22, -1,
20, 22, 23, -1,
24, 25, 26, -1,
24, 26, 27, -1,
24, 28, 29, -1,
24, 29, 25, -1,
25, 29, 30, -1,
25, 30, 26, -1,
26, 30, 31, -1,
26, 31, 27, -1,
27, 31, 28, -1,
27, 28, 24, -1,
29, 28, 31, -1,
29, 31, 30, -1,
32, 33, 34, -1,
32, 34, 35, -1,
36, 37, 38, -1,
36, 38, 39, -1,
40, 41, 42, -1,
40, 42, 43, -1,
44, 45, 46, -1,
44, 46, 47, -1,
32, 48, 49, -1,
32, 49, 33, -1,
48, 50, 51, -1,
48, 51, 49, -1,
35, 34, 52, -1,
35, 52, 53, -1,
53, 52, 54, -1,
53, 54, 55, -1,
36, 56, 57, -1,
36, 57, 37, -1,
56, 58, 59, -1,
56, 59, 57, -1,
39, 38, 60, -1,
39, 60, 61, -1,
61, 60, 51, -1,
61, 51, 50, -1,
40, 62, 63, -1,
40, 63, 41, -1,
62, 64, 65, -1,
62, 65, 63, -1,
43, 42, 66, -1,
43, 66, 67, -1,
67, 66, 59, -1,
67, 59, 58, -1,
44, 68, 69, -1,
44, 69, 45, -1,
68, 55, 54, -1,
68, 54, 69, -1,
47, 46, 70, -1,
47, 70, 71, -1,
71, 70, 65, -1,
71, 65, 64, -1,
72, 23, 33, -1,
72, 33, 49, -1,
73, 72, 49, -1,
73, 49, 51, -1,
74, 73, 51, -1,
74, 51, 60, -1,
75, 74, 60, -1,
75, 60, 38, -1,
76, 77, 57, -1,
76, 57, 59, -1,
78, 76, 59, -1,
78, 59, 66, -1,
20, 78, 66, -1,
20, 66, 42, -1,
21, 20, 42, -1,
21, 42, 41, -1,
79, 21, 41, -1,
79, 41, 63, -1,
80, 79, 63, -1,
80, 63, 65, -1,
81, 80, 65, -1,
81, 65, 70, -1,
82, 81, 70, -1,
82, 70, 46, -1,
83, 82, 46, -1,
83, 46, 45, -1,
84, 83, 45, -1,
84, 45, 69, -1,
85, 84, 69, -1,
85, 69, 54, -1,
86, 85, 54, -1,
86, 54, 52, -1,
86, 52, 34, -1,
86, 34, 22, -1,
23, 22, 34, -1,
23, 34, 33, -1,
84, 86, 22, -1,
84, 22, 83, -1,
79, 81, 82, -1,
79, 82, 21, -1,
82, 83, 22, -1,
82, 22, 21, -1,
72, 74, 75, -1,
72, 75, 23, -1,
77, 76, 78, -1,
72, 73, 74, -1,
84, 85, 86, -1,
79, 80, 81, -1,
87, 88, 89, -1,
87, 89, 90, -1,
91, 92, 93, -1,
91, 93, 94, -1,
95, 96, 97, -1,
95, 97, 98, -1,
99, 100, 101, -1,
99, 101, 102, -1,
103, 104, 105, -1,
103, 105, 106, -1,
107, 108, 109, -1,
107, 109, 110, -1,
111, 112, 113, -1,
111, 113, 114, -1,
115, 116, 117, -1,
115, 117, 118, -1,
119, 120, 121, -1,
119, 121, 122, -1,
123, 124, 125, -1,
123, 125, 126, -1,
127, 128, 129, -1,
127, 129, 130, -1,
131, 132, 133, -1,
131, 133, 134, -1,
97, 126, 133, -1,
120, 117, 106, -1,
105, 114, 121, -1,
132, 129, 98, -1,
131, 100, 130, -1,
113, 109, 122, -1,
119, 108, 118, -1,
125, 101, 134, -1,
116, 87, 103, -1,
104, 90, 111, -1,
112, 89, 110, -1,
107, 88, 115, -1,
128, 93, 95, -1,
96, 92, 123, -1,
124, 91, 102, -1,
99, 94, 127, -1,
103, 87, 90, -1,
103, 90, 104, -1,
110, 89, 88, -1,
110, 88, 107, -1,
95, 93, 92, -1,
95, 92, 96, -1,
102, 91, 94, -1,
102, 94, 99, -1,
105, 121, 120, -1,
105, 120, 106, -1,
97, 133, 132, -1,
97, 132, 98, -1,
108, 119, 122, -1,
108, 122, 109, -1,
100, 131, 134, -1,
100, 134, 101, -1,
87, 116, 115, -1,
87, 115, 88, -1,
89, 112, 111, -1,
89, 111, 90, -1,
91, 124, 123, -1,
91, 123, 92, -1,
93, 128, 127, -1,
93, 127, 94, -1,
98, 129, 128, -1,
98, 128, 95, -1,
99, 127, 130, -1,
99, 130, 100, -1,
101, 125, 124, -1,
101, 124, 102, -1,
96, 123, 126, -1,
96, 126, 97, -1,
106, 117, 116, -1,
106, 116, 103, -1,
107, 115, 118, -1,
107, 118, 108, -1,
109, 113, 112, -1,
109, 112, 110, -1,
104, 111, 114, -1,
104, 114, 105, -1,
113, 122, 121, -1,
113, 121, 114, -1,
117, 120, 119, -1,
117, 119, 118, -1,
125, 134, 133, -1,
125, 133, 126, -1,
129, 132, 131, -1,
129, 131, 130, -1,
135, 136, 137, -1,
135, 137, 138, -1,
139, 140, 141, -1,
139, 141, 142, -1,
143, 144, 145, -1,
143, 145, 146, -1,
147, 148, 149, -1,
147, 149, 150, -1,
151, 152, 153, -1,
151, 153, 154, -1,
116, 115, 124, -1,
116, 124, 123, -1,
148, 144, 136, -1,
135, 139, 149, -1,
138, 152, 140, -1,
143, 153, 137, -1,
142, 116, 150, -1,
151, 115, 141, -1,
147, 123, 145, -1,
146, 124, 154, -1,
143, 137, 136, -1,
143, 136, 144, -1,
148, 136, 135, -1,
148, 135, 149, -1,
152, 138, 137, -1,
152, 137, 153, -1,
139, 135, 138, -1,
139, 138, 140, -1,
149, 139, 142, -1,
149, 142, 150, -1,
153, 143, 146, -1,
153, 146, 154, -1,
151, 141, 140, -1,
151, 140, 152, -1,
141, 115, 116, -1,
141, 116, 142, -1,
147, 145, 144, -1,
147, 144, 148, -1,
145, 123, 124, -1,
145, 124, 146, -1,
154, 124, 115, -1,
154, 115, 151, -1,
150, 116, 123, -1,
150, 123, 147, -1,
155, 156, 157, -1,
158, 159, 160, -1,
161, 111, 162, -1,
163, 112, 164, -1,
155, 157, 165, -1,
155, 165, 166, -1,
160, 159, 16, -1,
160, 16, 15, -1,
111, 161, 167, -1,
111, 167, 168, -1,
164, 112, 169, -1,
164, 169, 170, -1,
160, 157, 156, -1,
160, 156, 158, -1,
162, 111, 112, -1,
162, 112, 163, -1,
160, 15, 4, -1,
160, 4, 157, -1,
168, 169, 112, -1,
168, 112, 111, -1,
163, 164, 159, -1,
163, 159, 158, -1,
156, 155, 161, -1,
156, 161, 162, -1,
164, 5, 16, -1,
164, 16, 159, -1,
166, 167, 161, -1,
166, 161, 155, -1,
163, 158, 156, -1,
163, 156, 162, -1,
3, 17, 6, -1,
3, 6, 5, -1,
6, 17, 2, -1,
6, 2, 4, -1,
1, 0, 7, -1,
1, 7, 10, -1,
167, 171, 172, -1,
167, 172, 168, -1,
2, 1, 10, -1,
2, 10, 9, -1,
167, 166, 173, -1,
167, 173, 171, -1,
174, 175, 176, -1,
177, 178, 179, -1,
180, 181, 128, -1,
182, 183, 127, -1,
184, 175, 174, -1,
184, 174, 173, -1,
13, 179, 178, -1,
13, 178, 14, -1,
171, 180, 128, -1,
171, 128, 172, -1,
185, 127, 183, -1,
185, 183, 186, -1,
176, 175, 178, -1,
176, 178, 177, -1,
127, 128, 181, -1,
127, 181, 182, -1,
11, 14, 178, -1,
11, 178, 175, -1,
11, 175, 184, -1,
11, 184, 9, -1,
127, 185, 172, -1,
127, 172, 128, -1,
179, 183, 182, -1,
179, 182, 177, -1,
180, 174, 176, -1,
180, 176, 181, -1,
13, 12, 183, -1,
13, 183, 179, -1,
180, 171, 173, -1,
180, 173, 174, -1,
176, 177, 182, -1,
176, 182, 181, -1,
19, 18, 8, -1,
19, 8, 12, -1,
9, 18, 19, -1,
9, 19, 11, -1,
166, 165, 184, -1,
166, 184, 173, -1,
169, 185, 186, -1,
169, 186, 170, -1,
2, 9, 184, -1,
2, 184, 165, -1,
172, 185, 169, -1,
172, 169, 168, -1,
3, 170, 186, -1,
3, 186, 8, -1,
3, 8, 7, -1,
3, 7, 0, -1,
4, 2, 165, -1,
4, 165, 157, -1,
170, 3, 5, -1,
170, 5, 164, -1,
12, 8, 186, -1,
12, 186, 183, -1
]
}
}
]
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9cdf43594348ebb79565eeb2ae9d69c8b180cb7bf42e2153fdb473db55612eee
size 26515

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2c3bf9db55c73ebefdfcd839af10d2a17c3f9789df4aef5d4d0b22a684a66600
size 9984

View File

@@ -0,0 +1,331 @@
#VRML V2.0 utf8
Group {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.975 0.486 0.975
specularColor 0.7 0.7 1.0
}
}
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
0.010357 -0.177380 0.185066,
0.016228 -0.177380 0.185066,
0.016228 -0.176759 0.188590,
0.010357 -0.176759 0.188590,
0.016228 -0.174970 0.191689,
0.010357 -0.174970 0.191689,
0.016228 -0.172229 0.193989,
0.010357 -0.172229 0.193989,
0.016228 -0.168866 0.195213,
0.010357 -0.168866 0.195213,
0.016228 -0.165288 0.195213,
0.010357 -0.165288 0.195213,
0.016228 -0.161925 0.193989,
0.010357 -0.161925 0.193989,
0.016228 -0.159184 0.191689,
0.010357 -0.159184 0.191689,
0.016228 -0.157395 0.188590,
0.010357 -0.157395 0.188590,
0.016228 -0.156774 0.185066,
0.010357 -0.156774 0.185066,
0.016228 -0.157395 0.181542,
0.010357 -0.157395 0.181542,
0.016228 -0.159184 0.178443,
0.010357 -0.159184 0.178443,
0.016228 -0.161925 0.176143,
0.010357 -0.161925 0.176143,
0.016228 -0.165288 0.174920,
0.010357 -0.165288 0.174920,
0.016228 -0.168866 0.174920,
0.010357 -0.168866 0.174920,
0.016228 -0.172229 0.176143,
0.010357 -0.172229 0.176143,
0.016228 -0.174970 0.178443,
0.010357 -0.174970 0.178443,
0.016228 -0.176759 0.181542,
0.010357 -0.176759 0.181542,
0.021160 -0.178557 0.185066,
0.021160 -0.177864 0.188992,
0.021160 -0.175871 0.192445,
0.021160 -0.172817 0.195008,
0.021160 -0.169070 0.196371,
0.021160 -0.165084 0.196371,
0.021160 -0.161337 0.195008,
0.021160 -0.158283 0.192445,
0.021160 -0.156290 0.188992,
0.021160 -0.155597 0.185066,
0.021160 -0.156290 0.181140,
0.021160 -0.158283 0.177687,
0.021160 -0.161337 0.175124,
0.021160 -0.165084 0.173761,
0.021160 -0.169070 0.173761,
0.021160 -0.172817 0.175124,
0.021160 -0.175871 0.177687,
0.021160 -0.177864 0.181140,
0.026091 -0.181955 0.185066,
0.036068 -0.181955 0.185066,
0.036068 -0.181057 0.190155,
0.026091 -0.181057 0.190155,
0.036068 -0.178474 0.194629,
0.026091 -0.178474 0.194629,
0.036068 -0.174516 0.197950,
0.026091 -0.174516 0.197950,
0.036068 -0.169660 0.199718,
0.026091 -0.169660 0.199718,
0.036068 -0.164494 0.199718,
0.026091 -0.164494 0.199718,
0.036068 -0.159638 0.197950,
0.026091 -0.159638 0.197950,
0.036068 -0.155680 0.194629,
0.026091 -0.155680 0.194629,
0.036068 -0.153097 0.190155,
0.026091 -0.153097 0.190155,
0.036068 -0.152200 0.185066,
0.026091 -0.152200 0.185066,
0.036068 -0.153097 0.179978,
0.026091 -0.153097 0.179978,
0.036068 -0.155680 0.175503,
0.026091 -0.155680 0.175503,
0.036068 -0.159638 0.172182,
0.026091 -0.159638 0.172182,
0.036068 -0.164494 0.170415,
0.026091 -0.164494 0.170415,
0.036068 -0.169660 0.170415,
0.026091 -0.169660 0.170415,
0.036068 -0.174516 0.172182,
0.026091 -0.174516 0.172182,
0.036068 -0.178474 0.175503,
0.026091 -0.178474 0.175503,
0.036068 -0.181057 0.179978,
0.026091 -0.181057 0.179978,
0.036854 -0.181388 0.185066,
0.036854 -0.180525 0.189961,
0.036854 -0.178040 0.194265,
0.036854 -0.174233 0.197460,
0.036854 -0.169562 0.199160,
0.036854 -0.164592 0.199160,
0.036854 -0.159921 0.197460,
0.036854 -0.156114 0.194265,
0.036854 -0.153629 0.189961,
0.036854 -0.152766 0.185066,
0.036854 -0.153629 0.180172,
0.036854 -0.156114 0.175867,
0.036854 -0.159921 0.172672,
0.036854 -0.164592 0.170973,
0.036854 -0.169562 0.170973,
0.036854 -0.174233 0.172672,
0.036854 -0.178040 0.175867,
0.036854 -0.180525 0.180172,
0.036854 -0.167077 0.185066,
]
}
coordIndex [
0, 1, 2, -1,
0, 2, 3, -1,
3, 2, 4, -1,
3, 4, 5, -1,
5, 4, 6, -1,
5, 6, 7, -1,
7, 6, 8, -1,
7, 8, 9, -1,
9, 8, 10, -1,
9, 10, 11, -1,
11, 10, 12, -1,
11, 12, 13, -1,
13, 12, 14, -1,
13, 14, 15, -1,
15, 14, 16, -1,
15, 16, 17, -1,
17, 16, 18, -1,
17, 18, 19, -1,
19, 18, 20, -1,
19, 20, 21, -1,
21, 20, 22, -1,
21, 22, 23, -1,
23, 22, 24, -1,
23, 24, 25, -1,
25, 24, 26, -1,
25, 26, 27, -1,
27, 26, 28, -1,
27, 28, 29, -1,
29, 28, 30, -1,
29, 30, 31, -1,
31, 30, 32, -1,
31, 32, 33, -1,
33, 32, 34, -1,
33, 34, 35, -1,
35, 34, 1, -1,
35, 1, 0, -1,
36, 37, 2, -1,
36, 2, 1, -1,
37, 38, 4, -1,
37, 4, 2, -1,
38, 39, 6, -1,
38, 6, 4, -1,
39, 40, 8, -1,
39, 8, 6, -1,
40, 41, 10, -1,
40, 10, 8, -1,
41, 42, 12, -1,
41, 12, 10, -1,
42, 43, 14, -1,
42, 14, 12, -1,
43, 44, 16, -1,
43, 16, 14, -1,
44, 45, 18, -1,
44, 18, 16, -1,
45, 46, 20, -1,
45, 20, 18, -1,
46, 47, 22, -1,
46, 22, 20, -1,
47, 48, 24, -1,
47, 24, 22, -1,
48, 49, 26, -1,
48, 26, 24, -1,
49, 50, 28, -1,
49, 28, 26, -1,
50, 51, 30, -1,
50, 30, 28, -1,
51, 52, 32, -1,
51, 32, 30, -1,
52, 53, 34, -1,
52, 34, 32, -1,
53, 36, 1, -1,
53, 1, 34, -1,
54, 55, 56, -1,
54, 56, 57, -1,
57, 56, 58, -1,
57, 58, 59, -1,
59, 58, 60, -1,
59, 60, 61, -1,
61, 60, 62, -1,
61, 62, 63, -1,
63, 62, 64, -1,
63, 64, 65, -1,
65, 64, 66, -1,
65, 66, 67, -1,
67, 66, 68, -1,
67, 68, 69, -1,
69, 68, 70, -1,
69, 70, 71, -1,
71, 70, 72, -1,
71, 72, 73, -1,
73, 72, 74, -1,
73, 74, 75, -1,
75, 74, 76, -1,
75, 76, 77, -1,
77, 76, 78, -1,
77, 78, 79, -1,
79, 78, 80, -1,
79, 80, 81, -1,
81, 80, 82, -1,
81, 82, 83, -1,
83, 82, 84, -1,
83, 84, 85, -1,
85, 84, 86, -1,
85, 86, 87, -1,
87, 86, 88, -1,
87, 88, 89, -1,
89, 88, 55, -1,
89, 55, 54, -1,
56, 55, 90, -1,
56, 90, 91, -1,
58, 56, 91, -1,
58, 91, 92, -1,
60, 58, 92, -1,
60, 92, 93, -1,
62, 60, 93, -1,
62, 93, 94, -1,
64, 62, 94, -1,
64, 94, 95, -1,
66, 64, 95, -1,
66, 95, 96, -1,
68, 66, 96, -1,
68, 96, 97, -1,
70, 68, 97, -1,
70, 97, 98, -1,
72, 70, 98, -1,
72, 98, 99, -1,
74, 72, 99, -1,
74, 99, 100, -1,
76, 74, 100, -1,
76, 100, 101, -1,
78, 76, 101, -1,
78, 101, 102, -1,
80, 78, 102, -1,
80, 102, 103, -1,
82, 80, 103, -1,
82, 103, 104, -1,
84, 82, 104, -1,
84, 104, 105, -1,
86, 84, 105, -1,
86, 105, 106, -1,
88, 86, 106, -1,
88, 106, 107, -1,
55, 88, 107, -1,
55, 107, 90, -1,
90, 108, 91, -1,
91, 108, 92, -1,
92, 108, 93, -1,
93, 108, 94, -1,
94, 108, 95, -1,
95, 108, 96, -1,
96, 108, 97, -1,
97, 108, 98, -1,
98, 108, 99, -1,
99, 108, 100, -1,
100, 108, 101, -1,
101, 108, 102, -1,
102, 108, 103, -1,
103, 108, 104, -1,
104, 108, 105, -1,
105, 108, 106, -1,
106, 108, 107, -1,
107, 108, 90, -1,
36, 54, 57, -1,
36, 57, 37, -1,
37, 57, 59, -1,
37, 59, 38, -1,
38, 59, 61, -1,
38, 61, 39, -1,
39, 61, 63, -1,
39, 63, 40, -1,
40, 63, 65, -1,
40, 65, 41, -1,
41, 65, 67, -1,
41, 67, 42, -1,
42, 67, 69, -1,
42, 69, 43, -1,
43, 69, 71, -1,
43, 71, 44, -1,
44, 71, 73, -1,
44, 73, 45, -1,
45, 73, 75, -1,
45, 75, 46, -1,
46, 75, 77, -1,
46, 77, 47, -1,
47, 77, 79, -1,
47, 79, 48, -1,
48, 79, 81, -1,
48, 81, 49, -1,
49, 81, 83, -1,
49, 83, 50, -1,
50, 83, 85, -1,
50, 85, 51, -1,
51, 85, 87, -1,
51, 87, 52, -1,
52, 87, 89, -1,
52, 89, 53, -1,
53, 89, 54, -1,
53, 54, 36, -1
]
}
}
]
}

View File

@@ -0,0 +1,13 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material.003
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.840000 0.80000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
# map_Kd WoodFine0035_1_S.jpg

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:45d43f6540ab3e1dec9c9abe324f2df79ad7113568be4846b2e9bdf512c7fa57
size 14685

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a38b920d147518363a463d0c2d2623da4e322191aae876e4e578f6ea1e712e96
size 4884

View File

@@ -0,0 +1,148 @@
#VRML V2.0 utf8
Group {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.975 0.486 0.975
specularColor 0.7 0.7 1.0
}
}
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
-0.253246 -0.345280 -0.041860,
-0.253246 0.345280 -0.041860,
-0.253246 0.345280 0.042860,
-0.253246 -0.345280 0.042860,
0.254200 0.346280 -0.042860,
0.254200 -0.346280 -0.042860,
-0.254200 -0.346280 -0.042860,
-0.254200 0.346280 -0.042860,
0.254200 0.345280 0.042860,
0.254200 0.346280 0.042860,
-0.254200 0.346280 0.042860,
-0.254200 -0.346280 0.042860,
0.254200 -0.346280 0.042860,
0.254200 -0.345280 0.042860,
0.254200 0.345280 -0.041860,
0.254200 -0.345280 -0.041860,
-0.257500 -0.346280 0.042860,
-0.257500 -0.346280 -0.042860,
-0.257500 0.346280 -0.042860,
-0.257500 0.346280 0.042860,
0.254200 0.349580 0.042860,
-0.254200 0.349580 0.042860,
0.254200 0.349580 -0.042860,
0.254200 -0.379410 -0.061912,
0.254200 -0.379410 0.061912,
0.254200 0.379410 0.061912,
0.254200 0.379410 -0.061912,
0.273200 0.379410 0.061912,
0.273200 0.379410 -0.061912,
0.273200 -0.379410 0.061912,
0.273200 -0.379410 -0.061912,
-0.254200 -0.349575 0.042860,
0.254200 -0.349575 0.042860,
0.254200 -0.349575 -0.042860,
-0.254200 -0.349575 -0.042860,
-0.257471 -0.346280 -0.042860,
-0.257471 -0.346280 0.042860,
-0.254200 0.349580 -0.042860,
-0.257454 0.349580 0.042860,
-0.257454 0.346280 0.042860,
-0.257471 -0.349575 -0.042860,
-0.257471 -0.349575 0.042860,
-0.257454 0.346280 -0.042860,
-0.257454 0.349580 -0.042860,
]
}
coordIndex [
0, 1, 2, -1,
2, 3, 0, -1,
4, 5, 6, -1,
6, 7, 4, -1,
8, 9, 10, -1,
11, 12, 13, -1,
11, 13, 3, -1,
2, 8, 10, -1,
11, 3, 2, -1,
10, 11, 2, -1,
4, 9, 8, -1,
4, 8, 14, -1,
13, 12, 5, -1,
4, 14, 15, -1,
15, 13, 5, -1,
4, 15, 5, -1,
11, 6, 6, -1,
11, 6, 11, -1,
5, 12, 12, -1,
5, 12, 5, -1,
6, 11, 16, -1,
6, 16, 17, -1,
10, 7, 18, -1,
10, 18, 19, -1,
10, 9, 20, -1,
10, 20, 21, -1,
9, 4, 22, -1,
9, 22, 20, -1,
0, 15, 14, -1,
14, 1, 0, -1,
2, 1, 14, -1,
14, 8, 2, -1,
15, 0, 3, -1,
3, 13, 15, -1,
23, 24, 25, -1,
25, 26, 23, -1,
26, 25, 27, -1,
27, 28, 26, -1,
28, 27, 29, -1,
29, 30, 28, -1,
24, 23, 30, -1,
30, 29, 24, -1,
30, 23, 26, -1,
26, 28, 30, -1,
27, 25, 24, -1,
24, 29, 27, -1,
11, 6, 6, -1,
11, 6, 11, -1,
12, 11, 11, -1,
12, 11, 12, -1,
6, 5, 5, -1,
6, 5, 6, -1,
12, 11, 11, -1,
12, 11, 12, -1,
12, 11, 31, -1,
12, 31, 32, -1,
6, 5, 33, -1,
6, 33, 34, -1,
5, 12, 12, -1,
5, 12, 5, -1,
6, 5, 5, -1,
6, 5, 6, -1,
33, 32, 31, -1,
31, 34, 33, -1,
11, 6, 35, -1,
11, 35, 36, -1,
5, 12, 32, -1,
5, 32, 33, -1,
20, 22, 37, -1,
37, 21, 20, -1,
4, 7, 37, -1,
4, 37, 22, -1,
10, 21, 38, -1,
10, 38, 39, -1,
17, 16, 19, -1,
19, 18, 17, -1,
7, 6, 17, -1,
7, 17, 18, -1,
11, 10, 19, -1,
11, 19, 16, -1
]
}
}
]
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9ca449eaff0949f2dd4bbf0aac638fd4175930b701cd1dd8c5981329b3cb60c8
size 3024

View File

@@ -0,0 +1,92 @@
#VRML V2.0 utf8
# Generated by VCGLIB, (C)Copyright 1999-2001 VCG, IEI-CNR
NavigationInfo {
type [ "EXAMINE", "ANY" ]
}
Transform {
scale 1 1 1
translation 0 0 0
children
[
Shape
{
geometry IndexedFaceSet
{
creaseAngle .5
solid FALSE
coord Coordinate
{
point
[
0.246736 -0.334919 -0.04286, 0.2732 0.343763 0.058129, 0.250769 0.381796 0.064545, 0.250769 0.381796 -0.064286,
0.2732 -0.343696 -0.057857, 0.250769 -0.381796 0.064545, 0.2732 0.343763 -0.057869, 0.2732 -0.343696 0.058117,
0.245999 0.353094 0.045453, 0.250769 -0.381796 -0.064286, 0.245999 -0.353094 0.045453, 0.246736 0.334919 -0.04286,
-0.24594 -0.344106 -0.04286, -0.250343 -0.004807 0.045468, -0.259883 -0.004807 0.045468, -0.259883 -0.353127 0.045468,
-0.259883 -0.004807 -0.045208, -0.245317 0.00132 -0.04186, -0.245569 -0.353127 0.045468, -0.259883 -0.353127 -0.045208,
-0.259883 -0.004772 -0.045208, -0.245569 0.353162 0.045468, -0.259883 0.353162 0.045468, -0.259883 0.353162 -0.045208,
-0.245317 -0.011068 -0.04186, -0.259883 -0.004772 0.045468, -0.24594 0.343891 -0.04286, -0.250343 -0.004772 0.045468,
0.2542 -0.343539 0.046982, -0.245569 -0.353162 -0.045208, -0.232838 -0.339216 -0.04286, 0.2542 -0.338607 -0.046722,
0.2542 -0.353401 -0.046722, -0.245569 -0.353162 0.045468, 0.2542 -0.353401 0.046982, -0.245569 -0.343618 0.045468,
-0.253246 -0.338622 -0.0417, -0.245569 -0.338844 -0.045208, 0.2542 0.000805 -0.040356, -0.253246 0.000445 -0.040361,
0.2542 -0.344421 -0.040356, -0.253246 -0.344062 -0.040361, -0.245569 -0.004772 -0.045208, -0.245569 -0.004772 -0.045208,
0.2542 0.344581 -0.040356, -0.253246 0.344211 -0.040361, 0.2542 -0.010509 -0.040356, -0.253246 -0.010139 -0.040361,
-0.245569 0.338844 -0.045208, 0.2542 0.343539 0.046982, -0.232838 0.339216 -0.04286, -0.245569 0.353162 -0.045208,
0.2542 0.338607 -0.046722, 0.2542 0.353401 -0.046722, -0.245569 0.353162 0.045468, 0.2542 0.353401 0.046982,
-0.245569 0.343618 0.045468, -0.253246 0.338622 -0.0417
]
}
color Color
{
color
[
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941
]
}
coordIndex
[
0,8,11,-1, 2,1,3,-1, 1,2,5,-1, 3,1,6,-1, 1,4,6,-1, 4,1,7,-1,
1,5,7,-1, 5,4,7,-1, 2,3,8,-1, 5,2,8,-1, 0,3,9,-1, 4,5,9,-1,
3,6,9,-1, 6,4,9,-1, 8,0,10,-1, 5,8,10,-1, 0,9,10,-1, 9,5,10,-1,
3,0,11,-1, 8,3,11,-1, 12,18,19,-1, 13,14,15,-1, 15,14,16,-1, 16,14,17,-1,
14,13,17,-1, 12,16,17,-1, 12,17,18,-1, 13,15,18,-1, 17,13,18,-1, 18,15,19,-1,
16,12,19,-1, 15,16,19,-1, 25,24,27,-1, 22,21,23,-1, 20,22,23,-1, 22,20,25,-1,
21,22,25,-1, 20,24,25,-1, 23,21,26,-1, 20,23,26,-1, 24,20,26,-1, 21,24,26,-1,
24,21,27,-1, 21,25,27,-1, 35,28,36,-1, 29,30,31,-1, 31,28,32,-1, 29,31,32,-1,
29,32,33,-1, 32,28,34,-1, 33,32,34,-1, 28,33,34,-1, 33,28,35,-1, 33,35,36,-1,
30,29,36,-1, 31,30,36,-1, 28,31,36,-1, 29,33,36,-1, 39,38,42,-1, 38,39,40,-1,
37,38,40,-1, 37,40,41,-1, 39,37,41,-1, 40,39,41,-1, 37,39,42,-1, 38,37,42,-1,
45,44,48,-1, 44,45,46,-1, 43,44,46,-1, 43,46,47,-1, 45,43,47,-1, 46,45,47,-1,
43,45,48,-1, 44,43,48,-1, 49,56,57,-1, 50,51,52,-1, 49,52,53,-1, 52,51,53,-1,
53,51,54,-1, 54,49,55,-1, 49,53,55,-1, 53,54,55,-1, 49,54,56,-1, 56,54,57,-1,
51,50,57,-1, 50,52,57,-1, 52,49,57,-1, 54,51,57,-1
]
}
appearance Appearance
{
material Material
{
ambientIntensity 0.2
diffuseColor 0.9 0.9 0.9
specularColor .1 .1 .1
shininess .5
}
}
}
]
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:41065b59579cd98df0ad6af3896c84e110b90921ceab593b8e743fff4781758f
size 564

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4a00e9073372ce38c96578e125e96a34dc7fc82b3c4aecb3d2325ce9e32d3b78
size 358

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d35ab30caf5eecdd020f88ab5c1ef071d3bccfb00cca98b6ba73bf63d7ee841f
size 355

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8db539911359bdd49871465fec53939ecd16ee6b9e002593d40226c658c08c2b
size 403

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:609e21fcb2a3ec415de08b2f3132bb15f04f8be222b9f1a2714c63fb07505e49
size 263

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8f7bc1f4c477ffb96db189ba24b1f16c868474305b871efefa8ec9ee558abf37
size 262

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ed6fced79e57e0e3b1db0c714d81b0c7812e8fe59ade78abb7caf3b19217a1a9
size 394

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ba84b51cda8363a3df8765423f8d6fbea9407ee5dae6be51f7e5fd917d359ced
size 101173

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c549fdf19e95f53a0362df7ad85031fa55b533fb59bbf20e8019a13a84f60b76
size 42484

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:46738e1fac2c61283c3882f3b089e0529d1833543611882a262f49b6ef62cd81
size 4264

View File

@@ -0,0 +1,111 @@
#VRML V2.0 utf8
# Generated by VCGLIB, (C)Copyright 1999-2001 VCG, IEI-CNR
NavigationInfo {
type [ "EXAMINE", "ANY" ]
}
Transform {
scale 1 1 1
translation 0 0 0
children
[
Shape
{
geometry IndexedFaceSet
{
creaseAngle .5
solid FALSE
coord Coordinate
{
point
[
0.273353 -0.083513 0.00574, 0.295333 -0.083513 0.00574, 0.273229 -0.049378 0.020858, 0.295243 -0.07641 0.020633,
0.273229 -0.049378 -0.002386, 0.295088 -0.075261 -0.001999, 0.273429 -0.078417 0.019655, 0.273599 -0.075261 -0.001999,
0.294921 -0.04339 -0.002934, 0.295246 -0.083359 0.013693, 0.294921 -0.04339 0.021407, 0.273444 -0.07641 0.020633,
0.273441 -0.083359 0.013693, 0.273475 -0.081322 0.001825, 0.295149 -0.079252 -9.6e-05, 0.295258 -0.082386 0.015684,
0.295258 -0.078417 0.019655, 0.273429 -0.082386 0.015684, 0.295212 -0.081322 0.001825, 0.273538 -0.079252 -9.6e-05,
0.296194 -0.083475 0.005632, 0.311329 0.002299 0.020597, 0.311857 0.005292 -0.002934, 0.311857 -0.080429 -0.000816,
0.297343 0.003336 -0.002405, 0.296317 -0.075672 0.020896, 0.311857 -0.07725 0.021407, 0.297101 0.004917 0.021305,
0.296436 -0.074115 -0.002241, 0.311857 -0.076193 -0.002934, 0.296224 -0.083302 0.01385, 0.311329 -0.081672 0.013678,
0.296299 -0.078813 -0.000417, 0.296272 -0.077934 0.019944, 0.311329 -0.081672 0.00578, 0.296227 -0.082256 0.015902,
0.296253 -0.081089 0.001569, 0.273475 0.081322 0.001825, 0.295243 0.07641 0.020633, 0.273444 0.07641 0.020633,
0.294921 0.04339 -0.002934, 0.273229 0.049378 0.020858, 0.294921 0.04339 0.021407, 0.272704 0.048687 -0.002934,
0.295088 0.075261 -0.001999, 0.295246 0.083359 0.013693, 0.273441 0.083359 0.013693, 0.273599 0.075261 -0.001999,
0.295333 0.083513 0.00574, 0.273353 0.083513 0.00574, 0.295149 0.079252 -9.6e-05, 0.273429 0.078417 0.019655,
0.295258 0.082386 0.015684, 0.273429 0.082386 0.015684, 0.295258 0.078417 0.019655, 0.295212 0.081322 0.001825,
0.273538 0.079252 -9.6e-05, 0.296284 0.081117 0.0016, 0.311857 0.077246 0.021407, 0.311857 0.079359 0.020347,
0.311857 0.005299 -0.002934, 0.297101 0.00563 0.021305, 0.311857 0.076189 -0.002934, 0.297343 0.007024 -0.002405,
0.311329 0.007939 0.020597, 0.296343 0.075786 0.020856, 0.295984 0.042337 -0.002934, 0.296254 0.083309 0.013833,
0.311329 0.082017 0.00578, 0.296457 0.07433 -0.002209, 0.295984 0.042337 0.021407, 0.311857 0.080423 -0.000816,
0.29622 0.083479 0.005644, 0.311329 0.082017 0.013678, 0.296216 0.079388 0.018995, 0.296331 0.078874 -0.000377,
0.311857 0.080423 0.019289, 0.296256 0.082271 0.015877, 0.296298 0.077997 0.019906
]
}
color Color
{
color
[
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941,
0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941, 0.752941 0.752941 0.752941
]
}
coordIndex
[
14,13,19,-1, 0,2,4,-1, 2,0,6,-1, 5,7,8,-1, 4,2,8,-1, 1,5,8,-1,
7,4,8,-1, 0,1,9,-1, 3,1,10,-1, 1,8,10,-1, 8,2,10,-1, 2,6,11,-1,
6,3,11,-1, 10,2,11,-1, 3,10,11,-1, 0,9,12,-1, 1,0,13,-1, 0,4,13,-1,
7,5,14,-1, 9,1,15,-1, 12,9,15,-1, 1,3,16,-1, 3,6,16,-1, 15,1,16,-1,
6,15,16,-1, 6,0,17,-1, 0,12,17,-1, 15,6,17,-1, 12,15,17,-1, 5,1,18,-1,
1,13,18,-1, 13,14,18,-1, 14,5,18,-1, 4,7,19,-1, 13,4,19,-1, 7,14,19,-1,
27,32,36,-1, 22,21,26,-1, 23,22,26,-1, 25,26,27,-1, 21,22,27,-1, 22,24,27,-1,
26,21,27,-1, 28,24,29,-1, 22,23,29,-1, 24,22,29,-1, 23,26,31,-1, 30,20,31,-1,
27,24,32,-1, 24,28,32,-1, 28,29,32,-1, 29,23,32,-1, 26,25,33,-1, 25,27,33,-1,
27,20,33,-1, 20,23,34,-1, 31,20,34,-1, 23,31,34,-1, 20,30,35,-1, 31,26,35,-1,
30,31,35,-1, 26,33,35,-1, 33,20,35,-1, 23,20,36,-1, 20,27,36,-1, 32,23,36,-1,
50,47,56,-1, 38,39,42,-1, 39,41,42,-1, 42,41,43,-1, 40,42,43,-1, 40,43,44,-1,
44,43,47,-1, 38,42,48,-1, 42,40,48,-1, 40,44,48,-1, 46,45,48,-1, 46,48,49,-1,
37,43,49,-1, 48,37,49,-1, 44,47,50,-1, 39,38,51,-1, 41,39,51,-1, 43,41,51,-1,
45,46,52,-1, 48,45,52,-1, 51,52,53,-1, 46,49,53,-1, 49,43,53,-1, 43,51,53,-1,
52,46,53,-1, 38,48,54,-1, 51,38,54,-1, 48,52,54,-1, 52,51,54,-1, 48,44,55,-1,
37,48,55,-1, 50,37,55,-1, 44,50,55,-1, 43,37,56,-1, 47,43,56,-1, 37,50,56,-1,
74,65,78,-1, 59,58,60,-1, 59,60,62,-1, 60,61,63,-1, 60,58,64,-1, 61,60,64,-1,
58,61,64,-1, 62,60,66,-1, 60,63,66,-1, 63,61,66,-1, 62,66,69,-1, 61,58,70,-1,
58,65,70,-1, 66,61,70,-1, 59,62,71,-1, 57,66,72,-1, 66,70,72,-1, 71,57,72,-1,
68,71,72,-1, 71,68,73,-1, 72,67,73,-1, 68,72,73,-1, 70,65,74,-1, 67,72,74,-1,
72,70,74,-1, 66,57,75,-1, 62,69,75,-1, 69,66,75,-1, 71,62,75,-1, 57,71,75,-1,
59,71,76,-1, 73,67,76,-1, 71,73,76,-1, 74,59,76,-1, 74,76,77,-1, 67,74,77,-1,
76,67,77,-1, 58,59,78,-1, 65,58,78,-1, 59,74,78,-1
]
}
appearance Appearance
{
material Material
{
ambientIntensity 0.2
diffuseColor 0.9 0.9 0.9
specularColor .1 .1 .1
shininess .5
}
}
}
]
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4dc04080b3c27816c22f1270aaffbd6e3462e760ed70a9063c8beeab6531fb6e
size 165584

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14f804a49108b6943d29ca0acf1d3bd729c92633a8c9349469b38cda174ea6df
size 165584

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a4c3248cf9f2c925d18aa9bb2e3659ef0d6a703252b006a3d9f1bc8ec2e917fb
size 653284

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:93c508d0575ebd1a57550fa81f71fe62d98adfa04bf63748fd7fc4185988e97d
size 165584

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1bbd7dce7071851482eb7c47e17934847c98f3ead2cc1a148387dbec969ba4c4
size 165584

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:136475599e901768a0195df51634cb3f007d0d5a0c647855056aac31dc62a73b
size 653284

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dc86b6a32e9471c70a3d61c32647e94ef1757a49af21b81167c1723a8c95f9eb
size 849934

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a99f73338c90276cd7a90573714300c4a1383c5514d3a5e0671fb60b440ac5d4
size 368984

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f86f502db343c512a1b1307189d1b0b2d448af4886e84bd9d09e8e125d9ad165
size 51884

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c1fbc2fef86689e5a5b1d5b8a8d6c5e68cc9a548dee461de0c759a18e5023317
size 280684

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:008894df7deb20d9aec98b4dbc3ac8e12dbc31b90e6a8485542140eb0ab3ded5
size 189684

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d3a46b4b619bfd28d8948d5335f8bd62284ea0742ec4fb2b7ac5e5ab858d67f8
size 368484

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5d903745e9369009ac064bc24c080d03f503b3386b8e14325a318cf8fde0959d
size 185784

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2fc93b2bc970eadca950afa3120129766e2bead60234c6d8752d3b223e407046
size 184184

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f9d0216056f7e1512858033163b0415973e1db573a1fee5af1609171967c043f
size 195784

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3f902cd207e284336242946a7fb519f8a499b4278048ba4646d64feba14dbdea
size 732484

View File

@@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 0
Ka 0.000000 0.000000 0.000000
Kd 0.425 0.5 0.725
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:330af0191f900598a8c73d19111e60b08d2f0e1c3b32c27a0767fc747644082d
size 15408

View File

@@ -0,0 +1,9 @@
# File produced by Open Asset Import Library (http://www.assimp.sf.net)
# (assimp v3.1.187496374)
newmtl DefaultMaterial
Kd 0.6 0.6 0.6
Ka 0.05 0.05 0.05
Ks 0.6 0.6 0.6
illum 1

Some files were not shown because too many files have changed in this diff Show More