Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

πŸ“Έ Визуализация ΠΈ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³

Π’ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ созданной сцСны Genesis управляСт visualizer сцСны (Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ scene.visualizer). Π‘Ρ†Π΅Π½Ρƒ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ двумя способами: 1) с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ просмотрщика, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅Π³ΠΎ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅; 2) Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ добавляя ΠΊΠ°ΠΌΠ΅Ρ€Ρƒ Π² сцСну ΠΈ получая изобраТСния Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°ΠΌΠ΅Ρ€Ρƒ.

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Ρ‰ΠΈΠΊ

Если ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Ρ‘Π½ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€, для Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сцСны ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ просмотрщик. Genesis ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ€Π°Π·Π½Ρ‹Π΅ Π³Ρ€ΡƒΠΏΠΏΡ‹ options для настройки Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² сцСны. Π§Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ просмотрщик, ΠΌΠ΅Π½ΡΡŽΡ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π² viewer_options ΠΏΡ€ΠΈ создании сцСны. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, vis_options Π·Π°Π΄Π°ΡŽΡ‚ свойства Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΈ просмотрщик, ΠΈ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ (ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Ρ‡ΡƒΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅).

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ сцСны с Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Ρ‹ΠΌΠΈ настройками просмотрщика ΠΈ Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ (выглядит слоТнСС, Ρ‡Π΅ΠΌ Π½ΡƒΠΆΠ½ΠΎ, Π½ΠΎ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ возмоТности):

scene = gs.Scene(
    show_viewer    = True,
    viewer_options = gs.options.ViewerOptions(
        res           = (1280, 960),
        camera_pos    = (3.5, 0.0, 2.5),
        camera_lookat = (0.0, 0.0, 0.5),
        camera_fov    = 40,
        max_FPS       = 60,
    ),
    vis_options = gs.options.VisOptions(
        show_world_frame = True, # ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ систСму ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ `world` Π² Π΅Ρ‘ Π½Π°Ρ‡Π°Π»Π΅
        world_frame_size = 1.0, # Π”Π»ΠΈΠ½Π° систСмы ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ ΠΌΠΈΡ€Π° (Π² ΠΌΠ΅Ρ‚Ρ€Π°Ρ…)
        show_link_frame  = False, # НС ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ систСмы ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ звСньСв сущностСй
        show_cameras     = False, # НС ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ сСтку ΠΈ усСчённый конус Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… ΠΊΠ°ΠΌΠ΅Ρ€
        plane_reflection = True, # Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΎΡ‚Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡ‚ плоскости
        ambient_light    = (0.1, 0.1, 0.1), # Настройка ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰Π΅Π³ΠΎ освСщСния
    ),
    renderer = gs.renderers.Rasterizer(), # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ растСризатор для Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π° ΠΊΠ°ΠΌΠ΅Ρ€
)

Π—Π΄Π΅ΡΡŒ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΠΎΠ·Ρƒ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ просмотрщика ΠΈ ΡƒΠ³ΠΎΠ» ΠΎΠ±Π·ΠΎΡ€Π°. Если max_FPS установлСн Π² None, просмотрщик Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚Π°ΠΊ быстро, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅Ρ‚. Если res установлСн Π² None, Genesis автоматичСски создаст ΠΎΠΊΠ½ΠΎ с ΡΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ΠΌ сторон 4:3 ΠΈ высотой, Ρ€Π°Π²Π½ΠΎΠΉ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π΅ высоты ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π°. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ‹ΡˆΠ΅ для Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π° ΠΊΠ°ΠΌΠ΅Ρ€ Π²Ρ‹Π±Ρ€Π°Π½ растСризатор. Genesis прСдоставляСт Π΄Π²Π° бэкСнда Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°: gs.renderers.Rasterizer() ΠΈ gs.renderers.RayTracer(). ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Ρ‰ΠΈΠΊ всСгда ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ растСризатор; ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ растСризатор ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΈ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹.

ПослС создания сцСны ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ просмотрщика доступСн Ρ‡Π΅Ρ€Π΅Π· scene.visualizer.viewer ΠΈΠ»ΠΈ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΡƒΡŽ запись scene.viewer. МоТно Π·Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ ΠΈΠ»ΠΈ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΠΎΠ·Ρƒ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ просмотрщика:

