ROBROS

Human First,

line

Always

개발자 센터

Last Updated On: 2026-07-10

ControlMode

본 페이지는 기존 "Low Level Control" 페이지를 Control Mode 로 개편한 것으로,
IGRIS-C가 지원하는 각 제어 모드의 의미와 전환 방법, 그리고 저수준(Low-Level) 제어에 필요한 메시지 인터페이스를 정리합니다.

  • IGRIS-C의 동작 계층은 Control Mode 로 전환합니다. 모드 전환 명령은 SDK의 IgrisC_Client::SendControlModeCommand() (내부적으로 ControlModeCommandRequest Request/Response)로 컨트롤러에 전달되며, 컨트롤러는 이를 내부 RobotControlMode 로 매핑해 제어 루프 동작을 바꿉니다.

struct ControlModeCommandRequest {
  Header                  header;
  string                  request_id;    // 요청 매칭용 ID
  ControlModeCommandType  command_type;  // 전환할 모드 (아래 목록)
  string                  preset_id;     // MOTION_PRESET 전용
  boolean                 is_cyclic;     // MOTION_PRESET_CYCLIC_TOGGLE 전용
};
// 응답: ServiceResponse { request_id, success, message, error_code(0=성공) }

1. Control Mode 목록

ControlModeCommandType (총 19종, 값 0~18). 컨트롤러 동작은 robotHandler 디스패치 기준입니다.

#

command_type

컨트롤러 매핑/동작

계층

0

MOTION_PRESET

startMotionPreset(preset_id)

High-Level

1

MOTION_PRESET_CYCLIC_TOGGLE

setMotionPresetCyclic(is_cyclic)

High-Level

2

JOINT_POSITION_HOLD

→ JOINT_HOLD_MODE

-

3

MOTION_STOP

holdCurrentPosition()

High-Level

4

WALKMODE_ON

→ WALK_MODE

-

5

LOW_LEVEL_JOINT_CONTROL

→ LOW_LEVEL_MODE

Low-Level

6

LOW_LEVEL_WALKMODE_ON

→ LOW_LEVEL_WALK_MODE

Low-Level

7

HIGH_LEVEL_WALKMODE_ON

→ HIGH_LEVEL_WALK_MODE

High-Level

8

HIGH_LEVEL_JOINT_CONTROL

→ HIGH_LEVEL_MODE

High-Level

9~18

CUSTOM_MODE_1 ~ CUSTOM_MODE_10

(내부 전용)

미제공

command_type 값은 igris_c::msg::dds::ControlModeCommandType::CONTROL_MODE_CMD_<NAME> 형식입니다
(예: CONTROL_MODE_CMD_MOTION_PRESET).

⚠️ CUSTOM_MODE_1~CUSTOM_MODE_10 (9~18)은 현재 사용자에게 제공되지 않습니다.
enum에 슬롯만 예약되어 있는 내부/확장 전용 항목이며, SDK 사용 시 사용하지 마세요.

2. 각 모드 설명

저수준 제어 (Low-Level)

  • SDK가 rt/lowcmd 로 각 모터의 목표(q·dq·tau·kp·kd)를 직접 지령합니다. 제어 루프 책임이
    외부(SDK)에 있는 모드입니다. (메시지 인터페이스는 c.5 참고)

    • LOW_LEVEL_JOINT_CONTROL (5) — LOW_LEVEL_MODE. SDK LowCmd로 관절을 직접 제어.

    • LOW_LEVEL_WALKMODE_ON (6) — LOW_LEVEL_WALK_MODE. 저수준 제어 기반 보행 모드.

고수준 제어 (High-Level)

  • 컨트롤러 내장 로직이 상위 명령을 받아 모션을 생성·유지합니다. 모션 프리셋 실행은 이 계층에서만
    가능합니다.

    • HIGH_LEVEL_JOINT_CONTROL (8) — HIGH_LEVEL_MODE. 컨트롤러 고수준 관절 제어.

    • HIGH_LEVEL_WALKMODE_ON (7) — HIGH_LEVEL_WALK_MODE. 고수준 보행 모드.

