Curieux.JY
  • Post
  • Note
  • Jung Yeon Lee

On this page

  • 1 API Demos
  • 2 Code ์‚ดํŽด๋ณด๊ธฐ
    • 2.1 Modules
    • 2.2 Helpers
    • 2.3 Main
  • 3 Closing

๐Ÿ‘ฉโ€๐Ÿ’ปOrbit Existing Scripts

orbit
isaacsim
code
Isaac Orbit Series 002
Published

April 23, 2023

Orbit์€ IsaacLab์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Orbit ์‹œ๋ฆฌ์ฆˆ์˜ ๋‘๋ฒˆ์งธ ํฌ์ŠคํŒ…์œผ๋กœ ์ด๋ฒˆ์—๋Š” Orbit์—์„œ ์ œ๊ณตํ•˜๋Š” scripts๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ Orbit์œผ๋กœ ์–ด๋–ค ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ์ˆ˜ ์žˆ์„์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ณต์‹ Documents์—์„œ Running existing scripts๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ณด๋ฉฐ ์ง„ํ–‰๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

1 API Demos

Orbit์˜ ๋ฉ”์ธ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“ˆ์€ omni.isaac.orbit ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ชจ๋“ˆ์—์„œ๋Š” ๋กœ๋ด‡๋“ค์˜ actuator๋‚˜ object, sensor ๋“ฑ์„ ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” interface๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž์„  ์‹œ๋ฆฌ์ฆˆ ํฌ์ŠคํŒ…์—์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ 4์กฑ ๋ณดํ–‰๋กœ๋ด‡๋“ค์„ ๋„์›Œ๋ณด๋Š” script๋ฅผ ์‹คํ–‰ ์‹œ์ผœ๋ณด์•˜์—ˆ๋Š”๋ฐ ์ด์™€ ๊ฐ™์€ standlone/demo์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ช‡๊ฐ€์ง€ ์˜ˆ์ œ๋“ค์„ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ํŒŒ์ผ ์œ„์น˜์™€ ์‹คํ–‰ ์ „์ œ

Orbit ์‹œ๋ฆฌ์ฆˆ ํฌ์ŠคํŒ…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด์ „ ํฌ์ŠคํŒ…์— ์ด์–ด์„œ ์ง„ํ–‰๋˜๋Š” ํฌ์ŠคํŒ…์ด๋ฏ€๋กœ Orbit ํŒŒ์ผ์„ Github์—์„œ ๋‹ค์šด๋ฐ›๊ณ  orbit ์„ค์น˜๋ฅผ ์ „์ œ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด์ „์— Orbit repository๋ฅผ ๋‹ค์šด ๋ฐ›์€ ์œ„์น˜์—์„œ ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”. orbit ์‹คํ–‰ ๋ช…๋ น์–ด๋„ orbit์œผ๋กœ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. -p ์˜ต์…˜์€ Isaac Sim์˜ python.sh๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ python ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋„๋ก ํ•˜๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

  • 4์กฑ ๋ณดํ–‰ ๋กœ๋ด‡๋“ค์„ ๋†“๊ณ  ๋ฐœ(feet) marker๋ฅผ ์‹œ๊ฐํ™”ํ•˜๊ณ  stadning pose๋ฅผ ์œ ์ง€ํ•˜๋„๋ก position command๋ฅผ ์ ์šฉ์‹œํ‚จ ์˜ˆ์ œ

    orbit -p source/standalone/demo/play_quadrupeds.py

    orbit2-5

  • 2๋Œ€์˜ Franka ๋งค๋‹ˆํ“ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋†“๊ณ  ๋žœ๋คํ•œ position command๋ฅผ ์ ์šฉ์‹œ์ผœ์„œ ์›€์ง์ด๊ฒŒ ํ•˜๋Š” ์˜ˆ์ œ

    orbit -p source/standalone/demo/play_arms.py --robot franka_panda

    orbit2-1

  • 128๋Œ€์˜ Franka ๋งค๋‹ˆํ“ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋†“๊ณ  inverse kinematics controller๋ฅผ ์ด์šฉํ•˜์—ฌ ์ œ์–ดํ•˜๋Š” ์˜ˆ์ œ

    orbit -p source/standalone/demo/play_ik_control.py --robot franka_panda --num_envs 128

    orbit2-2

  • ์นด๋ฉ”๋ผ๋ฅผ ์„ค์ •ํ•˜๊ณ  pointcloud๋ฅผ ์–ป๋Š” ์˜ˆ์ œ(cpu์™€ gpu ์„ ํƒ๊ฐ€๋Šฅ)

    # CPU
    orbit -p source/standalone/demo/play_camera.py
    # GPU
    orbit -p source/standalone/demo/play_camera.py --gpu

    orbit2-3

