goal_object 是你希望作为目标抓取的仿真物体,在你的环境中它等于 args.goal_obj_idx; yolo_target_label 是 YOLO 模型中你定义的 “目标类别索引”,比如 5 是 cube,你可以根据你定义的类别文件 .yaml 来确认; 两者未必要一致,但你要确保抓取逻辑中使用的是 正确的对应关系。我是想要抓取的所以两者应该对应上的,我如何检查是非能够对应上呢?
非常好的问题!你确实已经抓住了关键逻辑点——要让机械臂“抓对目标”,goal_object
(仿真物体索引) 和 yolo_target_label
(YOLO分类标签) 必须间接对应同一个物体实例。
接下来我手把手教你 如何确认两者是否“真正对应上了”:
名称 | 作用 | 示例值 |
---|---|---|
goal_object (goal_obj_idx ) |
指定仿真中目标物体的位置(索引) | 4 表示 self.object_handles[4] 是目标 |
yolo_target_label |
YOLO 分类中,目标物体的类别标签 | 5 表示 “cube” 类别(你设定的目标) |
⚠️ 注意:YOLO 识别的是“类别”,而仿真是随机加载了多个具体物体实例。
你加载物体的逻辑是随机选取模型并放入仿真场景,比如:
self.obj_mesh_ind = np.random.randint(0, len(self.mesh_list), size=self.num_obj)
你通过 goal_obj_idx=4
来说“第 5 个加载物体是目标”。
但 你不确定这个物体到底是不是 “cube” 对应的 .ttm
文件,所以 YOLO 分割时可能识别不到它是标签5。
.ttm
文件名robot.py
的 add_objects()
函数中加一行:找到加载物体时的这一段:
curr_mesh_file = os.path.join(self.obj_mesh_dir, self.mesh_list[self.obj_mesh_ind[object_idx]])
在这行下面加入:
print(f"[Object {object_idx}] Loaded: {curr_mesh_file}")
再在最后一行加入:
print(f"[Goal object index: {self.goal_object}] ==> {self.mesh_list[self.obj_mesh_ind[self.goal_object]]}")
这样运行后你会在终端看到类似:
[Object 0] Loaded: cube2.ttm
[Object 1] Loaded: phone1.ttm
[Object 2] Loaded: can1.ttm
[Object 3] Loaded: mouse3.ttm
[Object 4] Loaded: cube1.ttm
...
[Goal object index: 4] ==> cube1.ttm
如果你看到目标就是 cube 开头的 .ttm
文件,就说明 goal_obj_idx=4
正确对应了仿真中的“cube”,可以与 YOLO 的 yolo_target_label=5
对上。
在 get_segmentation_mask()
中,你会有这段代码:
if target_label not in labels:
print(f"Warning: Target label {target_label} not detected.")
你可以再加一行:
print(f"YOLO detected labels this frame: {labels}")
这会显示你这帧中 YOLO 识别了哪些标签,比如:
YOLO detected labels this frame: [2, 5, 3]
Target label 5 found.
如果你发现:
goal_obj_idx=4
对应的是 "mouse.ttm"
、"phone.ttm"
等
YOLO 的标签是 5
,对应的是 "cube"
类
就说明你指定的目标不是 cube。你应该调整命令行参数为那个 cube 对应的索引,比如:
python main.py --goal_obj_idx 3 ...
或者在代码里自动匹配,找到 .ttm
文件名中包含 "cube"
的物体位置:
for i in range(self.num_obj):
mesh_name = self.mesh_list[self.obj_mesh_ind[i]]
if "cube" in mesh_name:
self.goal_object = i
break
条件 | 检查方式 |
---|---|
goal_obj_idx 对应的仿真物体是否是 cube? |
打印 mesh_list[self.obj_mesh_ind[goal_obj_idx]] |
YOLO 检测中 label == 5 的物体是否出现在画面中? |
打印 labels 并检查是否有 5 |
需要的话,我可以帮你添加一个自动匹配逻辑:加载场景后自动将 goal_obj_idx 设置为 cube 的索引,是否需要?
这是我的代码def add_objects(self):。请你将更改后的代码发给我,并在更改的代码中注释修改的地方是哪里
下面是你提供的 add_objects()
函数经过修改后的版本,增加了打印功能以便调试 goal_obj_idx
是否真的对应了 cube 类的物体。我还在注释中标注了哪些是新增或修改的内容:
def add_objects(self):
# 固定加载 10 个物体到仿真环境(你这里用的是前 5 个)
fixed_objects = [
'cup2.ttm',
'can2.ttm',
'mouse3.ttm',
'cube1.ttm',
'phone2.ttm',
]
# 获取所有 .ttm 文件路径
mesh_list = [f for f in os.listdir(self.obj_mesh_dir) if f.endswith('.ttm')]
# 检查所有固定物体是否存在于目录中
for fixed_object in fixed_objects:
if fixed_object not in mesh_list:
raise ValueError(f"固定物体 {fixed_object} 不存在于目录 {self.obj_mesh_dir} 中!")
# 初始化物体句柄列表
self.object_handles = []
self.loaded_object_names = [] # ✅ 新增:用于存储成功加载的物体名
# 加载固定物体
for object_idx, fixed_object in enumerate(fixed_objects):
try:
curr_mesh_file = os.path.join(self.obj_mesh_dir, fixed_object)
curr_shape_name = 'shape_%02d' % object_idx # 生成物体名称
# 设置物体的随机位置和方向
drop_x = (self.workspace_limits[0][1] - self.workspace_limits[0][0] - 0.2) * np.random.random_sample() + self.workspace_limits[0][0] + 0.1
drop_y = (self.workspace_limits[1][1] - self.workspace_limits[1][0] - 0.2) * np.random.random_sample() + self.workspace_limits[1][0] + 0.1
object_position = [drop_x, drop_y, 0.15] # z 轴高度固定为 0.15
object_orientation = [2 * np.pi * np.random.random_sample(),
2 * np.pi * np.random.random_sample(),
2 * np.pi * np.random.random_sample()] # 随机方向
# 使用 simxLoadModel 加载物体
res, handle = sim.simxLoadModel(self.sim_client, curr_mesh_file, 0, sim.simx_opmode_blocking)
if res != sim.simx_return_ok:
print(f"❌ 无法加载物体: {curr_mesh_file},返回码: {res}")
continue
# 设置物体的位置和方向
sim.simxSetObjectPosition(self.sim_client, handle, -1, object_position, sim.simx_opmode_blocking)
sim.simxSetObjectOrientation(self.sim_client, handle, -1, object_orientation, sim.simx_opmode_blocking)
print(f"✅ 成功加载固定物体: {curr_mesh_file},句柄: {handle}")
self.object_handles.append(handle)
self.loaded_object_names.append(fixed_object) # ✅ 新增:保存加载的物体名称
except Exception as e:
print(f"❗加载固定物体时发生异常: {fixed_object},错误: {str(e)}")
# ✅✅✅ 新增调试输出:打印 goal_obj_idx 对应的物体名称
if self.goal_object < len(self.loaded_object_names):
print(f" 当前目标 goal_obj_idx={self.goal_object} 对应的物体是:{self.loaded_object_names[self.goal_object]}")
else:
print(f"⚠️ 警告:goal_obj_idx={self.goal_object} 超出已加载物体数量范围!(共加载 {len(self.loaded_object_names)} 个物体)")
修改位置 | 注释说明 |
---|---|
self.loaded_object_names |
新增一个列表用于记录每个加载进仿真场景的物体文件名 |
每次成功加载物体时保存文件名 | self.loaded_object_names.append(fixed_object) |
加载完所有物体后检查 goal_obj_idx 的对应物体名 |
打印出目标索引对应的 .ttm 文件名,确认是否是 "cube" |
你运行程序时如果传入了:
--goal_obj_idx 3
你会看到终端输出:
当前目标 goal_obj_idx=3 对应的物体是:cube1.ttm
如果是别的,比如 mouse3.ttm
,你就知道 你选错了目标索引,应该调整为 goal_obj_idx=3
或者对应上 cube 的位置。
是否需要我同时提供一段自动检测 “cube” 所在索引并自动赋值给 goal_obj_idx
的版本?(免得手动数)