diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8abc4f8..694319b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,18 @@
# 🔖 Release Note
-## 🏷️ v1.4
+## 🏷️ v1.5 (2025.12.29)
+
+- support simulation mode
+
+- add CycloneDDS interface name parameter
+
+- upgrade teleimager version
+
+- [Migrate IPC to @ virtual address](https://github.com/unitreerobotics/xr_teleoperate/commit/46603c5ff385da7a9de59fb4a4a5dca1de4d9133)
+
+- [add caching to speed-up urdf loading](https://github.com/unitreerobotics/xr_teleoperate/commit/6cab654620735bfa347c1cd32a0d8c0c1e6ec343)
+
+## 🏷️ v1.4 (2025.11.21)
- The **image server** has been changed to [teleimager](https://github.com/silencht/teleimager). Please refer to the repository README for details.
@@ -14,7 +26,7 @@
- Added **CPU affinity mode**. If you are not familiar with this mode, you can ignore it.
- Added **motion-switcher** functionality, allowing automatic debug mode entry and exit without using a remote controller.
-## 🏷️ v1.3
+## 🏷️ v1.3 ( 2025.10.14)
- add [](https://github.com/unitreerobotics/xr_teleoperate/wiki) [](https://discord.gg/ZwcVwxv5rq)
@@ -34,17 +46,17 @@
- Fixed logic of the start button.
- Fixed various bugs in simulation mode.
-## 🏷️ v1.2
+## 🏷️ v1.2 (2025.7.22)
1. Upgrade the Dex1_1 gripper control code to be compatible with the [dex1_1 service](https://github.com/unitreerobotics/dex1_1_service) driver.
-## 🏷️ v1.1
+## 🏷️ v1.1 (2025.7.18)
1. Added support for a new end-effector type: **`brainco`**, which refers to the [Brain Hand](https://www.brainco-hz.com/docs/revolimb-hand/) developed by [BrainCo](https://www.brainco.cn/#/product/dexterous).
2. Changed the **DDS domain ID** to `1` in **simulation mode** to prevent conflicts during physical deployment.
3. Fixed an issue where the default frequency was set too high.
-## 🏷️ v1.0 (newvuer)
+## 🏷️ v1.0 (newvuer) (2025.7.8)
1. Upgraded the [Vuer](https://github.com/vuer-ai/vuer) library to version **v0.0.60**, expanding XR device support to two modes: **hand tracking** and **controller tracking**. The project has been renamed from **`avp_teleoperate`** to **`xr_teleoperate`** to better reflect its broader capabilities.
@@ -59,7 +71,7 @@
5. Various other improvements and optimizations.
-## 🏷️ v0.5 (oldvuer)
+## 🏷️ v0.5 (oldvuer) (2025.4.30)
1. The repository was named **`avp_teleoperate`** in this version.
2. Supported robot included: `G1_29`, `G1_23`, `H1_2`, and `H1`.
diff --git a/CHANGELOG_zh-CN.md b/CHANGELOG_zh-CN.md
index 2a1a17c..c65e4bb 100644
--- a/CHANGELOG_zh-CN.md
+++ b/CHANGELOG_zh-CN.md
@@ -1,6 +1,14 @@
# 🔖 版本说明
-## 🏷️ v1.4
+## 🏷️ v1.5 (2025.12.29)
+
+- 支持**仿真模式**
+- 添加 cyclonedds 网卡名称参数
+- 升级 teleimager 版本
+- [将 IPC 迁移至 @ 虚拟地址](https://github.com/unitreerobotics/xr_teleoperate/commit/46603c5ff385da7a9de59fb4a4a5dca1de4d9133)
+- [引入缓存机制以加速 URDF 加载](https://github.com/unitreerobotics/xr_teleoperate/commit/6cab654620735bfa347c1cd32a0d8c0c1e6ec343)
+
+## 🏷️ v1.4 (2025.11.21)
- **图像服务器**变更为 [teleimager](https://github.com/silencht/teleimager),具体请查看仓库README。
@@ -20,7 +28,7 @@
- 支持 **inspire_FTP** 灵巧手
-## 🏷️ v1.3
+## 🏷️ v1.3 ( 2025.10.14)
- 添加 [](https://github.com/unitreerobotics/xr_teleoperate/wiki) [](https://discord.gg/ZwcVwxv5rq)
@@ -40,17 +48,17 @@
- 修复了启动按钮逻辑错误。
- 修复了仿真模式中的若干 bug。
-## 🏷️ v1.2
+## 🏷️ v1.2 (2025.7.22)
1. 升级Dex1_1夹爪控制代码,匹配 [dex1_1 service](https://github.com/unitreerobotics/dex1_1_service) 驱动
-## 🏷️ v1.1
+## 🏷️ v1.1 (2025.7.18)
1. 末端执行器类型新增'brainco',这是[强脑科技第二代灵巧手](https://www.brainco-hz.com/docs/revolimb-hand/)
2. 为避免与实机部署时发生冲突,将仿真模式下的 dds 通道的domain id修改为1
3. 修复默认频率过高的问题
-## 🏷️ v1.0 (newvuer)
+## 🏷️ v1.0 (newvuer)(2025.7.8)
1. 升级 [Vuer](https://github.com/vuer-ai/vuer) 库至 v0.0.60 版本,XR设备支持模式扩展为**手部跟踪**和**控制器跟踪**两种。为更准确反映功能范围,项目由 **avp_teleoperate** 更名为 **xr_teleoperate**。
@@ -64,7 +72,7 @@
5. 其他一些优化
-## 🏷️ v0.5 (oldvuer)
+## 🏷️ v0.5 (oldvuer) (2025.4.30)
1. 该版本曾经命名为 `avp_teleoperate`
2. 支持 'G1_29', 'G1_23', 'H1_2', 'H1' 机器人类型
diff --git a/README.md b/README.md
index 049dcce..c5cd2b8 100644
--- a/README.md
+++ b/README.md
@@ -36,20 +36,14 @@
# 🔖[Release Note](CHANGELOG.md)
-## 🏷️ v1.4
+## 🏷️ v1.5 (2025.12.29)
-- The **image server** has been changed to [teleimager](https://github.com/silencht/teleimager). Please refer to the repository README for details.
+- support simulation
+- add CycloneDDS interface name parameter
+- [add caching to speed-up urdf loading](https://github.com/unitreerobotics/xr_teleoperate/commit/6cab654620735bfa347c1cd32a0d8c0c1e6ec343)
+- ...
-- Upgraded [televuer](https://github.com/silencht/televuer). Please see the repository README for details.
- > The new versions of [teleimager](https://github.com/silencht/teleimager/commit/ab5018691943433c24af4c9a7f3ea0c9a6fbaf3c) + [televuer](https://github.com/silencht/televuer/releases/tag/v3.0) support transmitting **head camera images via WebRTC**.
- > Supports **pass-through**, **ego**, and **immersive** modes.
-
-- Improved the system’s **state machine** information and IPC mode.
-
-- Added support for **Inspire_FTP dexterous hand**.
-
-- …
# 0. 📖 Introduction
@@ -212,14 +206,15 @@ build cert.pem key.pem LICENSE pyproject.toml README.md rootCA.key rootCA
- **Basic control parameters**
-| ⚙️ Parameter | 📜 Description | 🔘 Available Options | 📌 Default |
-| :---------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
-| `--frequency` | Set the FPS for recording and control | Any reasonable float value | 30.0 |
-| `--input-mode` | Choose XR input mode (how to control the robot) | `hand` (hand tracking)`controller` (controller tracking) | `hand` |
-| `--display-mode` | Choose XR display mode (how to view the robot perspective) | `immersive` (immersive)`ego` (pass-through + small first-person window)`pass-through` (pass-through only) | `immersive` |
-| `--arm` | Select the robot arm type (see 0. 📖 Introduction) | `G1_29` `G1_23` `H1_2` `H1` | `G1_29` |
-| `--ee` | Select the end-effector type of the arm (see 0. 📖 Introduction) | `dex1` `dex3` `inspire_ftp` `inspire_dfx` `brainco` | None |
-| `--img-server-ip` | Set the image server IP address for receiving image streams and configuring WebRTC signaling | `IPv4` address | `192.168.123.164` |
+| ⚙️ Parameter | 📜 Description | 🔘 Available Options | 📌 Default |
+| :-------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
+| `--frequency` | Set the FPS for recording and control | Any reasonable float value | 30.0 |
+| `--input-mode` | Choose XR input mode (how to control the robot) | `hand` (hand tracking)`controller` (controller tracking) | `hand` |
+| `--display-mode` | Choose XR display mode (how to view the robot perspective) | `immersive` (immersive)`ego` (pass-through + small first-person window)`pass-through` (pass-through only) | `immersive` |
+| `--arm` | Select the robot arm type (see 0. 📖 Introduction) | `G1_29` `G1_23` `H1_2` `H1` | `G1_29` |
+| `--ee` | Select the end-effector type of the arm (see 0. 📖 Introduction) | `dex1` `dex3` `inspire_ftp` `inspire_dfx` `brainco` | None |
+| `--img-server-ip` | Set the image server IP address for receiving image streams and configuring WebRTC signaling | `IPv4` address | `192.168.123.164` |
+| `--network-interface` | Set the network interface for CycloneDDS communication | Network Interface Name | `None` |
- **Mode switch parameters**
@@ -245,7 +240,6 @@ build cert.pem key.pem LICENSE pyproject.toml README.md rootCA.key rootCA
## 2.1 📥 Environment Setup
-> Since the image service has been upgraded to `teleimager`, the simulation deployment for v1.4 is temporarily unavailable. Please use v1.3 for testing for now.
First, install [unitree_sim_isaaclab](https://github.com/unitreerobotics/unitree_sim_isaaclab). Follow that repo’s README.
diff --git a/README_zh-CN.md b/README_zh-CN.md
index 5122922..82ccb62 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -36,21 +36,14 @@
# 🔖 [版本说明](CHANGELOG_zh-CN.md)
-## 🏷️ v1.4
+## 🏷️ v1.5 (2025.12.29)
-- **图像服务器**变更为 [teleimager](https://github.com/silencht/teleimager),具体请查看仓库README。
+- 支持**仿真模式**
+- 添加 cyclonedds 网卡名称参数
+- [引入缓存机制以加速 URDF 加载](https://github.com/unitreerobotics/xr_teleoperate/commit/6cab654620735bfa347c1cd32a0d8c0c1e6ec343)
+- ...
-- 升级 [televuer](https://github.com/silencht/televuer),具体请查看仓库README。
- > 新版本的 [teleimager](https://github.com/silencht/teleimager/commit/ab5018691943433c24af4c9a7f3ea0c9a6fbaf3c) + [televuer](https://github.com/silencht/televuer/releases/tag/v3.0) 支持通过 webrtc 传输头部相机图像
- >
- > 支持 pass-through, ego, immersive 三种模式
-
-- 完善系统的**状态机**信息、IPC模式。
-
-- 支持 **inspire_FTP** 灵巧手。
-
-- ···
# 0. 📖 介绍
@@ -225,14 +218,15 @@ build cert.pem key.pem LICENSE pyproject.toml README.md rootCA.key rootCA
- 基础控制参数
-| ⚙️ 参数 | 📜 说明 | 🔘 目前可选值 | 📌 默认值 |
-| :---------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
-| `--frequency` | 设置录制和控制的 FPS | 任意正常范围内的浮点数 | 30.0 |
-| `--input-mode` | 选择 XR 输入模式(通过什么方式控制机器人) | `hand`(**手势跟踪**)
`controller`(**手柄跟踪**) | `hand` |
-| `--display-mode` | 选择 XR 显示模式(通过什么方式查看机器人视角) | `immersive`(沉浸式)
`ego`(通透+第一人称小窗)
`pass-through`(通透) | `immersive` |
-| `--arm` | 选择机器人设备类型(可参考 0. 📖 介绍) | `G1_29`
`G1_23`
`H1_2`
`H1` | `G1_29` |
-| `--ee` | 选择手臂的末端执行器设备类型(可参考 0. 📖 介绍) | `dex1`
`dex3`
`inspire_ftp`
`inspire_dfx`
`brainco` | 无默认值 |
-| `--img-server-ip` | 设置图像服务器的 IP 地址,用于接收图像服务流、配置 WebRTC 信令服务地址 | `IPv4` 地址 | `192.168.123.164` |
+| ⚙️ 参数 | 📜 说明 | 🔘 目前可选值 | 📌 默认值 |
+| :-------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
+| `--frequency` | 设置录制和控制的 FPS | 任意正常范围内的浮点数 | 30.0 |
+| `--input-mode` | 选择 XR 输入模式(通过什么方式控制机器人) | `hand`(**手势跟踪**)
`controller`(**手柄跟踪**) | `hand` |
+| `--display-mode` | 选择 XR 显示模式(通过什么方式查看机器人视角) | `immersive`(沉浸式)
`ego`(通透+第一人称小窗)
`pass-through`(通透) | `immersive` |
+| `--arm` | 选择机器人设备类型(可参考 0. 📖 介绍) | `G1_29`
`G1_23`
`H1_2`
`H1` | `G1_29` |
+| `--ee` | 选择手臂的末端执行器设备类型(可参考 0. 📖 介绍) | `dex1`
`dex3`
`inspire_ftp`
`inspire_dfx`
`brainco` | 无默认值 |
+| `--img-server-ip` | 设置图像服务器的 IP 地址,用于接收图像服务流、配置 WebRTC 信令服务地址 | `IPv4` 地址 | `192.168.123.164` |
+| `--network-interface` | 设置 cyclonedds 通信的网卡接口 | 网卡名称 | `None` |
- 模式开关参数
@@ -261,7 +255,6 @@ build cert.pem key.pem LICENSE pyproject.toml README.md rootCA.key rootCA
## 2.1 📥 环境配置
-> 因为图像服务升级为`teleimager`,v1.4 版本仿真部署暂未上线,请暂时使用 v1.3 进行测试
首先,请安装 [unitree_sim_isaaclab](https://github.com/unitreerobotics/unitree_sim_isaaclab)。具体安装步骤,可参考该仓库 README 文档。
diff --git a/teleop/robot_control/robot_arm.py b/teleop/robot_control/robot_arm.py
index 79d6c4c..2961110 100644
--- a/teleop/robot_control/robot_arm.py
+++ b/teleop/robot_control/robot_arm.py
@@ -80,12 +80,6 @@ class G1_29_ArmController:
self._gradual_start_time = None
self._gradual_time = None
- # initialize lowcmd publisher and lowstate subscriber
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
-
if self.motion_mode:
self.lowcmd_publisher = ChannelPublisher(kTopicLowCommand_Motion, hg_LowCmd)
else:
@@ -368,11 +362,6 @@ class G1_23_ArmController:
self._gradual_start_time = None
self._gradual_time = None
- # initialize lowcmd publisher and lowstate subscriber
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
if self.motion_mode:
self.lowcmd_publisher = ChannelPublisher(kTopicLowCommand_Motion, hg_LowCmd)
@@ -648,11 +637,6 @@ class H1_2_ArmController:
self._gradual_start_time = None
self._gradual_time = None
- # initialize lowcmd publisher and lowstate subscriber
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
if self.motion_mode:
self.lowcmd_publisher = ChannelPublisher(kTopicLowCommand_Motion, hg_LowCmd)
@@ -932,11 +916,6 @@ class H1_ArmController:
self._gradual_start_time = None
self._gradual_time = None
- # initialize lowcmd publisher and lowstate subscriber
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
self.lowcmd_publisher = ChannelPublisher(kTopicLowCommand_Debug, go_LowCmd)
self.lowcmd_publisher.Init()
self.lowstate_subscriber = ChannelSubscriber(kTopicLowState, go_LowState)
@@ -1138,7 +1117,9 @@ class H1_JointIndex(IntEnum):
if __name__ == "__main__":
from robot_arm_ik import G1_29_ArmIK, G1_23_ArmIK, H1_2_ArmIK, H1_ArmIK
- import pinocchio as pin
+ import pinocchio as pin
+
+ ChannelFactoryInitialize(1) # 0 for real robot, 1 for simulation
arm_ik = G1_29_ArmIK(Unit_Test = True, Visualization = False)
arm = G1_29_ArmController(simulation_mode=True)
diff --git a/teleop/robot_control/robot_hand_brainco.py b/teleop/robot_control/robot_hand_brainco.py
index 9625d5a..d0f5d9a 100644
--- a/teleop/robot_control/robot_hand_brainco.py
+++ b/teleop/robot_control/robot_hand_brainco.py
@@ -32,10 +32,6 @@ class Brainco_Controller:
else:
self.hand_retargeting = HandRetargeting(HandType.BRAINCO_HAND_Unit_Test)
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
# initialize handcmd publisher and handstate subscriber
self.LeftHandCmb_publisher = ChannelPublisher(kTopicbraincoLeftCommand, MotorCmds_)
diff --git a/teleop/robot_control/robot_hand_inspire.py b/teleop/robot_control/robot_hand_inspire.py
index 26f8213..abb9c5d 100644
--- a/teleop/robot_control/robot_hand_inspire.py
+++ b/teleop/robot_control/robot_hand_inspire.py
@@ -29,10 +29,6 @@ class Inspire_Controller_DFX:
else:
self.hand_retargeting = HandRetargeting(HandType.INSPIRE_HAND_Unit_Test)
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
# initialize handcmd publisher and handstate subscriber
self.HandCmb_publisher = ChannelPublisher(kTopicInspireDFXCommand, MotorCmds_)
@@ -178,10 +174,6 @@ class Inspire_Controller_FTP:
else:
self.hand_retargeting = HandRetargeting(HandType.INSPIRE_HAND_Unit_Test)
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
# Initialize hand command publishers
self.LeftHandCmd_publisher = ChannelPublisher(kTopicInspireFTPLeftCommand, inspire_dds.inspire_hand_ctrl)
diff --git a/teleop/robot_control/robot_hand_unitree.py b/teleop/robot_control/robot_hand_unitree.py
index 93c4ca4..d10fd7a 100644
--- a/teleop/robot_control/robot_hand_unitree.py
+++ b/teleop/robot_control/robot_hand_unitree.py
@@ -63,11 +63,6 @@ class Dex3_1_Controller:
else:
self.hand_retargeting = HandRetargeting(HandType.UNITREE_DEX3_Unit_Test)
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
-
# initialize handcmd publisher and handstate subscriber
self.LeftHandCmb_publisher = ChannelPublisher(kTopicDex3LeftCommand, HandCmd_)
self.LeftHandCmb_publisher.Init()
@@ -268,11 +263,6 @@ class Dex1_1_Gripper_Controller:
self.smooth_filter = WeightedMovingFilter(np.array([0.5, 0.3, 0.2]), 2)
else:
self.smooth_filter = None
-
- if self.simulation_mode:
- ChannelFactoryInitialize(1)
- else:
- ChannelFactoryInitialize(0)
# initialize handcmd publisher and handstate subscriber
self.LeftGripperCmb_publisher = ChannelPublisher(kTopicGripperLeftCommand, MotorCmds_)
@@ -414,6 +404,8 @@ if __name__ == "__main__":
args = parser.parse_args()
logger_mp.info(f"args:{args}\n")
+ ChannelFactoryInitialize(1) # 0 for real robot, 1 for simulation
+
# image client
img_client = ImageClient(host='127.0.0.1') #host='192.168.123.164'
if not img_client.has_head_cam():
diff --git a/teleop/teleop_hand_and_arm.py b/teleop/teleop_hand_and_arm.py
index cf442c4..b4afb92 100644
--- a/teleop/teleop_hand_and_arm.py
+++ b/teleop/teleop_hand_and_arm.py
@@ -12,6 +12,7 @@ current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
+from unitree_sdk2py.core.channel import ChannelFactoryInitialize # dds
from televuer import TeleVuerWrapper
from teleop.robot_control.robot_arm import G1_29_ArmController, G1_23_ArmController, H1_2_ArmController, H1_ArmController
from teleop.robot_control.robot_arm_ik import G1_29_ArmIK, G1_23_ArmIK, H1_2_ArmIK, H1_ArmIK
@@ -78,6 +79,7 @@ if __name__ == '__main__':
parser.add_argument('--arm', type=str, choices=['G1_29', 'G1_23', 'H1_2', 'H1'], default='G1_29', help='Select arm controller')
parser.add_argument('--ee', type=str, choices=['dex1', 'dex3', 'inspire_ftp', 'inspire_dfx', 'brainco'], help='Select end effector controller')
parser.add_argument('--img-server-ip', type=str, default='192.168.123.164', help='IP address of image server, used by teleimager and televuer')
+ parser.add_argument('--network-interface', type=str, default=None, help='Network interface for dds communication, e.g., eth0, wlan0. If None, use default interface.')
# mode flags
parser.add_argument('--motion', action = 'store_true', help = 'Enable motion control mode')
parser.add_argument('--headless', action='store_true', help='Enable headless mode (no display)')
@@ -96,6 +98,12 @@ if __name__ == '__main__':
logger_mp.info(f"args: {args}")
try:
+ # setup dds communication domains id
+ if args.sim:
+ ChannelFactoryInitialize(1, networkInterface=args.network_interface)
+ else:
+ ChannelFactoryInitialize(0, networkInterface=args.network_interface)
+
# ipc communication mode. client usage: see utils/ipc.py
if args.ipc:
ipc_server = IPC_Server(on_press=on_press,get_state=get_state)
diff --git a/teleop/utils/motion_switcher.py b/teleop/utils/motion_switcher.py
index 81dde9a..48ad835 100644
--- a/teleop/utils/motion_switcher.py
+++ b/teleop/utils/motion_switcher.py
@@ -8,7 +8,6 @@ import time
# MotionSwitcher used to switch mode between debug mode and ai mode
class MotionSwitcher:
def __init__(self):
- ChannelFactoryInitialize(0)
self.msc = MotionSwitcherClient()
self.msc.SetTimeout(1.0)
self.msc.Init()
@@ -33,7 +32,6 @@ class MotionSwitcher:
class LocoClientWrapper:
def __init__(self):
- ChannelFactoryInitialize(0)
self.client = LocoClient()
self.client.SetTimeout(0.0001)
self.client.Init()
@@ -45,7 +43,7 @@ class LocoClientWrapper:
self.client.Move(vx, vy, vyaw, continous_move=False)
if __name__ == '__main__':
- ChannelFactoryInitialize(0)
+ ChannelFactoryInitialize(1) # 0 for real robot, 1 for simulation
ms = MotionSwitcher()
status, result = ms.Enter_Debug_Mode()
print("Enter debug mode:", status, result)
diff --git a/teleop/utils/sim_state_topic.py b/teleop/utils/sim_state_topic.py
index 5203701..9ad90a4 100644
--- a/teleop/utils/sim_state_topic.py
+++ b/teleop/utils/sim_state_topic.py
@@ -221,10 +221,6 @@ class SimStateSubscriber:
def is_running(self) -> bool:
"""Check if subscriber is running"""
return self.running
-
- def __del__(self):
- """Destructor"""
- self.stop_subscribe()
def start_sim_state_subscribe(shm_name: str = "sim_state_cmd_data", shm_size: int = 4096) -> SimStateSubscriber:
@@ -245,7 +241,7 @@ def start_sim_state_subscribe(shm_name: str = "sim_state_cmd_data", shm_size: in
# if __name__ == "__main__":
# # example usage
# logger_mp.info("Starting sim state subscriber...")
-# ChannelFactoryInitialize(0)
+# ChannelFactoryInitialize(1) # 0 for real robot, 1 for simulation
# # create and start subscriber
# subscriber = start_sim_state_subscribe()