Go to file
CortexCore e27cce2ac3 调整了模板 2023-07-17 04:10:14 +08:00
Artists 调整了模板 2023-07-17 04:10:14 +08:00
BITKit 调整了模板 2023-07-17 04:10:14 +08:00
EXE 更新了生产过程 2023-07-05 10:20:08 +08:00
Mods 调整了模板 2023-07-17 04:10:14 +08:00
ReadMe/工业互联网标识解析与注册 调整了模板 2023-07-17 04:10:14 +08:00
Temp 添加了部分界面 2023-07-08 00:02:32 +08:00
addons 调整了模板 2023-07-17 04:10:14 +08:00
android read me 2023-06-15 21:52:13 +08:00
.gitattributes Init 2023-06-12 15:51:41 +08:00
.gitignore Init 2023-06-12 15:51:41 +08:00
README.md Breakpoint 2023-07-04 04:08:18 +08:00
iFactory.csproj 提交更新 2023-07-12 15:27:27 +08:00
iFactory.csproj.old 添加了部分界面 2023-07-08 00:02:32 +08:00
iFactory.sln 添加了标识查询 2023-07-03 02:34:01 +08:00
icon.svg readme 2023-06-19 00:41:44 +08:00
icon.svg.import Init 2023-06-12 15:51:41 +08:00
project.godot 调整了模板 2023-07-17 04:10:14 +08:00

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 EditorRuntime模式,可以在编辑器或运行时编辑行为
  • 基于行为树,你可以让EntitySignal执行各种各样的操作,包括且不限于:
    • 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编写用户界面,例如HtmlUnity.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)
	{
		//任务已取消,你需要做些什么,比如回滚数据
	}
}