보행 (Walk)

  • WALKMODE_ON (4) — WALK_MODE. 보행 모드 진입.

모션 프리셋 (Motion Preset)

  • MOTION_PRESET (0) — preset_id 로 지정한 사전 정의 모션을 재생(startMotionPreset).
    HIGH_LEVEL_MODE 또는 HIGH_LEVEL_WALK_MODE 에서만 시작할 수 있습니다(그 외 모드에서는 거부됨).
    요청 시 preset_id 인자를 채웁니다.

  • MOTION_PRESET_CYCLIC_TOGGLE (1) — 프리셋 반복(cyclic) 재생 여부를 토글(setMotionPresetCyclic).
    요청 시 is_cyclic 인자를 사용합니다.

정지 / 홀드 (Stop / Hold)

  • JOINT_POSITION_HOLD (2) — JOINT_HOLD_MODE. 현재 관절 위치를 유지(홀드)합니다.

  • MOTION_STOP (3) — 진행 중인 모션을 멈추고 현재 자세를 유지(holdCurrentPosition).
    HIGH_LEVEL_MODE/HIGH_LEVEL_WALK_MODE 에서만 지원됩니다.

사용자 정의 (Custom) — 현재 미제공

  • CUSTOM_MODE_1~CUSTOM_MODE_10 (9~18) — 현재 사용자에게 제공되지 않는 내부/확장 전용 슬롯입니다.
    enum에는 정의되어 있으나 SDK 사용자가 호출할 수 있는 모드가 아니므로, 일반 제어에는 사용하지 마세요.

3. 모드 전환 API (SDK)

모드 전환은 IgrisC_Client::SendControlModeCommand() 한 메서드로 수행합니다.

ServiceResponse SendControlModeCommand(
    ControlModeCommandType command_type,
    const std::string&     preset_id = "",     // MOTION_PRESET 전용
    bool                   is_cyclic = false,  // MOTION_PRESET_CYCLIC_TOGGLE 전용
    int                    timeout_ms = 5000);

사용 예 (examples/cyclonedds/cyclonedds_service.cpp 기준):

using igris_c::msg::dds::ControlModeCommandType;
// 모션 프리셋 "HOME" 실행 (HIGH_LEVEL 계층에서)
res = client.SendControlModeCommand(
    ControlModeCommandType::CONTROL_MODE_CMD_MOTION_PRESET, "HOME", false, 60000);
// 현재 위치 홀드
res = client.SendControlModeCommand(
    ControlModeCommandType::CONTROL_MODE_CMD_JOINT_POSITION_HOLD, "", false, 60000);
// 진행 중 모션 정지
res = client.SendControlModeCommand(
    ControlModeCommandType::CONTROL_MODE_CMD_MOTION_STOP, "", false, 60000);
// 저수준 관절 제어 모드로 전환 (이후 rt/lowcmd 사용)
res = client.SendControlModeCommand(
    ControlModeCommandType::CONTROL_MODE_CMD_LOW_LEVEL_JOINT_CONTROL, "", false, 60000);

리턴 ServiceResponse 의 success / error_code(0=성공) / message 로 결과를 확인합니다.

4. 서비스 토픽 정리

SDK 클라이언트가 사용하는 Request/Response 서비스 채널:

기능

서비스 토픽

SDK 메서드

BMS/모터 초기화

rt/service/bms_init

InitBms()

토크 ON/OFF

rt/service/torque

SetTorque()

핸드 초기화

rt/service/hand_init

InitHand()

제어 모드 전환

rt/service/control_mode

SendControlModeCommand()

Mujoco 시뮬 제어 (sim 전용)

rt/service/mujoco_sim

SendMujocoSimCmd()

각 서비스는 <토픽>/request(요청 발행) · <토픽>/response(응답 구독) 쌍으로 동작합니다.
예: rt/service/bms_init/request · rt/service/bms_init/response. (위 표는 base 토픽)

저수준 스트림: rt/lowcmd (LowCmd, 명령) / rt/lowstate (LowState, 상태).

5. 저수준 제어 메시지 인터페이스

