> 文章列表 > Unity开发数字化看板-通用的设备运动同步

Unity开发数字化看板-通用的设备运动同步

Unity开发数字化看板-通用的设备运动同步

通用的设备运动同步

通过获取实时采集运动位置,发送到unity程序中,通过比例运算,转换成模型的运动位置,实现虚实同步。

在工业设备中,复杂的运动进行分析、分解,最本质的的运动就是平移和转动,在空间上就是3个维度的平移和旋转,包括:x轴平移,y轴平移,z轴平移,x轴旋转,Y轴旋转,Z轴旋转。

当然根据接收的数据不同,可能有的是一维运动,有的是多个维度合并一起运动。

实现实控虚的主要几个点:

  1. 初始化位置映射,实际设备确定一个零点,在模型需要找到对应零点,记录当前位置
  2. 比例换算,模型显示跟实际尺寸存在非完全一致或者单位换算的问题,对部件进行平移需要换算,旋转角度则不需要
  3. 旋转中心点调整

实现运动控制脚本:

主要实现一个运动控制基类MoveBase和3个维度平移和旋转控制(6个脚本)

基类MoveBase实现

首先实现初始化

InitPosition变量用于存储当前部件模型的初始化位置,虚函数InitLocation()用于根据InitPosition值和不同类型的运动进行不同初始化,具体初始化内容在子类中实现。

/// <summary>/// 初始化位置/// </summary>public float InitPosition;/// <summary>/// 初始化位置参数/// </summary>public virtual void InitLocation(){}

比例换算:

在平移中:

(模型位置−模型初始位置)模型可运动长度=实际位置实际可运动长度\\frac{(模型位置-模型初始位置)}{模型可运动长度}=\\frac{实际位置}{实际可运动长度} 模型可运动长度(模型位置模型初始位置)=实际可运动长度实际位置

在旋转:

模型当前角度=模型偏转零点+转动角度模型当前角度=模型偏转零点+转动角度 模型当前角度=模型偏转零点+转动角度

设置了四个参数,DataPosition是传过来的位置,就是实际位置;NowPosition是当前位置,就是模型当前位置;MoveLength是模型可运动长度;ActualLength是实际可运动长度;MoveLengthActualLength只有在平移运动式有效,如果是旋转则默认设置为0,不处理。

    /// <summary>/// 传过来的位置/// </summary>protected float DataPosition;/// <summary>/// 当前位置/// </summary>public float NowPosition;/// <summary>/// 模型可移动长度,比例计算/// </summary>public float MoveLength = 1;/// <summary>/// 实际可移动长度/// </summary>public float ActualLength = 1;

运算公式:

模型实时位置=模型初始化位置+实际位置∗模型可移动长度实际可移动长度模型实时位置=模型初始化位置+\\frac{实际位置*模型可移动长度}{实际可移动长度} 模型实时位置=模型初始化位置+实际可移动长度实际位置模型可移动长度

在脚本FixedUpdate()中实时更新模型位置,先使用公式计算当前模型位置,然后调用UpdateModelPosition()更新位置,具体更新在对应子类中转换为坐标更新或者角度旋转。

    private void FixedUpdate(){if (IsChange()){NowPosition = InitPosition + DataPosition * MoveLength / ActualLength;UpdateModelPosition();}}/// <summary>/// 更新位置/// </summary>public virtual void UpdateModelPosition(){}

MoveBase基类完整脚本:

/// <summary>
/// 运动控制基类(平移、旋转)
/// </summary>
public class MoveBase : MonoBehaviour
{/// <summary>/// 运动控制对象/// </summary>public Transform MoveObject;/// <summary>/// 传过来的位置/// </summary>protected float DataPosition;/// <summary>/// 初始化位置/// </summary>public float InitPosition;/// <summary>/// 当前位置/// </summary>public float NowPosition;/// <summary>/// 模型移动长度,比例计算/// </summary>public float MoveLength = 1;/// <summary>/// 实际移动长度/// </summary>public float ActualLength = 1;/// <summary>/// 设置实时数据/// </summary>/// <param name="pos"></param>public virtual void SetDataPos(float pos){DataPosition = pos;}public bool IsChange(){if (NowPosition != DataPosition){return true;}else{return false;}}void Start(){MoveObject = gameObject.transform;}/// <summary>/// 初始化位置参数/// </summary>public virtual void InitLocation(){}private void FixedUpdate(){if (IsChange()){NowPosition = InitPosition + DataPosition * MoveLength / ActualLength;UpdateModelPosition();}}/// <summary>/// 更新位置/// </summary>public virtual void UpdateModelPosition(){}
}

各个维度控制脚本:

X轴平移:

public class XMove : MoveBase
{public override void InitLocation(){MoveObject.localPosition = new Vector3(InitPosition, MoveObject.localPosition.y, MoveObject.localPosition.z);}public override void UpdateModelPosition(){MoveObject.localPosition = new Vector3(NowPosition, MoveObject.localPosition.y, MoveObject.localPosition.z);}
}

Y轴平移:

public class YMove : MoveBase
{public override void InitLocation(){MoveObject.localPosition = new Vector3(MoveObject.localPosition.x, InitPosition, MoveObject.localPosition.z);}public override void UpdateModelPosition(){MoveObject.localPosition = new Vector3(MoveObject.localPosition.x, NowPosition, MoveObject.localPosition.z);}
}

Z轴平移:

public class ZMove : MoveBase
{public override void InitLocation(){MoveObject.localPosition = new Vector3(MoveObject.localPosition.x, MoveObject.localPosition.y, InitPosition);}public override void UpdateModelPosition(){MoveObject.localPosition = new Vector3(MoveObject.localPosition.x, MoveObject.localPosition.y, NowPosition);}
}

X轴旋转:

public class XRotate : MoveBase
{public override void InitLocation(){MoveObject.localRotation = Quaternion.Euler(InitPosition, MoveObject.localPosition.y, MoveObject.localPosition.z);}public override void UpdateModelPosition(){MoveObject.localRotation = Quaternion.Euler(NowPosition, MoveObject.localPosition.y, MoveObject.localPosition.z);}
}

Y轴旋转:

public class YRotate : MoveBase
{public override void InitLocation(){MoveObject.localRotation = Quaternion.Euler(MoveObject.localPosition.x, InitPosition, MoveObject.localPosition.z);}public override void UpdateModelPosition(){MoveObject.localRotation = Quaternion.Euler(MoveObject.localPosition.x, NowPosition, MoveObject.localPosition.z);}
}

Z轴旋转:

public class ZRotate : MoveBase
{public override void InitLocation(){MoveObject.localRotation = Quaternion.Euler(MoveObject.localPosition.x, MoveObject.localPosition.y, InitPosition);}public override void UpdateModelPosition(){MoveObject.localRotation = Quaternion.Euler(MoveObject.localPosition.x, MoveObject.localPosition.y, NowPosition);}
}

测试:

创建两个Cube物体用于测试

Unity开发数字化看板-通用的设备运动同步

在MoveCube上面挂上Zmove脚本,并且修改脚本参数用于模拟运动

Unity开发数字化看板-通用的设备运动同步

写一个测试的控制脚本,将他挂在随便一个物体上(相机或者Cube),将MoveCube物体复制给Move参数,然后运行,就可以看到物体运动。

Unity开发数字化看板-通用的设备运动同步

public class MoveTest : MonoBehaviour
{public MoveBase Move;int pos = 0;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}private void FixedUpdate(){pos++;Move.SetDataPos(pos);}
}

效果:

在这里插入图片描述