GaiaX开源解读 | 表达式作为逻辑动态化的基础,我们是如何设计的
GaiaX跨端模板引擎,是在阿里优酷、淘票票、大麦内广泛使用的Native动态化方案,其核心优势是性能、稳定和易用。本系列文章《GaiaX开源解读》,带大家看看过去三年GaiaX的发展过程。
前言
GaiaX【https://github.com/alibaba/GaiaX】是由优酷应用中心技术团队研发的一款跨端高性能渲染引擎,目前该方案已经向技术社区开源,其核心目标是解决多端卡片化UI组件的研发效能问题。
先看一下GaiaX构建的总体链路:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vZwRQ7gE-1676431808555)(/img/bVc6nzq)]](https://img-blog.csdnimg.cn/215a6a5dde514bc7998bc7eabe129865.png)
图 - GaiaX构建总体链路
可以看到,在 GaiaX 中从结构化的模板文件到端渲染,经过了模板解析、节点树构建、视图树构建、表达式运算、扩展交互等步骤。
本文主要将主要从表达式的方案设计、语法树构建以及表达式的跨平台实现这几个方面对表达式运算这个模块进行介绍。
表达式介绍
在GaiaX模板的构建过程中,表达式是较为重要的一个模块,其主要的能力是对数据进行取值或运算,并绑定到对应的视图中,它作为逻辑动态化的基础,承接着上层业务对视图数据绑定的具体描述,视图的数据变化和具体表述均由表达式作为纽带。
{"data":{"gx-expression-value":{"value": "$data.text"},"gx-expression-calculate":{"value": "1+2*3%3+$data.num"},"gx-expression-function":{"value": "Size($data.array)"}}
}
在表达式中,我们支持取值运算、函数计算以及表达式运算的能力,为了实现双端一致性,我们使用了C++作为表达式的底层开发语言。
技术方案设计
表达式的解析过程

图 - 表达式各端解析流程
表达式的解析过程其实就是编译的过程,编译即把通过源语言编写成的源程序转化为目标程序的过程,通常编译的完整流程是把源程序通过词法分析、语法分析、语义分析、中间代码生成等步骤生成计算机可以理解的机器语言,考虑到GaiaX的表达式的作用范围,我们只考虑前半部分,即词法分析、语法分析以及语义分析。
我们先通过一个简单的流程图,了解一下表达式的整个解析流程:
词法分析
词法分析是对表达式输入的字符流进行扫描,根据对应的构词规则对每个词进行划分和分类,将其组成有意义的词素序列。
语法分析
语法分析是在词法分析的基础上,将词法分析生成的词素组成各类语法短语,并判断表达式在结构上是否正确,最终构建出符合语法规则的语法树以及对应的符号表。
语义分析
语义分析则是结合语法分析中生成的语法树和符号表,对输入的表达式的语义规则进行分析,判断语义是否符合规则。
在GaiaX表达式中,我们使用LR(1)文法进行语法分析并构建语法树,并将语法分析和语义分析结合起来,即在语法树的构建过程中,判断表达式是否符合语义规则,并在语法树构建完成后返回最终的结果。
语法树的构建 - LR(1)文法
上文说到表达式的解析过程,其实就是一个编译的过程。在GaiaX表达式方案中,我们采用了编译原理中经典的LR(1)文法作为表达式语法树的构建方案。
LR(k)分析方法是1965年Knuth提出的,括号中的k表示向右查看输入事符号的个数。这种方法比起自顶向下的LL(k)分析方法和自底向上的优先分析方法对文法的限制要少得多,也就是说,对于大多数用无二义性上下文无关文法描述的语有都可以用相定的LR分析器进行识别,而且这种方法还具有分析速度快,能准确即时地指出出错位置的特点。
LR(1)文法
LR(1)文法的意思是从左向右扫描,最右推导,往前多看一个字符。
| 字符 | 含义 |
|---|---|
| L | 从左到右扫描输入串 |
| R | 利用最右分析方法来识别句子 |
| (1) | 向右展望1个字符 |
在具体介绍LR(1)分析法之前,我们需要先了解两个基本概念:
| 名称 | 含义 |
|---|---|
| 推导 | 一个字符串x通过一个规则变换成另一个字符串y,称为x推导出y,即x->y |
| 规约 | 与推导相反,语法规则为x->y时,由y规约到x即为规约 |
GaiaX表达式语法树构建流程
LR(1)的分析过程是规约的过程,我们以GaiaX表达式中的运算语法为例,深入了解GaiaX表达式语法树的构建流程。
在GaiaX表达式中,四则运算的语法如下:
S -> S + E #加|S - E #减|E
E -> E * num #乘|E / num #除|num
假设我们有表达式:a*b+c
在这个表达式中,我们可以看到,乘法的优先级是要大于加法的,那么在LR(1)文法中,我们应该怎么去撰写我们的语法,使得乘法的优先级要大于加法呢?
在前文中,我们了解到,推导是从上往下一直推导出整个式子,而LR(1)文法是规约的过程,规约与推导相反,是从下往上,从底部一直推到到根部节点的过程,根据这点,我们可以了解到,在LR(1)文法中,语法的推导层级越深,那么就会越先被运算,它的优先级就越高。
所以在GaiaX的四则运算语法中,我们让乘除法的层级在加减法之下,从而实现乘除法的优先级大于加减法的优先级。
语法树的构建流程
在确认了具体的语法之后,我们就可以根据语法去构建具体的语法树了,我们先来看一下语法树的构建流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLZeGZcM-1676431808557)(/img/bVc6nAj)]
图 - 语法树构建流程
在初始化以及词法分析流程后,得到了分析表和词素序列,接下来我们通过不断把词素入栈并匹配判断是否可以规约,来构建最终的语法树。
示例的语法树构建流程如下:
| 步骤 | 栈 | 输入 | 说明 |
|---|---|---|---|
| 1 | null | num*num+num | 表达式输入 |
| 2 | num | *num+num | 移进 |
| 3 | num* | num+num | 移进 |
| 4 | E | +num | 移进,num*num规约为E |
| 5 | E+ | num | 移进 |
| 6 | S | null | 移进,E+num规约为S,分析成功 |
在一步步移进和规约的过程中,当规约到最后的根结点时,便生成了一棵完整的语法树,如下图所示,可以看到,乘法的优先级更高,所以离根节点越远,加法的优先级较乘法低,离根节点越近。