cam_pose = scene.viewer.camera_pose()
scene.viewer.set_camera_pose(cam_pose)

ΠšΠ°ΠΌΠ΅Ρ€Ρ‹ ΠΈ Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²Ρ‹ΠΉ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² сцСну ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ. ΠšΠ°ΠΌΠ΅Ρ€Π° Π½Π΅ связана с просмотрщиком ΠΈΠ»ΠΈ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠΌ: ΠΎΠ½Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡ‚Ρ€Π΅Π½Π΄Π΅Ρ€Π΅Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎΠ³Π΄Π°, ΠΊΠΎΠ³Π΄Π° это Π½ΡƒΠΆΠ½ΠΎ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΊΠ°ΠΌΠ΅Ρ€Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΈ Π² Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅ (headless).

cam = scene.add_camera(
    res    = (1280, 960),
    pos    = (3.5, 0.0, 2.5),
    lookat = (0, 0, 0.5),
    fov    = 30,
    GUI    = False
)

Если GUI=True, каТдая ΠΊΠ°ΠΌΠ΅Ρ€Π° создаёт ΠΎΠΊΠ½ΠΎ OpenCV, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ динамичСски ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΎΡ‚Ρ€Π΅Π½Π΄Π΅Ρ€Π΅Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: это Π½Π΅ Ρ‚ΠΎ ΠΆΠ΅ самоС, Ρ‡Ρ‚ΠΎ GUI просмотрщика.

ПослС построСния сцСны ΠΊΠ°ΠΌΠ΅Ρ€Π° ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΡ‚ΡŒ изобраТСния. Наши ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ ΡƒΠΌΠ΅ΡŽΡ‚ Π²Ρ‹Π΄Π°Π²Π°Ρ‚ΡŒ RGB-изобраТСния, ΠΊΠ°Ρ€Ρ‚Ρ‹ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, маски сСгмСнтации ΠΈ Π½ΠΎΡ€ΠΌΠ°Π»ΠΈ повСрхностСй. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ рСндСрится Ρ‚ΠΎΠ»ΡŒΠΊΠΎ RGB; ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π΅ΠΆΠΈΠΌΡ‹ Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ camera.render():

scene.build()
# Π Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ RGB, ΠΊΠ°Ρ€Ρ‚Ρ‹ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, маски сСгмСнтации ΠΈ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π½ΠΎΡ€ΠΌΠ°Π»Π΅ΠΉ
rgb, depth, segmentation, normal = cam.render(depth=True, segmentation=True, normal=True)

Если использован GUI=True ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Ρ‘Π½ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π²ΠΈΠ΄Π½ΠΎ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ ΠΎΠΊΠ½Π°. (Иногда ΠΎΠΊΠ½Π° OpenCV ΠΎΡ‚ΡΡ‚Π°ΡŽΡ‚; Ссли ΠΎΠΊΠ½ΠΎ Ρ‡Ρ‘Ρ€Π½ΠΎΠ΅, ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ cv2.waitKey(1) ΠΈΠ»ΠΈ просто снова Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ render(), Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΠΊΠ½ΠΎ.)

Π—Π°ΠΏΠΈΡΡŒ Π²ΠΈΠ΄Π΅ΠΎ с ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΡ‚Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ RGB-изобраТСния, пСрСмСстим ΠΊΠ°ΠΌΠ΅Ρ€Ρƒ ΠΈ запишСм Π²ΠΈΠ΄Π΅ΠΎ. Для записи Genesis прСдоставляСт ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ инструмСнт:

# ΠΠ°Ρ‡Π°Ρ‚ΡŒ запись с ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹. ВсС ΠΎΡ‚Ρ€Π΅Π½Π΄Π΅Ρ€Π΅Π½Π½Ρ‹Π΅ RGB-изобраТСния Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒΡΡ Π²Π½ΡƒΡ‚Ρ€ΠΈ
cam.start_recording()
import numpy as np
for i in range(120):
    scene.step()
    # МСняСм ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹
    cam.set_pose(
        pos    = (3.0 * np.sin(i / 60), 3.0 * np.cos(i / 60), 2.5),
        lookat = (0, 0, 0.5),
    )

    cam.render()
# ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ запись ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π²ΠΈΠ΄Π΅ΠΎ. Если `filename` Π½Π΅ Π·Π°Π΄Π°Π½, имя Π±ΡƒΠ΄Π΅Ρ‚ создано автоматичСски ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ Ρ„Π°ΠΉΠ»Π°
cam.stop_recording(save_to_filename='video.mp4', fps=60)

ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сохраняСт Π²ΠΈΠ΄Π΅ΠΎ Π² video.mp4:

import genesis as gs
gs.init(backend=gs.cpu)
scene = gs.Scene(
    show_viewer = True,
    viewer_options = gs.options.ViewerOptions(
        res           = (1280, 960),
        camera_pos    = (3.5, 0.0, 2.5),
        camera_lookat = (0.0, 0.0, 0.5),
        camera_fov    = 40,
        max_FPS       = 60,
    ),
    vis_options = gs.options.VisOptions(
        show_world_frame = True,
        world_frame_size = 1.0,
        show_link_frame  = False,
        show_cameras     = False,
        plane_reflection = True,
        ambient_light    = (0.1, 0.1, 0.1),
    ),
    renderer=gs.renderers.Rasterizer(),
)
plane = scene.add_entity(
    gs.morphs.Plane(),
)
franka = scene.add_entity(
    gs.morphs.MJCF(file='xml/franka_emika_panda/panda.xml'),
)
cam = scene.add_camera(
    res    = (640, 480),
    pos    = (3.5, 0.0, 2.5),
    lookat = (0, 0, 0.5),
    fov    = 30,
    GUI    = False,
)
scene.build()
# Π Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ RGB, ΠΊΠ°Ρ€Ρ‚Ρ‹ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, маски сСгмСнтации ΠΈ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π½ΠΎΡ€ΠΌΠ°Π»Π΅ΠΉ
# rgb, depth, segmentation, normal = cam.render(rgb=True, depth=True, segmentation=True, normal=True)
cam.start_recording()
import numpy as np
for i in range(120):
    scene.step()
    cam.set_pose(
        pos    = (3.0 * np.sin(i / 60), 3.0 * np.cos(i / 60), 2.5),
        lookat = (0, 0, 0.5),
    )
    cam.render()
cam.stop_recording(save_to_filename='video.mp4', fps=60)

Π’ исходном Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅ здСсь Π±Ρ‹Π» встроСнный Π²ΠΈΠ΄Π΅ΠΎΠΏΠ»Π΅Π΅Ρ€ с записью этого ΠΊΠΎΠ΄Π°; Π² этой вСрсии Π΅Π³ΠΎ Π½Π΅Ρ‚, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ запись получаСтся ΠΏΡ€ΠΈ запускС ΠΊΠΎΠ΄Π°.

ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ симуляция

import torch
import genesis as gs

gs.init(backend=gs.gpu)

scene = gs.Scene(
    show_viewer   = False,
    rigid_options = gs.options.RigidOptions(
        dt                = 0.01,
    ),
)

plane = scene.add_entity(
    gs.morphs.Plane(),
)

franka = scene.add_entity(
    gs.morphs.MJCF(file='xml/franka_emika_panda/panda.xml'),
)

scene.build(n_envs=30000)

# УправляСм всСми Ρ€ΠΎΠ±ΠΎΡ‚Π°ΠΌΠΈ сразу
franka.control_dofs_position(
    torch.tile(
        torch.tensor([0, 0, 0, -1.0, 0, 0, 0, 0.02, 0.02], device=gs.device), (30000, 1)
    ),
)

for i in range(1000):
    scene.step()

ВСстовый скрипт с Π±ΡƒΡ‚Ρ‹Π»ΠΊΠΎΠΉ: test_genesis_bottle.py

import argparse
import time

import genesis as gs
import numpy as np
import torch

parser = argparse.ArgumentParser()
parser.add_argument("-B", type=int, default=1) # Π Π°Π·ΠΌΠ΅Ρ€ Π±Π°Ρ‚Ρ‡Π°
parser.add_argument("-v", action="store_true", default=False) # Визуализация
parser.add_argument("-r", action="store_true", default=False) # Π‘Π»ΡƒΡ‡Π°ΠΉΠ½Ρ‹Π΅ дСйствия

