Mech-Viz 인터페이스

이 부분에는 Mech-Viz와 관련된 인터페이스를 소개하고자 합니다. 구체적으로 다음과 같은 인터페이스을 포함합니다.

Mech-Viz를 시작하기

adapter.py 파일의 Adapter 클래스에서 Mech-Viz를 시작하는 함수를 정의했기 때문에 코드에서 직접 start_viz()를 호출하면 됩니다. 또한 Mech-Viz를 시작하기 전/시작한 후의 작업을 자체 정의하기 위해 프로젝트의 기능에 근거하여 self.before_start_viz() 및 self.after_start_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

Mech-Viz를 시작하는 작업 이외의 다른 작업에 영향을 미치지 않도록 start_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])

Mech-Viz가 외부 이동 태스크를 실행할 때 getMoveTargets() 함수를 호출할 것입니다. 서비스 명칭을 통해 다른 외부 이동 태스크를 구분합니다.

def _register_service(self):
   self.outer_move_service = CustomOuterMoveService()
   self._outer_move_server, port = register_service(outer_move_service, port)

Mech-Viz에서 외부 이동 태스크의 파라미터는 아래 그림과 같습니다.

../../../../../_images/viz_interface_01.png

주의

외부 이동 태스크 전에 피킹 태스크가 있어야 합니다. 그렇지 않으면 "- 물체를 잡고 있지 않은 경우에 물체 포즈가 무효합니다!" 라는 오류 메시지가 나옵니다.

팔레타이징

Mech-Viz가 실행될 때 다른 팔레타이징 태스크에 따라 다른 파라미터를 설정해야 할 경우가 종종 있습니다. 이런 경우에 팔레타이징 태스크의 명칭을 통해 수정할 태스크를 찾을 수 있습니다. 프로젝트 편집 구역에 있는 태스크를 선택하고 Mech-Viz 파라미터 편집 구역에 나온 모든 파라미터를 수정할 수 있습니다.

예시

예를 들어 [자체 정의한 파렛트 패턴] 태스크에 대해 일반적으로 파라미터 현재 인덱스파일 명칭 을 수정해야 하며 ( 동적 로딩 을 선택해야 폴더 경로 를 볼 수 있음) 메인 프로그램에서 다음과 같은 함수를 정의할 수 있습니다.

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

그 중에 "curIndex"는 파라미터 현재 인덱스 와 대응하며 "fileName"은 파라미터 파일 명칭 과 대응합니다. "curIndex" 및 "fileName" 의 파라미터 명칭은 모두 Mech-Viz에서 정의됩니다.

다음 방법을 통해 set_stack_pallet() 함수를 호출하십시오.

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

[미리 설정된 파렛트 패턴] 태스크에 대해 일반적으로 파라미터 현재 인덱스 , 파렛트 패턴 , 상자 너비 , 상자 높이 , 층수 , 행수 , 열수 등을 수정해야 하며 메인 프로그램에서 다음과 같은 함수를 정의할 수 있습니다.

def set_stack_pallet(self, name, curIndex, 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": {
            "curIndex": curIndex,
            "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의 수치를 통해 찾아볼 수 있습니다. Mech-Viz에서 "curIndex", "palletType" 및 "cartonLength" 등 명칭은 정해진 것입니다.

자체 정의한 파렛트 패턴미리 설정된 파렛트 패턴 클래스의 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 Mech-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를 시작하지 않고 바로 분기 태스크를 호출하면 “이그제큐터가 없습니다!”라는 오류 메시지가 나옵니다.

카운터

카운터 태스크를 사용할 때 일반적으로 카운터 총수와 현재 카운터를 설정해야 합니다. 해당 태스크를 정의하는 코드가 다음과 같습니다.

예시

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}

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 상위 클래스가 대응한 인터페이스 함수를 제공합니다.