printf("ho_tari\n");

[협동] ROS-2 프로그램을 활용한 협동로봇 동작 운영 실습 2일차 본문

두산 로보틱스 부트캠프 ROKEY/실무 프로젝트

[협동] ROS-2 프로그램을 활용한 협동로봇 동작 운영 실습 2일차

호타리 2025. 1. 1. 21:55

2024.12.26

 

# pick and place in 1 method. from pos1 to pos2 @20241104

import rclpy
import DR_init

# for single robot
ROBOT_ID = "dsr01"
ROBOT_MODEL = "m0609"
VELOCITY, ACC = 60, 60

DR_init.__dsr__id = ROBOT_ID
DR_init.__dsr__model = ROBOT_MODEL

OFF, ON = 0, 1


def main(args=None):
    rclpy.init(args=args)
    node = rclpy.create_node("force_control", namespace=ROBOT_ID)

    DR_init.__dsr__node = node

    try:
        from DSR_ROBOT2 import (
            release_compliance_ctrl,
            check_force_condition,
            task_compliance_ctrl,
            set_desired_force,
            set_tool,
            set_tcp,
            movej,
            movel,
            get_current_posx,
            set_digital_output,
            get_digital_input,
            wait,
            DR_FC_MOD_REL,
            DR_AXIS_Z,
            DR_BASE,
        )

        from DR_common2 import posx

    except ImportError as e:
        print(f"Error importing DSR_ROBOT2 : {e}")
        return

    # 위치 리스트 (PICK & PLACE)
    pickList =  [[447.66845703125, 149.0836639404297, 240.62635803222656, 167.5069580078125, 180.0, 166.8032989501953],[400.4941711425781, 148.47911071777344, 188.19166564941406, 48.09524154663086, 180.0, 48.17793273925781],[346.8483581542969, 149.53216552734375, 193.3278350830078, 99.93858337402344, 180.0, 101.1941146850586]]
    placeList = [[452.34429931640625, -0.11756063252687454, 190.96731567382812, 44.95091247558594, 180.0, 44.90541458129883],[396.9905700683594, -3.8059051036834717, 201.14144897460938, 20.58327293395996, 180.0, 21.770511627197266],[346.99237060546875, 0.9880767464637756, 218.13966369628906, 93.85528564453125, 180.0, 95.06006622314453]]
    
    def release():
        set_digital_output(2, ON)
        set_digital_output(1, OFF)
        print("release")
        wait(1)

    def grip():
        #release()
        set_digital_output(1, ON)
        set_digital_output(2, OFF)
        print("grip")
        wait(1)

    # 초기 위치
    JReady = [226.76063537597656, 7.510124683380127, 210.95468139648438, 146.1909942626953, -179.83033752441406, 145.9329071044922]
    set_tool("Tool Weight_2FG")
    set_tcp("2FG_TCP")

    # 초기 위치로 이동
    movel([JReady[0], JReady[1], JReady[2], JReady[3], JReady[4], JReady[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)
    print("home")
    previous_pos = 235
    for pick_pos, place_pos in zip(pickList, placeList):
        # Step 1: PICK 단계
        release()
        pick_pre = pick_pos.copy()
        pick_pre[2] = previous_pos
        movel(pick_pre, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        pick_z40 = pick_pos.copy()
        pick_z40[2] = 70# Z축 40으로 설정
        movel(pick_z40, vel=VELOCITY, acc=ACC, ref=DR_BASE)  # pick z=40 위치로 이동

        # Force Control 활성화 (아래로 이동하며 감지)
        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -10, 0, 0, 0], dir=[0, 0, 1, 0, 0, 0], mod=DR_FC_MOD_REL)

        while not check_force_condition(DR_AXIS_Z, max=5):  # Force 감지 대기
            pass
        height_pos = get_current_posx()[0][2]  # 감지된 Z축 위치 저장
        release_compliance_ctrl()

        # 위로 약간 상승
        movel([pick_pos[0], pick_pos[1], height_pos + 10, pick_pos[3], pick_pos[4], pick_pos[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)
        
        grip()  # 물체 잡기
        movel([pick_pos[0], pick_pos[1], height_pos + 140, pick_pos[3], pick_pos[4], pick_pos[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)  # 위로 크게 이동

        # Step 2: PLACE 단계
        # Z축 높이를 유지한 상태에서 X, Y 이동
        movel([place_pos[0], place_pos[1], height_pos + 140, pick_pos[3], pick_pos[4], pick_pos[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)

        movel([place_pos[0], place_pos[1], height_pos+50, pick_pos[3], pick_pos[4], pick_pos[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)
        # Force Control로 Z축 하강
        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -10, 0, 0, 0], dir=[0, 0, 1, 0, 0, 0], mod=DR_FC_MOD_REL)

        while not check_force_condition(DR_AXIS_Z, max=8):  # Force 감지 대기
            pass
        release()  # 그리퍼 열기
        release_compliance_ctrl()

        # 위로 이동
        movel([place_pos[0], place_pos[1], height_pos + 200, pick_pos[3], pick_pos[4], pick_pos[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)
        previous_pos  = height_pos+200
    # 최종 완료 후 초기 위치로 복귀
    movel([JReady[0], JReady[1], JReady[2], JReady[3], JReady[4], JReady[5]], vel=VELOCITY, acc=ACC, ref=DR_BASE)
    print("home")
    rclpy.shutdown()


if __name__ == "__main__":
    main()

 

이 코드는 금속블록의 위치 좌표로 로봇팔이 이동하도록 한 후 힘제어를 통해 금속블록을 들어올려 지정된 다른 위치 좌표로 이동시키는 내용이다. 실행 결과는 다음과 같다.

 

https://youtube.com/shorts/nj9h2WH4HF8

 

 

import rclpy
import DR_init

# ------------------------
# 로봇/툴/그리퍼 설정
# ------------------------
ROBOT_ID = "dsr01"
ROBOT_MODEL = "m0609"
VELOCITY, ACC = 60, 60  # 기본 속도/가속도
OFF, ON = 0, 1

# Doosan 로봇 init 설정
DR_init.__dsr__id = ROBOT_ID
DR_init.__dsr__model = ROBOT_MODEL

def main(args=None):
    rclpy.init(args=args)
    node = rclpy.create_node("force_pick_sort", namespace=ROBOT_ID)
    DR_init.__dsr__node = node

    try:
        from DSR_ROBOT2 import (
            release_compliance_ctrl,
            check_force_condition,
            task_compliance_ctrl,
            set_desired_force,
            set_tool,
            set_tcp,
            movej,
            movel,
            get_current_posx,
            set_digital_output,
            wait,
            DR_FC_MOD_REL,
            DR_AXIS_Z,
            DR_BASE,
        )
        from DR_common2 import posx

    except ImportError as e:
        print(f"Error importing DSR_ROBOT2 : {e}")
        return

    # --------------------------------------
    # 1) 초기 준비: 툴/TCP/그리퍼/초기자세
    # --------------------------------------
    set_tool("Tool Weight_GR")   # 예: 등록된 툴 명
    set_tcp("GripperDA_v1")            # 예: 등록된 그리퍼 TCP 명

    # 초기 자세(예시): 실제 로봇 환경에서 안전 높이의 Pose
    JReady = [226.7606, 7.5101, 210.9546, 146.1909, -179.8303, 145.9329]

    def grip_open():
        set_digital_output(2, ON)
        set_digital_output(1, OFF)
        print("release")
        wait(1)

    def grip_close():
        #release()
        set_digital_output(1, ON)
        set_digital_output(2, OFF)
        print("grip")
        wait(1)

    # 초기 위치로 이동 + 그리퍼는 닫힌 상태로 시작 (사용자가 요구한 시나리오)
    movel(JReady, vel=VELOCITY, acc=ACC, ref=DR_BASE)
    print("Move to Home.")
    grip_close()

    # --------------------------------------
    # 2) Pick 후보 위치(여기서는 예시로 2~3개)
    #    실제 물체 위치는 카메라 인식 or Teach 으로 지정
    # --------------------------------------
    pick_candidates = [
        [450.33221435546875, 148.03155517578125, 240.62635803222656, 167.5069580078125, 180.0, 166.8032989501953],
        [400.4941711425781, 148.47911071777344, 188.19166564941406, 48.09524154663086, 180.0, 48.17793273925781],
        [348.27850341796875, 149.02813720703125, 193.3278350830078, 99.93858337402344, 180.0, 101.1941146850586],
    ]

    # --------------------------------------
    # 3) 높이에 따른 Place 위치 분류
    #    예: contact_z < 100 → A, 100~150 → B, 150 이상 → C
    # --------------------------------------
    place_A = [449.85003662109375, -1.4901727437973022, 190.96731567382812, 44.95091247558594, 180.0, 44.90541458129883]  # 낮은 물건
    place_B = [396.9905700683594, -3.8059051036834717, 201.14144897460938, 20.58327293395996, 180.0, 21.770511627197266]  # 중간
    place_C = [347.75433349609375, -0.5798255801200867, 218.13966369628906, 93.85528564453125, 180.0, 95.06006622314453]  # 높은 물건

    # --------------------------------------
    # 4) 메인 루프: Pick → 분류 → Place
    # --------------------------------------
    for idx, candidate_pos in enumerate(pick_candidates):
        print(f"\n======= [Target {idx+1}] Start =======")

        # 4-1) 물체 상부로 이동 (접근 위치)
        movel(candidate_pos, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        print(f"Move to candidate_pos {candidate_pos}")

        # ============================
        # (A) 힘제어로 '접촉' 감지
        # ============================
        
        # 2) 일정 Z까지 movel (예: 120mm)
        target_z = 100
        force_down_pos = candidate_pos.copy()
        force_down_pos[2] = target_z
        movel(force_down_pos, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        
        # 1) 힘제어 활성화
        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -10, 0, 0, 0],  # Z- 방향 10N
                          dir=[0, 0, 1, 0, 0, 0],
                          mod=DR_FC_MOD_REL)

        # 3) Force 감지 대기
        while not check_force_condition(DR_AXIS_Z, max=5):
            pass
        print("[Force Detected] Contact found.")

        # 4) 접촉 순간의 Z좌표 읽기
        current_pose = get_current_posx()[0]  # [x, y, z, rx, ry, rz]
        contact_z = current_pose[2]
        print(f" >> contact_z = {contact_z:.2f}")
        
        # 5) 힘제어 해제
        release_compliance_ctrl()

        # ============================
        # (B) 그리퍼 열고 조금 더 내려간 뒤 잡기
        # ============================
        # 1) 그리퍼 열기
        grip_open()

        # 2) 조금 더 하강 (ex: +10mm 더 내려가 보기)
        #    실제 물건 형상에 따라 조정
        pick_z = contact_z - 15
        final_down_pos = current_pose.copy()
        final_down_pos[2] = pick_z if pick_z > 0 else 0  # 음수로 내려가면 안 되니 체크
        movel(final_down_pos, vel=60, acc=60, ref=DR_BASE)
        print(f"   >> Move down to {pick_z:.2f} and grip close")

        # 3) 그리퍼 닫기 → 물건 잡기
        grip_close()

        # 4) 위로 상승 (예: contact_z + 50)
        safe_up_pos = current_pose.copy()
        safe_up_pos[2] = contact_z + 140
        movel(safe_up_pos, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        print("   >> Move up with object")

        # ============================
        # (C) 높이별 분류
        # ============================
        # 예) contact_z < 100 → place_A
        #    100 <= contact_z < 150 → place_B
        #    else → place_C
        if contact_z < 61:
            place_target = place_C
            print("   >> Class: LOW object → Place A")
        elif 65 <= contact_z < 71:
            place_target = place_B
            print("   >> Class: MEDIUM object → Place B")
        else:
            place_target = place_A
            print("   >> Class: HIGH object → Place C")

        # ============================
        # (D) Place 지점 이동 → 내려놓기
        # ============================
        movel(place_target, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        print(f"   >> Move to place target: {place_target}")

        # 2) 힘제어 켜고, 하강
        target_down = 100
        place_down = place_target.copy()
        place_down[2] = target_down  # 100mm 더 내려가면서 바닥/물체 접촉 감지
        movel(place_down, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        
        print("   >> Force control down to place...")

        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -10, 0, 0, 0],
                          dir=[0, 0, 1, 0, 0, 0],
                          mod=DR_FC_MOD_REL)

        # 3) Force 감지 대기
        while not check_force_condition(DR_AXIS_Z, max=8):
            pass
        
        release_compliance_ctrl()
        print("[Force Detected] Place contact found.")

        # 4) 접촉 순간 그리퍼 오픈(물건 내려놓기)
        grip_open()

        # 힘제어 해제

        # 5) 위로 상승
        place_up = get_current_posx()[0]  # 현재 접촉 지점 pose
        place_up[2] += 100.0               # 50mm 위로
        print("get_current_posx()[0]:", get_current_posx()[0])
        print("place up:", place_up)
        movel(place_up, vel=VELOCITY, acc=ACC, ref=DR_BASE)
        print("   >> Object placed. Back up.")

        # 다음 Pick 전, 그리퍼 닫거나 유지
        grip_close()

    # --------------------------------------
    # 5) 모든 Pick & Place 완료 후 홈으로 복귀
    # --------------------------------------
    movel(JReady, vel=VELOCITY, acc=ACC, ref=DR_BASE)
    print("Done. Back to Home.")

    rclpy.shutdown()


if __name__ == "__main__":
    main()

 

이 코드는 지정된 위치에 존재하는 금속블록의 높이를 힘제어를 통해 확인한 후 높이별로 구분하여 지정된 위치에 정렬하여 옮기는 내용이다. 실행 결과는 다음과 같다.

 

https://youtube.com/shorts/x2m_hnxs5Ds

 

 

# pick and place in 1 method. from pos1 to pos2 @20241104

import rclpy
import DR_init
import time

# for single robot
ROBOT_ID = "dsr01"
ROBOT_MODEL = "m0609"
VELOCITY, ACC = 200, 200

DR_init.__dsr__id = ROBOT_ID
DR_init.__dsr__model = ROBOT_MODEL

OFF, ON = 0, 1

def main(args=None):
    rclpy.init(args=args)
    node = rclpy.create_node("dsr_example_demo_py", namespace=ROBOT_ID)

    DR_init.__dsr__node = node

    try:
        from DSR_ROBOT2 import (
            set_digital_output,
            get_digital_input,
            release_compliance_ctrl,
            check_force_condition,
            task_compliance_ctrl,
            set_desired_force,
            get_current_posx,
            set_tool,
            set_tcp,
            movej,
            movel,
            wait,
            mwait,
            DR_FC_MOD_REL,
            DR_AXIS_Z,
            DR_BASE,
            trans,
        )

        from DR_common2 import posx, posj

    except ImportError as e:
        print(f"Error importing DSR_ROBOT2 : {e}")
        return

    JReady = posj([0, 0, 90, 0, 90, 0])
    set_tool("Tool Weight_2FG")
    set_tcp("2FG_TCP")
   # 계산된 좌표 값
    x00 = [498.748, 97.436, 23.648, 17.387, 179.305, 15.346]
    x10 = [498.748, 44.982, 23.648, 17.387, 179.305, 15.346]
    x20 = [498.748, -7.472, 23.648, 17.387, 179.305, 15.346]
    x01 = [548.415, 97.436, 23.648, 17.387, 179.305, 15.346]
    x11 = [548.415, 44.982, 23.648, 17.387, 179.305, 15.346]
    x21 = [548.415, -7.472, 23.648, 17.387, 179.305, 15.346]
    x02 = [598.082, 97.436, 23.648, 17.387, 179.305, 15.346]
    x12 = [598.082, 44.982, 23.648, 17.387, 179.305, 15.346]
    x22 = [598.082, -7.472, 23.648, 17.387, 179.305, 15.346]
    
    k11 = [548.415, -103.545, 23.648, 17.387, 179.305, 15.346]


    global pallet_i
    pallet = [0,0,0,0,2,0,0,0,0]
    top_pallet = [x00, x01, x02, x10, x11, x12, x20, x21, x22]


    def wait_digital_input(sig_num):
        # while not get_digital_input(sig_num):
        #     wait(0.5)
        #     print("Wait for digital input", sig_num)
        #     pass
        wait(1)
        
    def release():
        set_digital_output(2, ON)
        set_digital_output(1, OFF)
        print("Release", end='')
        wait_digital_input(2)

    def grip():
        release()
        set_digital_output(1, ON)
        set_digital_output(2, OFF)
        # if flag:
        #     print("Grip", end='')
        wait_digital_input(1)
        wait(1.0)

    def sort_block(z):
        if z < 50: 
            if not 0 in pallet[0:3]:
                return "s", "blank"
            index = pallet.index(0,0,3)
            print("S")
            return "s",index
        elif 50 <= z and z < 60: 
            if not 0 in pallet[3:6]:
                return "m", "blank"
            index = pallet.index(0,3,6)
            print("M")
            return "m", index
        elif 60 <= z:
            if not 0 in pallet[6:9]:
                return "l", "blank"
            index = pallet.index(0,6,9)
            print("L")
            return "l", index
        else:
            print("Error: height")


    def check(base_pose):
        base_point_up =  trans(base_pose, [0,0,100,0,0,0], DR_BASE, DR_BASE )
        force_start_point =  trans(base_pose, [0,0,47,0,0,0], DR_BASE, DR_BASE)
        movel(base_point_up, vel=VELOCITY, acc=ACC)
        movel(force_start_point, vel=VELOCITY, acc=ACC)#내려감
        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -10, 0, 0, 0], dir=[0, 0, 1, 0, 0, 0], mod=DR_FC_MOD_REL)
        while not check_force_condition(DR_AXIS_Z, max=10):
            pass
        release_compliance_ctrl()
        time.sleep(2.0)
        # z축 sorting
        place = get_current_posx()
        result = sort_block(place[0][2])
        movel(base_point_up, vel=VELOCITY, acc=ACC)
        return result

    def pick(base_pose):
        base_point_up =  trans(base_pose, [0,0,100,0,0,0], DR_BASE, DR_BASE )
        movel(base_point_up, vel=VELOCITY, acc=ACC)
        release()
        movel(base_pose, vel=VELOCITY, acc=ACC)
        grip()
        movel(base_point_up, vel=VELOCITY, acc=ACC)
        print("current position4 : ", get_current_posx())

    def place(base_pose):
        base_pose_up = trans(base_pose, [0,0,70,0,0,0], DR_BASE, DR_BASE)
        force_start_point = trans(base_pose, [0,0,27,0,0,0], DR_BASE, DR_BASE)
        movel(base_pose_up, vel=VELOCITY, acc=ACC)
        print("current position2 : ", get_current_posx())
        movel(force_start_point, vel=VELOCITY, acc=ACC)#내려감
        print("current position3 : ", get_current_posx())
        task_compliance_ctrl(stx=[500, 500, 500, 100, 100, 100])
        set_desired_force(fd=[0, 0, -15, 0, 0, 0], dir=[0, 0, 1, 0, 0, 0], time=0.1, mod=DR_FC_MOD_REL)
        while not check_force_condition(DR_AXIS_Z, max=10):
            pass
        release_compliance_ctrl()
        time.sleep(0.5)
        release()
        movel(base_pose_up, vel=VELOCITY, acc=ACC)
        grip()

    def handle_block_mismatch(block_size, assigned_index):
        
        if assigned_index == "blank":
            start = pallet.index(0)
            end = pallet.index(2)
            pick(top_pallet[start])
            place(top_pallet[end]) 
            pallet[start] = 2
            pallet[end] = 1
            return

        block_size2, _ = check(top_pallet[assigned_index])
        start = pallet.index(0)
        end = assigned_index
        buffer = pallet.index(2)
        if block_size2 == block_size:
            pallet[assigned_index] = 1
            print(pallet)
            if pallet[assigned_index+1] == 2:
                handle_block_mismatch(block_size, assigned_index+2)
                return
            handle_block_mismatch(block_size, assigned_index+1)
        else:
            pick(top_pallet[end])
            place(top_pallet[buffer])  # 미리 지정된 임시 위치
            pick(top_pallet[start])
            place(top_pallet[end])
            print(pallet)
            pallet[buffer] = 0
            print(pallet)
            pallet[start] = 2
            print(pallet)
            pallet[end] = 1
            print(pallet)

    
    if rclpy.ok():
        movej(JReady, vel=VELOCITY, acc=ACC)
        release()
        movel(trans(x11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        movel(x11, vel=VELOCITY, acc=ACC)
        grip()
        movel(trans(x11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        movel(trans(k11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        movel(k11, vel=VELOCITY, acc=ACC)
        release()
        movel(trans(k11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        
        grip()
        while 0 in pallet:
            print(pallet)
            block_size, assigned_index = check(top_pallet[pallet.index(0)])
            if pallet.index(0) < 3:
                if block_size == "s":   pallet[pallet.index(0)] = 1
                else:
                    handle_block_mismatch(block_size, assigned_index)

            elif pallet.index(0) >=3 and pallet.index(0) <6:
                if block_size == "m":   pallet[pallet.index(0)] = 1
                else: 
                    handle_block_mismatch(block_size, assigned_index)
            else:
                if block_size == "l":   pallet[pallet.index(0)] = 1
                else:
                    handle_block_mismatch(block_size, assigned_index)

        release()
        movel(trans(k11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        movel(k11, vel=VELOCITY, acc=ACC)
        grip()
        movel(trans(k11, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        
        target = top_pallet[pallet.index(2)]

        movel(trans(target, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        movel(target, vel=VELOCITY, acc=ACC)
        release()
        movel(trans(target, [0,0,100,0,0,0], DR_BASE, DR_BASE ), vel=VELOCITY, acc=ACC)
        


        
        

    rclpy.shutdown()


if __name__ == "__main__":
    main()