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