HAPTIX C API - modulabs/gazebo-tutorial GitHub Wiki
C-API ๋ฌธ์๋ฅผ ์ฐพ๋๋ค๋ฉด? http://gazebosim.org/haptix/api์ ๋ค์ด๊ฐ ๋ณด์๋ผ
์ด ํํ ๋ฆฌ์ผ์ ์์ ์ค๋ช ์ ์์ฒญํ๊ฑฐ๋ ์กฐ์ธํธ ๋ช ๋ น์ ๋ณด๋ด๊ณ ์ํ๋ฅผ ์ ๋ฐ์ดํธ ๋ฐ๊ธฐ ์ํ C HAPTIX ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ธ๋ฆฌ `haptix-comm' ์ฌ์ฉ๋ฒ์ ๋ํ์ฌ ์ค๋ช ํ๋ค. ์ค์น ์์์ ๋ฐ๋ผ ์ด๋ฏธ ์๋ฃํ์๋ค๊ณ ๊ฐ์ ํ๋ค.
์ด ํํ ๋ฆฌ์ผ์์๋ ๋ชจ๋ ์ ๊ด์ ์ sin ํจ์๋ฅผ ์ ์ฉํ๋ ์์ฃผ ๊ธฐ๋ณธ์ ์ธ ์ปจํธ๋กค๋ฌ๋ฅผ ํฌํจํฉ๋๋ค. ๋จผ์ , ์ปจํธ๋กค๋ฌ๋ฅผ ์ปดํ์ผํ๊ณ haptix-comm ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋งํฌํด์ผํ๋ค.
Visual Studio 2013์ ์ด๊ณ ํธ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์ํ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค. File->New Project->Visual C++๋ฅผ ์ ํํ๊ณ , ์ค๋ฅธ์ชฝ ์ฐฝ์์ Win32 Console Application๋ฅผ ์ ํํ๋ค. ํ๋ก์ ํธ ์ด๋ฆ์ ์
๋ ฅํ๋ค, ์๋ฅผ ๋ค๋ฉด MyBasicController. OK์ ๋๋ฅด๊ณ , Finish๋ฅผ ๋๋ฅธ๋ค.
ํ์ฌ ํ๋ก์ ํธ์ ์์ค์ฝ๋๋ฅผ ๊ธฐ๋ณธ ์ปจํธ๋กค๋ฌ ์ฝ๋๋ก ๋ฐ๊พผ๋ค. ์์ค ์ฝ๋๋ ์ฌ๊ธฐ์์ ๋ณต์ฌํ์ฌ ํ์ฌ ํ๋ก์ ํธ์ ๋ณต์ฌํ๋ค.
์์ค์ฝ๋ ์์ ์์น์ ์๋ ์ค์ ์ถ๊ฐํ๋ค:
#include "stdafx.h"** Note: 32-bit SDK๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ฒ ์ฅ์ ์๋ตํ๋ค **
ํด๋ฐ์ ์๋ Win32๋ผ๊ณ ๋์ด์๋ ๋๋กญ๋ค์ด ๋ฉ๋ด์์(dropdown menu) Configuration Manager๋ฅผ ์ ํํ๋ค.

Active solution platform ๋๋กญ๋ค์ด ๋ฉ๋ด์์ <New...>๋ฅผ ์ ํํ๋ค. Type or select the new platform์ ๋๋ฅด๊ณ ARM์ x64๋ก ๋ณ๊ฒฝํ๊ณ Close๋ฅผ ๋๋ฅธ๋ค.
View->Other Windows->Property Manager๋ฅผ ๋๋ฌ Property Manager๋ฅผ ์ฐ๋ค. ๊ทธ๋ฌ๋ฉด HAPTIX ๋ผ์ด๋ธ๋ฌ๋ฆฌ SDK์์ ์ ๊ณตํ๋ ์์ฑ ์ํธ๋ฅผ ์ฌ์ฉํ ์ ์๋ค. Property Managerํฌ์ผ๋ก ์ด๋ํ์ฌ ํ๋ก์ ํธ์์ ์ฐํด๋ฆญ์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ Add Existing Property Sheet...๋ฅผ ์ ํํ๋ค. ์๋ก์ด ํ์
์ฐฝ์ด ๋ํ๋๋ฉด HAPTIX ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ SDK๋ฅผ ๋ค์ด๋ก๋ ํ ํด๋๋ก ์ด๋ํ์ฌ haptix-comm์ด๋ผ๋ ๋ฑ๋ก ์ ๋ณด ์ํธ๋ฅผ ์ ํํ๋ค. ์ด ์์
์ ํ๋ก์ ํธ์ ๋ชจ๋ dependencies์ ์ฒ๋ฆฌํด์ค๋ค.
์๋จ์ ํด๋ฐ์์ target build๋ฅผ Debug๋ฅผ Release๋ก ๋ฐ๊พธ๊ณ BUILD->Build Solution์ ๋๋ฌ ์ปจํธ๋กค๋ฌ๋ฅผ ๋น๋ํ๋ค.
- ๋ค์ด๋ก๋์ ์์ ์ปดํ์ผ์ ์ํ์ฌ ์๋ ํจํค์ง๋ฅผ ์ค์นํ๋ค.
sudo apt-get install wget cmake build-essential
- ์ค์ต์ ์ํ์ฌ
haptix_controller๋ผ๋ ์ด๋ฆ์ ์๋ก์ด ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑํ๊ณ ๊ทธ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํ๋ค.
mkdir ~/haptix_controller
cd ~/haptix_controller
- ์ปจํธ๋กค๋ฌ ์์คํ์ผ๊ณผ cmake ํ์ผ์ ๋ค์ด๋ก๋ ํ๋ค.
wget http://bitbucket.org/osrf/haptix-comm/raw/default/example/hx_controller.c
wget http://bitbucket.org/osrf/gazebo_tutorials/raw/default/haptix_comm/files/CMakeLists.txt
- ๋น๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑํ๊ณ ์์คํ์ผ์ ์ปดํ์ผํ๋ค.
mkdir build
cd build
cmake ..
make
๋ฆฌ๋
์ค ์ปดํจํฐ์์๋ haptixStart ๋ฐ์คํฌํ ์์ด์ฝ์ ๋๋ธํด๋ฆญํ์ฌ ์๋ฎฌ๋ ์ด์
์ ์์ํ๋ค.
Visual Studio๋ฅผ ์ฌ์ฉํ์ฌ ์์ค์ฝ๋๋ฅผ ์คํํ ์ค๋น๊ฐ ๋์๋ค๋ฉด DEBUG-> Start Without Debugging... ํด๋ฆญํ๋ค. (๋๋ Ctrl+F5๋ฅผ ๋๋ฅธ๋ค)
Note: ๋ง์ฝ์ ์๋์ฐ ๋ฐฉํ๋ฒฝ์ด ํ์ฑํ๋์ด ์์ผ๋ฉด ์ต๊ทผ์ ์ปดํ์ผ ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ์คํํ ์ ์๋ ๊ถํ์ ๋ฌป๋ "Windows ๋ณด์ ๊ฒฝ๊ณ , Windows ๋ฐฉํ๋ฒฝ์์์ด ํ๋ก๊ทธ๋จ์ ์ผ๋ถ ๊ธฐ๋ฅ์ ์ฐจ๋จํ์ต๋๋ค."๋ผ๋ ์ฐฝ์ด ๋ฐ๊ฒ์ด๋ค. ์ด๋ ๊ธฐ๋ณธ ์ต์
("์ง ๋๋ ์ง์ฅ ๋คํธ์ํฌ์ ๊ฐ์ ์ฌ์ค๋ง")์ ๊ทธ๋๋ก ๋๊ณ "์ก์ธ์ค ํ์ฉ"์ ํด๋ฆญ ํ๋ค.
- ์ปจํธ๋กค๋ฌ ์ฝ๋๋ฅผ ์คํํ ๋ฆฌ๋
์ค ์ปดํจํฐ์์ ํฐ๋ฏธ๋์ฐฝ์ ์ด๊ณ ์คํํ ์ปจ๋๋กค๋ฌ์ ์์น์ ์๋
/build๋๋ ํ ๋ฆฌ๋ก ์ด๋ํ๋ค.
cd ~/haptix_controller/build
- ์ปจํธ๋กค๋ฌ๋ฅผ ์คํํ๋ค.
./hx_controller
์ปจํธ๋กค๋ฌ๊ฐ ์คํ๋๋ ๋์ ๊ฐ์ ๋ณด์์ ์์ด ๋ถ๋๋ฌ์ด ๊ฒฝ๋ก(smooth trajectory)๋ฅผ ๋ฐ๋ผ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
int main(int argc, char **argv)
{
int i;
int counter = 0;
hxRobotInfo robotInfo;
hxCommand cmd;
hxSensor sensor;
// Capture SIGINT signal.
if (signal(SIGINT, sigHandler) == SIG_ERR)
printf("Error catching SIGINT\n");
// Capture SIGTERM signal.
if (signal(SIGTERM, sigHandler) == SIG_ERR)
printf("Error catching SIGTERM\n");
// Connect to the simulator / hardware
if (hx_connect(NULL, 0) != hxOK)
{
printf("hx_connect(): Request error.\n");
return -1;
}
// Requesting robot information.
if (hx_robot_info(&robotInfo) != hxOK)
{
printf("hx_getrobotinfo(): Request error.\n");
return -1;
}
// Print the robot information.
printRobotInfo(&robotInfo);
// Uncomment this block to start logging.
// if (hxs_start_logging("/tmp/log/") != hxOK)
// printf("hxs_start_logging(): error.\n");
int steps = 0;
// Send commands at ~100Hz.
while (steps < 3000)
{
// Create a new command based on a sinusoidal wave.
for (i = 0; i < robotInfo.motor_count; ++i)
{
// Set the desired position of this motor
cmd.ref_pos[i] = (float)(350 * 0.5 *
sin(0.05 * 2.0 * M_PI * counter * 0.01));
// We could set a desired maximum velocity
// cmd.ref_vel[i] = 1.0;
// cmd.ref_vel_max[i] = 1.0;
// We could set a desired controller position gain
// cmd.gain_pos[i] = 1.0;
// We could set a desired controller velocity gain
// cmd.gain_vel[i] = 1.0;
}
// Indicate that the positions we set should be used.
cmd.ref_pos_enabled = 1;
// We're not setting it, so indicate that ref_vel should be ignored.
cmd.ref_vel_enabled = 0;
// We're not setting it, so indicate that ref_vel_max should be ignored.
cmd.ref_vel_max_enabled = 0;
// We're not setting it, so indicate that gain_pos should be ignored.
cmd.gain_pos_enabled = 0;
// We're not setting it, so indicate that gain_vel should be ignored.
cmd.gain_vel_enabled = 0;
// Send the new joint command and receive the state update.
if (hx_update(&cmd, &sensor) != hxOK)
{
printf("hx_update(): Request error.\n");
continue;
}
// Debug output: Print the state.
if (!(counter % 100))
printState(&robotInfo, &sensor);
if (++counter == 10000)
counter = 0;
++steps;
// Here is where you would do your other work, such as reading from EMG
// sensors, decoding that data, computing your next control command,
// etc. In this example, we're just sleeping for 10ms.
//
// You might also want to sleep in your code, because there's a maximum
// rate at which the limb can process new commands and produce new
// sensor readings. Depending on how long your computation takes, you
// might want to wait here until it's time to send a new command. Or
// you might want to run as fast as possible, computing and sending new
// commands constantly (but knowing that not all of them will be
// executed by the limb).
unsigned int sleeptime_us = 10000;
#ifdef _WIN32
Sleep((DWORD)(sleeptime_us / 1e3));
#else
usleep(sleeptime_us);
#endif
}
// Uncomment this block to stop logging.
// if (hxs_stop_logging() != hxOK)
// printf("hxs_stop_logging(): error.\n");
// Disconnect from the simulator / hardware
if (hx_close() != hxOK)
{
printf("hx_close(): Request error.\n");
return -1;
}
return 0;
}HAPTIX C API๋ 5 ๊ฐ์ C ํจ์ ํธ์ถ๋ก ๊ตฌ์ฑ๋๋ค: hx_connect(), hx_robot_info(), hx_update(), hx_read_sensors() hx_close(). hx_connect()์ hx_close()๋ Gazebo ์๋ฎฌ๋ ์ดํฐ์์๋ ์ ํ ์ฌํญ์ด์ง๋ง MuJoCo์์ ํธํ์ฑ์ ์ํด ํฌํจ ์์ต๋๋ค.
hx_robot_info()๋ ์ฃผ์ด์ง ์ฅ์น(Gazebo์์ ์๋ฎฌ๋ ์ด์
๋ ์)๋ก๋ถํฐ ์ ๋ณด๋ฅผ ์์ฒญํ๋ค. ์ด ํธ์ถ์ ์๋ต์ด ์์ ๋ ๋๊น์ง ์ฐจ๋จ(block)๋๋ค.
hx_robot_info()์ ๋ํ ๋งค๊ฐ ๋ณ์๋ ์์ฒญ ๋ ์ฅ์น์ ๋ํ ๋ชจํฐ, ์กฐ์ธํธ, ์ ์ด ์ผ์, IMU ๋ฐ ์กฐ์ธํธ ์ ํ ์๋ฅผ ํฌํจํ๋ hxRobotInfo ๊ตฌ์กฐ์ฒด์ด๋ค. ๋ํ ์ฅ์น ์
๋ฐ์ดํธ ์ฃผ๊ธฐ์ธ ์
๋ฐ์ดํธ ์๋๋ ํฌํจ๋ฉ๋๋ค. ์๋ต์ด ์ ํจํ๋ค๋ฉด ๋ฐํ ๊ฐ์ hxOK์ด๋ค.
์ด ์์ ์๋ ๋๋ฒ๊น
๋ชฉ์ ์ผ๋ก ์์ ๋ ๋ชจ๋ ํ๋๋ฅผ ์ธ์ํ๋ ๋์ ํจ์ printRobotInfo()๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
์ผ๋จ ๋ก๋ด ์ ๋ณด๋ฅผ ํ์ธํ๋ฉด ์์ ์ ์ดํ๊ธฐ์ํ ๋ช
๋ น์ ๋ณด๋ผ ์ ์๋ค. hx_update() ํจ์๋ ์๋ก์ด ๋ช
๋ น์ ๋ณด๋ด๊ณ ํ์ฌ ์์ ์ํ๋ฅผ ๋ฐ๋ ์ญํ ์ ํ๋ค.
๋จผ์ , ๊ฐ ๊ด์ ์ ์์น, ์๋ ๋ฐ ์ด๋์ ํฌํจํ๋ hxCommand ๊ตฌ์กฐ์ฒด๋ฅผ ์ฑ์ธ ํ์๊ฐ ์๋ค. hxCommand ๊ตฌ์กฐ์ฒด์ ๋ํ ์์ธํ ๋ด์ฉ์ haptix-comm API์์ ํ์ธํ ์ ์๋ค. ์ด ์์ ์ ๊ฒฝ์ฐ, sin ํจ์์ ๋ฐ๋ผ ๋ชจ๋ ๊ด์ ์ ์์น๋ฅผ ๋ฐ๊พธ๊ณ ์๋ค.
hx_update()์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ ๋ณ์์ธ cmd๋ ์ด๋ฏธ ์
๋ ฅ๋์ด์๋ ์ฅ์น๋ก ๋ณด๋ด๋ ค๋ ๋ช
๋ น์ด๋ค. ๋ ๋ฒ์งธ ์ถ๋ ฅ ๋ช
๋ น sensor๋ ํจ์์ ์ ๋ฌ๋๋ค; ์ด๊ฒ์ ๋ช
๋ น์ด ์ ์ฉ๋ ํ ์์ ์ํ๋ฅผ ํฌํจํ๊ณ ์๋ค.
๋๋ฒ๊น
๋ชฉ์ ์ผ๋ก ๋ชจ๋ ์ํ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋์ ํจ์ printState()๊ฐ ์๋ค. hx_robot_info()์ ๋ง์ฐฌ๊ฐ์ง๋ก, hx_update() ํจ์๋ ๋ช
๋ น์ด ์ฑ๊ณต์ ์ผ๋ก ๋ณด๋ด์ง๊ณ ์ํ๊ฐ ์์ ๋๋ฉด hxOK๋ฅผ ๋ฐํํ๋ค.
์ผ๋ฐ์ ์ผ๋ก Visual Studio์์ ์์ํ ๋ช
๋ น ์ค์์ ์ค๋ฅ ๋ฉ์์ง hx_robot_info() Service call timed out๊ฐ ์ถ๋ ฅ๋๋ค. ์ด๊ฒ์ Gazebo Linux ์๋ฒ์์ ํต์ ์ด ์คํจํ์์ ์๋ฏธํ๋ค.
์ฒซ ๋ฒ์งธ ํ์ธ์ฌํญ: ๋ ์์คํ ์ด ๋์ผํ ๋คํธ์ํฌ์ ์๊ณ ์๋ก ๋๋ฌ ํ ์ ์๋๊ฐ? ๋จ์ํ ์์ชฝ(windows command๊ณผ Linux shell)์์ ping ๋ช ๋ น์ ์ฌ์ฉํ๋ฉด, ์ฐ๊ฒฐ์ ํ์ธํ ์ ์๋ค. ์๋ํ์ง ์๋ ๊ฒฝ์ฐ ๋คํธ์ํฌ ๊ตฌ์ฑ์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ด๋ค. ๋ ๋ค ๋์ผํ ๋คํธ์ํฌ์ ์ฐ๊ฒฐ๋์ด ์๋์ง ํ์ธํ์ฌ๋ผ.
๋ ๋ฒ์งธ ํ์ธ์ฌํญ: ํต์ ๋ ์ด์ด๊ฐ ์ฌ๋ฐ๋ฅธ ๋คํธ์ํฌ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ณ ์๋๊ฐ? Gazebo Linux ์๋ฒ์ Windows์์ IGN_IP๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ํ๋์ง ๋ค์ ํ์ธํ์ฌ๋ผ. windows command์์ echo % IGN_IP %์์ ํ์ธํ ์ ์์ต๋๋ค. ์์ ํ ํ์คํ๊ฒ ํ๋ ค๋ฉด, ์ฌ์ฉ์ ์ธ์
์์ ๋ก๊ทธ ์์ ํ ๋ค์ ๋ค์ ๋ก๊ทธ์ธํ๊ณ Visual Studio๋ฅผ ์ฐ๋ค.
์ธ ๋ฒ์งธ ํ์ธ์ฌํญ: Windows ๋ฐฉํ๋ฒฝ์ด ํต์ ์ ์ํฅ์ ์ฃผ๋๊ฐ? Windows ์ ์ดํ์์์ด ๊ธฐ๋ฅ์ ๋นํ์ฑํ ํ ์ ์๋ค (Windows ๋ฐฉํ๋ฒฝ์ ๋ค๋ฅธ ํ๋กํ์ด ์์์ ๊ธฐ์ตํ๊ณ , ๋ชจ๋ ๋นํ์ฑํํด์ผ ํจ). Visual Studio๋ฅผ ๋ค์ ์์ํ๋ค.
๋ค ๋ฒ์งธ ํ์ธ์ฌํญ: ๋ผ์ฐํฐ๊ฐ ํต์ ์ ๋๊ณ ์๋๊ฐ? ๋ช ๊ฐ์ง ํด๊ฒฐ์ฑ : ๋ผ์ฐํฐ์ ๋ก๊ทธ์ธํ๊ณ ๋ชจ๋ ์ข ๋ฅ์ ๋ฐฉํ๋ฒฝ์ ๋นํ์ฑํํ๋ค. ๊ทธ๋ ๊ฒ ํ ์ ์๋ค๋ฉด ์ด๋๋ท ์ผ์ด๋ธ์ ์ฌ์ฉํ์ฌ ๋ ์์คํ ์ ์ง์ ์ฐ๊ฒฐํ์ญ์์ค. ๋์ผํ ์๋ธ๋ท(192.168.X.Y/255.255.255.0 ๋ฐ 192.168.X.Y+1/255.255.255.0)์ ์๋์ผ๋ก ์ ํ ํด์ผ ํ๋ค.
์๋ง๋ IGN_IP ๋ณ์์์ IP ์ฃผ์๋ฅผ ์๋ชป ์
๋ ฅํ์ ๊ฒ์ด๋ค.
์ด ์๋ฌ๋ ๋ฆฌ๋ ์ค ์๋ฎฌ๋ ์ดํฐ์์ ์๋์ฐ ์์คํ ์ผ๋ก ๋ค์ ์ฐ๊ฒฐ๋์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๊ฒ์ ์๋์ฐ ๋ฐฉํ๋ฒฝ์ด ์์ธ์ผ ์ ์๋ค.
๋ฌด์ ์ฐ๊ฒฐ์ ์ฌ์ฉํ๋ค๋ฉด, ์ง์ฐ์ผ๋ก ์ธํ ์ฐ๊ฒฐ ์คํจ๊ฐ ๋ฐ์ํ ์ ์๋ค. ์ ์ ์ฐ๊ฒฐ์ ์๋ํด ๋ณด์๋ผ.
์ค๋ฅ๋ก ์ธํด ์๋ชป๋ ๋จ์ถ๋ฅผ ๋๋ฅด๋ฉด ์๋์ฐ ์ ์ดํ์์ Windows ๋ฐฉํ๋ฒฝ ๊ณ ๊ธ ๋ณด์์ผ๋ก ๋ค์ด๊ฐ์ ์ธ๋ฐ์ด๋ ๊ท์น์ผ๋ก ์ด๋ํ์ฌ ConsoleApplication (๋๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ค ์ด๋ฆ) ์ด๋ฆ์ผ๋ก ๋ณด์์ ์ ๊ฑฐ ํ ์ ์๋ค. ๋๋ค๋ฅธ ์ต์
์ Solution Explorer window์ ๋ํ๋๋ ํ๋ก์ ํธ ์์ฑ ์ด๋ฆ(์๋ฃจ์
์ด๋ฆ์ด ์๋)์์ ์์ฉ ํ๋ก๊ทธ๋จ ์ด๋ฆ์ ์์ ํ๋ ๊ฒ์ด๋ค. ํ๋ก์ ํธ๋ฅผ cleanํ๊ณ ๋ค์ ๋น๋ํ๊ณ ๋ค์ ์คํํ๋ค.
