Unity를 이용한 자기 부상 시뮬레이션

14224 단어 Unity3D
Unity에서 자기 부상을 모의하는 프로그램을 만들었습니다.

1. 요구사항



[1] 자기 부상 액추에이터를 2개로 한다.
[2] 자기 부상 액추에이터는 부상체의 하면에 붙인다.
[3] 어느 위치에 정지시킨다(정위치 제어)

2. 실시 사항



[1] 자기 부상 액추에이터를 자식 오브젝트로한다.
[2] 부상체는 부모 오브젝트로서 자기 부상 액추에이터인 자식 오브젝트를 Fixed Joint로 고정한다.

3. 구체적인 실시 사항



· 부모 개체에 추가하는 스크립트에서 자식 개체를 읽고 자식 개체에 중력에 반하는 힘을 발생시킵니다.
・정위치 제어로서 위치 P 속도 PI 제어 및 중력 보상을 가한다.



동영상이 포함될 수 없기 때문에 상황은 이해하기 어렵지만 스크립트 만 첨부하므로,
참고가 되면 생각합니다.

4. 스크립트



4.1 코드


using UnityEngine;

public class Carrier_Control : MonoBehaviour
{
    public Rigidbody carrier;
    private double f1;
    private double f2;
    private double posY_old1 = 0;
    private double posY_old2 = 0;
    private double posY_old = 0;
    private double Kp = 20;
    private double Kv = 20;
    private double Ts = 1;
    private double Ki = 0.02;
    private double M = 10;
    private double G = 9.8;
    private double Mg;
    private double velY_old = 0;
    private double velY = 0;
    private double refV = 0;
    private double refV_old = 0;

    // Start is called before the first frame update
    void Start()
    {
        Mg = M/2 * G;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        Transform myTransform = this.transform;

        Vector3 pos = myTransform.position;

        Transform mag1Transform = transform.GetChild(0).gameObject.GetComponent<Transform>();
        Transform mag2Transform = transform.GetChild(1).gameObject.GetComponent<Transform>();

        Vector3 magPos1 = mag1Transform.position;
        Vector3 magPos2 = mag2Transform.position;

        velY = (pos.y - posY_old)/Ts;
        refV = (0.45 - pos.y) * Kp;          
        f1 =  (refV-velY_old) * Kv + (refV + refV_old - velY_old) * Ki * Kv;
        f2 =  (refV-velY_old) * Kv + (refV + refV_old - velY_old) * Ki * Kv;

        Vector3 force1 = new Vector3(0.0f, (float)(f1*M/2+Mg), 0.0f);
        Vector3 force2 = new Vector3(0.0f, (float)(f2*M/2+Mg), 0.0f);

        Rigidbody mag1 = transform.GetChild(0).gameObject.GetComponent<Rigidbody>();
        Rigidbody mag2 = transform.GetChild(1).gameObject.GetComponent<Rigidbody>();

        mag1.AddForce(force1);
        mag2.AddForce(force2);

        posY_old1 = magPos1.y;
        posY_old2 = magPos2.y;
        posY_old = pos.y;
        velY_old = velY;
        refV_old = refV - velY_old;
    }
}

4.2 코드 포인트



Qiita의 참고 기사 에도 있습니다만, Unity의 기본은 gameObject를 이용하는 것이며, Transform 클래스를 컴퍼넌트로서 취득해, 한층 더, 위치 정보를 취득하는 점.
        Transform mag1Transform = transform.GetChild(0).gameObject.GetComponent<Transform>();
        Transform mag2Transform = transform.GetChild(1).gameObject.GetComponent<Transform>();

        Vector3 magPos1 = mag1Transform.position;
        Vector3 magPos2 = mag2Transform.position;

Rigidbody 클래스를 컴퍼넌트로서 취득해, 아이 오브젝트에 힘을 발생시키는 점.
        Rigidbody mag1 = transform.GetChild(0).gameObject.GetComponent<Rigidbody>();
        Rigidbody mag2 = transform.GetChild(1).gameObject.GetComponent<Rigidbody>();

        mag1.AddForce(force1);
        mag2.AddForce(force2);

5. 감상



Unity를 잘 다루기 위해서는 GameObject의 이해가 중요하네요. 참고 기사 1
덧붙여서, 데이터의 순차 계산 부분은, FixedUpdate()를 이용해 주세요.
Update()에서는 부상시킬 수 없었습니다.

좋은 웹페이지 즐겨찾기