Mech-Viz接口

本节介绍使用 Mech-Viz 相关的接口,具体包含以下接口:

启动 Mech-Viz

在 adapter.py 文件的 Adapter 类中已定义了启动 Mech-Viz 的函数,因此代码中可直接调用 start_viz()。另外,可根据项目功能需要重写 self.before_start_viz() 和 self.after_start_viz() 以实现自定义 Mech-Viz 启动前后的操作。

函数定义

def start_viz(self, in_new_thread=True, timeout=None):
    if not self.is_viz_registered():
        logging.error("{} has not registered in {}.".format(jk.mech_viz, jk.mech_center))
        self.code_signal.emit(ERROR, VIZ_NOT_REGISTERED)
        self.viz_finished_signal.emit(True)
        self.viz_not_registerd()
        return False
    if self.is_viz_in_running():
        logging.info("{} is already running.".format(jk.mech_viz))
        self.code_signal.emit(WARNING, VIZ_IS_RUNNING)
        self.viz_finished_signal.emit(False)
        self.viz_is_running()
        return False
    self._read_viz_settings()
    if not self.viz_project_dir:
        self.msg_signal.emit(ERROR, _translate("messages", "The project of {0} is not registered. Please make sure Autoload Project is selected in {0}.").format(jk.mech_viz))
        self.viz_finished_signal.emit(True)
        return False
    msg = {"simulate": self.is_simulate, "project_dir": self.viz_project_dir}
    if self.is_keep_viz_state:
        msg["keep_exec_state"] = self.is_keep_viz_state
    if self.is_save_executor_data:
        msg["save_executor_data"] = self.is_save_executor_data
    self.before_start_viz()
    self.viz_finished_signal.emit(False)
    if in_new_thread:
        threading.Thread(target=self.wait_viz_result, args=(msg, timeout)).start()
    else:
        self.wait_viz_result(msg, timeout)
    self.after_start_viz()
    return True

start_viz() 默认在新线程中等待 Mech-Viz 运行完成,此目的是避免影响启动 Mech-Viz 之外的其他操作。

接下来以动态设置步骤参数为例,演示如何重写 self.before_start_viz(),如下所示。

def before_start_viz(self):
     self.set_move_offset(x, y, z)

在 Mech-Viz 启动前,根据读取的数据,配置某个移动点 x、y、z 方向的偏置。

停止 Mech-Viz

在 adapter.py 文件的 Adapter 类中已定义了停止 Mech-Viz 的函数,因此代码中可直接调用 stop_viz()。

函数定义

def stop_viz(self, timeout=None):
    if not self.is_viz_registered():
        self.code_signal.emit(WARNING, VIZ_NOT_REGISTERED)
        return False
    self.call_viz("stop", timeout=timeout)
    self.code_signal.emit(INFO, VIZ_STOP_OK)
    return True

暂停与继续 Mech-Viz

在 adapter.py 文件的 Adapter 类中已定义了暂停与继续 Mech-Viz 的函数,其作用与 Mech-Viz 中的暂停按钮相同,只能在仿真时使用。

函数定义

def pause_viz(self, msg, timeout=None):
       if not self.is_viz_registered():
           self.code_signal.emit(WARNING, ADAPTER_CANCEL_PAUSE)
           return
       self.call_viz("switchPauseContinue", msg, timeout)
       self.code_signal.emit(INFO, ADAPTER_PAUSE_VIZ if msg.get(
           "to_pause") else ADAPTER_CONTINUE_VIZ)

设置步骤参数

在 Mech-Viz 中,若需动态设置步骤参数,通常只需要调用 Adapter 类中的 set_task_property()。

函数定义

def set_task_property(self, msg, timeout=None):
    return self.call_viz("setTaskProperties", msg, timeout)

其中,msg 决定对不同步骤配置不同的参数。

定点移动

在 Mech-Viz 运行过程中,有时候需要微调定点移动步骤中 X、Y、Z 的偏移值,则在控制 Mech-Viz 的主程序中可以编写如下函数。

示例

def set_move_offset(self, name, x_offset, y_offset, z_offset):
    msg = {"name": name,
           "values": {"xOffset": x_offset / UNIT_PER_METER,
                      "yOffset": y_offset / UNIT_PER_METER,
                      "zOffset": z_offset / UNIT_PER_METER}}
    self.set_task_property(msg)

其中,name 表示定点移动步骤的名称;UNIT_PER_METER=1000,通常 x_offset、y_offset 与 z_offset 数据的单位为 mm,而 Mech-Viz 中的数据单位为 m,所以使用 UNIT_PER_METER 进行单位转化。

若按照如下方式调用 set_move_offset() 函数,则 Mech-Viz 中相应的 move_1 步骤的 X、Y、Z 偏移量就会发生相应变化。

self.set_move_offset("move_1", 100, 200, 300)

按序列移动/按阵列移动

按序列移动或按阵列移动通常需在 Mech-Viz 中提前编辑,然后 Adapter 根据逻辑来修改开始索引,用法同定点移动码垛

