(Demo3D 学习笔记)案例2:飞板传输货物,并按指定货位上架

1、模型描述

通过红色飞板,将输送机处的货物逐个传送到货架指定货位,货位由货位表指定。

2、模型布局

3、解决方案

3.1、载荷发生器

首先给载荷发生器创建自定义属性Loc,类型为表。

在载荷发生器的属性窗口中,找到自定义属性Loc,编辑此表,8行*3列,列名分别为rack(货架号)、bay(列号)、lvl(层号),对应货物上架存储的物理位置。每行代表一个载荷,每行值代表每个载荷将来要存放在货架上的位置。

接下来是对载荷生成器生成的每个载荷中,附带货架号、列号、层号信息。方法是在载荷的OnLoadCreated事件中,编写相应代码如下:

function LoadCreator1_OnLoadCreated( sender : Demo3D.Visuals.LoadCreatorVisual, load : Demo3D.Visuals.Visual )
{
    
    var table:Table=sender.Loc.Table;  //定义表,取值为载荷生成器的Loc自定义属性,注意引用表属性时,要额外加 .Table 后缀
    var rowcount:int=table.Rows.Count;  //定义表的总行数
    var seq:int=sender.SequenceNumber;       //定义载荷的生成序号,即载荷生成器创建的第几个载荷

//为当前载荷创建rack、col、lvl 属性,其值为表Loc 的相应列值
    if(!load.HasCustomProperty("rack")){
        load.AddSimpleProperty("rack",table.Rows[seq]["rack"],"rack");
    }
    if(!load.HasCustomProperty("col")){
        load.AddSimpleProperty("col",table.Rows[seq]["col"],"rack");
    }
    if(!load.HasCustomProperty("lvl")){
        load.AddSimpleProperty("lvl",table.Rows[seq]["lvl"],"rack");
    }

    //如果当前载荷序号超过了表的总行数,则禁止载荷生成器生成载荷    
    if(seq==rowcount-1){
    sender.ReleaseEnabled=False;
    }
}

在载荷生成器的OnReset事件中启用生成载荷

function LoadCreator1_OnReset( sender : Demo3D.Visuals.LoadCreatorVisual )
{
    sender.ReleaseEnabled=True;
}

3.2、飞板

3.2.1、飞板初始化

在飞板的OnReset事件中编写代码

//自定义移动速度属性

if ( ! sender.HasProperty("LinearSpeed") )
{
        sender.AddSimpleProperty("LinearSpeed", new SpeedProfile(1, 0.5, 0.5),"");
}

//自定义旋转速度属性
if ( ! sender.HasProperty("RotationSpeed") )
{
         sender.AddSimpleProperty("RotationSpeed", new AngularSpeedProfile(90,45, 45), "");
}

sender.WorldLocation = vector(0, 0, 0);         //设置飞板初始位置在世界坐标系原点
sender.WorldRotationY = 0;        //设置飞板的初始旋转轴

3.2.2、设置飞板监听光眼

   

 3.2.3、飞板的 OnMessage 事件

 编写代码如下:

function flyPad_OnMessage( sender : Demo3D.Visuals.BoxVisual, message : Demo3D.Visuals.ScriptingObject )
{
    //监听到的事件如果不是光眼 PE1的 OnBlocked 事件,则退出本程序,不作任何处理
    if(!(message["MessageType"]=="OnBlocked" && message.MessageSender.Name=="PE1")){
        return;
    }
    
    //否则,进行如下处理
    var load:Visual=message["load"];
    var pe:PhotoEys=message["MessageSender"];
    var conv:Demo3D.Visuals.StraightRollerConveyor= pe.Parent;
    conv.MotorOff();//关闭输送机马达
        
    //飞板原地升降,高度与输送机高度相同
    var targetLoc:Vector3=sender.WorldLocation;
    targetLoc.Y=conv.Height;
    sender.MoveTo(targetLoc,sender.LinearSpeed);
    sender.WaitForMove();
        
    //飞板原地旋转,X轴向与输送机X轴向相对    
    var targetRot:Vector3=Degrees(conv.WorldRotation);
    sender.TurnTo(Axis.Y,180+targetRot.Y,sender.RotationSpeed);
    sender.WaitForMove();
    
    //飞板移动到输送机出口处
    sender.SetInitialPosition();
    var convStartLoc:Vector3=sender.TransformFromWorld(conv.WorldLocation);
    var convEndLoc:Vector3=new Vector3();
    convEndLoc.X=convStartLoc.X-conv.Length-sender.Width/2.0;
    convEndLoc.Z=convStartLoc.Z;
    sender.MoveTo(sender,convEndLoc,sender.LinearSpeed);
    sender.WaitForMove();
    
    //叉齿伸出接货
    var extender:Visual=sender.FindChild("extender");
    extender.TranslateLocalX(load.Width+0.2,1);
    extender.WaitForMove();
    
    //货物绑定到叉齿,叉齿回缩
    load.Stick(extender);
    extender.TranslateLocalX(-load.Width-0.2,1);
    extender.WaitForMove();
    
    var rackIdx:int=load.rack-1;//定义货架排号,取值为货物附带的rack属性值
    var shelfIdx:int=load.lvl-1;//定义货架层号,取值为货物附带的lvl属性值
    var bayIdx:int=load.col-1;//定义货架格号,取值为货物附带的col属性值
    var rack1:Visual=doc.FindVisualByName("Rack1");//货架组件
    var racks:RackVisual[]=rack1.FindType(RackVisual);//定义一个数组,其元素对应为货架组件中的单排货架
    racks.Sort(new VisualDistanceComparer(rack1.WorldLocation));//货架数组排序,即racks[0]为第一排货架,rack[1]为第2排货架,等等
    
    var targetRack:RackVisual=racks[rackIdx];//货物待上架的目标货架
    var shelves:ShelfVisual[]=targetRack.FindType(ShelfVisual);//定义一个数组,其元素为目标货架的各搁板
    shelves.Sort(new VisualDistanceComparer(targetRack.WorldLocation));//搁板数组排序,即shelves[0]为第一层搁板,shelves[1]为第2层搁板,等等
    
    var targetShelf:ShelfVisual=shelves[shelfIdx];//目标搁板
    targetRot=Degrees(targetShelf.WorldRotation);//目标搁板的角度
        
    //奇偶数排货架,其货架前后端位置正好相反    
    if(rackIdx % 2==0){  //奇数排货架
        
        //飞板原地旋转
        sender.TurnTo(Axis.Y,targetRot.Y,sender.RotationSpeed);//飞板原地旋转,角度与目标搁板方向相同
        sender.WaitForMove();
        
        //飞板水平移动到目标搁板前端入口处
        sender.SetInitialPosition();
        targetLoc=targetShelf.WorldLocation;//目标搁板世界坐标
        targetLoc=sender.TransformFromWorld(targetLoc);//将目标搁板世界坐标转换为相对坐标
        //目标位置微调
        targetLoc.X -=sender.Width/2.0;
        targetLoc.Y =0;
        targetLoc.Z -=sender.Depth/2.0;
        //飞板水平移动
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        //目标货格位置
        var binLoc:BinLocation=new BinLocation();
        binLoc.Bay=bayIdx;
        binLoc.Bin=0;
        binLoc.Index=0;
        
        //目标货格坐标处理
        sender.SetInitialPosition();
        targetLoc=targetShelf.GetNextStoragePosition(binLoc);//获取目标货格相对目标搁板的的坐标(注意是相对坐标)
        targetLoc=targetShelf.TransformToWorld(targetLoc);//目标位置的相对坐标转换为世界坐标
        targetLoc=sender.TransformFromWorld(targetLoc);//目标位置的世界坐标再转换为相对飞板的相对坐标
        var targetBinLocY:Double=targetLoc.Y;//保存目标货格的Y坐标,用于定位下一步中飞板原地升降的高度
        //目标位置微调
        targetLoc.Y =0;
        targetLoc.Z =0;
        
        //飞板平移动到目标货格附近
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        //飞板原地转90°
        sender.SetInitialPosition();
        sender.TurnTo(sender,Axis.Y,270,sender.RotationSpeed);
        sender.WaitForMove();
        
        //飞板原地升降到目标货格高度
        sender.SetInitialPosition();
        targetLoc.X=0;
        targetLoc.Y=targetBinLocY;
        targetLoc.Z=0;
        sender.SetInitialPosition();
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        
        //叉齿伸出放货
        sender.SetInitialPosition();
        extender.TranslateLocalX(load.Width+targetShelf.BayDepth/2.0,1);
        extender.WaitForMove();
        
        //放货,将货物与目标搁板绑定
        load.Stick(targetShelf);
        //叉齿缩回
        sender.SetInitialPosition();
        extender.TranslateLocalX(-(load.Width+targetShelf.BayDepth/2.0),1);
        extender.WaitForMove();
        
        //飞板移动到目标搁板入口处
        sender.SetInitialPosition();
        targetLoc=targetShelf.WorldLocation;
        targetLoc=sender.TransformFromWorld(targetLoc);
        targetLoc.X -=sender.Width/2.0;
        targetLoc.Z +=sender.Depth/2.0;
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();

      }    
    else{        //偶数排货架
        //飞板原地旋转
        sender.TurnTo(Axis.Y,180+targetRot.Y,sender.RotationSpeed);//飞板原地旋转,角度与目标搁板方向相同
        sender.WaitForMove();
        
        //飞板水平移动到目标搁板后端入口处
        sender.SetInitialPosition();
        targetLoc=targetShelf.WorldLocation;//目标搁板世界坐标
        targetLoc=sender.TransformFromWorld(targetLoc);//将目标搁板世界坐标转换为相对坐标
        //目标位置微调
        targetLoc.X -=(targetShelf.OverallLength+sender.Width/2.0);
        targetLoc.Y =0;
        targetLoc.Z +=sender.Depth/2.0;
        //飞板水平移动
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        //目标货格位置
        var binLoc:BinLocation=new BinLocation();
        binLoc.Bay=bayIdx;
        binLoc.Bin=0;
        binLoc.Index=0;
        
        //目标货格坐标处理
        sender.SetInitialPosition();
        targetLoc=targetShelf.GetNextStoragePosition(binLoc);//获取目标货格相对目标搁板的的坐标(注意是相对坐标)
        targetLoc=targetShelf.TransformToWorld(targetLoc);//目标位置的相对坐标转换为世界坐标
        targetLoc=sender.TransformFromWorld(targetLoc);//目标位置的世界坐标再转换为相对飞板的相对坐标
        var targetBinLocY:Double=targetLoc.Y;//保存目标货格的Y坐标,用于定位下一步中飞板原地升降的高度
        //目标位置微调
        targetLoc.Y =0;
        targetLoc.Z =0;
        
        //飞板平移动到目标货格附近
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        //飞板原地转90°
        sender.SetInitialPosition();
        sender.TurnTo(sender,Axis.Y,90,sender.RotationSpeed);
        sender.WaitForMove();
        
        //飞板原地升降到目标货格高度
        sender.SetInitialPosition();
        targetLoc.X=0;
        targetLoc.Y=targetBinLocY;
        targetLoc.Z=0;
        sender.SetInitialPosition();
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();
        
        
        //叉齿伸出放货
        sender.SetInitialPosition();
        extender.TranslateLocalX(load.Width+targetShelf.BayDepth/2.0,1);
        extender.WaitForMove();
        
        //放货,将货物与目标搁板绑定
        load.Stick(targetShelf);
        //叉齿缩回
        sender.SetInitialPosition();
        extender.TranslateLocalX(-(load.Width+targetShelf.BayDepth/2.0),1);
        extender.WaitForMove();
        
        //飞板水平移动到目标搁板后端入口处
        sender.SetInitialPosition();
        targetLoc=targetShelf.WorldLocation;//目标搁板世界坐标
        targetLoc=sender.TransformFromWorld(targetLoc);//将目标搁板世界坐标转换为相对坐标
        //目标位置微调
        targetLoc.X -=sender.Depth/2.0;
        targetLoc.Z -=(targetShelf.OverallLength+sender.Width/2.0);
        //飞板水平移动
        sender.MoveTo(sender,targetLoc,sender.LinearSpeed);
        sender.WaitForMove();    
    
    }
    conv.MotorOn();//飞板完成传输任务后,开启输送机马达,使得输送机上的下一个载荷移动,又一次触发光眼的 OnBlocked 事件。

}

4、最终效果

 5、学习小结

5.1、利用载荷发生器的SequenceNumber属性,作为行号去读取一个表的行列值;

5.2、用代码对载荷发生器创建的载荷,创建待上架位置的自定义属性;

5.3、用代码开启某对象的监听功能,设置两个对象之间监听和被监听的关系;

5.4、对象的 OnMessage 事件,以及参数message的运用,注意参数 message 的数据类型是字典,其主要键名有MessageSender、MessageType;

5.5、利用飞板的 OnMessage 事件,来处理飞板监听到的光眼封堵事件;

5.6、对象移动函数 MoveTo()、旋转函数 TurnTo() 的应用,特别要注意参考坐标系的应用;

5.7、对象旋转时,应注意单位是角度还是弧度,以及角度单位的转换;

5.8、参考坐标系为相对坐标时,SetInitialPosition() 函数的应用;

5.9、注意货架组中,奇数排货架和偶数排货架的前端/后端位置正好相反;

5.10、获取货架的货格位置的相应坐标函数 Shelf.GetNextStoragePosition(binLoc) 的应用;

5.11、货架对象的层级关系:货架对象 > 货架组 RackVisual[ ]> 搁板组  ShelfVisual[ ]> 货格组;

5.12、Sort()函数对货架数组 RackVisual[ ]、搁板数组  ShelfVisual[ ] 中的元素按某种规则进行排序。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值