Motivation
总结一下最近探索Unity进行数字孪生的一些收获和体会。也欢迎各位小伙伴私信交流。
进展
先放一下进展效果图,嘿嘿。
有三条线,F1, F2分别是两个压力传感器,利用Arduino板子实时读取数据,来模拟在两个位置的受力情况。第三条线是最大位移曲线,实时读取网格当中最大的位移变化值。网格的颜色和空间位置会随着位移应力云图而发生视角上的空间位置的变化。其中数据是利用有限元软件提前算好放在数据库当中的,只是为了做一个demo演示,暂时没有用到代理模型。
过程当中遇到的问题
1、模型网格划分
当时为了3D打印实物,如下图,对模型进行了一点的简化,同时为了满足打印需要,管子中间太薄了,不得不将管子进行加厚,所以重新修改模型,并且重新划分网格。
可能是由于自己Abaqus的划分网格的技术不到家,Abaqus自动划分的网格质量太差,就没办法计算。或许之后得专门学一下Abaqus的划分网格技术。
不得以,只能花钱在淘宝请专业的工程师帮忙划分网格。
然而,网格划分的质量到底是不错,也能够计算了。但在Unity当中重构模型则发生了Bug, 哭死。这是因为工程师在用其他软件建网格的时候,修改和删减了模型的网格编号,造成类似节点编号不连续的情况:
在Unity当中网格节点使用列表的数据类型来存储的,所以必须得转化为连续的节点。但麻烦的是,单元构成的节点编号也需要变动。
有尝试用字典映射的方式重新确定单元的节点位置编号,但结果是:
这叫重建了,但又没有重建完全… 之后有时间看看再研究一下是怎么回事。
总结一下就是,当网格经过删减而在inp文件当中序号变得不连续的时候,需要千万小心!!!。
后来还是请师弟帮忙重新划分了一个模型,虽然网格质量一般般,但是Abaqus能顺利跑上了。
2、Unity模型和单片机的实时通讯
拿到板子和压力传感器之后,就是下图,调试好单片机,便需要让它连接Unity进行实时通讯。这里遇到的问题是单片机的读数是8位字节,所以需要编写代码对单片机进行的读数进行解析。核心代码放出来:
#region 按单个字节发送处理信息,不能接收中文
#endregion
#region 按字节数组发送处理信息,信息缺失
byte[] buffer = new byte[1024];
// int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
// 使用 StringBuilder 存储读取的字节数据
StringBuilder dataBuilder = new StringBuilder();
while (true)
{
// 读取单个字节
int byteRead = sp.ReadByte();
// 如果读取到分隔符,停止读取
if (byteRead == ';')
{
break;
}
// 将字节转换为字符并追加到 StringBuilder
char character = (char)byteRead;
dataBuilder.Append(character);
}
// 获取最终的字符串数据
string data = dataBuilder.ToString();
// // 处理读取到的数据
// Debug.Log("Read data: " + data);
// 将串口数据分割成数组
string[] dataValues = data.Split(",");
// 提取第一个数字和第二个数字
if (dataValues.Length >=2 )
{
//提取第一个数字
float FirstNumber;
if (float.TryParse(dataValues[0], out FirstNumber))
{
F1.text = FirstNumber.ToString();
// // 处理第一个数字
// Debug.Log($"第一个数字是:{FirstNumber}");
// 提取第二个数字
float SecondNumber;
if (float.TryParse(dataValues[1], out SecondNumber))
{
F2.text = SecondNumber.ToString();
// // 处理第二个数字
// Debug.Log($"第二个数字是:{SecondNumber}");
}
}
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
3、模型随传感器的读数实时显示位移云图和变形情况
由于模型建立得比较粗糙,网格节点数也没有很多,也就几万个节点,所以干脆就直接计算有限元两种情况的数据,F1 从 0 - 1000, 间隔20 ,和 F2 从0-1000, 间隔15,连续跑了一天的数据,大约有几个g的数据,按规则写好表名,全部放在数据库当中。一开始还想写一个线性插值的函数,但后来发现完全没必要,直接编写算法获取F1 和 F2的传感器数值,然后取数据库当中比较接近的点就行,这样展示效果也还行。
之所以做一下模型的位移动态显示是因为只是位移云图的变化有点太单调,就想着怎么做可以更炫酷一些。其实这个也很简单,就直接提取模型的网格节点,将其中的节点空间位置加上有限元算出来的x y z三个方向上的位移。另外,函数不能写在Update函数当中,这个函数刷新的帧率太快了,特别吃电脑内存。直接新开一个协程就可以,将函数执行的时间调在0.3s左右就可以。
后续持续更新中…(之后应该就是年后了,毕竟快放假了)