포스트

[IsaacLab Part 2] Unitree Go2 환경 구성하기

Isaac Lab의 InteractiveSceneCfg와 SimulationContext로 Unitree Go2 scene을 구성하는 과정을 정리한다.

[IsaacLab Part 2] Unitree Go2 환경 구성하기

사담

드디어 내 로봇개 go2가 도착했습니다!!

이번 프로젝트의 최종 목표는 로봇개로 건물 전체를 매핑하는 일인데.. 세부 목표를 따지면 아래와 같을 것 같습니다.

  1. isaac lab을 통해 isaac sim상에서 로봇개의 걷는 policy 학습하기

  2. sim to real을 통해 ros로 로봇개의 움직임 제어..

Interactive scene구성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from isaaclab.scene import InteractiveSceneCfg
from isaaclab.terrains import TerrainImporterCfg
from isaaclab.sensors.ray_caster import RayCasterCfg
from isaaclab.sensors.ray_caster.patterns import GridPatternCfg
from isaaclab.sensors.ray_caster import patterns
from isaaclab.utils import configclass
from isaaclab_assets.robots.unitree import UNITREE_GO2_CFG  # isort:skip
from isaaclab.assets import ArticulationCfg, AssetBaseCfg
import isaaclab.sim as sim_utils

@configclass
class Myscene(InteractiveSceneCfg):
    # 지형 정의
    terrain = TerrainImporterCfg(
        prim_path = "/World/ground",
        terrain_type = "plane",
    )

    # 로봇 정의
    go2: ArticulationCfg = UNITREE_GO2_CFG.replace(prim_path="{ENV_REGEX_NS}/Go2")

    # 센서 정의
    height_scanner = RayCasterCfg(
        prim_path = "{ENV_REGEX_NS}/Go2/base",
        update_period = 0.02,
        offset=RayCasterCfg.OffsetCfg(pos=(0.0, 0.0, 20.0)),
        ray_alignment="yaw",
        pattern_cfg=patterns.GridPatternCfg(resolution=0.1, size=[1.6, 1.0]), # pattern_cfg
        debug_vis=True,
        mesh_prim_paths=["/World/ground"],
    )

    # 조명 정의
    light = AssetBaseCfg(
        prim_path = "/World/light",
        spawn = sim_utils.DistantLightCfg(intensity=1000.0),
    )
  • Isaac lab은 InteractiveScene과 InteractiveCfg를 통해 환경을 구성할 수 있는데요 그중에는 Terrain(장애물), robot, sensor, light등이 있습니다.
    • Terrain : 일단 prim_path와 type을 지정하여 아무것도 없는 지면으로 구성하였습니다.
    • robot : asset으로부터 unitree go2로봇의 cfg파일을 가져와 로봇의 관절이나, 여러 파라미터 구성해줍니다.
    • sensor : hight_scanner sensor를 장착했는데요. 로봇의 강화학습에 필요한 지형높이정보를 수집하는데 사용될 수 있습니다. 예를들어 robot의 base로부터 mesh_prim_path인 ground까지의 높이를 측정합니다.

Simulation setting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import os
import hydra
import rclpy
import torch
import time
import math
import argparse
from isaaclab.app import AppLauncher
# add argparse arguments
parser = argparse.ArgumentParser(description="Unitree go2 ros2 setup")

# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()

# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app

"""Rest everything follows."""

import torch
import isaaclab.sim as sim_utils
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sim import SimulationContext

from go2.go2_env import Myscene


FILE_PATH = os.path.join(os.path.dirname(__file__), "config")
@hydra.main(config_path=FILE_PATH, config_name="sim", version_base=None)
def run_simulator(cfg):
    sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
    sim = SimulationContext(sim_cfg)
    sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0])
    scene_cfg = Myscene(num_envs=cfg.num_envs, env_spacing=2.0)
    scene = InteractiveScene(scene_cfg)
    # play the simulator
    sim.reset()
    print("[INFO]: simulation started")
    sim_dt = sim.get_physics_dt()
    count = 0
    robot = scene["go2"]
    while simulation_app.is_running():
        if count % 300 == 0:
            count = 0
            root_state = robot.data.default_root_state.clone()
            root_state[:,:3] += scene.env_origins
            robot.write_root_pose_to_sim(root_state[:,:7])
            robot.write_root_velocity_to_sim(root_state[:,7:])
            joint_pos, joint_vel = robot.data.default_joint_pos.clone(), robot.data.default_joint_vel.clone()
            joint_pos += torch.rand_like(joint_pos) * 0.1
            robot.write_joint_state_to_sim(joint_pos, joint_vel)
            scene.reset()
            print("[INFO]: Resetting robot scene")

        joint_pos_target = torch.randn_like(robot.data.joint_pos) * 0.1
        # apply action to the robot
        robot.set_joint_position_target(joint_pos_target)
        # -- write data to sim
        scene.write_data_to_sim()
        # Perform step
        sim.step()
        # Increment counter
        count += 1
        # Update buffers
        scene.update(sim_dt)
    simulation_app.close()

if __name__ == "__main__":
    run_simulator()
  • hydra를 통해 cfg를 가져오고 run_simulator안에서 SimulationContext를 통해 simulation을 시작한 후 위에서 구성한 scene의 Cfg를 통해 scene을 생성합니다.
  • scene[“go2”]를 통해 scene안에 있는 로봇에 접급할 수 있습니다. 300번의 step마다 로봇의 pos와 joint값을 reset하게 함으로써 우리가 원하는 scene을 isaaclab에서 불러 올 수 있게 됩니다.

관절이 기묘하게 뒤틀린 go2..

관절이 기묘하게 뒤틀린 go2..

결과적으로 random 값을 로봇의 joint에 주고 있어서 관절이 기묘하게 꺽이고 있지만 isaac sim안에서 scene은 원하는대로 구성된 모습입니다..

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.