HAPTIX Simulation World API - modulabs/gazebo-tutorial GitHub Wiki

Overview

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” haptix-comm simulation-specific API์˜ ์ „๋ฐ˜์ ์ธ ๋‚ด์šฉ์„ ๋‹ค๋ฃฌ๋‹ค.

์„ค์น˜ ๋‹จ๊ณ„๋Š” ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

Documentation

API ๋ฌธ์„œ๋Š” ์—ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•˜๋ผ.

Conventions and terminology

3์ฐจ์› ์ขŒํ‘œ ๋ฐ ํšŒ์ „์— ๋Œ€ํ•œ '๋ณ€ํ™˜'์€ pose๋ผ๊ณ  ํ•œ๋‹ค. world API์—์„œ ํšŒ์ „์€ ์ฟผํ„ฐ๋‹ˆ์•ˆ์œผ๋กœ ์„ค๋ช…ํ•œ๋‹ค.

๋ฌธ์„œ๋ฅผ ํ†ตํ•ด "๋งํฌ", "์กฐ์ธํŠธ"๋ฐ "๋ชจ๋ธ"์„ ์ฐธ์กฐํ•œ๋‹ค.

"๋งํฌ"๋Š” ์ „์ฒด๊ฐ€ ์›€์ง์ด๋Š” ๊ฐ•์ฒด์ด๋‹ค.

"์กฐ์ธํŠธ"๋Š” ๋‘ ๊ฐœ์˜ ๋งํฌ๋ฅผ ๊ฒฐํ•ฉ์‹œํ‚ค๊ณ  ๋ชจ์…˜์„ ์ œํ•œํ•œ๋‹ค. ์กฐ์ธํŠธ๋Š” ํ•œ๊ณ„๋ฅผ ์งˆ ์ˆ˜ ์žˆ๋‹ค.

"๋ชจ๋ธ"์€ 0๊ฐœ ์ด์ƒ์˜ ๋งํฌ์™€ ์กฐ์ธํŠธ๋กœ ๊ตฌ์„ฑ ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค. ์ด ์˜ˆ์ œ์˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ฐ์ฒด์—๋Š” ๋‚˜๋ฌด ํ๋ธŒ์™€ ํฌ๋ฆฌ์ผ“ ๋ณผ๊ณผ ๊ฐ™์€ ํ•˜๋‚˜์˜ ๋งํฌ์™€ 0๊ฐœ์˜ ์กฐ์ธํŠธ๋กœ ๋˜์–ด์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋กœ๋ด‡ ์ธ๊ณต ํŒ”์€ ๋งŽ์€ ๋งํฌ์™€ ๊ด€์ ˆ์ด์žˆ๋Š” ๋ชจ๋ธ์˜ ํ•œ ์˜ˆ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ผ๋ฐ˜์ ์ธ ์ถœ์ž…๊ตฌ์—๋Š” ์„ธ ๊ฐœ์˜ ๋งํฌ๊ฐ€ ์žˆ๋‹ค: ๊ณ ์ •๋œ ํ”„๋ ˆ์ž„, ๋ฌธ ์ž์ฒด, ๊ทธ๋ฆฌ๊ณ  ํ•ธ๋“ค. ํ”„๋ ˆ์ž„๊ณผ ๋ฌธ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒฝ์ฒฉ์€ ๋ฌธ์„ ํšŒ์ „์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์กฐ์ธํŠธ๋กœ ๋ชจ๋ธ๋ง๋œ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฌธ๊ณผ ์†์žก์ด๋Š” ์†์žก์ด๋ฅผ ๋Œ๋ฆด ์ˆ˜์žˆ๋Š” ์กฐ์ธํŠธ๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค. ์ถœ์ž…๊ตฌ๋Š” ์ „์ฒด์ ์œผ๋กœ ๋ชจ๋ธ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

Example

์ด ์˜ˆ์ œ์—์„œ๋Š”, ARAT world์—์„œ ๋ฌผ์ฒด๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด world API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค€๋‹ค.

Run the code: MATLAB

