RobotService 인터페이스¶
이 부분에서 아래와 같이 RobotService와 관련된 인터페이스를 소개하고자 합니다.
RobotServer 서비스 시뮬레이션¶
RobotServer 시뮬레이션 서비스는 보통 풀 컨트롤(full control)인 경우 실제 RobotServer를 통해 로봇을 컨트롤하는 대신 RobotService를 만들어 RobotServer의 기능을 시뮬레이션하는 것입니다. RobotService가 Mech-Center에서 등록된 후 Mech-Viz가 리얼 로봇과 통신하는 것처람 RobotService와 상호적으로 통신할 것입니다.
RobotServer서비스 시뮬레이션의 주요 응용 시나리오가 아래와 같습니다.
Eye In Hand 경우에 Mech-Vision 계산에 사용되는 로봇 관절 각도를 획득합니다.
리얼 로봇에서 포즈를 획득하여 RobotService에 보냅니다.
예시
Adapter 하위 클래스에서 호출하는 방식은 아래와 같습니다.
def _register_service(self):
"""
register_service
:return:
"""
if self.robot_service:
return
self.robot_service = RobotService(self)
other_info = {'robot_type': self.robot_service.service_name}
self.server, _ = register_service(self.hub_caller, self.robot_service, other_info)
self.robot_service.setJ([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
RobotService의 클래스가 아래와 같습니다.
class RobotService(JsonService):
service_type = "robot"
service_name = "robot"
jps = [0, 0, 0, 0, 0, 0]
pose = [0, 0, 0, 1, 0, 0, 0]
def getJ(self, *_):
return {"joint_positions": self.jps}
def setJ(self, jps):
logging.info("setJ:{}".format(jps))
self.jps = jps
def getL(self, *_):
return {"tcp_pose": self.pose}
def getFL(self, *_):
return {"flange_pose": self.pose}
def setL(self, pose):
logging.info("setL:{}".format(pose))
self.pose = pose
def moveXs(self, params, _):
pass
def stop(self, *_):
pass
def setTcp(self, *_):
pass
def setDigitalOut(self, params, _):
pass
def getDigitalIn(self, *_):
pass
def switchPauseContinue(self, *_):
pass
getJ¶
getJ() 함수는 Mech-Viz와 Mech-Vision가 현재 관절 각도를 획득하는 데 사용됩니다. 구체적으로 아래와 같습니다. 보통 먼저 setJ() 함수를 통해 현재 관절 각도를 설정한 후 getJ()를 호출합니다.
예시
def getJ(self, *_):
pose = {"joint_positions": self._jps}
return pose
Eye In Hand:로봇에서 보내 온 관절 각도를 setJ()에 입력합니다.
def setJ(self, jps): assert len(jps) == 6 for i in range(6): jps[i] = deg2rad(float(jps[i])) self._jps = jps logging.info("SetJ:{}".format(self._jps))
그 중 jps는 로봇에서 보내 온 관절 각도 데이터이고 getJ()에게 호출되도록 self._jps에 수치를 할당합니다. getJ()가 라디안 포맷의 데이터를 획득하기 때문에 단위의 전환를 주의해야 합니다.
Eye To Hand: 로봇의 현재 관절 각도에 따라 설정할 필요는 없지만 실제 로봇 상태를 시뮬레이션하려면 안전한 목표점을 시작점(보통 Home 포인트)으로 설정해야 합니다. 그렇지 않으면 임의의 숫자가 할당되며 오류가 발생하기 쉽습니다.
def getJ(self, *_): return {"joint_positions": [1.246689,-0.525868,-0.789761,-1.330814, 0.922581, 4.364021]}
getFL¶
getFL() 함수는 로봇이 이미지를 캡처할 때의 플랜지 포즈를 제공하는 데 사용됩니다. Eye In Hand 모드에서 진행되는 캘리브레이션은 플랜지와 카메라의 상대적인 위치 관계를 설명하지만 결국 베이스 좌표계 아래의 데이터를 사용하기 때문에 이미지를 캡처했을 때의 플랜지 포즈를 제공해야 합니다.
def getFL(self, *_):
return {"flange_pose": self.pose}
Eye In Hand 방식을 통해 포즈를 제공할 때 다음과 같은 사항을 주의해야 합니다.
로봇이 이미지를 캡처했을 때의 JPs를 반환하면 RobotService에서 직접 setJ()함수를 호출하여(단위: 라디안) 이 함수를 []에 반환하십시오.
로봇이 플랜지 포즈를 반환하면 다음과 같이 처리하십시오.
Mech-Vision 프로젝트 외부 파라미터 파일 extri_param.json 중 파라미터 "is_eye_in_hand"의 값은 true로 설정하십시오.
RobotService의 setFL()를 호출하십시오(단위: 미터, 포즈 유형: 사원수).
moveXs¶
Adapter를 통해 생성한 RobotService 서비스는 moveXs()를 사용하여 Mech-Viz가 계획한 경로 이동 목표점을 수신합니다. 구체적으로 아래와 같습니다.
함수 정의
def moveXs(self, params, _):
with self.lock:
for move in params["moves"]:
self.targets.append(move)
return {"finished": True}
그중에 params가 Mech-Viz 프로젝트의 모든 파라미터를 입력하고 params[《moves》]를 통해 모든 이동 포인트(비전 이동, 상대적인 이동 등 포함)의 포즈를 획득할 수 있습니다. 포즈는 기본적으로 관절 각도의 형식으로 반환되고 포즈를 self.targets에 입력한 후 나중에 파라미터를 조절하는 데 사용될 것입니다.
예시
일반적으로 이 기능은 [알림[ 태스크와 함께 사용되어야 합니다. Adapter가 알림에서 보내 온 메시지를 수신했을 때 self.targets를 함수에 입력하고 전환 및 압축한 후 로봇에 전송합니다. 예를 들면 아래와 같습니다.
def notify(self, request, _):
msg = request["notify_message"]
logging.info("{} notify message:{}".format(self.service_name, msg))
if msg == "started":
with self.lock:
self.move_targets.clear()
elif msg == "finished":
with self.lock:
targets = self.move_targets[:]
self.move_targets.clear()
self.send_moves(targets)
메시지 "started"를 수신했을 때 Mech-Viz 오류로 인해 중단되어 이동 전/후 두 개의 이동 포인트가 서로 겹치는 것을 방지하기 위해 목표점 리스트를 지워야 합니다. 메시지 "finished"를 수신했을 때 목표점 리스트를 pack_move 함수에 입력해 데이터를 정리하고 보내는 데 사용됩니다.
def pack_move(self, move_param):
move_list = []
for i, move in enumerate(move_param):
target = move["target"]
move_list.append(target)
logging.info("move list num:{}".format(len(move_list)))
logging.info("move list:{}".format(*move_list))
motion_cmd = pack('>24f', *move_list)
self.send(motion_cmd)
작업 현장의 실제 수요에 따라 Mech-Viz의 모든 이동 목표점을 전송해도 되고 index에 근거하여 몇 개를 선택해서 전송해도 됩니다. pack_move() 함수는 각 로봇 브랜드가 필요한 데이터 포맷에 따라 데이터를 정리합니다(일반적으로 통신 프로토콜에서 미리 설정됨).