IGRIS-C Topic List

  • Low-level Cmd & State (high frequency): rt/lowcmd / rt/lowstate

  • Service State (low frequency)

Common (igris_c::msg::dds)

const uint32 N_JOINTS = 31; // Fixed DOF Num
// Kinematic Space (MS=Motor Space/AB, PJS=Parallel Joint Space/PR)
enum KinematicMode { MS, PJS };
// 모터 제어는 HYBRID 모드 전용입니다. (이전 MotorMode { CURRENT, HYBRID } enum은 제거됨)

Command Side

struct MotorCmd {            // HYBRID 전용
  uint16 id;   // MS: motor index / PJS: virtual joint index
  float  q;    // Position (rad)
  float  dq;   // Velocity (rad/s)
  float  tau;  // Feedforward Torque (Nm)
  float  kp;   // kP
  float  kd;   // kD
};
struct LowCmd {
  Header        header;
  KinematicMode kinematic_modes[5];  // parallel-link 그룹별: waist / L_ankle / R_ankle / L_wrist / R_wrist
  MotorCmd      motors[31];          // 고정 길이 31 DOF
};
// 사용 예: 전체 그룹을 동일 모드로 설정
cmd.kinematic_modes().fill(KinematicMode::PJS);

State Side

struct IMUState {
  float quaternion[4];     // w, x, y, z
  float gyroscope[3];      // rad/s
  float accelerometer[3];  // m/s^2
  float rpy[3];            // rad (intrinsic ZYX)
};
struct MotorState {
  float  q;             // Position (rad)
  float  dq;            // Velocity (rad/s)
  float  tau_est;       // Estimated Torque (Nm)
  int16  temperature;   // Motor Temperature (°C)
  uint32 status_bits;   // Status Bits (fault/limit, 별도 문서)
};
struct JointState {
  float  q;            // PJS Position (rad)
  float  dq;           // PJS Velocity (rad/s)
  float  tau_est;      // PJS Estimated Torque (Nm)
  uint32 status_bits;  // Status Bits
};
struct LowState {
  Header     header;
  IMUState   imu_state;               // Base IMU state
  MotorState motor_state[N_JOINTS];   // MS raw state
  JointState joint_state[N_JOINTS];   // PJS derived state
};

모든 타입은 igris_c::msg::dds 네임스페이스(IDL의 module)에 정의됩니다. 실제 사용 시
igris_c::msg::dds::TypeName 으로 참조합니다.

6. System & Mode Control API (초기화 / 토크 / 핸드)

#include <igris_c_sdk/channel_factory.hpp>
#include <igris_c_sdk/igris_c_client.hpp>
using namespace igris_c_sdk;
using namespace igris_c::msg::dds;
int main() {
    int domain_id = 0;
    ChannelFactory::Instance()->Init(domain_id, "igris_c_IG01");  // domain + 로봇 호기 namespace (b.3 참고)
    if (!ChannelFactory::Instance()->IsInitialized()) { return 1; }
    IgrisC_Client client;
    client.Init();
    client.SetTimeout(10.0f);  // 10초 타임아웃
    // ... 이후 서비스 호출
}

BMS / 모터 초기화

ServiceResponse res = client.InitBms(BmsInitType::BMS_INIT, 30000);           // BMS 전원 ON
res = client.InitBms(BmsInitType::MOTOR_INIT, 30000);                         // 모터만 초기화
res = client.InitBms(BmsInitType::BMS_AND_MOTOR_INIT, 30000);                 // 전원 ON + 모터 (전체 시퀀스)
res = client.InitBms(BmsInitType::BMS_INIT_NONE, 30000);                      // BMS 전원 OFF
  • init_type (BmsInitType) — bridge가 실제 처리하는 값:

    • BMS_INIT_NONE (0) — BMS 전원 OFF (setBmsPowerAsync(false))

    • BMS_INIT (1) — BMS 전원 ON

    • MOTOR_INIT (2) — 모터 초기화

    • BMS_AND_MOTOR_INIT (3) — 전원 ON + 모터 초기화 (전체 시퀀스)

    • BMS_OFF (4) — enum에 정의는 있으나 현재 bridge 미처리(error_code -2) → 사용 금지

  • timeout_ms — 타임아웃(ms, 기본 5000)

  • 리턴 ServiceResponse — request_id, success, message, error_code(0=성공)

