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에서 외부 이동 태스크의 파라미터는 아래 그림과 같습니다.
주의
외부 이동 태스크 전에 피킹 태스크가 있어야 합니다. 그렇지 않으면 "- 물체를 잡고 있지 않은 경우에 물체 포즈가 무효합니다!" 라는 오류 메시지가 나옵니다.
팔레타이징¶
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 상위 클래스가 대응한 인터페이스 함수를 제공합니다.