HAPTIX MATLAB SDK์—๋Š” ์ด ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ ๋œ hxs_example.m ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค. ๋งŒ์•ฝ ์ด๋™์‹œํ‚ค๊ฑฐ๋‚˜ ์‚ญ์ œํ•œ ๊ฒฝ์šฐ ์—ฌ๊ธฐ์—์„œ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์‹œ ๋‹ค์šด๋กœ๋“œํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ์Šคํฌ๋ฆฝํŠธ๋ฅผ HAPTIX MATLAB SDK๊ฐ€ ํฌํ•จ ๋œ ํด๋” ๋‚˜ MATLAB ๊ฒฝ๋กœ์— ์œ„์น˜์‹œ์ผœ์•ผํ•œ๋‹ค.

์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋จผ์ € Gazebo๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•œ๋‹ค (๋ฐ”ํƒ• ํ™”๋ฉด ์•„์ด์ฝ˜์„ ๋‘ ๋ฒˆ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ„ฐ๋ฏธ๋„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค).

MATLAB์„ ์—ด๊ณ  HAPTIX SDK ํด๋”๋กœ ์ด๋™ํ•œ ๋‹ค์Œ hxs_example์„ ๋ช…๋ น ํ”„๋กฌํ”„ํŠธ์— ์ž…๋ ฅํ•œ๋‹ค.

๊ฐ ์˜ˆ์ œ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ Gazebo ์ฐฝ์„ ๋ณด์•„๋ผ.

Run the code: Octave on Linux

Linux์—์„œ haptix-comm ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๋ฉด /usr/lib/x86_64-linux-gnu/haptix-comm์— ์˜ฅํƒ€๋ธŒ ํด๋”๊ฐ€ ์„ค์น˜๋œ๋‹ค. ์ด ํด๋”์—๋Š” ์ด ์‹ค์Šต์—์„œ ์‚ฌ์šฉ ๋œ hxs_example ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค. ์ด๋™ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œ ํ•œ ๊ฒฝ์šฐ ์—ฌ๊ธฐ์—์„œ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋จผ์ € Gazebo๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•œ๋‹ค (๋ฐ”ํƒ• ํ™”๋ฉด ์•„์ด์ฝ˜์„ ๋‘๋ฒˆ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ„ฐ๋ฏธ๋„์„ ์‚ฌ์šฉํ•˜์—ฌ๋ผ).

ํ„ฐ๋ฏธ๋„์—์„œ ์•ž์„œ ์–ธ๊ธ‰ ํ•œ haptix-comm/octave ํด๋”๋กœ ์ด๋™ํ•˜์—ฌ octave hxs_example.m์„ ์ž…๋ ฅํ•œ๋‹ค.

๊ฐ ์˜ˆ์ œ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ Gazebo ์ฐฝ์„ ๋ณด์•„๋ผ.

The code explained

hxs_sim_info

ํ˜„์žฌ ์นด๋ฉ”๋ผ ๋ณ€ํ˜•๊ณผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ๋ชจ๋“  ๋ชจ๋ธ ๋ชฉ๋ก์„ ํฌํ•จํ•˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•œ๋‹ค. ์ด API ํ˜ธ์ถœ์€ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์˜ ๋ชจ๋“  ๋ชจ๋ธ์„ ๋ฐ˜๋ณต์ ‘๊ทผํ•˜๊ธฐ์— ์ข‹์€ ์‹œ์ž‘์ ์ด๋‹ค.

info = hxs_sim_info();

์ด ์˜ˆ์ œ์—์„œ๋Š” ๊ฒฐ๊ณผ ์ •๋ณด ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ world์˜ ๋ชจ๋“  ๋ชจ๋ธ์„ ๋ฐ˜๋ณต์ ‘๊ทผํ•˜์—ฌ ๋ชจ๋“  ๋ชจ๋ธ, ๋งํฌ ๋ฐ ์กฐ์ธํŠธ์˜ ์ด๋ฆ„์„ ํ‘œ์‹œํ•œ๋‹ค. ์ด ๋ฃจํ”„์—์„œ๋Š” ์œ„์น˜, ์†๋„ ๋ฐ ๋‚ด/์™ธ๋ถ€ ํž˜/ ํ† ํฌ์™€ ๊ฐ™์€ ํ˜„์žฌ ๋™์  ์ƒํƒœ์— ๋Œ€ํ•œ ๋งํฌ์™€ ์ ‘ํ•ฉ์„ ์š”์ฒญ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

hxs_camera_transform and hxs_set_camera_transform