args = parser.parse_args()

########################## init ##########################
gs.init(backend=gs.gpu)

########################## create a scene ##########################
scene = gs.Scene(
    show_viewer=args.v,
    rigid_options=gs.options.RigidOptions(
        dt=0.01,
        constraint_solver=gs.constraint_solver.Newton,
        enable_self_collision=True,
    ),
)

########################## entities ##########################
plane = scene.add_entity(
    gs.morphs.Plane(),
)

obj = scene.add_entity(
    morph=gs.morphs.URDF(
        file="../assets/urdf/bottle/bottle.urdf",
        scale=0.09,
        pos=(0.65, 0.0, 0.036),
        euler=(0, 90, 0),
    ),
)
franka = scene.add_entity(
    gs.morphs.MJCF(file="../assets/xml/franka_emika_panda/panda.xml")
)

########################## build ##########################
n_envs = args.B
scene.build(n_envs=n_envs)

# ΠšΠΎΡΡ„Ρ„ΠΈΡ†ΠΈΠ΅Π½Ρ‚Ρ‹ управлСния (ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ значСния ΠΈΠ· MuJoCo XML Franka)
franka.set_dofs_kp(
    np.array([4500, 4500, 3500, 3500, 2000, 2000, 2000, 100, 100]),
)
franka.set_dofs_kv(
    np.array([450, 450, 350, 350, 200, 200, 200, 10, 10]),
)
franka.set_dofs_force_range(
    np.array([-87, -87, -87, -87, -12, -12, -12, -100, -100]),
    np.array([87, 87, 87, 87, 12, 12, 12, 100, 100]),
)

motors_dof = np.arange(7)
fingers_dof = np.arange(7, 9)

grasp_qpos = np.array([-0.9937,  1.4588,  1.3058, -1.6924, -1.4882,  1.8461,  1.4577,  0.04, 0.04])
lift_qpos = np.array([-1.0411,  1.2861,  1.5200, -1.7065, -1.2946,  1.6572,  1.4315,  0.04, 0.04])
franka.set_dofs_position(grasp_qpos)

# Π—Π°Ρ…Π²Π°Ρ‚
franka.control_dofs_position(grasp_qpos[:-2], motors_dof)
franka.control_dofs_force(np.array([-4, -4]), fingers_dof)


for i in range(100):
    scene.step()

# ΠŸΠΎΠ΄ΡŠΡ‘ΠΌ
franka.control_dofs_position(lift_qpos[:-2], motors_dof)
for i in range(50):
    scene.step()

ref_pos = torch.tile(torch.tensor(lift_qpos[:7]), [n_envs, 1]).cuda()

t0 = time.perf_counter()
for i in range(500):
    if args.r and i % 2 == 0: # Π‘ΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅ с частотой управлСния ManiSkill 50 Π“Ρ†
        # Π‘ΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅ со случайными дСйствиями ManiSkill
        franka.control_dofs_position(ref_pos + torch.rand((n_envs, 7), device='cuda')*0.05 - 0.025, motors_dof)
    scene.step()
t1 = time.perf_counter()

print(f'per env: {500 / (t1 - t0):,.2f} FPS')
print(f'total  : {500 / (t1 - t0) * n_envs:,.2f} FPS')

03test_genesis_cube.py

import argparse
import time

import genesis as gs
import numpy as np
import torch

parser = argparse.ArgumentParser()
parser.add_argument("-B", type=int, default=1) # Π Π°Π·ΠΌΠ΅Ρ€ Π±Π°Ρ‚Ρ‡Π°
parser.add_argument("-v", action="store_true", default=False) # Визуализация
parser.add_argument("-r", action="store_true", default=False) # Π‘Π»ΡƒΡ‡Π°ΠΉΠ½Ρ‹Π΅ дСйствия
parser.add_argument("-m", action="store_true", default=False) # Π”Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ Ρ‚Ρ€Π°Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ
parser.add_argument("--mjcf", action="store_true", default=False) # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ MJCF

