ROS2 xacro 保姆级使用教程!零基础从入门到精通
目录
5.5 visual、collision、inertial 的区别
目录
前言
本篇是《松灵 ROS2》课程中关于 LIMO 机器人模型描述 的学习笔记,主要围绕一个简化版 LIMO 四轮 xacro 文件展开。
通过本节内容,可以理解:
- ROS2 中机器人模型文件的基本结构;
- URDF 和 xacro 的关系;
- link、joint、visual、collision、inertial 的作用;
- 如何通过 xacro:macro 复用轮子模型;
- LIMO 四个轮子在坐标系中的安装位置。
这个例子虽然是一个简化模型,但它已经包含了机器人建模中非常核心的内容。
本篇内容延续了【松灵ROS2专栏·第 3 讲】ROS的URDF编写和Gazebo仿真控制,链接如下:
一、本章核心知识点
1.1 本节主要学习内容
本节主要学习以下内容:
- xacro 文件的基本写法。
- robot 根标签的作用。
- xacro:property 参数定义方法。
- base_link 底盘建模方法。
- inertial、visual、collision 三部分的区别。
- 使用 xacro:macro 定义轮子模板。
- 通过宏调用生成四个轮子。
- 使用命令将 xacro 转换为 URDF。
1.2 URDF 和 xacro 的关系
在 ROS2 中,机器人模型通常使用 URDF 描述。
URDF 可以描述机器人的:
| 内容 | 作用 |
|---|---|
| link | 机器人刚体部件,例如底盘、轮子、雷达 |
| joint | 两个 link 之间的连接关系 |
| visual | 模型在 RViz / Gazebo 中显示的样子 |
| collision | 仿真中用于碰撞检测的形状 |
| inertial | 质量、惯性矩阵等物理属性 |
但是,如果直接写 URDF,当机器人有很多重复结构时会非常麻烦。
例如四个轮子,结构几乎一样,只是名称和位置不同。
如果直接写 URDF,就要重复写四份类似代码。
所以实际开发中经常使用 xacro。
xacro 可以理解为:
带变量、宏和参数复用能力的 URDF。
常见 xacro 语法如下:
| xacro 语法 | 作用 |
|---|---|
| xacro:property | 定义变量 |
| xacro:macro | 定义宏模板 |
| ${变量名} | 引用变量 |
| <xacro:xxx/> | 调用宏 |
二、xacro 文件结构解析
2.1 整体结构
这个文件整体可以分成四个部分:
| 部分 | 作用 |
|---|---|
| XML 与 robot 根标签 | 声明这是一个机器人模型文件 |
| property 参数定义 | 定义底盘尺寸、轮子半径、轮子质量等参数 |
| base_link 底盘 | 定义机器人主体底盘 |
| limo_wheel 宏 | 定义轮子模板,并调用四次生成四个轮子 |
整体逻辑可以理解为:
- 先定义机器人名称。
- 再定义一些全局参数。
- 创建一个底盘 base_link。
- 创建一个轮子宏模板。
- 调用四次模板,生成左前、右前、左后、右后四个轮子。
2.2 为什么要用宏
如果不用宏,四个轮子需要重复写四份代码。
使用 xacro:macro 后,只需要定义一次轮子模板:
<xacro:macro name="limo_wheel" params="prefix xyz rpy">
然后通过不同参数调用四次:
<xacro:limo_wheel prefix="front_left" xyz="0.16 0.18 -0.06" rpy="0 0 0"/>
这样做的好处是:
| 好处 | 说明 |
|---|---|
| 减少重复代码 | 四个轮子共用一个模板 |
| 方便统一修改 | 修改轮子半径时只改一处 |
| 结构更清晰 | 每个轮子只需要关注名称和位置 |
| 不容易出错 | 避免复制粘贴导致 link 或 joint 重名 |
三、代码逐段讲解
3.1 完整代码
<?xml version="1.0"?>
<robot name="limo_simple_wheels" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- Basic dimensions. Adjust these to match your real robot. -->
<xacro:property name="base_length" value="0.45"/>
<xacro:property name="base_width" value="0.32"/>
<xacro:property name="base_height" value="0.12"/>
<xacro:property name="wheel_radius" value="0.06"/>
<xacro:property name="wheel_width" value="0.035"/>
<xacro:property name="wheel_mass" value="0.2"/>
<!-- A minimal base_link so the wheel joints have a parent link. -->
<link name="base_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="5.0"/>
<inertia ixx="0.05" ixy="0" ixz="0"
iyy="0.08" iyz="0"
izz="0.10"/>
</inertial>
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
<material name="base_gray">
<color rgba="0.45 0.45 0.45 1"/>
</material>
</visual>
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
</collision>
</link>
<!--
Wheel macro.
prefix: wheel name prefix, for example front_left
xyz: joint position relative to base_link
rpy: joint rotation relative to base_link
-->
<xacro:macro name="limo_wheel" params="prefix xyz rpy">
<link name="${prefix}_wheel_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="${wheel_mass}"/>
<inertia ixx="0.0002" ixy="0" ixz="0"
iyy="0.0004" iyz="0"
izz="0.0002"/>
</inertial>
<visual>
<!-- Cylinder's default axis is Z. Rotate it so the wheel axle is Y. -->
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
<material name="${prefix}_wheel_black">
<color rgba="0.02 0.02 0.02 1"/>
</material>
</visual>
<collision>
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
</collision>
</link>
<joint name="${prefix}_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="${prefix}_wheel_link"/>
<origin xyz="${xyz}" rpy="${rpy}"/>
<axis xyz="0 1 0"/>
</joint>
</xacro:macro>
<!-- Four wheel instances. Coordinate convention: X forward, Y left, Z up. -->
<xacro:limo_wheel prefix="front_left"
xyz="0.16 0.18 -0.06"
rpy="0 0 0"/>
<xacro:limo_wheel prefix="front_right"
xyz="0.16 -0.18 -0.06"
rpy="0 0 0"/>
<xacro:limo_wheel prefix="rear_left"
xyz="-0.16 0.18 -0.06"
rpy="0 0 0"/>
<xacro:limo_wheel prefix="rear_right"
xyz="-0.16 -0.18 -0.06"
rpy="0 0 0"/>
</robot>
3.2 XML 和 robot 根标签
代码开头是:
<?xml version="1.0"?>
表示当前文件是一个 XML 文件。
URDF 和 xacro 本质上都是 XML 格式,所以一般会在第一行声明 XML 版本。
接着是:
<robot name="limo_simple_wheels" xmlns:xacro="http://www.ros.org/wiki/xacro">
这里定义了整个机器人模型
其中:
name="limo_simple_wheels"
表示机器人模型名字叫 limo_simple_wheels。
而:
xmlns:xacro="http://www.ros.org/wiki/xacro"
表示启用 xacro 命名空间。
有了这一句,后面才能使用:
<xacro:property .../>
<xacro:macro ...>
<xacro:limo_wheel .../>
这些 xacro 语法。
3.3 参数定义 property
代码中定义了几个全局参数:
<xacro:property name="base_length" value="0.45"/>
<xacro:property name="base_width" value="0.32"/>
<xacro:property name="base_height" value="0.12"/>
<xacro:property name="wheel_radius" value="0.06"/>
<xacro:property name="wheel_width" value="0.035"/>
<xacro:property name="wheel_mass" value="0.2"/>
xacro:property 相当于定义变量。
例如:
<xacro:property name="wheel_radius" value="0.06"/>
可以理解为:
wheel_radius = 0.06
后面可以通过下面这种方式引用:
${wheel_radius}
这些参数的含义如下:
| 参数名 | 含义 | 当前值 |
|---|---|---|
| base_length | 底盘长度 | 0.45 m |
| base_width | 底盘宽度 | 0.32 m |
| base_height | 底盘高度 | 0.12 m |
| wheel_radius | 轮子半径 | 0.06 m |
| wheel_width | 轮子厚度 | 0.035 m |
| wheel_mass | 单个轮子质量 | 0.2 kg |
这里要注意,URDF / xacro 中长度单位一般按 米 理解,质量单位一般按 kg 理解。
3.4 base_link 底盘部分
底盘从下面代码开始:
<link name="base_link">
link 表示机器人中的一个刚体部件。
这里定义的是:
base_link
也就是机器人底盘主体。
在 ROS 机器人模型中,base_link 通常是最核心的参考坐标系。
很多部件,比如轮子、雷达、相机、IMU,都会通过 joint 连接到 base_link 或它的子 link 上。
1)base_link 的 inertial 惯性信息
代码如下:
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="5.0"/>
<inertia ixx="0.05" ixy="0" ixz="0"
iyy="0.08" iyz="0"
izz="0.10"/>
</inertial>
inertial 描述物体的物理惯性信息,主要用于 Gazebo 等仿真环境。
其中:
<origin xyz="0 0 0" rpy="0 0 0"/>
表示惯性中心的位置和姿态。
| 属性 | 含义 |
|---|---|
| xyz | 位置,分别对应 X、Y、Z |
| rpy | 姿态,分别对应 roll、pitch、yaw |
rpy 的含义是:
| 名称 | 含义 |
|---|---|
| roll | 绕 X 轴旋转 |
| pitch | 绕 Y 轴旋转 |
| yaw | 绕 Z 轴旋转 |
质量部分:
<mass value="5.0"/>
表示底盘质量是 5.0 kg。
惯性矩阵部分:
<inertia ixx="0.05" ixy="0" ixz="0" iyy="0.08" iyz="0" izz="0.10"/>
其中:
| 参数 | 含义 |
|---|---|
| ixx | 绕 X 轴的转动惯量 |
| iyy | 绕 Y 轴的转动惯量 |
| izz | 绕 Z 轴的转动惯量 |
| ixy、ixz、iyz | 惯性积,简化模型中通常写 0 |
这个示例中的惯性参数是简化值。
2)base_link 的 visual 可视化
代码如下:
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
<material name="base_gray">
<color rgba="0.45 0.45 0.45 1"/>
</material>
</visual>
visual 描述模型在 RViz 或 Gazebo 中显示出来的样子。
这里底盘使用的是长方体:
<box size="${base_length} ${base_width} ${base_height}"/>
变量展开后相当于:
<box size="0.45 0.32 0.12"/>
也就是:
| 尺寸 | 数值 |
|---|---|
| 长度 | 0.45 m |
| 宽度 | 0.32 m |
| 高度 | 0.12 m |
颜色部分如下:
<color rgba="0.45 0.45 0.45 1"/>
rgba 分别表示:
| 参数 | 含义 |
|---|---|
| r | 红色 |
| g | 绿色 |
| b | 蓝色 |
| a | 透明度 |
所以这里设置的是一个不透明的灰色底盘。
3)base_link 的 collision 碰撞体
代码如下:
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
</collision>
collision 描述的是碰撞检测使用的形状。
在仿真中,机器人和地面、障碍物是否发生碰撞,主要由 collision 决定。
这里 collision 和 visual 一样,都是一个长方体。
可以这样理解:
| 标签 | 作用 |
|---|---|
| visual | 给人看的模型 |
| collision | 给物理引擎计算碰撞用的模型 |
| inertial | 给物理引擎计算质量和惯性用的信息 |
实际项目中,visual 可以使用精细的 mesh 模型,而 collision 通常会简化成 box、cylinder、sphere 等简单几何体,这样仿真计算会更快。
3.4 轮子宏定义
轮子宏从这里开始:
<xacro:macro name="limo_wheel" params="prefix xyz rpy">
xacro:macro 表示定义一个宏,也就是模板。
其中:
name="limo_wheel"
表示宏的名字叫 limo_wheel。
后面可以通过下面方式调用:
<xacro:limo_wheel prefix="front_left" xyz="0.16 0.18 -0.06" rpy="0 0 0"/>
这个宏需要传入三个参数:
| 参数 | 作用 |
|---|---|
| prefix | 轮子名称前缀 |
| xyz | 轮子关节相对 base_link 的位置 |
| rpy | 轮子关节相对 base_link 的姿态 |
1)轮子的 link
代码如下:
<link name="${prefix}_wheel_link">
这里定义一个轮子的刚体。
${prefix} 是参数替换。
如果调用时写:
prefix="front_left"那么展开后就是:
<link name="front_left_wheel_link">如果调用时写:
prefix="rear_right"那么展开后就是:
<link name="rear_right_wheel_link">
这样四个轮子的 link 名称就不会重复。
2)轮子的 inertial
代码如下:
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="${wheel_mass}"/>
<inertia ixx="0.0002" ixy="0" ixz="0"
iyy="0.0004" iyz="0"
izz="0.0002"/>
</inertial>
这里是轮子的惯性信息。
其中:
<mass value="${wheel_mass}"/>引用了前面定义的变量:
<xacro:property name="wheel_mass" value="0.2"/>所以展开后就是:
<mass value="0.2"/>
这里的惯性矩阵是简化写法。
如果是做高精度动力学仿真,需要根据真实轮子的质量、半径、宽度重新计算。
3)轮子的 visual
代码如下:
<visual>
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
<material name="${prefix}_wheel_black">
<color rgba="0.02 0.02 0.02 1"/>
</material>
</visual>
轮子可视化使用的是圆柱体:
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
变量展开后大致为:
<cylinder radius="0.06" length="0.035"/>
也就是:
| 参数 | 含义 |
|---|---|
| radius | 轮子半径 |
| length | 轮子厚度 |
这里最重要的是:
<origin xyz="0 0 0" rpy="1.5708 0 0"/>为什么要写 1.5708?
因为 URDF 里的圆柱默认轴线是 Z 轴。
但是轮子一般需要绕 Y 轴旋转。所以这里把圆柱绕 X 轴旋转 90 度:
1.5708 rad ≈ 90 度这样圆柱的轴线就从 Z 轴转到了 Y 轴。
颜色部分:
<color rgba="0.02 0.02 0.02 1"/>
表示轮子颜色接近黑色,并且不透明。
4)轮子的 collision
代码如下:
<collision>
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
</collision>
轮子的碰撞体同样是圆柱体,并且也旋转了 90 度:
rpy="1.5708 0 0"
这样做的目的是让:
- 看到的轮子方向正确;
- 碰撞检测的轮子方向正确;
- 后面 joint 的旋转轴方向也一致。
5)轮子的 joint
代码如下:
<joint name="${prefix}_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="${prefix}_wheel_link"/>
<origin xyz="${xyz}" rpy="${rpy}"/>
<axis xyz="0 1 0"/>
</joint>
joint 表示两个 link 之间的连接关系。
其中:
name="${prefix}_wheel_joint"
表示 joint 的名字也会根据 prefix 自动生成。
例如:
prefix="front_left"
展开后就是:
<joint name="front_left_wheel_joint" type="continuous">
type="continuous" 表示连续旋转关节。
轮子可以一直旋转,不限制角度,所以这里使用 continuous。
父子关系如下:
<parent link="base_link"/> <child link="${prefix}_wheel_link"/>
意思是:
当前轮子通过关节挂在 base_link 上。
安装位置如下:
<origin xyz="${xyz}" rpy="${rpy}"/>
这里使用的是宏调用时传入的参数。
旋转轴如下:
<axis xyz="0 1 0"/>
表示轮子绕 Y 轴旋转。
3.5 四个轮子的调用
四个轮子通过调用四次 limo_wheel 宏生成。
1)左前轮 front_left
<xacro:limo_wheel prefix="front_left"
xyz="0.16 0.18 -0.06"
rpy="0 0 0"/>
生成的名称为:
front_left_wheel_link
front_left_wheel_joint
位置含义:
| 坐标 | 数值 | 含义 |
|---|---|---|
| x | 0.16 | 前方 |
| y | 0.18 | 左侧 |
| z | -0.06 | 下方 |
所以这是左前轮。
2)右前轮 front_right
<xacro:limo_wheel prefix="front_right"
xyz="0.16 -0.18 -0.06"
rpy="0 0 0"/>
位置含义:
| 坐标 | 数值 | 含义 |
|---|---|---|
| x | 0.16 | 前方 |
| y | -0.18 | 右侧 |
| z | -0.06 | 下方 |
所以这是右前轮。
3)左后轮 rear_left
<xacro:limo_wheel prefix="rear_left"
xyz="-0.16 0.18 -0.06"
rpy="0 0 0"/>
位置含义:
| 坐标 | 数值 | 含义 |
|---|---|---|
| x | -0.16 | 后方 |
| y | 0.18 | 左侧 |
| z | -0.06 | 下方 |
所以这是左后轮。
4)右后轮 rear_right
<xacro:limo_wheel prefix="rear_right"
xyz="-0.16 -0.18 -0.06"
rpy="0 0 0"/>
位置含义:
| 坐标 | 数值 | 含义 |
|---|---|---|
| x | -0.16 | 后方 |
| y | -0.18 | 右侧 |
| z | -0.06 | 下方 |
所以这是右后轮。
四、命令实战:生成并检查 URDF
4.1 将 xacro 转换为 URDF
假设文件名为:
limo_simple_wheels.xacro
可以使用下面命令将 xacro 转换为 URDF:
ros2 run xacro xacro limo_simple_wheels.xacro > limo_simple_wheels.urdf
这条命令的作用是:
- 调用 ROS2 中的 xacro 工具;
- 读取 limo_simple_wheels.xacro;
- 展开里面的变量和宏;
- 生成普通 URDF 文件 limo_simple_wheels.urdf。
如果没有安装 xacro,可以执行:
sudo apt install ros-humble-xacro
如果你使用的不是 ROS2 Humble,需要把 humble 换成自己的 ROS2 版本。
4.2 检查 URDF 文件
1. 可以使用下面命令检查 URDF 文件是否正确:
check_urdf limo_simple_wheels.urdf2. 如果没有安装相关工具,可以执行:
sudo apt install liburdfdom-tools
检查时主要关注:
| 检查项 | 说明 |
|---|---|
| XML 标签是否闭合 | 少写结束标签会导致解析失败 |
| link 名称是否重复 | 每个 link 名字必须唯一 |
| joint 名称是否重复 | 每个 joint 名字必须唯一 |
| parent / child 是否存在 | joint 连接的 link 必须已经定义 |
| xacro 变量是否写错 | 变量名拼写错误会导致展开失败 |
4.3 在 RViz 中查看模型
可以先启动 robot_state_publisher:
ros2 run robot_state_publisher robot_state_publisher limo_simple_wheels.urdf
再打开 RViz:
rviz2
在 RViz 中添加 RobotModel,并把 Fixed Frame 设置为:
base_link
如果一切正常,就能看到一个灰色底盘和四个黑色轮子。
如果 RViz 中没有显示模型,可以检查:
- URDF 是否成功生成;
- robot_state_publisher 是否正常运行;
- Fixed Frame 是否设置为 base_link;
- link 和 joint 名称是否写错;
- xacro 文件是否有语法错误。
五、问题记录与易错点
5.1 为什么不直接写四个轮子,而要用宏?
(1)问题现象
如果直接写四个轮子,需要重复写四份类似代码:
wheel_link wheel_joint visual collision inertial
代码会非常长,而且后期修改麻烦。
(2)原因分析
四个轮子的结构完全相同,只是:
| 不同点 | 说明 |
|---|---|
| 名字不同 | front_left、front_right 等 |
| 位置不同 | xyz 坐标不同 |
| 姿态可能不同 | rpy 可以根据需要调整 |
这种情况非常适合使用 xacro:macro。
(3)解决方案
定义一个轮子宏:
<xacro:macro name="limo_wheel" params="prefix xyz rpy">
然后通过不同参数调用四次。
(4)最终结果
这样代码更简洁,后期维护也更方便。
例如想修改轮子半径,只需要改:
<xacro:property name="wheel_radius" value="0.06"/>
四个轮子都会一起改变。
5.2 为什么轮子要旋转 90 度?
(1)问题现象
如果不写下面这句:
<origin xyz="0 0 0" rpy="1.5708 0 0"/>
轮子的圆柱方向可能会不对,看起来像是竖着放的。
(2)原因分析
URDF 中圆柱体默认沿 Z 轴。
但是车轮通常要让轴线沿 Y 轴,这样才能绕 Y 轴旋转。
(3)解决方案
让圆柱绕 X 轴旋转 90 度:
rpy="1.5708 0 0"
其中:
1.5708 rad ≈ 90 度
(4)最终结果
圆柱轴线从 Z 轴转到 Y 轴,轮子方向正常。
5.3 为什么 joint 的 axis 是 0 1 0?
代码如下:
<axis xyz="0 1 0"/>
这表示轮子绕 Y 轴旋转。
原因是前面已经通过:
rpy="1.5708 0 0"
把圆柱的轴线转到了 Y 轴。
所以 joint 的旋转轴也应该设置为 Y 轴。
如果 visual 的方向和 joint 的旋转轴不一致,就可能出现:
- 轮子看起来方向正确,但实际旋转方向不对;
- 仿真时轮子运动异常;
- TF 和模型显示不符合预期。
5.4 为什么 joint 类型是 continuous?
代码如下:
<joint name="${prefix}_wheel_joint" type="continuous">
continuous 表示连续旋转关节。
轮子不像机械臂关节那样只在固定角度范围内运动。
车轮可以一直向前转,也可以一直向后转,所以应该使用 continuous。
常见 joint 类型对比如下:
| joint 类型 | 含义 | 适用场景 |
|---|---|---|
| fixed | 固定关节 | 雷达、相机固定安装 |
| revolute | 有角度限制的旋转关节 | 机械臂关节 |
| continuous | 无限旋转关节 | 车轮 |
| prismatic | 直线移动关节 | 滑轨、升降机构 |
5.5 visual、collision、inertial 的区别
这三个标签非常容易混淆,可以这样记:
| 标签 | 作用 | 类比 |
|---|---|---|
| visual | 机器人看起来是什么样 | 外观模型 |
| collision | 机器人碰撞检测用什么形状 | 碰撞边界 |
| inertial | 机器人质量和惯性是多少 | 物理属性 |
在实际项目中:
- visual 可以做得精细;
- collision 尽量简单;
- inertial 要尽量接近真实物理参数。
六、总结
本节主要学习了 简化四轮 xacro 模型的写法。
主要内容包括:
- xacro 是带变量和宏的 URDF,适合编写可复用机器人模型。
- xacro:property 可以定义底盘尺寸、轮子半径、轮子质量等参数。
- base_link 是机器人底盘主体,也是四个轮子的父 link。
- inertial 描述质量和惯性信息。
- visual 描述模型显示效果。
- collision 描述仿真碰撞体。
- xacro:macro 可以把重复的轮子结构封装成模板。
- 四个轮子通过不同的 prefix 和 xyz 参数生成。
- 轮子关节使用 continuous,表示可以连续旋转。
- 圆柱轮子需要通过 rpy="1.5708 0 0" 旋转,使轴线与 Y 轴一致。
- 可以通过 xacro 命令生成 URDF,再用 check_urdf 和 RViz 验证模型。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)