OrcaGym API Reference

本文件是 OrcaGym API Reference,用于开发者快速查接口,也便于 AI 检索与引用。
文档范围以 orca_gym相对稳定的 core + local env 为主;远程相关内容本文件暂不展开。

0. 文档导航(索引/细节/手册)

本仓库的 API 文档分为三层,本文件属于“摘要 + 关键链路(Recipes)”。需要全量符号索引、完整签名与 docstring 时,跳转到下列文档:

目录


1. 总览

OrcaGym 的核心形态是:Gymnasium 环境(Python) 驱动 MuJoCo 仿真,并通过 gRPC 与 OrcaSim 服务端通信。

最常见的对象关系:


2. 关键概念与术语

2.1 数组维度约定(AI/开发者查阅友好)

在 OrcaGym 里,很多 API 直接使用 MuJoCo 的维度定义:

常见 shape:


3. 顶层公共入口 (orca_gym)

文件:../orca_gym/__init__.py

公开导出(__all__):


4. Core API

4.1 OrcaGymBase (gRPC 基础封装)

文件:../orca_gym/core/orca_gym.py

用途:

常用属性:

常用方法(节选):

4.1.1 方法字典(更细)


4.2 OrcaGymModel (静态模型信息)

文件:../orca_gym/core/orca_gym_model.py

用途:

常见用法(动作空间生成):

关键词:

4.2.1 常见字段(概念上,非完整列表)

4.2.2 常用方法(按用途分组)


4.3 OrcaGymData (动态仿真状态)

文件:../orca_gym/core/orca_gym_data.py

用途:

核心字段:

核心方法:

4.3.1 使用建议


4.4 OrcaGymOptConfig (MuJoCo opt 配置)

文件:../orca_gym/core/orca_gym_opt_config.py

用途:

常见字段(节选):

4.4.1 与环境时间的关系


4.5 OrcaGymLocal (本地 MuJoCo backend)

文件:../orca_gym/core/orca_gym_local.py

用途:

4.5.1 关键辅助定义

4.5.2 初始化与模型加载

4.5.3 仿真控制与同步

4.5.4 常用查询(按类别)

4.5.5 方法字典(建议作为“查接口”主入口)

按主题分组如下:

A) 资源/模型加载与缓存
B) opt / timestep
C) 物理步进与数据同步(最常用调用链)

推荐调用链(核心规律):

对应方法:

D) 状态设置(qpos/qvel)与一致性
E) 常用查询(观测/奖励/控制常用)
F) 动力学常用接口(高级用户)
G) 接触与外力(debug/奖励常用)
H) 抓取/操控(mocap + 等式约束)

OrcaGym 常见抓取套路:

  1. 找到 anchor/mocap body(模型中通常名为 ActorManipulator_Anchor
  2. 更新 mocap 位姿:set_mocap_pos_and_quat(...)
  3. 更新等式约束:modify_equality_objects(...) + update_equality_constraints(...)

对应方法:


5. Environment API

5.1 OrcaGymBaseEnv (Gymnasium 基类)

文件:../orca_gym/environment/orca_gym_env.py

用途:

需要子类实现的方法(抽象契约):

常用工具方法:

5.1.1 BaseEnv 的“你一定会踩的点”


5.2 OrcaGymLocalEnv (本地环境实现)

文件:../orca_gym/environment/orca_gym_local_env.py

用途:

关键流程:

常用接口(节选):

5.2.1 方法字典(环境视角)

A) 初始化与关闭
B) step 的核心:do_simulation
C) 渲染与交互(锚点操控依赖渲染触发)
D) 查询与工具方法(Env 转发到 backend)

6. 典型调用链(Recipes)

本节是“开发者真正怎么把这些 API 串起来”的最小闭环,重点解决:

6.1 环境初始化与 reset 链

典型顺序(以 OrcaGymLocalEnv 为例):

OrcaGymLocalEnv.__init__
  -> OrcaGymBaseEnv.__init__
      -> initialize_grpc()
      -> pause_simulation()
      -> set_time_step()
      -> initialize_simulation()   # load_model_xml + init_simulation
      -> reset_simulation()
      -> init_qpos_qvel()

随后训练代码通常调用:

env.reset()
  -> reset_simulation()
  -> reset_model()         # 子类实现:设置初始关节/随机化等
  -> render()

参考:

最小代码片段(直接用 Gymnasium 初始化 + reset):

import gymnasium as gym

# 使用已注册的 env_id(例如任务环境 ID)
env = gym.make(
    "YOUR_ENV_ID",
    frame_skip=5,
    orcagym_addr="localhost:50051",
    agent_names=["agent0"],
    time_step=0.001,
    render_mode="none",
)

obs, info = env.reset()
print("obs keys/type:", type(obs), getattr(obs, "keys", lambda: None)())

6.2 step 链:action → ctrl → 物理步进 → data 刷新

最常见的“正确链路”是:

action (policy 输出)
  -> env.set_ctrl(ctrl) 或 env.do_simulation(ctrl, n_frames)
  -> (内部) gym.mj_step(nstep)
  -> (内部) gym.update_data()
  -> 读取 env.data / env.gym.data 生成 obs、reward

核心原则:

参考:

最小代码片段(标准 Gym step loop):

import numpy as np
import gymnasium as gym

env = gym.make(
    "YOUR_ENV_ID",
    frame_skip=5,
    orcagym_addr="localhost:50051",
    agent_names=["agent0"],
    time_step=0.001,
    render_mode="none",
)
obs, info = env.reset()

for _ in range(100):
    # 最稳妥:从 action_space 采样,保证 shape/范围正确
    action = env.action_space.sample().astype(np.float32)
    obs, reward, terminated, truncated, info = env.step(action)
    if terminated or truncated:
        obs, info = env.reset()