์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์นด๋ฉ”๋ผ ๊ฐ๋„์˜ ์œ„์น˜์™€ ๋ฐฉํ–ฅ์„ ์„ค์ •ํ•œ๋‹ค.

% Get the user camera pose
tx = hxs_camera_transform();
% Move and rotate the user camera pose
new_tx = tx;
new_tx.pos(3) = new_tx.pos(3) + 1;
% assign equvalent of Euler angles rpy(0, 0, M_PI)
new_tx.orient = [0 1 0 0]';
hxs_set_camera_transform(new_tx);

์—ฌ๊ธฐ์—์„œ๋Š” ํ˜„์žฌ ์นด๋งค๋ผ์˜ ์ด๋™๊ณผ ํšŒ์ „์— ๋Œ€ํ•œ ๋ณ€ํ™˜์‹์„ ๊ตฌ์กฐ์ฒด tx์— ์ €์žฅํ•˜๊ณ , ์นด๋ฉ”๋ผ๊ฐ€ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

hxs_model_color and hxs_set_model_color

์˜ค๋ธŒ์ ํŠธ์˜ ์ƒ‰์ƒ์„ 4-tuple (๋นจ๊ฐ•, ๋…น์ƒ‰, ํŒŒ๋ž‘, ์•ŒํŒŒ)๋กœ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ. ์—ฌ๊ธฐ์„œ ์•ŒํŒŒ๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ํˆฌ๋ช…๋„๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.์•ŒํŒŒ ๊ฐ’์ด 0 ์ธ ๊ฐ์ฒด๋Š” ์™„์ „ํžˆ ํˆฌ๋ช…(๋ณด์ด์ง€ ์•Š์Œ)์ธ ๋ฐ˜๋ฉด, ์•ŒํŒŒ ๊ฐ’์ด 1์ด๋ฉด ๊ฐ์ฒด๊ฐ€ ์™„์ „ํžˆ ๋ถˆํˆฌ๋ช…(์†”๋ฆฌ๋“œ)์„ ์˜๋ฏธํ•œ๋‹ค.

% Change the table color.
hxs_set_model_color('table', [1;0;0;1])
pause(1);
% Row vectors work, too
hxs_set_model_color('table', [0,1,0,1])
pause(1);
hxs_set_model_color('table', [0;0;1;1])
% Get the color
color = hxs_model_color('table');

์—ฌ๊ธฐ์—์„œ๋Š” ํ…Œ์ด๋ธ”์˜ ์ƒ‰์„ ๋นจ๊ฐ„์ƒ‰์—์„œ ์ดˆ๋ก์ƒ‰์œผ๋กœ, ๊ทธ๋ฆฌ๊ณ  ํŒŒ๋ž€์ƒ‰์œผ๋กœ ์„ค์ •ํ•˜์˜€๋‹ค.

hxs_contacts

ํ•œ ๋ชจ๋ธ์ด ๋‹ค๋ฅธ ๋ชจ๋ธ๊ณผ ์ ‘์ด‰ํ•˜๋Š” ์ง€์ ์„ ๊ฐ€์ ธ์˜จ๋‹ค.

% Get contact information for the cube after it collides with the table
% Applying a force here induces a collision
hxs_apply_force('wood_cube_5cm', 'link', [0, 0, -1], 0.1);
pause(0.05);
contacts = hxs_contacts('wood_cube_5cm');

์ด ์˜ˆ์ œ์—์„œ๋Š” ์ ‘์ด‰ ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ๊ฐ€๋กœ์ง€๋ฅด๋Š” ๋‚˜๋ฌด ํ๋ธŒ์— ๋Œ€ํ•œ ๊ฐ ์ ‘์ ์„ ์ถœ๋ ฅํ•œ๋‹ค. ํ๋ธŒ์˜ "๋šœ๊ป‘"๋งํฌ์™€ ์ ‘์ด‰ํ•˜๋Š” ์ž…๋ฐฉ์ฒด์˜ ๊ฐ ๋ชจ์„œ๋ฆฌ์— ํ•˜๋‚˜์”ฉ, 4์˜ ์ ‘์ ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

hxs_linear_velocity and hxs_set_linear_velocity

