순운동학과 역운동학

순운동학과 역운동학



로봇과 3D 모델의 관절을 제어하는 ​​방법으로 순운동학(Forward Kinematics)과 역운동학(Inverse Kinematics)이 있다.
  • 순 운동학 ... 관절 각도에서 손가락 끝과 발가락의 위치가 결정됩니다
  • 역 운동학 ... 손가락 끝이나 발가락 위치에서 관절 각도가 결정됩니다

  • 3D 모델의 모션 데이터는 스켈레톤의 각 관절의 SRT에 대한 곡선이며, 이것을 스켈레톤에 적용함으로써 모델의 자세가 결정된다. 이것은 순운동학.

    로봇 암에 무언가를 잡거나 3D 모델에 무언가를 집어 넣을 경우 팔의 끝 (손)을 목표 위치에 가져가기 위해 어깨와 팔꿈치의 자세를 어떻게하면 좋은지 물어볼 필요가 있다. 이것은 역운동학.

    순운동학 구현



    데모



    ㅡㅡㅡㅡㅜㅜㅜㅜㅜㅜㅜㅜㅜ 기주 b. 이오 / 텐타 cぇ FK /
    팔이 흔들립니다.



    역운동학 구현



    데모



    ㅡㅡㅡㅡㅜㅜㅜㅜㅜㅜㅜㅜㅜ 기주 b. 이오 / 텐타 c ㅇ K /
    화살표 키로 팔의 목표 위치를 조작할 수 있습니다.



    알고리즘



    Cyclic-Coordinate-Descent 방법 (CCD 방법)이라는 알고리즘을 사용합니다.
    자세한 내용은 여기을 참조하십시오.

    장점
    다른 IK 알고리즘에 비해 계산량이 작고 알고리즘도 간단
    단점
    관절의 회전 가동 영역을 설정하거나 이펙터의 위치와 방향을 동시에 지정한 계산에 어려움

    이러한 특징이 있기 때문에, 인간의 팔이나 다리와 같은 가동 영역이 명확하게 정해져 있는 경우에는 사용하기 어려울지도 모릅니다.
    한편, 오징어나 문어의 촉완, 생물의 꼬리와 같은 자유로운 가동역을 가지는 관절과는 궁합이 좋을 것 같습니다.

    소스 코드



    htps : // 기주 b. 코 m / 케탄 가탄 / 텐타 c ぇ
    가장 중요한 것은 ArmController.cs입니다.

    ArmController.cs(일부 발췌)
    // CCD アルゴリズムで IK
    if (armParts.Count >= 1) {
        GameObject armPart_Last = armParts [armParts.Count - 1];
    
        for (int i = 0; i < ccdIterNum; ++i) {
            // 末端から根本へイテレートする
            for (int iArmPart = armParts.Count - 1; iArmPart >= 0; --iArmPart) {
                GameObject armPart = armParts [iArmPart];
    
                // エフェクタ位置
                Vector3 posEffect = armPart_Last.transform.position + armPart_Last.transform.forward * 5.0f;
                // -MEMO- 値を決め打ちにしているが本当はロケータを置くのがよい
    
                // エフェクタ方向
                Vector3 dirEffect;
                {
                    dirEffect = posEffect - armPart.transform.position;
                    dirEffect.Normalize ();
                }
    
                // 目標方向
                Vector3 dirTarget;
                {
                    dirTarget = ikTarget.position - armPart.transform.position;
                    dirTarget.Normalize ();
                }
    
                // 回転角
                float rotateRad;
                {
                    float dot = Vector3.Dot (dirEffect, dirTarget);
                    rotateRad = Mathf.Acos (dot);
                }
    
                if (rotateRad > 0.001f) {
                    // 回転軸
                    Vector3 rotateAxis = Vector3.Cross (dirEffect, dirTarget);
                    rotateAxis.Normalize ();
    
                    // 回転
                    armPart.transform.Rotate (rotateAxis, rotateRad * Mathf.Rad2Deg);
                }
            }
        }
    }
    

    좋은 웹페이지 즐겨찾기