2 Code ์‚ดํŽด๋ณด๊ธฐ

์•ž์˜ ์˜ˆ์ œ์ฝ”๋“œ๋“ค ์ค‘ source/standalone/demo/play_quadrupeds.py๋ฅผ ํ•˜๋‚˜์”ฉ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ orbit์—์„œ ์–ด๋–ค ๋ชจ๋“ˆ๋“ค์„ ์ œ๊ณตํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์˜ˆ์ œ์—์„œ๋Š” 3์ข…๋ฅ˜์˜ 4์กฑ ๋ณดํ–‰๋กœ๋ด‡์„ ๋ถˆ๋Ÿฌ์™€ ์ง„ํ–‰ํ•˜๋Š”๋ฐ ๊ฐ ๋กœ๋ด‡์˜ ํ”Œ๋žซํผ์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•˜์‹  ๋ถ„๋“ค์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ํ™•์ธํ•ด๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  • ANYmal-B (from ANYbotics)
  • ANYmal-C (from ANYbotics)
  • A1 (from Unitree Robotics)

2.1 Modules

Orbit์ด ๊ธฐ๋ฐ˜ํ•˜๊ณ  ์žˆ๋Š” Isaac Sim Simulator์„ ๋จผ์ € ํ‚ค๊ธฐ ์œ„ํ•ด SimulationApp class๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์•ฑ์„ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋•Œ headless๋Š” ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์˜ GUI๋ฅผ ๋„์šฐ์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•˜๋Š” ์˜ต์…˜์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

"""Launch Isaac Sim Simulator first."""

from omni.isaac.kit import SimulationApp

import argparse
# add argparse arguments
parser = argparse.ArgumentParser("Welcome to Orbit: Omniverse Robotics Environments!")
parser.add_argument("--headless", action="store_true", default=False, help="Force display off at all times.")
args_cli = parser.parse_args()

# launch omniverse app
config = {"headless": args_cli.headless}
simulation_app = SimulationApp(config)

๋‹ค์Œ์œผ๋กœ importํ•˜๋Š” orbit์˜ core๋ชจ๋“ˆ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • prim_utils : ํ˜„์žฌ USD stage์— prim์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋ชจ๋“ˆ. (์ž์„ธํ•œ prim์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ๊ฐ„๋‹จํ•˜๊ฒŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์˜ ์˜ค๋ธŒ์ ํŠธ๋“ค์„ prim์œผ๋กœ ๋ณธ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.)

  • SimulationContext : ํƒ€์ž„๋ผ์ธ ๊ด€๋ จ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ (simulator ์ผ์‹œ ์ค‘์ง€, ์žฌ์ƒ, ๋‹จ๊ณ„์  ์‹คํ–‰ ๋˜๋Š” ์ค‘์ง€ ๋“ฑ), stage๋ฅผ ๊ตฌ์„ฑํ•˜๋ฉฐ(stage ๋‹จ์œ„๋‚˜ ์ƒ/ํ•˜ ๋ฐฉํ–ฅ๊ณผ ๊ฐ™์€ ์„ค์ •), physicsScene prim์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค(์ค‘๋ ฅ ๋ฐฉํ–ฅ ๋ฐ ํฌ๊ธฐ, ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ํฌ๊ธฐ, ๊ณ ๊ธ‰ ์†”๋ฒ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ค์ •๊ณผ ๊ฐ™์€ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ œ๊ณต). ์—ฌ๊ธฐ์„œ physicsScene prim์€ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์œ„ํ•œ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •์„ ๋‹ด๋‹นํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งํ•˜๋ฉฐ, SimulationContext๋Š” ์ด๋Ÿฌํ•œ physicsScene prim์„ ์ƒ์„ฑํ•˜๊ณ  ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์„ค์ •์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ํƒ€์ž„๋ผ์ธ ๊ด€๋ จ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์™€ ์Šคํ…Œ์ด์ง€ ์„ค์ •์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

  • set_camera_view : stage์—์„œ ์นด๋ฉ”๋ผ prim์˜ ์œ„์น˜์™€ ๋Œ€์ƒ์„ ์„ค์ •ํ•˜๊ณ , ํ•ด๋‹น prim์˜ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์นด๋ฉ”๋ผ prim์€ stage ์นด๋ฉ”๋ผ๋กœ ์‚ฌ์šฉ๋  ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ์œ„์น˜(location)์™€ ๋Œ€์ƒ(target)์€ ๊ฐ๊ฐ ์นด๋ฉ”๋ผ์˜ ์œ„์น˜์™€ ์นด๋ฉ”๋ผ๊ฐ€ ๋ฐ”๋ผ๋ณด๋Š” ๋Œ€์ƒ์˜ ์œ„์น˜๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ(path)๋Š” ์Šคํ…Œ์ด์ง€์—์„œ ํ•ด๋‹น ์นด๋ฉ”๋ผ prim์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ด๋ฆ„์ด๋‚˜ ๊ฒฝ๋กœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ด์™ธ์˜ ๋ชจ๋“ˆ์ค‘์—์„œ kit_utils๋Š” ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ์ œ๊ณตํ•˜๋Š” ground๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•œ(create_ground_plane) ๋ชจ๋“ˆ์ด๋ฉฐ ๋กœ๋ด‡์˜ ๋ฐœ ์œ„์น˜ ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด markers ๋ชจ๋“ˆ์—์„œ PointMarker, StaticMarker๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ robot ๋ชจ๋“ˆ์—์„œ 4์กฑ๋ณดํ–‰๋กœ๋ด‡๋“ค์„ ์œ„ํ•œ configuration๋“ค์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# from core