๋ชจ๋ธ์˜ ์„ ์†๋„๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ๋‹ค. ์„ ์†๋„๋Š” ์ดˆ๋‹น ๋ฏธํ„ฐ ๋‹จ์œ„๋กœ ๋ชจ๋ธ ์†๋„์˜ (x,y,z)์„ฑ๋ถ„์„ ๋‚˜ํƒ€๋‚ด๋Š” 3-vector ์ด๋‹ค.

vel = hxs_linear_velocity('wood_cube_5cm');

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๊ฒ€์ƒ‰ํ•œ ์†๋„๋Š” ๋ชจ๋ธ์˜ canonical link์˜ ์†๋„๋กœ ํ‘œํ˜„๋œ๋‹ค. ๋‚˜๋ฌด ํ๋ธŒ์™€ ๊ฐ™์€ ๋‹จ์ผ ๋งํฌ ๊ฐœ์ฒด์˜ ๊ฒฝ์šฐ ์ „์ฒด ๋ชจ๋ธ์˜ ์†๋„์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋กœ๋ด‡ ํŒ”์˜ ๊ฒฝ์šฐ์—๋Š” ํŒ”๋š ๋งํฌ(forearm link)์˜ ์†๋„์ด๋ฉฐ SDF์˜ ํ‘œ์ค€ ๋งํฌ๋กœ ์„ค์ •๋œ๋‹ค.

% Move by setting linear velocity
hxs_set_linear_velocity('wood_cube_5cm', [-0.5; 0; 0]);

์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๋ชจ๋ธ์˜ ์†๋„๋ฅผ ์„ค์ •ํ•˜๋ฉด API๊ฐ€ ๋ชจ๋ธ์˜ ๊ฐ ๋งํฌ ์†๋„๋ฅผ ์„ค์ •ํ•œ๋‹ค.

hxs_angular_velocity and hxs_set_angular_velocity

๋ชจ๋ธ์˜ ๊ฐ์†๋„๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ๋‹ค. ๊ฐ์†๋„๋Š” (x,y,z)์ถ•์— ๋Œ€ํ•œ ์ดˆ๋‹น ๋ผ๋””์•ˆ ๋‹จ์œ„๋กœ ๋‚˜ํƒ€๋‚ด๋Š” 3-vector์ด๋‹ค.

vel = hxs_angular_velocity('wood_cube_5cm');

์ด ํ•จ์ˆ˜๋Š” ๋ชจ๋ธ์˜ canonical link์˜ ๊ฐ์†๋„๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

% Move by setting angular velocity
hxs_set_angular_velocity('wood_cube_5cm', [0; 0; 100]);

๋‹จ์ผ ๋งํฌ ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ, hxs_set_angular_velocity๋Š” ๋งํฌ์˜ ์งˆ๋Ÿ‰ ์ค‘์‹ฌ์„ ๊ธฐ์ค€์œผ๋กœ ๋ชจ๋ธ์˜ ๊ฐ์†๋„๋ฅผ ์„ค์ •ํ•œ๋‹ค.

hxs_apply_force, hxs_apply_torque, and hxs_apply_wrench

hxs_apply_X ํ•จ์ˆ˜๋Š” ๋ชจ๋ธ, ๋งํฌ, ๋ฒกํ„ฐ ๋˜๋Š” ์ ์šฉ๋˜๋Š” ํž˜, ํ† ํฌ, ๋ Œ์น˜ ๋“ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ์ฒด, ๊ทธ๋ฆฌ๊ณ  ํž˜์ด ์ ์šฉ๋˜๋Š” ์ง€์† ์‹œ๊ฐ„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ง€์† ์‹œ๊ฐ„์ด "0"์ด๋ฉด ํž˜, ํ† ํฌ ๋˜๋Š” ๋ Œ์น˜์˜ ์ง€์† ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง„๋‹ค.

hxs_apply_force('wood_cube_5cm', 'link', [-1.0; 0; 0], 0.2);

์ด ํ•จ์ˆ˜๋Š” ๋ชฉ์žฌ ํ๋ธŒ ๋ชจ๋ธ์—์„œ X์˜ ์Œ์˜ ๋ฐฉํ–ฅ์œผ๋กœ 1 Newton์˜ ํž˜์„ 0.2 ์ดˆ ๋™์•ˆ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

hxs_apply_torque('wood_cube_5cm', 'link', [0; 0; 0.1], 0.1)

