# 로봇 조인트 및 링크 설정

로봇 시뮬레이션에서 조인트와 링크는 로봇의 구조적 기본 요소로, 로봇의 움직임과 동작을 정의하는 데 필수적이다. Unity를 활용한 로봇 시뮬레이션에서 조인트와 링크를 정확하게 설정함으로써 현실적인 물리 기반 동작을 구현할 수 있다. 이 절에서는 로봇 조인트 및 링크의 개념, Unity에서의 설정 방법, 주요 파라미터 및 예제 설정에 대해 상세히 설명한다.

#### 조인트의 종류

로봇 조인트는 로봇의 각 부분을 연결하여 특정 축을 중심으로 움직일 수 있게 하는 메커니즘이다. 주요 조인트의 종류는 다음과 같다:

1. **회전 조인트 (Revolute Joint)**\
   회전 조인트는 두 링크 간의 상대 회전을 허용하며, 주로 하나의 자유도를 갖는다. 이 조인트는 로봇의 조인트처럼 동작하여 특정 축을 중심으로 회전할 수 있다.
2. **프리즘 조인트 (Prismatic Joint)**\
   프리즘 조인트는 두 링크 간의 선형 이동을 허용하며, 역시 하나의 자유도를 갖는다. 이 조인트는 로봇의 슬라이딩 메커니즘에 사용된다.
3. **구 조인트 (Spherical Joint)**\
   구 조인트는 세 개의 자유도를 가지며, 두 링크 간의 모든 방향으로의 회전을 허용한다. 이는 인체의 어깨 조인트와 유사한 동작을 구현할 때 유용하다.
4. **고정 조인트 (Fixed Joint)**\
   고정 조인트는 두 링크 간의 상대적인 움직임을 전혀 허용하지 않는다. 주로 로봇의 기본 구조를 형성할 때 사용된다.

#### 링크의 정의 및 물리적 속성

링크는 조인트로 연결된 로봇의 각 부분을 의미한다. 링크의 물리적 속성은 시뮬레이션의 정확성과 성능에 큰 영향을 미친다. 주요 속성은 다음과 같다:

* **질량 (Mass)**\
  링크의 질량은 로봇의 전체 무게 중심과 동적 거동에 영향을 미친다. Unity에서는 Rigidbody 컴포넌트를 통해 질량을 설정할 수 있다.
* **관성 모멘트 (Inertia Tensor)**\
  관성 모멘트는 링크의 회전에 대한 저항을 나타낸다. 이는 로봇의 안정성과 동적 반응에 중요한 역할을 한다.
* **모양 및 크기 (Shape and Dimensions)**\
  링크의 모양과 크기는 충돌 감지 및 물리적 상호작용에 영향을 미친다. Unity에서는 Collider 컴포넌트를 사용하여 링크의 형태를 정의한다.

#### Unity에서의 조인트 설정

Unity에서는 다양한 조인트 컴포넌트를 제공하여 로봇의 조인트를 설정할 수 있다. 주요 조인트 컴포넌트는 다음과 같다:

1. **Hinge Joint**\
   Hinge Joint는 회전 조인트를 구현하는 데 사용된다. 특정 축을 중심으로 회전할 수 있도록 설정할 수 있으며, 회전 제한 및 스프링, 댐핑 등의 물리적 파라미터를 조정할 수 있다.

   ```csharp
   HingeJoint hinge = gameObject.AddComponent<HingeJoint>();
   hinge.axis = new Vector3(0, 1, 0); // Y축을 중심으로 회전
   hinge.useLimits = true;
   JointLimits limits = hinge.limits;
   limits.min = -90f;
   limits.max = 90f;
   hinge.limits = limits;
   ```
2. **Slider Joint**\
   Slider Joint는 프리즘 조인트를 구현하는 데 사용된다. 선형 이동을 허용하며, 이동 범위와 속도를 설정할 수 있다.

   ```csharp
   SliderJoint slider = gameObject.AddComponent<SliderJoint>();
   slider.axis = new Vector3(1, 0, 0); // X축을 따라 이동
   slider.useLimits = true;
   JointLimits limits = slider.limits;
   limits.min = 0f;
   limits.max = 10f;
   slider.limits = limits;
   ```
3. **Spring Joint**\
   Spring Joint는 스프링 효과를 추가하여 조인트의 동작을 보다 유연하게 만들 수 있다. 스프링 상수와 댐핑 비율을 설정하여 조인트의 반응을 조절한다.

   ```csharp
   SpringJoint spring = gameObject.AddComponent<SpringJoint>();
   spring.spring = 50f;
   spring.damper = 5f;
   spring.minDistance = 0.5f;
   spring.maxDistance = 2f;
   ```

#### 조인트의 파라미터 설정

조인트의 동작을 세밀하게 조정하기 위해 다양한 파라미터를 설정할 수 있다. 주요 파라미터는 다음과 같다:

* **Anchor**\
  조인트의 고정점으로, 두 링크가 연결되는 지점을 정의한다. Anchor는 로컬 좌표계에서 설정된다.

  ```csharp
  hinge.anchor = new Vector3(0, 0.5f, 0);
  ```
* **Axis**\
  조인트의 회전 또는 이동 방향을 정의한다. 이는 조인트가 어떤 방향으로 동작할지를 결정한다.

  ```csharp
  hinge.axis = new Vector3(0, 1, 0); // Y축을 중심으로 회전
  ```