图 - 示例语法树
跨平台实现方案设计
在前文中,我们简要介绍了GaiaX表达式各端调用的链路流程,我们了解到,表达式的计算能力可以被Android、iOS端所调用,接下来我们来了解一下GaiaX表达式跨平台能力的实现。
C++层调用各端取值与方法函数
在跨平台方案中,主要涉及两种情况:
第一种情况是双端调用C++层的方法,在iOS端,我们可以直接通过添加头文件引用直接调用C++函数;而在Android端,我们则需要使用中间层JNI来间接调用C++层的代码。
第二种情况则是C++层调用双端实现的方法,相较于端侧调用C++的代码,由C++层调用端侧实现的方法会更为复杂,我们先来看一下C++层调用端侧代码的大致链路:

图 - 双端取值和函数方法的调用与实现
由流程图我们可以看出,C++层调用Android以及iOS端的数据获取和函数调用方法,都是需要双端进行实现的,要达到双端实现C++层能够调用的方法,我们需要先在C++层定义GXAnalyze类并提供对应的方法虚函数。
class GXAnalyze {public://获取数据 $virtual long getSourceValue(string valuePath, void* source) = 0;//获取方法 Functionvirtual longgetFunctionValue(string funName, long *paramPointers, int paramsSize, void* source) = 0;
}
C++调用Android端方法的实现
在Android端中,为了实现C++提供的虚函数,并返回给C++层调用,我们创建了GXAnalyzeAndroid类,并在类中创建出对应的取值和方法调用接口。
class GXAnalyzeAndroid {// 计算逻辑的扩展interface IComputeExtend {// Computed value expressionfun computeValueExpression(valuePath: String, source: Any?): Long// Computed function expressionfun computeFunctionExpression(functionName: String, params: LongArray): Long}init {initNative(this) //初始化表达式并存储GXAnalyzeAndroid对象}
}
在JNI层,我们实现了两个方法,分别是getSourceValueFromJava取值方法调用以及getFunctionValueFromJava函数方法调用,以getSourceValueFromJava为例,我们通过获取在initNative时存储的GXAnalyzeAndroid对象,通过CallLongMethod调用其实现的取值方法。
object_in:initNative时存储的GXAnalyzeAndroid对象 static jlong getSourceValueFromJava(string valuePath, jobject source, jobject object_in) {JNIEnv *env = getJNIEnv(); //获取环境env变量if (env != nullptr) {jclass clazz;clazz = env->GetObjectClass(object_in);jfieldID analyze_fieldID = env->GetFieldID(clazz, "computeExtend","Lcom/expressionDir/GXAnalyzeAndroid$IComputeExtend;");jobject jobject = env->GetObjectField(object_in, analyze_fieldID);jclass analyzeJni = env->GetObjectClass(jobject);jmethodID getArrId = env->GetMethodID(analyzeJni, "computeValueExpression","(Ljava/lang/String;Ljava/lang/Object;)J");jlong res = env->CallLongMethod(jobject, getArrId,str2jstring(env, valuePath.c_str()),source);env->DeleteLocalRef(clazz);env->DeleteLocalRef(jobject);env->DeleteLocalRef(analyzeJni);return res;}return 0L;
}
需要注意的是,仅仅实现了JNI调用Java\Kotlin的方法还不足以实现在C++层调用Android端的代码,我们在JNI层在实现调用解析表达式的函数的同时,通过继承的方式,实现了GXAnalyze类的虚函数。
class GXJniAnalyze : public GXAnalyze {public:long getSourceValue(string valuePath, void *source) override {jobject dataSource = static_cast<jobject>(source);return getSourceValueFromJava(valuePath, dataSource, globalSelf);}
};
extern "C"
JNIEXPORT jlong JNICALL
Java_com_alibaba_gaiax_analyze_GXAnalyze_getResultNative(JNIEnv *env, jobject thiz, jobject self,jstring expression, jobject data) {GXJniAnalyze *jAnalyze = getJniAnalyze(env, self);long res = jAnalyze->getExpressionResult(jstring2str(env, expression), data);return (jlong) (res);
}
这样,我们在调用表达式解析的方法时,实际上调用的是继承自GXAnalyze并实现虚函数后的GXJniAnalyze里的getExpressionResult方法,在C++层,我们在调用取值或函数方法时,只需要使用this->getSourceValue(string,void*)就能调用在端侧实现了的虚函数,根据端侧的逻辑返回我们需要的结果。
C++调用iOS端方法的实现
在iOS端中,为了实现C++提供的虚函数,并返回给C++层调用,我们首先实现了GXAnalyzeBridge类,并在其中对取值以及函数调用方法进行了实现。
@interface GXAnalyzeBridge : NSObject- (long)getFunctionValue:(NSString *)funName paramPointers:(long *)paramPointers paramsSize:(int)paramsSize;- (long)getSourceValue:(NSString *)valuePath source:(id)source;@end
紧接着,我们创建出了GXAnalyze的继承类GXAnalyzeImpl,在类中,我们重写了函数以及取值调用方法,在方法中通过调用中间层GXAnalyzeBridge的具体实现方法,达到取值以及函数能力的实现。
class GXAnalyzeImpl: public GXAnalyze {public:
//解析取值
long getSourceValue(string valuePath, void* source);//解析方法
long getFunctionValue(string funName, long *paramPointers, int paramsSize, string source);};
最终,在C++层,我们在调用表达式的取值或函数方法时,实际上调用的是在iOS端已经实现了的继承类GXAnalyzeImpl里对应的方法。
统一数据类型
在GaiaX表达式中,会有端侧调用C++层的方法和C++层调用端侧这两种情况,但是各端的数据类型是不一致的,而且在表达式的计算过程中,每个数据的类型也是不一致的,为了能够实现一套数据类型,我们实现了GXValue数据类,在各端可以通过调用GXValue的多个数据创建方法创建对应类型的数据,作为结果返回即可。
class GXValue {
public:int64_t tag;int32_t int32; //Bool 1,0float float64; //Floatint64_t intNum; //longvoid *ptr; //Array,Mapchar *str; //String
};
成果展示

