构建世界


预计完成时间:14 分钟

4.12   添加角色(Actor)

在 Gazebo Sim 中,带动画的模型被称为 actor

当你希望在仿真中让某个实体沿着预先设定好的轨迹运动,同时又不受物理引擎影响时,动画就是非常有价值的工具。因此,这些对象不会受到重力或其他物体交互的影响。不过,它们仍然保留了可被 RGB 相机看到的 3D 外观,并且拥有能被 GPU 传感器检测到的 3D 网格。

动画主要有两种类型,它们可以单独使用,也可以组合使用:

骨骼动画(Skeleton animation):表示同一个模型内部各连杆之间的相对运动:

"Actor Skeleton Animation"

轨迹动画(Trajectory animation):表示把 actor 的所有连杆作为一个整体,沿着轨迹在世界中移动:

"Actor Trajectory Animation"

组合动画(Combined animation):用于实现既有骨骼动作、又能在世界中移动的动画:

"Actor Combined Animation"

Actor 具有以下特点:

  • 它们不会受到任何外部力的影响,包括重力、接触力或其他作用。
  • Actor 可以使用来自 COLLADA(.dae)和 BVH(.bvh)文件的骨骼动画。
  • Actor 的轨迹可以直接在 SDF 中编写。

更多关于 Actor 规范的信息,请参考 SDF 文档中的 Actor Specifications

要在 world SDF 文件中添加一个 actor,需要在 <actor> ... </actor> 标签内部为它指定两个核心部分:skeletontrajectory

下面给出一个包含脚本的 actor 示例:

<actor name="actor_walking">
    <skin>
        <filename>https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae</filename>
        <scale>1.0</scale>
    </skin>
    <animation name='walk'>
        <filename>https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae</filename>
    </animation>
    <script>
        <loop>true</loop>
        <delay_start>0.000000</delay_start>
        <auto_start>true</auto_start>
        <trajectory id="0" type="walk" tension="0.6">
            <waypoint>
                <time>0.0</time>
                <pose>0 0 1.0 0 0 0.00000</pose>
            </waypoint>
            ...
            ...
            <waypoint>
                <time>10.0</time>
                <pose>0 0 1.0 0 0 3.14159</pose>
            </waypoint>
        </trajectory>
    </script>
</actor>

skinanimation 标签属于 skeleton,而 script 则属于 trajectory

Gazebo Sim 支持两种骨骼动画文件格式:COLLADA(.dae)和 Biovision Hierarchy(.bvh)。

<skin> 标签中,你需要加载一个 COLLADA(.dae)文件,用来指定 actor 的外观。当在 <skin> 中使用 COLLADA 文件时,其中的动画也会一并加载。<scale> 用于控制外观的缩放。

<animation> 标签中,你需要指定 actor 的运动方式。如果不同的 skin 与动画拥有兼容的骨骼结构,就可以把它们组合起来使用。

所谓 Scripted Trajectory,是一种更高层次的 actor 动画方式。你只需要定义一系列要在特定时间点达到的姿态,Gazebo Sim 会负责在这些姿态之间进行插值,从而生成平滑连续的运动。

如果动画本身包含沿 X 轴的位移,那么骨骼会跟随轨迹一起移动,从而形成动态效果;但如果动画本身没有这类位移,那么即使存在轨迹,骨骼本身仍会保持在原地。

<script> 标签中,可以使用以下参数:

  • loop:当设置为 true 时,脚本会循环执行。若想获得无缝连续的运动效果,请确保最后一个 waypoint 与第一个 waypoint 对应一致。
  • delay_start:用于指定脚本开始前需要等待的秒数。如果脚本是循环执行的,那么每一轮开始前都会等待这段时间。
  • auto_start:如果你希望仿真一开始动画就自动启动,就把它设为 true;如果你希望动画只在某个插件触发后才开始,则设为 false。

<trajectory> 标签中,你需要定义 actor 将要经过的一系列 waypoint。<trajectory> 具有三个属性:idtypetension。其中 type 应与动画名称一致,通常为 “walk”。tension 参数用于控制轨迹对指定 waypoint 的贴合程度。默认值为 0,这会生成 Catmull-Rom 样条曲线,可能导致动画越过 waypoint;若将 tension 设为 1,则轨迹会更严格地贴合 waypoint。tension 的取值范围应在 0 到 1 之间。

<trajectory> 标签下,需要定义以下内容:

  • waypoint: Any number of waypoints can be included in a trajectory. Each waypoint comprises a time and a pose:
    • time:表示从脚本开始算起,应该在第几秒达到对应的姿态。
    • pose:表示相对于 actor 初始位置所期望达到的姿态。