外部移动

如果若干个外部目标位姿需要发给 Mech-Viz 进行规划控制,则可以通过外部移动步骤来实现。外部移动步骤支持设置 JPs、TCP、物体位姿,用法如下所示。

示例

class CustomOuterMoveService(OuterMoveService):
    def gather_targets(self, di, jps, flange_pose):
        self.add_target(self.move_target_type, [0.189430,-0.455540,0.529460,-0.079367,0.294292,-0.952178,0.021236])

CustomOuterMoveService类继承自OuterMoveService类。self.move_target_type表示移动点类型,取值为0、1或2,其中0表示JPs,1表示TCP,2表示物体位姿。Mech-Viz 运行到外部移动步骤时就会调用 getMoveTargets()。不同外部移动步骤之间通过服务名称进行区分。

def _register_service(self):
   self.outer_move_service = CustomOuterMoveService()
   self._outer_move_server, port = register_service(outer_move_service, port)
当self.move_target_type为2(表示物体位姿)时,外部移动步骤前面需要有一个步骤表示抓取,否则会报错误:“- 未持有物体时物体姿态无效!” 。

码垛

在 Mech-Viz 运行过程中,有时候需要根据不同的码垛步骤设置不同的参数,则通过码垛步骤的名称可以定位到需要修改的步骤。选中工程编辑区中的步骤,在 Mech-Viz 参数编辑区出现的参数都可修改。

示例

例如,对于自定义垛型,通常需要改变的参数值是 开始索引文件名 (需勾选 动态加载 ,才会出现 文件夹路径),因此可以在主程序中定义如下的函数。

def set_stack_pallet(self, name, startIndex, fileName):
    msg = {
        "name": name,
        "values": {
            "startIndex": startIndex,
            "fileName": fileName,
        }
    }
    self.set_task_property(msg)

其中,"startIndex" 对应 开始索引 ,"fileName" 对应 文件名 。"startIndex" 与 "fileName" 参数名称是在 Mech-Viz 中定义的。

使用以下方法调用 set_stack_pallet() 函数。

self.set_stack_pallet("common_pallet_1", 2, "re.json")

对于预设垛型,通常需要改变的参数值是 开始索引垛型箱子长度箱子宽度箱子高度垛型行数垛型列数垛型层数 ,因此可以在主程序中定义如下的函数。

def set_stack_pallet(self, name, startIndex, stack_type):
    pallet_info = self.box_data_info[stack_type]
    """
        pallet_info: Length(mm),Width(mm),Height(mm),pallet type,rows,columns,layers
    """
    msg = {
        "function": "setTaskProperties",
        "name": name,
        "values": {
            "startIndex": startIndex,
            "palletType": pallet_info[3],
            "cartonLength": pallet_info[0] / UNIT_PER_METER,
            "cartonWidth": pallet_info[1] / UNIT_PER_METER,
            "cartonHeight": pallet_info[2] / UNIT_PER_METER,
            "cylinderRows": pallet_info[4],
            "cylinderCols": pallet_info[5],
            "layerNum": pallet_info[6]
        }
    }
    self.set_task_property(msg)

由于需要设置的参数比较多,因此通常会将参数写入一个 excel 文件,然后读取 excel 文件中的数据并记录到 self.box_data_info 中,后续可以通过 stack_type 的值进行索引。"startIndex"、"palletType"、"cartonLength" 等名称在 Mech-Viz 中是固定的。

比较 自定义垛型预设垛型 类中的 msg 值,不难发现,不同之处就在 "values" 值。若需要设置某个步骤参数,只需在 "values" 中添加相应的参数名与值便可进行设置。对于其他垛型步骤的参数设置,参考上述讲解的示例。

消息分支

Mech-Viz 在执行到消息分支步骤时,会一直等待外部信号(指 Adapter)设置出口。对于消息分支步骤,定义如下函数可以进行分支控制。

示例

def set_branch(self, name, area):
    time.sleep(1) # The delay of 1s here is to wait for the {product-viz} executor to fully start
    try:
        info = {"out_port": area, "other_info": []}
        msg = {"name": name,
               "values": {"info": json.dumps(info)}}
        self.set_task_property(msg)
    except Exception as e:
        logging.exception(e)

其中,name 表示步骤的名称,area 表示出口号,出口从左到右编号为 0、1、2、…。如果此次步骤走最左侧出口,则 area=0。如果没有启动 Mech-Viz 就直接调用分支步骤,Mech-Viz 会返回“没有执行器”的错误。

计数器

在使用计数器步骤时,通常需要设置计数器步骤的总计数次数与当前计数次数,定义设置该步骤的代码如下所示。

示例

def set_counter_property(self, name, count, curCount):
    msg = {"name": name,
           "values": {"count": count, "currentCount": curCount}}
    self.set_task_property(msg)

调用该函数的示例如下所示。

self.set_counter_property("counter_1", 5, self.success_stack_num)