图 - GaiaStudio表达式编辑&运算
性能及稳定性保障
质量保障
由于采用了跨平台技术方案,因此稳定性保障是项目的重中之重。 在项目交付过程中,针对不同复杂度、取值类型进行了充分的单元测试用例设计,尽可能覆盖线上可能出现的各种边界异常情况。

图 - 单元测试用例
性能分析
由于技术方案底层由C++实现,因此基础性能表现是有保障的。
| 计算类型 | 表达式 | 耗时/次 |
|---|---|---|
| 单值 | 10000 | 0.017ms |
| 取值 | $data.xxx | 0.024ms |
| 取数据源 | $$ | 0.019ms |
| 数值运算 | 10%5 | 0.029ms |
| 三元表达式 | true ? 1 : 2 | 0.048ms |
| 函数计算 | Size(‘1000’) | 0.029ms |
| 复杂嵌套表达式 | $data.b % 5 > 2 ? $data.b % 5 : 1 | 0.060ms |
表 - Android端真机测试性能结果
总结
GaiaX表达式充分吸收了编译原理的精髓,通过跨平台技术方案从根本上保证了多端的一致性问题,为GaiaX在移动平台的落地提供了较高的可扩展性。目前来看,该方案在性能方面还有一定的优化空间,如规约算法、词法分析、数据结构等方面的优化,这也是我们后续重要的发力点。
跨端表达式方案目前已经在GaiaX开源项目(https://github.com/alibaba/GaiaX)中发布,非常欢迎广大技术爱好者一起探讨交流。
GaiaX开源解读系列文章
系列文章持续更新中,请各位拭目以待
• 《GaiaX开源解读 | 基于优酷业务特色的跨平台技术》
• 《GaiaX开源解读 | 跨端动态化模板引擎详解,看完你也能写一个》
• 《GaiaX开源解读 | 给Stretch(Rust编写的Flexbox布局引擎)新增特性,我掉了好多头发》
• 《GaiaX开源解读 | 表达式作为逻辑动态化的基础,我们是如何设计的》
• 《GaiaX开源解读 | 向经典致敬 ReactNaitve与GaiaX渲染核心技术分析》
• 《GaiaX开源解读 | 为了保障双端一致性,我们做了哪些努力》
• 《GaiaX开源解读 | 一条龙的模板研发体系,你不来看看么》
相关文章:
GaiaX开源解读 | 表达式作为逻辑动态化的基础,我们是如何设计的
GaiaX跨端模板引擎,是在阿里优酷、淘票票、大麦内广泛使用的Native动态化方案,其核心优势是性能、稳定和易用。本系列文章《GaiaX开源解读》,带大家看看过去三年GaiaX的发展过程。 前言 GaiaX【https://github.com/alibaba/GaiaX】是由优酷应…...
python中adb shell相关操作
1、python 实现adb交互,进入adb shell后,如何再发送消息 os.popen("adb -s 192.168.1.100:5555 shell \"dmesg > /data/dmesg.log\"")进入进入adb shell,在执行 dmesg > /data/dmesg.log 2、python(或BAT脚本)自…...
python 之 资源使用与控制 resource模块
一、背景 2021年做可信计算时,由于甲方给的CPU利用率不能不能超过20%; 目的:我们的程序部署甲方服务器上不能阻碍其甲方服务的正常运行 我们的程序在CPU超过20%时,可以休眠几秒后继续运行 此时需要检测控制服务器的CPU资源使用信…...
蓝库云|8项关键让你看透企业「数字转型」,零代码是惊喜
各行各业都要面对的多方竞争力及不断上涨的经营成本,以及随着时代的发展,有不少企业纷纷推动数字化转型,考虑藉着应用现代化的数据和科技工具的结合,协助企业创造新的营运模式及收入来源,以提升自动化效率、优化客户体…...
(五)、编辑页面-发布长文-富文本编辑【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】
1,edit页面 1.1 新建edit页面 1.2 从本地相册选择图片或使用相机拍照。 uni.chooseImage(OBJECT) 1.3 直接上传文件到云存储。 uploadFile(Object object) 1.4 从富文本编辑器获取编辑器内容 editorContext.getContents(OBJECT) 首页富文本编辑器初始化完成时…...
你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式
你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式😎前言🙌大小端介绍🙌什么大端小端呢?:大小端存储的标准定义:大端和小端存在的意义经典的面试题目🙌总结撒花💞&a…...
从零开始的数模(二十六)单因素方差分析
目录 一、概念 1.1相关概念 1.2用途 1.3数据要求:独立性/正态性/方差齐性 1.4步骤 编辑1.5专业名词 二、基于python的单因素方差分析 2.2单因素方差分析的作用 一、概念 1.1相关概念 单因素方差分析是一种常用的统计分析方法,它用于比较一个因…...
C++变量类型
目录 一、c中的变量定义 二、c中的变量声明 三、c中的左值和右值 一、c中的变量定义 变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。 变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示&…...
win10 安装 vs2015(社区版本)以及opencv-4.5.5
一、下载vs2015以及opencv-4.5.5从https://msdn.itellyou.cn/ 网站下载vs2015(社区版本)从https://opencv.org/releases/网站下载opencv-4.5.5二、安装vs2015和opencv-4.5.5解压后双击exe安装文件,完成安装(默认)双击下…...
867. 转置矩阵
给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。示例 1:输入:matrix [[1,2,3],[4,5,6],[7,8,9]]输出:[[1,4,7],[2,5,8],[3,6,9]]示例 2&a…...
Datawahle组队学习——妙趣横生大数据 Day1
妙趣横生大数据 Day1[妙趣横生大数据 Juicy Big Data](https://datawhalechina.github.io/juicy-bigdata/#/?id妙趣横生大数据-juicy-big-data)一、大数据概述大数据——第三次信息化浪潮大数据概念大数据应用大数据关键技术二、Hadoop背景介绍特性项目架构实验1. 准备工作2. …...
网友眼中越老越吃香的行业,果然是风向变了!
越老越吃香的行业,一直都是被热议的话题。对于年轻人来说,找到一个适合自己的并且具有前景的工作,不是一件容易的事情。 最近,看到有人在平台上问相关的问题,本着认真看一看的态度点进去,却差点被热评第一…...
为什么时间序列预测这么难?本文将给你答案
机器学习和深度学习已越来越多应用在时序预测中。ARIMA 或指数平滑等经典预测方法正在被 XGBoost、高斯过程或深度学习等机器学习回归算法所取代。 尽管时序模型越来越复杂,但人们对时序模型的性能表示怀疑。有研究表明,复杂的时序模型并不一定会比时序…...
STC15系列单片机通过串口多字节数据读写EEPROM操作
STC15系列单片机通过串口多字节数据读写EEPROM操作📌相关篇《STC15系列单片机EEPROM读写示例》 ⛳手册勘误信息注意事项 ⚡在手册上面描述STC15F2K60S2及STC15L2K60S2系列单片机内部EEPROM还可以用MOVC指令读,但此时首地址不再是0000H,而是程…...
计算机网络-ip数据报
在图中,网络层包含了四种协议:ARP、IP、ICMP、IGMP,由上下关系表明,ARP为IP协议服务,IP为ICMP和IGMP服务。 IP数据报格式 此处不区分数据报和分组的概念:当数据部分过长时,将数据部分拆分&…...
从零开始学C
以下是 该如何学习C语言的【思维导图】以及部分重点知识点的【博客链接】。其实C语言并不难,难的是没有人去教,没有耐心去学。不知道从哪下手学习,我将C的知识点做成一个思维导图,以供迷茫的小白参考,哪里不会…...
【云原生】手把手带你从零开始搭建kubernetes最新版本实战
文章目录前言一. 实验环境二. k8s 的介绍三 . k8s的安装3.1 搭建实验环境3.1.1 硬件层面的要求3.1.2 软件层面环境配置3.2 docker的安装3.2.1 搭建docker3.2.2 部署 cri-dockerd3.3 部署k8s3.3.1 配置添加阿里云的yum源3.3.2 安装kubeadm kubelet kubectl3.3.3 k8s-master节点初…...
trivy os软件包扫描原理分析
具体可以基于之前的博客来做 基于trivy获取基础镜像 参数修改一下: cliOpt.ListAllPkgs true 结果中会带有如下格式的结果: "Results":[{"Target":"192.168.1.94:443/test22/centos:7 (centos 7.9.2009)","Clas…...
算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ
算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物…...
Java 基础(1)—泛型简单使用
一、泛型定义及作用 泛型是一种编程机制,允许在编写代码时使用参数化类型,以在编译时实现类型安全。 以下是泛型作用: 增强代码可读性和可维护性:通过在代码中使用泛型参数,可以使代码更清晰、更具有可读性和可维护性…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