注意:

  • waypoint 的书写顺序不会影响执行顺序;它们会严格按照你提供的 time 值来执行。
  • 整个 trajectory 会作为一个整体进行平滑处理,以保证运动流畅,因此 waypoint 中给出的姿态不一定会被精确逐点到达。

好了,现在把一个 actor 添加到你的 demo_world.sdf 文件中。请把下面这一段内容放在 model 的 include 标签之后、关闭的 </world> 标签之前。

复制并粘贴

In [ ]:
<actor name="actor_walking">
    <skin>
        <filename>https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae</filename>
        <scale>1.0</scale>
    </skin>
    <animation name='walk'>
        <filename>https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae</filename>
    </animation>
    <script>
        <loop>true</loop>
        <delay_start>0.000000</delay_start>
        <auto_start>true</auto_start>
        <trajectory id="0" type="walk" tension="0.75">
            <waypoint>
                <time>0.0</time>
                <pose>0 0 1 0 0 3.14159</pose>
            </waypoint>
            <waypoint>
                <time>0.5</time>
                <pose>0 0 1 0 0 1.57079</pose>
            </waypoint>
            <waypoint>
                <time>3.0</time>
                <pose>0 5 1 0 0 1.57079</pose>
            </waypoint>
            <waypoint>
                <time>3.5</time>
                <pose>0 5 1 0 0 0.00000</pose>
            </waypoint>
            <waypoint>
                <time>8.5</time>
                <pose>10 5 1 0 0 0.00000</pose>
            </waypoint>
            <waypoint>
                <time>9.0</time>
                <pose>10 5 1 0 0 -1.57079</pose>
            </waypoint>
            <waypoint>
                <time>14.0</time>
                <pose>10 -5 1 0 0 -1.57079</pose>
            </waypoint>
            <waypoint>
                <time>14.5</time>
                <pose>10 -5 1 0 0 3.14159</pose>
            </waypoint>
            <waypoint>
                <time>19.5</time>
                <pose>0 -5 1 0 0 3.14159</pose>
            </waypoint>
            <waypoint>
                <time>20.0</time>
                <pose>0 -5 1 0 0 1.15079</pose>
            </waypoint>
            <waypoint>
                <time>22.5</time>
                <pose>0 0 1 0 0 1.15079</pose>
            </waypoint>
            <waypoint>
                <time>23.0</time>
                <pose>0 0 1 0 0 0.00000</pose>
            </waypoint>
            <waypoint>
                <time>25.0</time>
                <pose>0 0 1 0 0 0.00000</pose>
            </waypoint>
        </trajectory>
    </script>
</actor>

现在启动这个 world。记得先指定 Gazebo Sim 查找本地 Gazebo 模型时所使用的路径。

因此,在启动 Gazebo Sim 之前,先导出模型路径。

在 Web Shell 1 中执行

In [ ]:
export GZ_SIM_RESOURCE_PATH=/workspace/src/robot_description/models
In [ ]:
cd /workspace/src/robot_description/worlds
In [ ]:
gz sim demo_world.sdf

当 Gazebo Sim 加载完成后,你应该会看到与下图类似的结果:

"添加角色(Actor) Result"

如果你能看到 Gazebo、两只 Turtle,并且在播放仿真时人物能够动起来,那么你就已经成功学会了如何在 world 中加入 actor!

此时,你最终的 demo_world.sdf 文件内容应该如下:
demo_world.sdf

- 练习 4.11.1 结束 -

恭喜,你已经完成了本单元!现在该来做一个练习了!

这次练习的任务很简单:你需要创建一个 launch 文件,用于启动这个 demo_world.sdf,并把你设计的机器人生成到这个 world 中。机器人的生成位置由你自己决定。

**提示:** 可以参考这个版本的 setup.py 来让 launch 文件正常工作。请注意理解它与之前版本的区别,不要直接整段复制进你自己的 setup.py 文件里。

你的输出应与下图类似。注意,你自己的机器人生成位置可能会有所不同。

"Exercise 4 Result"

- 练习 4.11.1 -
- 练习 4.11.1 参考答案 -

在你自己尝试完成练习之前,不要先看答案。完成后再回头查看参考答案,会更方便你对比自己的实现。

如果你在完成练习时遇到问题,可以到论坛寻求支持。

demo_world_robot_spawn.launch.py

- 练习 4.11.1 参考答案结束 -