import omni.isaac.core.utils.prims as prim_utils
from omni.isaac.core.simulation_context import SimulationContext
from omni.isaac.core.utils.viewports import set_camera_view

import omni.isaac.orbit.utils.kit as kit_utils
from omni.isaac.orbit.markers import PointMarker, StaticMarker

from omni.isaac.orbit.robots.config.anymal import ANYMAL_B_CFG, ANYMAL_C_CFG
from omni.isaac.orbit.robots.config.unitree import UNITREE_A1_CFG
from omni.isaac.orbit.robots.legged_robot import LeggedRobot

2.2 Helpers

Main ์ฝ”๋“œ์—์„œ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์˜ Scene์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ Ground-plane, Lights๋“ค์„ ํŽธํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ helper ํ•จ์ˆ˜ design_scene()๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ์•ž์„œ importํ–ˆ๋˜ kit_utils๋ฅผ ์ด์šฉํ•ด์„œ ground๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  prim_utils๋ฅผ ์ด์šฉํ•˜์—ฌ ๋น› ์„ค์ •์„ ํ•ด์ค๋‹ˆ๋‹ค.

def design_scene():
    """Add prims to the scene."""
    # Ground-plane
    kit_utils.create_ground_plane(
        "/World/defaultGroundPlane",
        static_friction=0.5,
        dynamic_friction=0.5,
        restitution=0.8,
        improve_patch_friction=True,
    )
    # Lights-1
    prim_utils.create_prim(
        "/World/Light/GreySphere",
        "SphereLight",
        translation=(4.5, 3.5, 10.0),
        attributes={"radius": 2.5, "intensity": 600.0, "color": (0.75, 0.75, 0.75)},
    )
    # Lights-2
    prim_utils.create_prim(
        "/World/Light/WhiteSphere",
        "SphereLight",
        translation=(-4.5, 3.5, 10.0),
        attributes={"radius": 2.5, "intensity": 600.0, "color": (1.0, 1.0, 1.0)},
    )

2.3 Main

