本帖最后由 十日无冬 于 2024-11-28 10:52 编辑
复杂地形之斜坡
除了楼梯之外,斜坡也是机器人移动训练中非常经典的实用地形之一。斜坡地形与楼梯地形相比,具有连续的倾斜面,要求机器人在行进过程中持续调整平衡和步态,而不是应对离散的高度变化。与楼梯地形要求的步态精准和决策复杂度不同,斜坡更侧重于机器人在倾斜环境下的稳定性和协调能力训练。
在强化学习中,斜坡地形的重要性在于它能够提高机器人在不平坦表面上的平衡感知和运动控制能力。这种训练帮助机器人在各种倾斜地形中保持稳定,增强其在真实世界中应对各种动态和复杂环境的能力。因此,掌握斜坡地形的机器人将在面对连续变化的地形时表现出更高的适应性和可靠性。
类似的,本节将会解析isaacgym/python/isaacgym路径下的terrain_utils.py文件中提供的斜坡地形和金字塔斜坡地形。其中斜坡地形的创建代码如下所示:
- def big_slope(terrain, slope=1):
- x = np.arange(0, terrain.width)
- y = np.arange(0, terrain.length)
- xx, yy = np.meshgrid(x, y, sparse=True)
- xx = xx.reshape(terrain.width, 1)
- max_height = int(slope * (terrain.horizontal_scale / terrain.vertical_scale) * terrain.width / 10)
- terrain.height_field_raw[:, np.arange(terrain.length)] += (max_height * xx / terrain.width).astype(terrain.height_field_raw.dtype)
- return terrain
复制代码
斜坡的创建看起来比台阶复杂了不少,但其实仅仅是把之前通过for循环创建递增的值变成了用numpy的稀疏矩阵来创建递增的值,然后再赋值给height_field_raw数组。
这个斜坡远远超过了单个地形限制的大小,此处只为了展示创建,不建议直接使用,这个大斜坡创建在Issac sim仿真中如图所示:
复杂地形之金字塔斜坡
同样的,在训练地形中直接使用斜坡地形也是不可取的,同样会出现地形不连续的情况,出现非常大的高度差,导致机器人在训练中非常容易摔倒。这时我们就需要使用金字塔斜坡来替代,金字塔斜坡地形和金字塔楼梯地形稍有不同,它在顶部有一个平台,四周则是斜率相同的坡面,多个金字塔斜坡地形接壤如下图所示:
其创建代码如下:
- def pyramid_sloped_terrain(terrain, slope=1, platform_size=1.):
- """
- Generate a sloped terrain
- Parameters:
- terrain (terrain): the terrain
- slope (int): positive or negative slope
- platform_size (float): size of the flat platform at the center of the terrain [meters]
- Returns:
- terrain (SubTerrain): update terrain
- """
- x = np.arange(0, terrain.width)
- y = np.arange(0, terrain.length)
- center_x = int(terrain.width / 2)
- center_y = int(terrain.length / 2)
- xx, yy = np.meshgrid(x, y, sparse=True)
- xx = (center_x - np.abs(center_x-xx)) / center_x
- yy = (center_y - np.abs(center_y-yy)) / center_y
- xx = xx.reshape(terrain.width, 1)
- yy = yy.reshape(1, terrain.length)
- max_height = int(slope * (terrain.horizontal_scale / terrain.vertical_scale) * (terrain.width / 2))
- terrain.height_field_raw += (max_height * xx * yy).astype(terrain.height_field_raw.dtype)
- platform_size = int(platform_size / terrain.horizontal_scale / 2)
- x1 = terrain.width // 2 - platform_size
- x2 = terrain.width // 2 + platform_size
- y1 = terrain.length // 2 - platform_size
- y2 = terrain.length // 2 + platform_size
- min_h = min(terrain.height_field_raw[x1, y1], 0)
- max_h = max(terrain.height_field_raw[x1, y1], 0)
- terrain.height_field_raw = np.clip(terrain.height_field_raw, min_h, max_h)
- return terrain
复制代码
金字塔形斜坡的代码看起来非常复杂,但是有了之前的经验理解起来应该不会特别费劲,让我们逐行分析一下:
x = np.arange(0, terrain.width)
y = np.arange(0, terrain.length)
center_x = int(terrain.width / 2)
center_y = int(terrain.length / 2)
x,y为地形网络的网格点列表,center x,y是地形的中心点坐标
xx, yy = np.meshgrid(x, y, sparse=True)
xx = (center_x - np.abs(center_x - xx)) / center_x # 归一化到 [0, 1]
yy = (center_y - np.abs(center_y - yy)) / center_y # 归一化到 [0, 1]
xx = xx.reshape(terrain.width, 1) # 变为列向量
yy = yy.reshape(1, terrain.length) # 变为行向量
xx,yy为生成的稀疏网络,归一化坐标到[0, 1]后reshape方便计算
max_height = int(slope * (terrain.horizontal_scale / terrain.vertical_scale) * (terrain.width / 2))
terrain.height_field_raw += (max_height * xx * yy).astype(terrain.height_field_raw.dtype)
通过最大高度(由此函数的入参slope决定),xx,和yy计算出高度并赋值给height_field_raw数组,如果代码在这里停止,就会形成一个圆锥形状的地形
platform_size = int(platform_size / terrain.horizontal_scale / 2)
x1 = terrain.width // 2 - platform_size # 平台左边界
x2 = terrain.width // 2 + platform_size # 平台右边界
y1 = terrain.length // 2 - platform_size # 平台上边界
y2 = terrain.length // 2 + platform_size # 平台下边界
min_h = min(terrain.height_field_raw[x1, y1], 0) # 平台区域最小高度
max_h = max(terrain.height_field_raw[x1, y1], 0) # 平台区域最大高度
terrain.height_field_raw = np.clip(terrain.height_field_raw, min_h, max_h)
创建一个平台替换掉顶部的锥形,并使用np.clip 限制了高度,确保平台区域高度保持一致。至此就得到了一个金字塔斜坡的地形。
|