其中,self.success_stack_num 表示成功码垛的数量。如果在一次码垛过程中,箱子发生掉落,然后在人为干预下,Mech-Viz 停止。此时 Mech-Viz 中名为 "counter_1" 的计数器步骤不会保存 "currentCount" 的值。重启 Mech-Viz 后,通过 self.success_stack_num 可以重新设置计数器步骤的当前计数值。

读取步骤参数

在 Mech-Viz 运行过程中,如果需要读取某个步骤的参数,可以在主程序中定义如下函数。

示例

def read_move_pallet(self, name):
     msg = {"name": name,
            "properties": ["xOffset","yOffset","zOffset", ]}
     return read_task_property(msg)

其中,通过 "name" 定位需要读取的步骤名称;"properties" 后面的列表中的值可以根据需要添加或者删除参数,示例中表示读取 "xOffset"、"yOffset" 和 "zOffset" 的值,所以将该三个值添加到 "properties" ,调用方法如下所示。

self.read_move_pallet("move_3")

调用后得到如下结果。

{'zOffset': -0.23, 'xOffset': -0.12, 'yOffset': -0.15}

另外,需注意的是,从 Mech-Viz 步骤中获取的一些属性值,是规划进度下的数值,而非实际执行进度下的数值。规划进度往往超前于执行进度(即 Mech-Viz 会尽量提前规划未来的移动)。此处以码垛类步骤的当前索引(curIndex)属性值为例进行说明,用户可在主程序中定义如下函数。

def read_pallet_current_index(self, name):
     msg = {"name": name,
            "properties": ["curIndex"]}
     return read_task_property(msg)

通过如下调用方法获取 curIndex 属性值。

self.read_pallet_current_index("common_pallet_1")

调用上述方法后可能得到如下结果。

{'curIndex': 5}

此处的 5 表示当前规划已经完成了 5 轮。例如,对于码放箱子工程而言,5 表示在规划进度下已码放了 5 个箱子,而机器人实际码放的箱子很可能少于 5 个。因此,诸如 "curIndex" 这类属性值表示已规划的值,而非执行时的值。

设置 TCP

设置 TCP 只需指定 Mech-Viz 中末端工具列表中对应的索引即可。Mech-Viz 中末端工具列表的索引从上往下依次是 0、1、2、3、…… ,注意不可越界。设置 TCP 函数如下所示。

示例

def set_tcp(self, index):
    msg = {"function": "setTcp", "index": index}
    self.call("executor", msg)

设置运行时全局速度

在 Mech-Viz 运行过程中,如果需要动态调整机器人运行速度百分比,则可以在主程序中编写如下函数。

示例

def set_vel(self, vel_scale):
    msg = {"function": "setConfig",
           "velScale": vel_scale / 100, "accScale": vel_scale / 100}
    self.call("executor", msg)

如果将速度设置为 80%,则可以如以下调用该函数。

self.set_vel(80)
该函数必须在 Mech-Viz 启动后才能进行调用,否则会报错,即该模块的调用条件与消息分支步骤一致。因此,通常会在消息分支步骤中调用 set_vel() 函数,避免在一个新线程中调用 set_vel() 函数,示例如下所示。
def set_branch(self, name, area):
    time.sleep(1)
    if self.box_data_info[int(self.pallet_info)][7] <= 10:
        self.set_vel(100)
    else:
        self.set_vel(80)
    try:
        info = {"out_port": area, "other_info": []}
        msg = {"function": "setTaskProperties",
               "name": name,
               "values": {"info": json.dumps(info)}}
        self.set_task("executor", msg)
    except Exception as e:
        logging.exception(e)

设置点云碰撞参数

设置点云碰撞参数,Mech-Viz 对应的接口是 setConfig(),和设置运行时全局速度接口一样,只是设置信息不同,示例如下所示。

示例

msg = {}
msg["function"] = "setConfig"
msg["check_pcl_collision"] = True
msg["collided_point_thre"] = 5000
msg["collide_area_thre"] = 20
msg["pcl_resolution_mm"] = 2
self.call("executor", msg)

Mech-Viz 返回值

Mech-Viz 的返回值如下表所示。

返回值 含义

Finished

正常执行完毕,注意:当 Mech-Viz 工程中视觉移动的右分支连接步骤时,Mech-Viz 也会正常返回

Command Stop

按下停止或调用 stop_viz() 函数

No targets

没有视觉点,指 Mech-Vision 返回空

No proper vision poses

视觉点不可达,指机器人自身不可达当前识别物体或与其发生碰撞

PlanFail

Mech-Viz 规划路径失败

SceneCollision

发生碰撞

针对 Mech-Viz 的返回情况,Adapter 基类提供了对应的接口函数。

我们重视您的隐私

我们使用 cookie 为您在我们的网站上提供最佳体验。继续使用该网站即表示您同意使用 cookie。如果您拒绝,将使用一个单独的 cookie 来确保您在访问本网站时不会被跟踪或记住。