๋ฉ”์ธ ์ฝ”๋“œ์—์„œ๋Š” ๋จผ์ € SimulationContext๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์˜ ์‹œ๊ฐ„๊ด€๋ จ ์„ค์ • ๋“ฑ์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. dt๊ฐ€ 0.005๋ผ๋Š” ๊ฒƒ์€ ์‹œ๊ฐ„ ๋‹จ์œ„๊ฐ€ second๋กœ ์‹œ๊ฐ„๊ฐ„๊ฒฉ์ด 0.005์ดˆ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ backend๋Š” ์ดํ›„ ํฌ์ŠคํŒ…์—์„œ๋„ ์„ค๋ช…ํ•˜๊ฒ ์ง€๋งŒ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” tensor๋“ค์„ ์–ด๋–ค backend๋กœ ์บ์ŠคํŒ…ํ•  ๊ฒƒ์ธ์ง€ ์„ค์ •ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ orbit์—์„œ๋Š” torch๋งŒ ์ง€์›ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์˜ ์‹œ์ ์ด ๋˜๋Š” ์นด๋ฉ”๋ผ๋ฅผ ์„ค์ •ํ•˜๊ณ  ๊ฐ ๋กœ๋ด‡์„ ์–ด๋””์— ๋†“์„์ง€ ์ •ํ•˜๋Š” translation ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ํ•จ๊ป˜ spawningํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ helper ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋˜ design_scene()์„ ์ด์šฉํ•˜์—ฌ ground์™€ light๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

"""Imports all legged robots supported in Orbit and applies zero actions."""

# Load kit helper
sim = SimulationContext(stage_units_in_meters=1.0, physics_dt=0.005, rendering_dt=0.005, backend="torch")
# Set main camera
set_camera_view(eye=[3.5, 3.5, 3.5], target=[0.0, 0.0, 0.0])

# Spawn things into stage
# -- anymal-b
robot_b = LeggedRobot(cfg=ANYMAL_B_CFG)
robot_b.spawn("/World/Anymal_b/Robot_1", translation=(0.0, -1.5, 0.65))
robot_b.spawn("/World/Anymal_b/Robot_2", translation=(0.0, -0.5, 0.65))
# -- anymal-c
robot_c = LeggedRobot(cfg=ANYMAL_C_CFG)
robot_c.spawn("/World/Anymal_c/Robot_1", translation=(1.5, -1.5, 0.65))
robot_c.spawn("/World/Anymal_c/Robot_2", translation=(1.5, -0.5, 0.65))
# -- unitree a1
robot_a = LeggedRobot(cfg=UNITREE_A1_CFG)
robot_a.spawn("/World/Unitree_A1/Robot_1", translation=(1.5, 0.5, 0.42))
robot_a.spawn("/World/Unitree_A1/Robot_2", translation=(1.5, 1.5, 0.42))

# design props
design_scene()

์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” reset์„ ๋จผ์ € ์ง„ํ–‰ํ•ด์ค๋‹ˆ๋‹ค. ๊ฐ ๋กœ๋ด‡์˜ handle ๋˜ํ•œ ์ดˆ๊ธฐํ™”๋ฅผ ์‹œ์ผœ์ค๋‹ˆ๋‹ค. ๋กœ๋ด‡์˜ ๊ฐ ์ •๋ณด๋ฅผ ๋‹ด๊ธฐ ์œ„ํ•œ buffer๋„ reset์„ ํ•ด์„œ ๋ณธ๊ฒฉ์ ์ธ ์‹คํ–‰์„ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.

# Play the simulator
sim.reset()
# Acquire handles
# Initialize handles
robot_b.initialize("/World/Anymal_b/Robot.*")
robot_c.initialize("/World/Anymal_c/Robot.*")
robot_a.initialize("/World/Unitree_A1/Robot.*")
# Reset states
robot_b.reset_buffers()
robot_c.reset_buffers()
robot_a.reset_buffers()

4์กฑ ๋ณดํ–‰ ๋กœ๋ด‡์€ ์ œ์–ด๋ฅผ ํ•  ๋•Œ ๋ฐœ์˜ ์›€์ง์ž„์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฐœ์˜ ์œ„์น˜์— ๋งˆ์ปค๋ฅผ ์œ„์น˜์‹œ์ผœ์„œ ๋ฐœ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด marker๋ฅผ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค. ๋ฐœ์˜ x, y, z ์ถ•์„ ์‹œ๊ฐํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ StaticMarker๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์ •ํ•˜๊ณ  ๋ฐœ์ด contact ํฌ์ธํŠธ๋ฅผ ๋ณด๊ธฐ ์œ„ํ•ด PointMarker๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

# Debug visualization markers.
# -- feet markers
feet_markers: List[StaticMarker] = list()
feet_contact_markers: List[PointMarker] = list()
# iterate over robots
for robot_name in ["Anymal_b", "Anymal_c", "Unitree_A1"]:
    # foot
    marker = StaticMarker(f"/World/Visuals/{robot_name}/feet", 4 * robot_c.count, scale=(0.1, 0.1, 0.1))
    feet_markers.append(marker)
    # contact
    marker = PointMarker(f"/World/Visuals/{robot_name}/feet_contact", 4 * robot_c.count, radius=0.035)
    feet_contact_markers.append(marker)