* **Limits**\
  조인트의 움직임 범위를 제한한다. 회전 조인트의 경우 최소 및 최대 각도를, 프리즘 조인트의 경우 최소 및 최대 이동 거리를 설정할 수 있다.

  ```csharp
  JointLimits limits = hinge.limits;
  limits.min = -45f;
  limits.max = 45f;
  hinge.limits = limits;
  ```
* **Motor**\
  조인트에 모터를 추가하여 자동으로 움직임을 생성할 수 있다. 모터의 속도와 토크를 설정하여 조인트의 동작을 제어한다.

  ```csharp
  hinge.useMotor = true;
  JointMotor motor = hinge.motor;
  motor.targetVelocity = 100f;
  motor.force = 1000f;
  hinge.motor = motor;
  ```

#### 링크와 조인트의 연결

로봇의 링크와 조인트를 연결하여 전체 로봇 구조를 형성하는 과정은 다음과 같다:

1. **링크 생성**\
   각 링크는 별도의 GameObject로 생성되며, Rigidbody와 Collider 컴포넌트를 추가하여 물리적 특성을 부여한다.

   ```csharp
   GameObject link1 = new GameObject("Link1");
   Rigidbody rb1 = link1.AddComponent<Rigidbody>();
   rb1.mass = 5f;
   link1.AddComponent<BoxCollider>().size = new Vector3(1, 1, 1);
   ```
2. **조인트 추가 및 설정**\
   부모 링크에 조인트 컴포넌트를 추가하고, 자식 링크와 연결한다. Anchor와 Axis를 적절히 설정하여 조인트의 동작을 정의한다.

   ```csharp
   GameObject link2 = new GameObject("Link2");
   Rigidbody rb2 = link2.AddComponent<Rigidbody>();
   rb2.mass = 3f;
   link2.AddComponent<BoxCollider>().size = new Vector3(0.5f, 0.5f, 0.5f);

   // 부모 링크에 HingeJoint 추가
   HingeJoint hinge = link1.AddComponent<HingeJoint>();
   hinge.connectedBody = rb2;
   hinge.anchor = new Vector3(0, 0.5f, 0);
   hinge.axis = new Vector3(0, 1, 0);
   ```
3. **계층 구조 설정**\
   링크들을 계층 구조로 배치하여 부모-자식 관계를 설정한다. 이는 로봇의 전체 구조를 체계적으로 관리하는 데 도움이 된다.

   ```csharp
   link2.transform.parent = link1.transform;
   ```

#### 물리적 안정성 확보

로봇 시뮬레이션에서 물리적 안정성을 확보하기 위해 다음 사항을 고려해야 한다:

* **질량 분포의 균형**\
  링크들의 질량이 균형 있게 분포되어야 로봇이 시뮬레이션 중 불안정하게 움직이지 않는다. 질량 분포가 고르지 않으면 로봇이 쉽게 기울어지거나 불안정해질 수 있다.
* **충돌 체계의 최적화**\
  Collider의 크기와 형태를 적절히 설정하여 불필요한 충돌을 방지하고, 필요한 충돌만을 감지하도록 한다. 이는 시뮬레이션의 성능과 정확성에 영향을 미친다.
* **관성 모멘트의 조정**\
  Rigidbody의 관성 모멘트를 적절히 조정하여 로봇의 회전 반응을 현실적으로 만든다. 필요에 따라 커스텀 관성 텐서를 설정할 수 있다.

  ```csharp
  rb1.inertiaTensor = new Vector3(1, 1, 1);
  ```

#### 예제: 간단한 2-링크 로봇 팔 설정

다음은 Unity에서 간단한 2-링크 로봇 팔을 설정하는 예제이다.

1. **링크1 생성 및 설정**

   ```csharp
   GameObject link1 = GameObject.CreatePrimitive(PrimitiveType.Cube);
   link1.name = "Link1";
   link1.transform.localScale = new Vector3(0.2f, 1f, 0.2f);
   Rigidbody rb1 = link1.AddComponent<Rigidbody>();
   rb1.mass = 5f;
   link1.AddComponent<BoxCollider>();
   ```
2. **링크2 생성 및 설정**

   ```csharp
   GameObject link2 = GameObject.CreatePrimitive(PrimitiveType.Cube);
   link2.name = "Link2";
   link2.transform.localScale = new Vector3(0.2f, 1f, 0.2f);
   Rigidbody rb2 = link2.AddComponent<Rigidbody>();
   rb2.mass = 3f;
   link2.AddComponent<BoxCollider>();
   link2.transform.parent = link1.transform;
   ```
3. **조인트 추가 및 연결**

   ```csharp
   HingeJoint hinge1 = link1.AddComponent<HingeJoint>();
   hinge1.connectedBody = rb2;
   hinge1.anchor = new Vector3(0, 0.5f, 0);
   hinge1.axis = new Vector3(0, 0, 1);
   ```
4. **조인트 파라미터 설정**

   ```csharp
   hinge1.useLimits = true;
   JointLimits limits = hinge1.limits;
   limits.min = -90f;
   limits.max = 90f;
   hinge1.limits = limits;

   hinge1.useMotor = true;
   JointMotor motor = hinge1.motor;
   motor.force = 100f;
   motor.targetVelocity = 45f;
   hinge1.motor = motor;
   ```

이 예제는 두 개의 링크와 하나의 회전 조인트로 구성된 간단한 로봇 팔을 설정하는 과정을 보여준다. 각 링크는 Rigidbody와 Collider를 가지며, 조인트는 링크 간의 회전을 제어한다. 조인트의 한계와 모터를 설정하여 로봇 팔의 동작 범위와 움직임 속도를 조절할 수 있다.
