UnityVR--机械臂场景9-简单流水线应用1

目录

一. 整体介绍

二.  准备工作

三. 建立流水线

  1. 流水线包含的功能:

  2. 流水线的代码结构

  3. 场景实现

   4. 测试运行


一. 整体介绍

  流水线是在空间和时间上合理安排和组织工艺线路的一种形式,它涉及到一种或多种生产设备、传感器、物料传输设备等,并且有明显的生产节拍,是一个比较复杂的生产系统。当然,流水线的设计不是本篇的研究对象,这里记录一个机械臂和传送带配合运送工件的简单示例。

传送带IK演示

  这里只涉及到传送带、传感器、机械臂和工件相互间的通信,也就是通过传送带搬运工件,当传感器检测到工件的到来时,就通知传送带停止、机械臂去抓取工件,当机械臂将工件抓出传感器检测范围后,传送带继续搬运、机械臂回零。

二.  准备工作

  1. 考虑到在以上四个要素之间有不少信息需要通信传输,所以计划使用事件发送来实现,不然需要设立很多个判断,影响程序的可读性。关于事件中心的建立,请详见事件中心2(实在是不愿意看的同学只要复制粘贴这里面的4个类,放在工程文件中就可以使用了)。

  2. 关节旋转中需要用到DoTween插件,可以去AssetStore下载,免费的那个就行。不用也可以,只是为了好看。

   3. 本篇在上一篇ABB机械臂的逆向解算的基础上,请先将上一篇的代码测试成功。

下面正式开始:

三. 建立流水线

  1. 流水线包含的功能:

  流水线包含了2个方面的功能:

    A. 动画功能:使用材质(renderer.material)流动实现流水线向前运行的效果

    B. 物理功能:使用刚体(Rigidbody)实现让工件物理移动的效果。

  2. 流水线的代码结构

    2.1 机械基类MechanicBase.cs:

    由于考虑到工程场景中涉及到的机械部件较多,因此先建立一个机械基类,将机械部件需要的变量、方法等提炼出来,下面是本篇建立的机械基类。由于不同的机械单元驱动方式不同,因此将基类定义为抽象类,以便于在子类中重写它的抽象方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
//机械基类
[Serializable] 
public struct MechanicCell
{
    public MechanicBase unit;      //一个机械单元
    public float ratio;            //比率,控制这个单元的速度

    public MechanicCell(MechanicBase cell, float ratio)
    {
        unit = cell;
        this.ratio = ratio;
    }
}

public abstract class MechanicBase : MonoBehaviour
{//在基类中定义一个驱动引擎的方法
    public abstract void EngineDriver(float velocity);  
}

public enum Direction  //枚举,机械单元运动的方向
{
    forward, back, right, left
}

    2.2 定义一个引擎脚本BeltEngine.cs:

    BeltEngine.cs用于驱动本系统内所有的机械单元。我的设想参照了MGS-MechanicalDrive插件包,一个Engine的作用域仅限于当前的机械系统,类似于一个电机。比如一个Engine.cs实例,在传送带的系统中用于驱动皮带轮和同步带:

    

    代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//使用engine驱动所有部件

public class BeltEngine : MechanicBase
{//定义机械系统,将所有活动部件放入数组中
    public MechanicCell[] cells;
    public float enginePower = 50;  //动力系数

  void Start()
  {//注册一个停止事件,当收到停止命令时,将enginePower设置为0
        
    EventManager.Instance.AddEvent(EventType.OnConveyerCtrl, this, data=> {
    if ((data as EventDataConveyer).conveyerType == EConveyerType.Stop) enginePower = 0;
            else enginePower = 50;    });
  }

void FixedUpdate()
{
    EngineDriver(enginePower);
}

public override void EngineDriver(float velocity)
{//一旦方法被调用,就将本机械系统中的所有单元都驱动一遍
    foreach(var cell in cells)
    {
      cell.unit.EngineDriver(velocity * cell.ratio); 
    }
}
}

    2.3 传送带脚本BeltMove.cs

    传送带的实现需要用到传送带上的材质(Renderer)和刚体(Rigidbody),代码还是比较简单的:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Renderer))]  //绑定Renderer组件
[RequireComponent(typeof(Rigidbody))] //绑定Renderer组件

public class BeltMove : MechanicBase
{
    protected Renderer renderer; //定义材质
    private Rigidbody rig;       //定义刚体

    private float loadRate = 0.2f;   //负载的速率系数
    private float renderDir=1;       //传送带运动方向的系数

    void Start()
    {
        renderer = GetComponent<Renderer>(); //获取材质组件
        rig = GetComponent<Rigidbody>();     //获取刚体组件
    }

    public override void EngineDriver(float velocity)
    {//重写基类的EngineDriver方法
        x = velocity * Mathf.Deg2Rad * Time.fixedDeltaTime;
        y = 0;
        //实现传送带的材质流动,如果方向反了,可以将系数renderDir改为-1
        renderer.material.mainTextureOffset += new Vector2(y, x) *renderDir;
 
        //实现刚体之间的相对运动,如果方向不对,可修改Vector3.back
        Vector3 ori_pos = rig.position;  //传送带实际位置不改变      
        rig.position += Vector3.back* velocity*loadRate* Time.fixedDeltaTime;
        rig.MovePosition(ori_pos);
    }
}

  3. 场景实现

    3.1 没有找到合适的流水线模型,建立了两个Cube并拉长成合适的大小,随便贴个材质:

    

    3.2 给两条传送带分别挂上Collider和Rigidbody,由于本来就是Cube改造的,自带有BoxCollider,最重要的是将Rigidbody的IsKinematic打勾。

    原理是利用刚体运动"Rigidbody.MovePosition(position)",并且利用物理系统模拟的摩擦力实现两个刚体间的相对运动。但只需要工件移动,传送带的物理位置不能改变,因此传送带需要勾选IsKinematic

    

     3.3 建立相应的节点

    以下是本篇的一个传送带系统,包含了3条传送带和1个驱动引擎,其中每一条传送带都需要挂上BeltMove.cs脚本,并且修改脚本中的运动方向(上文中的Vector3.back):

    

    另外,Engine是个空节点,需要挂上BeltEngine.cs,并且将需要驱动的机械部件填入列表中:

    

   4. 测试运行

     以上就完成了传送带部分的建立。加一个工件测试运行一下(别忘了给工件加上碰撞器和刚体),并将EnginPower、Ratio等参数调整到适合状态

    

(总之就是一个非常简单的应用案例,如果有错误请批评指正)

猜你喜欢

转载自blog.csdn.net/tangjieitc/article/details/131641358