์ด ํ•จ์ˆ˜๋Š” ๋ชฉ์žฌ ํ๋ธŒ ๋ชจ๋ธ์—์„œ 0.1 ์ดˆ ๋™์•ˆ Z ์ถ•์— ๋Œ€ํ•ด 0.1 Newton-meter์˜ ํ† ํฌ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

% Apply force and torque at the same time.
wrench = struct('force', [0; 0; 1], 'torque', [0; 0; 0.1]);
hxs_apply_wrench('wood_cube_5cm', 'link', wrench, 0.1);

์ด ํ•จ์ˆ˜๋Š” ํž˜๊ณผ ํ† ํฌ๊ฐ€ ๋™์‹œ์— ์žˆ๋Š” ๋ Œ์น˜๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋ Œ์น˜๋Š” Z ์ถ• ๋ฐฉํ–ฅ์œผ๋กœ 1 Newton์˜ ํž˜ ์„ฑ๋ถ„๊ณผ Z ์ถ•์— ๋Œ€ํ•ด 0.1 Newton-meter์˜ ํ† ํฌ ์„ฑ๋ถ„์„ ๊ฐ€์ง„๋‹ค.

hxs_model_gravity_mode and hxs_set_model_gravity_mode

๋ชจ๋ธ์˜ ์ค‘๋ ฅ ๋ชจ๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ๋‹ค. ์ค‘๋ ฅ ๋ชจ๋“œ๊ฐ€ 1์ด๋ฉด ๋ชจ๋ธ์— ์ค‘๋ ฅ์ด ๋ฐœ์ƒํ•œ๋‹ค(๊ธฐ๋ณธ์ ์œผ๋กœ, Z์˜ ์Œ์˜ ๋ฐฉํ–ฅ์—์„œ 9.81 meters/second^2). ๋งŒ์•ฝ ์ค‘๋ ฅ ๋ชจ๋“œ๊ฐ€ 0์ด๋ฉด ๋ชจ๋ธ์— ์ค‘๋ ฅ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์™ธ๋ ฅ์— ์˜ํ•ด ๋ฐฉํ•ด๋ฐ›์ง€ ์•Š๋Š” ํ•œ ๊ณต๊ธฐ์ค‘์— ๋– ์žˆ๊ฒŒ๋œ๋‹ค.

% Check gravity mode on wooden cube
gravity_mode = hxs_model_gravity_mode('wood_cube_5cm');
disp(gravity_mode);
% Turn off gravity for cube, then nudge it upward
hxs_set_model_gravity_mode('wood_cube_5cm', 0);
% Row vectors work, too.
hxs_apply_force('wood_cube_5cm', 'link', [0, 0, 0.1], 0.1);
% Let it fly
pause(1);
% Bring it back down
hxs_set_model_gravity_mode('wood_cube_5cm', gravity_mode);

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ˜„์žฌ ์ค‘๋ ฅ ๋ชจ๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•œ๋‹ค.์ด ๋ชจ๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ 1์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ค‘๋ ฅ์„ ๋„๊ณ  ์œ„๋กœ ๋ฐ€์–ด๋ณด๋‚ธ๋‹ค. ์ค‘๋ ฅ์ด ํ๋ธŒ์—์„œ ์ž‘์šฉํ•˜๋ฉด ํ…Œ์ด๋ธ”์ชฝ์œผ๋กœ ๋’ค๋กœ ๋–จ์–ด์ง€์ง€๋งŒ ์ค‘๋ ฅ์ด ๊บผ์กŒ๊ธฐ๋•Œ๋ฌธ์— ํ…Œ์ด๋ธ”์ด ๋– ์žˆ๊ฒŒ๋œ๋‹ค.

hxs_model_transform and hxs_set_model_transform

๋ชจ๋ธ์˜ ๋ณ€ํ˜•์„ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ๋‹ค. ์ด๊ฒƒ์€ canonical link์˜ ํ˜„์žฌ ๋ณ€ํ™˜(์ผ๋ฐ˜์ ์œผ๋กœ ๋‹จ์ผ ๋งํฌ ๋ชจ๋ธ์˜ ์งˆ๋Ÿ‰ ์ค‘์‹ฌ)์œผ๋กœ ์ •์˜๋œ๋‹ค.