๊ฐ ๋กœ๋ด‡์€ action์„ ํ•˜๊ฒŒ๋˜๊ณ  ์ด๋ฅผ ๋กœ๋ด‡์„ ์ œ์–ดํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. get_default_dof_state()์€ ๋กœ๋ด‡์˜ ๊ฐ ๊ฐ์ฒด์— ์žˆ๋Š” method๋กœ ๊ฐ ๋กœ๋ด‡์˜ standing ์ž์„ธ์— ๋Œ€ํ•œ joint position(dof) ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค.

# dummy action
actions = torch.zeros(robot_a.count, robot_a.num_actions, device=robot_a.device)

# Define simulation stepping
sim_dt = sim.get_physics_dt()
sim_time = 0.0
count = 0
# Simulate physics
while simulation_app.is_running():
    # If simulation is stopped, then exit.
    if sim.is_stopped():
        break
    # If simulation is paused, then skip.
    if not sim.is_playing():
        sim.step(render=not args_cli.headless)
        continue
    # reset
    if count % 1000 == 0:
        # reset counters
        sim_time = 0.0
        count = 0
        # reset dof state
        for robot in [robot_a, robot_b, robot_c]:
            dof_pos, dof_vel = robot.get_default_dof_state()
            robot.set_dof_state(dof_pos, dof_vel)
            robot.reset_buffers()
        # reset command
        actions = torch.zeros(robot_a.count, robot_a.num_actions, device=robot_a.device)
        print(">>>>>>>> Reset!")
    # apply actions
    robot_b.apply_action(actions)
    robot_c.apply_action(actions)
    robot_a.apply_action(actions)
    # perform step
    sim.step()
    # update sim-time
    sim_time += sim_dt
    count += 1

์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ resetํ–ˆ๋˜ buffer์— ๊ฐ ๋กœ๋ด‡์˜ ์ •๋ณด๋ฅผ ๋‹ด์Šต๋‹ˆ๋‹ค. marker๋กœ ์„ค์ •ํ•ด๋‘์—ˆ๋˜ foot_marker์™€ contact_marker๋„ ๊ฐ ๋กœ๋ด‡์—์„œ ๋ถˆ๋Ÿฌ์™€์„œ state update๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# note: to deal with timeline events such as stopping, we need to check if the simulation is playing
if sim.is_playing():
    # update buffers
    robot_b.update_buffers(sim_dt)
    robot_c.update_buffers(sim_dt)
    robot_a.update_buffers(sim_dt)
    # update marker positions
    for foot_marker, contact_marker, robot in zip(
        feet_markers, feet_contact_markers, [robot_b, robot_c, robot_a]
    ):
        # feet
        foot_marker.set_world_poses(
            robot.data.feet_state_w[..., 0:3].view(-1, 3), robot.data.feet_state_w[..., 3:7].view(-1, 4)
        )
        # contact sensors
        contact_marker.set_world_poses(
            robot.data.feet_state_w[..., 0:3].view(-1, 3), robot.data.feet_state_w[..., 3:7].view(-1, 4)
        )
        contact_marker.set_status(torch.where(robot.data.feet_air_time.view(-1) > 0.0, 1, 2))

3 Closing

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” standalone example๋กœ ๋‚˜์™€์žˆ๋˜ play_quadrupeds.py์ฝ”๋“œ์˜ ์ „์ฒด์ ์ธ ๊ตฌ์„ฑ๊ณผ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์•„์ง orbit์˜ ๋งŽ์€ ๋ชจ๋“ˆ๋“ค์— ์ต์ˆ™ํ•˜์ง€ ์•Š์•„ roughํ•˜๊ฒŒ ์ฝ”๋“œ์˜ ํ๋ฆ„์„ ์‚ดํŽด๋ณด์•˜์ง€๋งŒ ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ empty scene์—์„œ ์‹œ์ž‘ํ•˜๋ฉด์„œ ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณผ ์˜ˆ์ •์ด๋‹ˆ ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ์ข€ ๋” orbit๊ณผ ์นœํ•ด์ ธ๋ด…์‹œ๋‹ค.

Copyright 2024, Jung Yeon Lee