args = parser.parse_args()

########################## init ##########################
gs.init(backend=gs.gpu)

########################## create a scene ##########################
scene = gs.Scene(
    show_viewer=args.v,
    rigid_options=gs.options.RigidOptions(
        dt=0.01,
        constraint_solver=gs.constraint_solver.Newton,
        enable_self_collision=True,
    ),
)

########################## entities ##########################
plane = scene.add_entity(
    gs.morphs.Plane(),
)

cube = scene.add_entity(
    gs.morphs.Box(
        size=(0.04, 0.04, 0.04),
        pos=(0.65, 0.0, 0.02),
    ),
)
franka = scene.add_entity(
    gs.morphs.MJCF(file="../assets/xml/franka_emika_panda/panda.xml") if args.mjcf else gs.morphs.URDF(file="../assets/urdf/franka_description/robots/franka_panda.urdf", fixed=True),
)

########################## build ##########################
n_envs = args.B
scene.build(n_envs=n_envs)

# ΠšΠΎΡΡ„Ρ„ΠΈΡ†ΠΈΠ΅Π½Ρ‚Ρ‹ управлСния (ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ значСния ΠΈΠ· MuJoCo XML Franka)
franka.set_dofs_kp(
    np.array([4500, 4500, 3500, 3500, 2000, 2000, 2000, 100, 100]),
)
franka.set_dofs_kv(
    np.array([450, 450, 350, 350, 200, 200, 200, 10, 10]),
)
franka.set_dofs_force_range(
    np.array([-87, -87, -87, -87, -12, -12, -12, -100, -100]),
    np.array([87, 87, 87, 87, 12, 12, 12, 100, 100]),
)

motors_dof = np.arange(7)
fingers_dof = np.arange(7, 9)

grasp_qpos = np.array([-1.0104,  1.5623,  1.3601, -1.6840, -1.5863,  1.7810,  1.4598,  0.0400, 0.0400])
lift_qpos = np.array([-1.0426,  1.4028,  1.5634, -1.7114, -1.4055,  1.6015,  1.4510,  0., 0.])
franka.set_dofs_position(grasp_qpos)

# Π—Π°Ρ…Π²Π°Ρ‚
franka.control_dofs_position(grasp_qpos[:-2], motors_dof)
franka.control_dofs_force(np.array([-0.5, -0.5]), fingers_dof)


for i in range(100):
    scene.step()

# ΠŸΠΎΠ΄ΡŠΡ‘ΠΌ
franka.control_dofs_position(lift_qpos[:-2], motors_dof)
for i in range(50):
    scene.step()

ref_pos = torch.tile(torch.tensor(lift_qpos[:7]), [n_envs, 1]).cuda()

t0 = time.perf_counter()
if args.m:
    init_qpos = torch.tile(torch.tensor([-1.0426,  1.4028,  1.5634, -1.7114, -1.4055,  1.6015,  1.4510]), [n_envs, 1]).cuda()
    target_qpos = torch.tile(torch.tensor([1.0426,  -1.4028,  1.5634, -1.7114, -1.4055,  1.6015,  1.4510]), [n_envs, 1]).cuda()
    for i in range(500):
        if i % 2 == 0: # Π‘ΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅ с частотой управлСния ManiSkill 50 Π“Ρ†
            franka.control_dofs_position(init_qpos + (target_qpos - init_qpos) * i / 500, motors_dof)
        scene.step()
else:
    for i in range(500):
        if args.r and i % 2 == 0: # Π‘ΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅ с частотой управлСния ManiSkill 50 Π“Ρ†
            # Π‘ΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅ со случайными дСйствиями ManiSkill
            franka.control_dofs_position(ref_pos + torch.rand((n_envs, 7), device='cuda')*0.05 - 0.025, motors_dof)
        scene.step()
t1 = time.perf_counter()

print(f'per env: {500 / (t1 - t0):,.2f} FPS')
print(f'total  : {500 / (t1 - t0) * n_envs:,.2f} FPS')

ΠžΠ±Ρ€Π°Ρ‚Π½Π°Ρ ΠΊΠΈΠ½Π΅ΠΌΠ°Ρ‚ΠΈΠΊΠ°