% Get the pose of the cube
tx = hxs_model_transform('wood_cube_5cm');
disp('Cube position:');
disp(tx.pos);
disp('Cube orientation:');
disp(tx.orient);
% Modify and set the pose
tx.pos(2) = tx.pos(2) + 0.25;
% define a 45 deg rotation about yaw (z) axis
tx.orient = [cos(pi/8) 0 0 sin(pi/8)]';
hxs_set_model_transform('wood_cube_5cm', tx);

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ๋ธŒ์˜ ๋ณ€ํ˜•์„ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ ๋‹ค๋ฅธ ์œ„์น˜์™€ ๋ฐฉํ–ฅ์œผ๋กœ ์ˆ˜์ •ํ•œ๋‹ค.

ํŒ” ๋ณ€ํ™˜ ์„ค์ • ๋กœ๋ด‡ ํŒ”์˜ ์œ„์น˜์™€ ๋ฐฉํ–ฅ์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

% Set the position of the arm. Note that if the motion tracking device is
% active and unpaused, this change will be transient.
arm_tx = struct('pos', [1.0, 0, 1.5], 'orient', [1, 0, 0, 0]);
hxs_set_model_transform(hand, arm_tx)

์ด ๋ช…๋ น๋“ค์€ Optitrack๊ณผ ๊ฐ™์€ ๋ชจ์…˜ ์ถ”์  ๊ธฐ์ˆ ์— ์˜ํ•ด ๋ฌด์‹œ๋  ๊ฒƒ์ด๋‹ค. ํšจ๊ณผ๋ฅผ์„ ์ ์šฉํ•˜๋ ค๋ฉด ๋ชจ์…˜ ์ถ”์ ์ด ์ผ์‹œ ์ค‘์ง€๋˜์—ˆ๋Š”์ง€ ๋˜๋Š” ์‚ฌ์šฉ ์ค‘์ง€๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์—ฌ๋ผ.

hxs_model_collide_mode and hxs_set_model_collide_mode

๋ชจ๋ธ์˜ ์ถฉ๋Œ ๋ชจ๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•œ๋‹ค. ์„ธ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ถฉ๋Œ ๋ชจ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • hxsCOLLIDE: ๊ธฐ๋ณธ ์ถฉ๋Œ ๋ชจ๋“œ. ๋ชจ๋ธ์ด ์ถฉ๋Œ ๋ชจ๋“œ๋กœ ์„ค์ •๋œ ๋‹ค๋ฅธ ๋ชจ๋ธ๊ณผ ์ถฉ๋Œํ•œ๋‹ค.
  • hxsNOCOLLIDE: ๋ชจ๋ธ์ด ์•„๋ฌด ๊ฒƒ๋„ ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋ธ์ด hxsCOLLIDE๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด๋„ ๋‹ค๋ฅธ ๋ชจ๋ธ์„ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์ด ๋‹ค๋ฅธ ๋ชจ๋ธ์„ ํ†ต๊ณผ ํ•  ๋•Œ hxs_contacts๋Š” ์ ‘์ด‰๋ฅผ ํƒ์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • hxsDETECTIONONLY: hxsNOCOLLIDE์™€ ๊ฐ™์ด ๋ชจ๋ธ์ด ๋‹ค๋ฅธ ๋ชจ๋ธ์„ ํ†ต๊ณผํ•˜๊ณ  ์ ‘์ด‰๋ ฅ์ด ๋ฌด์‹œ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ถฉ๋Œ์€ ์—ฌ์ „ํžˆ hxs_contacts์— ์˜ํ•ด ๊ฐ์ง€๋œ๋‹ค. ์ฆ‰, hxsDETECTIONONLY ๋ชจ๋ธ์ด ๋‹ค๋ฅธ ๋ชจ๋ธ์„ ํ†ต๊ณผํ•˜๋ฉด hxs_contacts๋Š” ํ•ด๋‹น ํƒ€์ž„ ์Šคํ…์˜ ๋ชจ๋ธ์— ๋Œ€ํ•œ ์ ‘์ด‰ ์ •๋ณด๋ฅผ ๊ฐ–๋Š”๋‹ค (๋ชจ๋ธ์— hxsNOCOLLIDE๊ฐ€ ์„ค์ •๋œ ๊ฒฝ์šฐ ์ œ์™ธ).

๋Œ€๋ถ€๋ถ„์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” hxsCOLLIDE ๋˜๋Š” hxsDETECTIONONLY๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค.