6.3 修改状态链:set_qpos/qvel 后为什么要 mj_forward

当直接修改状态(例如 reset、mocap 更新、关节设定)后:

set_joint_qpos / set_joint_qvel / set_mocap_pos_and_quat
  -> mj_forward()
  -> (可选) update_data()  # 若后续需要从 env.data 读取

原因:

参考:

最小代码片段(直接改关节位置 → forward → 读取位姿):

import numpy as np

# 前置:已有 env(OrcaGymLocalEnv),并需将部分关节设置到目标位置
# joint_qpos = {"hip_joint": np.array([0.1], dtype=np.float64), ...}
joint_qpos = {}

env.set_joint_qpos(joint_qpos)
env.mj_forward()     # 关键:刷新派生量(body/site 位姿、传感器等)
env.update_data()    # 如果后续从 env.data 读(可选但常用)

# 之后再读 env.data / 查询位姿才更可靠
# print(env.data.qpos.copy())

6.4 渲染链:什么时候会触发 UI/交互控制

本地环境常见现象:一些交互(例如 anchor 操作、UI 覆盖控制)在渲染时才会被处理

典型链路:

env.render()
  -> gym.render()                    # 发送 qpos/time 到服务端渲染
  -> (返回) override_ctrls           # UI 侧可能覆盖部分执行器控制
  -> env.do_body_manipulation()      # 一些交互逻辑在这里处理

因此,当依赖“场景交互”但 render_mode 非 human/force,或渲染频率过低时,可能出现:

参考:

最小代码片段(human 渲染 + 让 UI 覆盖控制生效):

import time
import gymnasium as gym

env = gym.make(
    "YOUR_ENV_ID",
    frame_skip=5,
    orcagym_addr="localhost:50051",
    agent_names=["agent0"],
    time_step=0.001,
    render_mode="human",
)
env.reset()

# 在 human 模式下周期 render,UI 侧的交互/override 才会被处理并回传
for _ in range(200):
    env.render()
    time.sleep(env.dt)

6.5 抓取/锚定链:mocap + 等式约束(WELD/CONNECT)

OrcaGym 的抓取/锚定通常是“两件事”的组合:

典型步骤(概念链路):

1) 识别目标 actor / anchor body
2) 更新 mocap 位姿:set_mocap_pos_and_quat(...)
3) 选择约束类型:AnchorType.WELD / AnchorType.BALL
4) 更新约束对象与参数:
   - modify_equality_objects(...)
   - update_equality_constraints(eq_list)
5) 必要时 mj_forward() / update_data()

注意点:

参考:

可复制伪代码(依赖模型里存在 anchor body/eq/mocap 定义;通常名字类似 ActorManipulator_Anchor):

import numpy as np
from orca_gym.core.orca_gym_local import AnchorType

# 1) 选择目标 actor(物体 body 名称),以及锚点类型
actor_name = "SomeObjectBodyName"
anchor_type = AnchorType.WELD  # 或 AnchorType.BALL

# 2) 让环境层完成“锚定逻辑”(会处理 eq_list、obj id 等转换)
env.anchor_actor(actor_name, anchor_type)

# 3) 通过 mocap 移动锚点(驱动物体跟随)
# 注意:mocap 名称需与模型一致;多数场景会在 env 内部封装好 anchor body 名称
env.set_mocap_pos_and_quat({
    env._anchor_body_name: {  # 这是 OrcaGymLocalEnv 里的默认锚点名(模型里需存在)
        "pos": np.array([0.5, 0.0, 0.8], dtype=np.float64),
        "quat": np.array([1.0, 0.0, 0.0, 0.0], dtype=np.float64),
    }
})

# 4) 刷新(避免派生量不一致)
env.mj_forward()
env.update_data()

6.6 观测构建链:从 data/model/sensor 拼观测

自定义环境时,常见的观测来源包括:

建议的构建流程:

do_simulation(...) / update_data()
  -> 读取 data(qpos/qvel...)
  -> (可选) 读取传感器:query_sensor_data(...)
  -> 拼成 obs(np.ndarray 或 Dict[str, np.ndarray])
  -> 第一次 reset 时用 obs 推断 observation_space(generate_observation_space)

参考:

最小代码片段(从 data 拼一个 numpy 观测):

import numpy as np

# 假设 env 已经过 do_simulation/step 且 data 已更新
qpos = env.data.qpos.copy()
qvel = env.data.qvel.copy()

# 最简观测:拼接 qpos + qvel(实际项目通常会做归一化/裁剪)
obs = np.concatenate([qpos, qvel]).astype(np.float32)

6.7 接触/外力链:contact → contact_force/cfrc_ext

调试/奖励中常见链路:

update_data()
  -> query_contact_simple()           # 先拿有哪些接触
  -> query_contact_force(contact_ids) # 再拿接触力
  -> get_cfrc_ext()                   # 或直接看每个 body 的外部约束力

注意点:

参考:

最小代码片段(列出接触对并打印接触力):

# 确保已 do_simulation/step 且 data 已更新
contacts = env.query_contact_simple()
contact_ids = [c["ID"] for c in contacts]

if contact_ids:
    forces = env.query_contact_force(contact_ids)
    first_id = contact_ids[0]
    print("first contact force6d:", forces[first_id])

# 或者直接读每个 body 的外力(用于快速定位异常)
cfrc_ext = env.get_cfrc_ext()
print("cfrc_ext shape:", cfrc_ext.shape)

6.8 常见“数据不同步”问题自检表

若出现“读到旧状态 / 观测跳变 / 位姿不对”,优先检查: