|
||
---|---|---|
Artists | ||
BITKit | ||
EXE | ||
Mods | ||
ReadMe/工业互联网标识解析与注册 | ||
Temp | ||
addons | ||
android | ||
.gitattributes | ||
.gitignore | ||
README.md | ||
iFactory.csproj | ||
iFactory.csproj.old | ||
iFactory.sln | ||
icon.svg | ||
icon.svg.import | ||
project.godot |
README.md
iFactory.Godot
基于虚实交互和数模驱动,iFactory
能满足仿真(以虚映实)、控制(以虚控实)、预测(以虚预实)、优化(以虚优实)等应用服务需求,其中连接与交互是实现数字孪生动态运行和虚实空间高效融合的核心关键
基于Godot的iFactory客户端(网络服务和服务端已定义接口,预计使用KCP实现)
正在从Unity版(内网链接)一步一步移植到Godot中
该项目主要使用ECS架构,BITKit作为基本的dotnet框架
该项目为基准演示
,主要通过一些场景展现该软件的所有功能
由于Godot未提供相关的编辑器功能(例如暴露可编辑的class
和自定义接口实例
),该项目的进度并没有Unity
的实现速度快
Installation 安装过程
1.首先你需要安装 Godot4.0.3 Net 👉GodotEngine.Net
2.通过Git Clone一些仓库到与该仓库相同路径的文件夹,文件结构看起来像这样:
GitHub (你的项目文件夹的上一级)
iFactory.Godot 外网仓库链接
BITKit 外网仓库链接
BITKit.Godot BITKit.Godot
AGV_System 内网仓库链接
3.最后在Godot中导入iFactory.Godot
4.安装完成⭐
Features 功能与模块
场景介绍
-
基于AGV小车提供的三维环境感知场景
- 基于AGV小车提供的三维环境感知,可视化当前小车的环境,任务和运行路线,可演示并手动控制小车
- 支持演示模式,实时为小车编辑任务并模拟运行和实际运行演示
-
CPS数字孪生验证场景
- 由于塞昇提供的一体机没有独立显卡,该项目首先为塞昇提供低配可流畅运行的领克和嘉际模型小车装配过程验证
- 当前塞昇客户端的运行情况为运行时占用2G内存和20FPS,长时间运行后占用6G内存和1FPS
-
虚拟客机装配
- 该场景主要演示在该软件的快速规划下,自定义小车,装配路线和过程,验证及演示装配客机的过程
-
虚拟泊车演示
- 该场景主要用于验证和展示泊车AGV的调度方案,通过添加车辆(停车)和调取车辆(取车)的方式,验证泊车方案和并展示泊车过程
功能介绍
机位同步
- 超炫酷
零延迟
机位同步(可能需要一些硬件支持) - 基于角度的
Loopback
算法,解决了同步角度和位置时0>1>0的值被线性插值解析为0>0.7414>0的问题 - 基于物理
PBR
的三维模型,确保和现实中的设备看起来几乎一致 - 基于
Lancer.SCADA
返回数据的物料同步(例如SR7C1L
夹着物料多功能笔记本
放进交付气缸夹
)
实时数据
- 通过
Lancer.SCADA
返回的数据,试试展示重要数据
生产回放
- 录制生产时的数据,可离线播放生产过程
- 支持数据追溯,收集和录制重要数据,可对数据进行加工、提炼和分析,找到可能存在的重要数据
- WebGL版本支持云端回放
环境扫描
- 基于具有环境感知的设备对现场环境进行扫描,快速还原现场外观和环境
- 支持多个具有环境感知的设备同时对现场环境进行并行扫描
监控和摄像头接入
- 接入
网络摄像头
和串口摄像头
- 支持
RTSP
协议,支持网络流媒体直播(例如海康RSTP
)
布局规划
- 拖放
模型库
/预制件
到场景中,快速完成场景的基础规划 - 选中
实体
并编辑数值或节点,可快速定制模型
,例如- 自定义围墙,围栏,输送带的尺寸,如 长
4096mm
,宽256mm
- 编辑贝塞尔曲线,标记
AGV
或其他可运动设备的路线
- 快速替换预览设备的型号,例如将
KUKA.AGV
替换为Intelli.AGV
\
- 自定义围墙,围栏,输送带的尺寸,如 长
沙盒仿真(南岸信的可能性需求)
- 基于
行为树
的顺序执行模式带来相对直观的设计 - 基于
行为树
你可以直接设计生产流程,并支持通过http接入MES系统 - 行为树支持
Godot Editor
和Runtime
模式,可以在编辑器或运行时编辑行为 - 基于行为树,你可以让
Entity
和Signal
执行各种各样的操作,包括且不限于:- AGV移动到指定位置(可等待到达,或指定到达时间以及移动速度)
- 等待条件达成(e.g.等待某个信号
Signal
)后执行操作 - 手动触发信号,以及设置信号断点
- 支持信号日志
- 根据需求接入
ABB Studio
,接入后可直接在ABB Studio
或西门子 PLC
等平台中直接设计程序,并在iFactory
中进行仿真演算和验证
教学平台与考试模式
- 支持课程编辑器,可根据提供的文件快速生成课程讲解与教学实训
- 基于与
ABB Studio
之间的通讯,可设置相关实训和考试目标,在ABB Studio
中设计程序,并在iFactory
中验证题目是否完成并给出评分 - 支持考试模式,主要的监管客户端可监控所有实训客户端的所有状态,支持对实训端给出信号或干预("某极域客户端的黑屏提示")
标识解析与注册
- 支持手动为相关元素(例如
物料
和工序
等)进行标识码注册与解析 - 支持标识解析可视化,根据当前进度和数据实时显示重要信息到看板中
- 实训模式和考试模式下支持模拟标识注册与解析
方案展示
基于布局规划
和沙盒仿真
的组合展示场景,向用户展示方案的设计,过程与验证结果
虚实联动
- 手动控制
AGV
或机械臂
等设备 - 已支持
Lancer.AGV
可手动控制小车移动 - 手动编辑机械臂角度信息,在没有示教器的情况下进行手动演示
- 可手动编辑并发起相关信号,例如亮灯,单片机信号以及自定义指令等
多终端实时同步场景
PC客户端
进行布局规划,Mixed Reality
客户端(例如AR
)可直接在现场看到设备规划的位置和生产路线- 虚拟化生产过程,用户可通过
手机AR
或者AR眼睛
在现场预览生产过程并对过程进行评估AGV
夹起物料
放入装配单元
AGV
向装配单元
提供物料
装配单元
进行虚拟化装配AGV
从装配单元
取走产品,并放入交付单元
所有客户端
可对现实坐标进行标记(文字消息
图像消息
)- 标记需要改进的工序或移动的位置
- 标记用户希望的生产路线
数据查询
- 可快速查询数据库和记录,例如工单数据和异常记录
- 开发者模式下,可通过自定义数据库查询语句
- 具有完整的权限体系,用户模式下仅可查询部分记录,开发者模式下通过
数字签名
或电子令牌
查询所有记录
智能诊断
- 基于
Lancer.SCADA
提供的数据,自动分析重要数据的值并返回异常和诊断数据 - 可通过
WebApi
接口下发异常 - 接入
微信
和E-Mail
,异常
诊断报告
等日常维护数据将自动推送给相关人员微信
将通过公众号推送工单的方式推送数据E-Mail
通过自建邮箱服务器推送数据
- 智能诊断建议
- 在无法自动解决异常时,分析并提供相关的操作建议和解决方式建议
- 异常解决后,可快速输入异常解决方式,当异常再次发生时,可快速自动解决或快速提供建议
功能清单
以下的大多数功能都正在从Unity
移植到Godot
中
- 基于
Lancer.SCADA
的基本数据请求服务WebApi/GetInfos
——请求json,处理json嵌套,向内部提交数据 - 基于
Lancer.SCADA
的基本的角度和位置同步 - 基于
AI
算法的零延迟同步 - 基于
硬件本身的api
提供的零延迟同步 - 基于
Lancer.SCADA
的装配过程同步 - 基于
ObjectMatcher
的装配过程同步——Lancer.SCADA
没有提供的数据,通过匹配关键词的方式对数据进行分析和匹配,计算出当前的物料情况 ObjectMatcher
——关键词匹配引擎,通过分析数据,得到对应的最接近的结果- 全平台通用网络通讯接口(基于KCP的基本网络服务)
NetProvider
NetClient
NetServer
- 基于
Camera3D
的虚拟相机服务观察场景
例如移动视角
拖动视角
缩放视角
保存与加载预设视角
Android
支持WebGL
支持依赖注入
——已接入Microsoft.Extension.DependencyInjection
数据库支持
——通过EntityFrameworkCore
接入数据库离线回放
——录制Lancer.SCADA
返回的数据,在线回放
——基于WebDAB
同步云端的录制数据场景编辑器
——拖动预制件到场景中,完成组合场景,可用于对现场规划进行三维浏览和布局评估网络场景
——多个平台和客户端同步场景,例如在PC上更改场景,在Mixed Reality
中可实时看到场景的更改自诊断服务
——通过解析数据,找到空值
或null
的数据并向指定接口(例如微信推送
数据库日志
)提交异常微信推送服务
——完成申请微信公众号后接入E-Mail推送服务
——通过宝塔邮局
推送文件打包服务
——保存生产回放和其他数据,都是通过该服务进行读取和写入的环境扫描
——通过对现场环境进行三维扫描和重建,得到最接近和还原的三维场景- 基于HTML或类HTML的
用户界面框架
——统一技术栈,使用html编写用户界面,例如Html
和Unity.UI Toolkit
的关系 标识解析
——支持手动注册与解析标识实训平台
——提供线上教学线下考试的服务
Getting Started 使用指南
所有注释和指南都包括在代码中,用例正在编写中
基本设置
你需要在项目设置
自动加载
中添加一个挂载BITAppForGodot
的节点
然后就OK了
依赖注入
基于Microsoft.Extensions.DependencyInjection
的依赖注入服务
用例:
注册服务
public interface IService{}
public class MyService:Node,IService
{
public MyService()
{
//注入服务
BITApp.ServiceCollection.AddSingleton<IService>(this);
}
}
注入服务
初始化加载(可能遇到服务还没注入的情况)
public class MyService:Node
{
public override void _Ready()
{
var myService = BITApp.ServiceProvider.GetService<IService>();
}
}
基于封装的懒加载
public class MyService:Node
{
//声明懒加载服务
private readonly ServiceLoader<IService> myService=new();
public override void _Process(double delta)
{
//如果服务未加载,则跳过执行
if(myService.Loaded is false)return;
//获取服务
var _myService = myService.Value;
//执行
_myService.DoSomething();
}
}
实体,数据与系统的结构
Root/场景
Service
\System
处理逻辑和数据的服务或系统
RotationService
获取数据并应用角度的服务
Entity
存放数据的基本实体
RotationComponent
存放数据的组件,例如角度偏移Offset
和角度权重Weight
等数据
创建基本组件
组件需要继承自EntityComponent
或者IEntityComponent
,这样Entity
才能识别并注册组件
//基本的角度组件
/// <summary>
/// ECS中iFactory.Rotation的角度组件
/// </summary>
public partial class RotationComponent : EntityComponent
{
/// <summary>
/// 获取角度的路径
/// </summary>
[Export] public string Path { get; private set; }
/// <summary>
/// 角度的绝对权重,例如90* (0,0,1) = 0,0,90
/// </summary>
[Export] public Vector3 Weight { get; private set; }
/// <summary>
/// 角度的相对偏移
/// </summary>
[Export] public Vector3 Offset { get; private set; }
/// <summary>
/// 默认角度的缓存
/// </summary>
public Vector3 OriginalEuler { get; private set; }
public override void _Ready()
{
//保存默认角度
OriginalEuler = Rotation;
}
}
创建服务
基于场景的服务,可直接放入场景中的节点即可
基于全局的服务,可在Godot.ProjectSettings.AutoLoad中添加自动加载
非ECS服务
public partial class RotationService:Node
{
//在构造函数中注入依赖
public ApplyRotationService()
{
BITApp.ServiceCollection.AddSingleton(this);
}
//非基于ECS的注册方式,例如Node在_Ready回调中调用该方法注册
public static void Register(IObj obj);
//基于非ECS的注册方式,例如Node在Dispose方法中调用该方法注销
public static void UnRegister(IObj obj)
//通常情况下,Register和UnRegister最好使用Queue作为队列的方式注册和注销元素,而非List<T>.Add和List<T>.Remove
//使用消息队列可以解决异步中动态注册和注销导致队列被更改的问题
public override _Process(double delta)
{
//在这里遍历已注册的元素,并
foreach(var element in registriedElement)
{
//你的Code,不,是你的Code
element.Rotation = new(0,1,0);
}
}
}
基于ECS的服务(System)
目前IEntitiesService
的实例为GodotEntitiesService
public partial class RotationService:Node
{
//在构造函数中注入依赖
public ApplyRotationService()
{
BITApp.ServiceCollection.AddSingleton(this);
}
public override _Process(double delta)
{
//遍历所有包含RotationComponent的Entity
foreach(var entity in EntitiesManager.Query<RotationComponent>())
{
//或者RotationComponent组件
if(entity.TryGetComponent<RotationComponent>(out var rotationComponent)
{
//获取该组件的角度
var angle = //你的Code
//应用组件计算后的角度
rotationComponent.Rotation = angle * rotationComponent.Weight;
}
}
}
}
配置UI
首先你需要确保基于Control
节点的UXService
存在与项目设置
中的自动加载
中
创建UI面板
接下来,创建一个新的类,继承自IUXPanel
或者直接为UI面板的节点添加UXPanel
就完成了UI的基本配置
UXService
是基于消息队列的,你可以从多线程中添加队列
UXService
支持Return
,例如:
//进入提示面板
UXService.Entry<Alert>();
//返回到当前面板
UXService.Return();
如何进入某个UI面板?
在脚本中调用
UXService.Entry(this as IUXPanel);
或者在信号中连接面板
UXPanel.Open();
自动加载配置文件
你需要手动在场景中添加节点Exec
并配置好json
文件的相对路径,例如:Mods/EIPC/appsettings.json
默认情况下,都会加载项目根目录下的appsettings.json
或者可以手动加载:
DataParser.Set(json);
所有基本的json类型都会加载到全局变量Data
中
获取和监听配置文件
//获取配置(全局变量)
Data.Get<T>(string:key);
//获取单个配置
Data.Get<T>();
//监听变量
Data.AddListener<T>("MyEvent",MyCallback);
void MyCallaback(T value);
//设置变量
Data.Invoke<T>("MyEvent",value);
基于UniTask的异步与多线程使用方式
原理就是在处理数据时切换到线程池,并在处理完成后返回主线程 这里涉及到
//处理任务之前的准备,例如
//创建计时器,计算任务耗时
Stopwatch stopwatch = new();
stopwatch.Start();
//切换到任务池(默认为线程池)
await UniTask.SwitchToTaskPool();
//在这里处理你的复杂任务,例如:
DiggingBitcoin();
CrackWifiPassword();
RmRf();
//在完成任务后,切换回主线程
try
{
//切换回主线程的同时,应该添加CancellationToken
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext,
cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
//任务取消后应该怎么处理,比如回滚数据
return;
}
//完成任务后,打印出任务耗时时间
Console.WriteLine($"该任务耗时:{stopwatch.ElapsedMilliseconds}ms");
怎么取消任务
在创建await任务时,添加CancellationToken
通常CancellationToken是这么构成的
//声明一个CancellationTokenSource
private CancellationTokenSource cancellationTokenSource;
public override void _Ready()
{
//创建新的CancellationTokenSource
cancellationTokenSource = new CancellationTokenSource();
}
public override void _ExitTree()
{
//取消任务
cancellationTokenSource.Cancel();
}
public override void _Process()
{
//如果任务已取消,抛出任务取消的异常
cancellationTokenSource.Token.ThrowIfCancellationRequested();
//用try catch捕获取消异常
try
{
//等待某个任务,并添加CancellationToken
await SomeAsync(cancellationTokenSource.Token);
}catch(OperationCanceledException)
{
//任务已取消,你需要做些什么,比如回滚数据
}
}