% Check collide mode on the cube
collide_mode = hxs_model_collide_mode('wood_cube_5cm');
disp(collide_mode);
% Let it drop through the table
hxs_set_model_collide_mode('wood_cube_5cm', 0);
% Hack: apply a small force to disturb the cube to make it actually fall.
hxs_apply_force('wood_cube_5cm', 'link', [0; 0; 0.1], 0.1);
pause(1);
% Turn collisions back on (won't bring the cube back, of course)
hxs_set_model_collide_mode('wood_cube_5cm', collide_mode);

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ๋ธŒ์˜ ์ถฉ๋Œ ๋ชจ๋“œ๋ฅผ ํ™•์ธํ•œ๋‹ค. ์ถฉ๋Œ ๋ชจ๋“œ๋Š” ๊ธฐ๋ณธ hxsCOLLIDE๋กœ ์„ค์ •๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ…Œ์ด๋ธ”์„ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ๊ฒŒ hxsNOCOLLIDE`์— ํ•ด๋‹นํ•˜๋Š” ํ•ญ๋ชฉ์„ 0์œผ๋กœ ์„ค์ •ํ•œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์›๋ž˜ ์ถฉ๋Œ ๋ชจ๋“œ๋กœ ๋‹ค์‹œ ์„ค์ •ํ•œ๋‹ค.

hxs_add_model and hxs_remove_model

hxs_add_model์€ ์™„์ „ํ•œ SDF ์„ค๋ช…์„ ๊ธฐ๋ฐ˜์œผ๋กœ scene์— ์ƒˆ ๋ชจ๋ธ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๋ชจ๋ธ์˜ ์ƒˆ ์ด๋ฆ„๊ณผ ์ดˆ๊ธฐ ์œ„์น˜ ๋ฐ ๋ฐฉํ–ฅ์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

SDF์—์„œ ๋ชจ๋ธ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„ ๋ณด๋ ค๋ฉด Gazebo ๋ชจ๋ธ ์ž‘์„ฑ ์ž์Šต์„œ๋ฅผ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜ ๋ชจ๋ธ ํŽธ์ง‘๊ธฐ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ฐธ๊ณ ํ•˜๋ผ.

hxs_remove_model์€ world์—์„œ ์ผ์น˜ํ•˜๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋ชจ๋ธ์„ ์ œ๊ฑฐํ•œ๋‹ค. hxs_remove_model`์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ชจ๋ธ์„ ์ œ๊ฑฐํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

% Define a new model.  Here, we're taking the cricket_ball model from:
%  https://bitbucket.org/osrf/gazebo_models/src/default/cricket_ball/model.sdf
% and tweaking it slightly (just changing the color from Red to Green).
sdf = '<sdf version="1.5"> <model name="cricket_ball"> <link name="link"> <pose>0 0 0.0375 0 0 0</pose> <inertial> <mass>0.1467</mass> <inertia> <ixx>8.251875e-05</ixx> <ixy>0</ixy> <ixz>0</ixz> <iyy>8.251875e-05</iyy> <iyz>0</iyz> <izz>8.251875e-05</izz> </inertia> </inertial> <collision name="collision"> <geometry> <sphere> <radius>0.0375</radius> </sphere> </geometry> </collision> <visual name="visual"> <geometry> <sphere> <radius>0.0375</radius> </sphere> </geometry> <material> <script> <uri>file://media/materials/scripts/gazebo.material</uri> <name>Gazebo/Green</name> </script> </material> </visual> </link> </model> </sdf>';
% Add the new model to the world, at the world origin, 5m off the ground, with
% gravity enabled.  Then it will drop onto the table.
hxs_add_model(sdf, 'green_cricket_ball', [0; 0; 5], [0; 0; 0], 1);
pause(2);
% Define and add a constraint
constraint_sdf = '<sdf version="1.5"><joint name="test_constraint" type="revolute"><parent>table::link</parent><child>wood_cube_5cm::link</child><axis><xyz>0 1 0</xyz></axis></joint></sdf>';
% Enable when there's an implementation of hxs_add_constraint in Gazebo.
hxs_add_constraint(constraint_sdf, 'wood_cube_5cm');
pause(2);
% Roll the ball to the right
hxs_apply_torque('green_cricket_ball', 'link', [0; 0.05; 0], 0.1)
pause(2);
% Remove constraint
% Enable when there's an implementation of hxs_remove_constraint in Gazebo.
hxs_remove_constraint('test_constraint', 'wood_cube_5cm'); 
pause(2);
% Remove the model
hxs_remove_model('green_cricket_ball');

์ด ์˜ˆ์ œ์—์„œ๋Š” ํ•˜๋“œ ์ฝ”๋“œ ๋œ SDF ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜๊ณ  ์ƒˆ๋กœ์šด green_cricket_ball ๋ชจ๋ธ์„ ๋งŒ๋“ ๋‹ค. ๋ชจ๋ธ์€ ์œ„์น˜ (0, 0, 5)์— ์žˆ๋Š” ์ „์—ญ ์ขŒํ‘œ๊ณ„ ํ”„๋ ˆ์ž„์— ๋‚˜ํƒ€๋‚˜๋ฉฐ, ์ด๋Š” ๋‚˜๋ฌด ์ผ€์ด์Šค ์œ„๋กœ ๋–จ์–ด์ง€๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ชจ๋ธ์ด ์™ธ๋ถ€ ๊ต๋ž€์— ๋ฐ˜์‘ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ํ† ํฌ๋ฅผ ์ ์šฉํ•œ ๋‹ค์Œ ์ด๋ฅผ world์—์„œ ์ œ๊ฑฐํ•œ๋‹ค.

hxs_set_model_joint_state

ํ•˜๋‚˜ ์ด์ƒ์˜ ๊ด€์ ˆ์ด์žˆ๋Š” ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ, ์ด ํ•จ์ˆ˜๋Š” ๋ชจ๋ธ, ๊ด€์ ˆ ์ค‘ ํ•˜๋‚˜์˜ ์ด๋ฆ„, ๋‘ ๊ฐœ์˜ ์Šค์นผ๋ผ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์Šค์นผ๋ผ ์ž…๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋ธ์—์„œ ์ง€์ •๋œ ์กฐ์ธํŠธ์˜ ์œ„์น˜์™€ ์†๋„๋ฅผ ์„ค์ •ํ•œ๋‹ค.

% Set the state of a wrist joint.  Note that, because there's a controller
% acting on the wrist, this change will only be transient; the controller will
% restore the wrist back to the current target position.
hxs_set_model_joint_state(hand, hand_joint, 0.5, 0.0);
pause(1);

% Set the position of the arm. Note that if the motion tracking device is
% active and unpaused, this change will be transient.
arm_tx = struct('pos', [1.0, 0, 1.5], 'orient', [1, 0, 0, 0]);
hxs_set_model_transform(hand, arm_tx)

% Move the camera
hxs_set_camera_transform(new_tx);
pause(1);
% Reset the world, which will move the camera back
hxs_reset(1);
pause(1);

์ด ์˜ˆ์ œ์—์„œ๋Š” ๋กœ๋ด‡ ํŒ”์˜ ์†๋ชฉ ๊ด€์ ˆ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•œ๋‹ค. ํŒ”์˜ ๋ชจํ„ฐ๊ฐ€ ๊ด€์ ˆ์„ actively controllingํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ด€์ ˆ์€ ์›๋ž˜ ์œ„์น˜๋กœ ๋˜๋Œ์•„๊ฐ„๋‹ค. ์†๋ชฉ ๊ด€์ ˆ์„ ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •ํ•˜๋ ค๋ฉด, hx_update๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค (๋‹ค๋ฅธ ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์„ค๋ช…ํ•จ).

hxs_reset

world๋ฅผ ๋‹ค์‹œ ์„ค์ •ํ•œ๋‹ค. ์ธ์ˆ˜๋ฅผ "0"์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์žฌ์„ค์ •ํ•˜๋ฉด ๋กœ๋ด‡ ํŒ”๊ณผ viewpoint๋Š” ์žฌ์„ค์ •๋˜์ง€ ์•Š๋Š”๋‹ค. reset์— 0์ด ์•„๋‹Œ ์ธ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด ์ „ ์„ธ๊ณ„์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์ด ์›๋ž˜ ์œ„์น˜๋กœ ์žฌ์„ค์ •๋œ๋‹ค.

% Move the camera
hxs_set_camera_transform(new_tx);
pause(1);
% Reset the world, which will move the camera back
hxs_reset(1);
โš ๏ธ **GitHub.com Fallback** โš ๏ธ