토크 제어

ServiceResponse res = client.SetTorque(TorqueType::TORQUE_ON, 30000);
res = client.SetTorque(TorqueType::TORQUE_OFF, 30000);
  • torque (TorqueType) — TORQUE_NONE(0, 예약) / TORQUE_ON(1) / TORQUE_OFF(2)

  • timeout_ms — 타임아웃(ms, 기본 5000)

핸드 초기화

ServiceResponse res = client.InitHand(30000);   // end effector 캘리브레이션/호밍

(핸드 제어 상세는 e. Hand 페이지 참고)

BMS 상태 조회 (rt/bmsstate, 저주기)

tick, body_power(RELAY_OFF/ON), legs_power, estop, connect, battery(전압), bms_init_state

7. Python binding

igris_c_sdk_public 저장소의 dist/*.whl 을 Python 환경에 설치하면 C++ 과 동일한
getter/setter 방식으로 사용할 수 있습니다. 예제는
examples/python 폴더에 있습니다.

import igris_c_sdk as igc_sdk
channel_instance = igc_sdk.ChannelFactory.Instance()
channel_instance.Init(0, "igris_c_IG01")   # domain_id + 로봇 호기 namespace (b.3 참고)
client = igc_sdk.IgrisC_Client()
client.Init()
client.SetTimeout(20.0)

lowstate 실시간 구독

lowstate_subscriber = igc_sdk.LowStateSubscriber("rt/lowstate", igc_sdk.QosProfile.SensorData())
def lowstate_callback(msg):
    imu = msg.imu_state()
    q   = imu.quaternion(); gyro = imu.gyroscope(); acc = imu.accelerometer(); rpy = imu.rpy()
    m0  = msg.motor_state()[0]
    print(m0.q(), m0.dq(), m0.tau_est(), m0.temperature(), m0.status_bits())
lowstate_subscriber.init(lowstate_callback)

서비스 호출 (init / torque / control mode)

# BMS / 모터
client.InitBms(igc_sdk.BmsInitType.BMS_INIT, 5000)
client.InitBms(igc_sdk.BmsInitType.BMS_AND_MOTOR_INIT, 5000)
# 토크
client.SetTorque(igc_sdk.TorqueType.TORQUE_ON, 5000)
# 제어 모드 (C++ SendControlModeCommand 와 동일)
client.SendControlModeCommand(
    igc_sdk.ControlModeCommandType.CONTROL_MODE_CMD_MOTION_PRESET, "HOME", False, 60000)
client.SendControlModeCommand(
    igc_sdk.ControlModeCommandType.CONTROL_MODE_CMD_JOINT_POSITION_HOLD, "", False, 60000)
# 핸드
client.InitHand(5000)

LowCmd 전송 (예: 목 yaw/pitch 모터 제어)

lowcmd_publisher = igc_sdk.LowCmdPublisher("rt/lowcmd", igc_sdk.QosProfile.SensorData())
lowcmd_publisher.init()
low_cmd_msg = igc_sdk.LowCmd()
for i in range(0, 31):
    motor_cmd = low_cmd_msg.motors()[i]
    motor_cmd.id(i); motor_cmd.q(0.0); motor_cmd.dq(0.0); motor_cmd.tau(0.0)  # 기본값
    if i == 30:          # Neck Pitch
        motor_cmd.q(0.3); motor_cmd.kp(5); motor_cmd.kd(0.1)
    elif i == 29:
        motor_cmd.kp(2);  motor_cmd.kd(0.05)
    else:
        motor_cmd.kp(0.0); motor_cmd.kd(0.0)
# kinematic_modes는 parallel-link 그룹별 5개 배열(waist/L_ankle/R_ankle/L_wrist/R_wrist)입니다.
# (C++ 예: cmd.kinematic_modes().fill(KinematicMode.PJS))
lowcmd_publisher.write(low_cmd_msg)

Github Repository에서 전체 예제를 확인할 수 있습니다.