

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 自定义奖励函数
<a name="reward-function"></a>

创建奖励函数就像设计激励计划一样。参数是可用于制定激励计划的值。

不同的激励策略会导致不同的车辆行为。若要让车辆更快地行驶，请尝试在赛车花费太长时间才能完成一圈或偏离赛道时奖励负值。为了避免车辆出现曲线驾驶模式，请尝试设定一个转向角度的范围限制，并对车辆在直线赛道上较少激进转向时给予奖励。

您可以使用航点（沿着赛道中心线以及外缘和内边缘放置的编号标记）来帮助您将某些驾驶行为与赛道的特定特征（例如直道和曲线）相关联。

设计有效的奖励函数是一个创造性和迭代性的过程。尝试不同的策略，混合搭配参数，最重要的是，玩得开心！

**Topics**
+ [编辑 Python 代码以自定义您的奖励函数](#edit-reward-function)
+ [AWS DeepRacer 奖励函数的输入参数](#deepracer-reward-function-input)

## 编辑 Python 代码以自定义您的奖励函数
<a name="edit-reward-function"></a>

在 AWS DeepRacer Student 中，你可以编辑示例奖励函数，为你的模型制定自定义的赛车策略。

**自定义您的奖励功能**

1. 在 “ AWS DeepRacer 学生**创建模型**” 体验的 “**步骤 5：自定义奖励功能**” 页面上，选择一个奖励函数示例。

1. 使用奖励函数示例选择器下方的代码编辑器，使用 Python 代码自定义奖励函数的输入参数。

1. 选择**验证**以检查您的代码是否有效。或者，选择**重置**重新开始。

1. 完成更改后，选择**下一步**。

使用 [AWS DeepRacer 奖励函数的输入参数](#deepracer-reward-function-input) 了解每个参数。在奖励函数示例中查看如何使用不同的参数。

## AWS DeepRacer 奖励函数的输入参数
<a name="deepracer-reward-function-input"></a>

 AWS DeepRacer 奖励函数将作为变量传递的字典对象作为输入。`params`

```
def reward_function(params) :

    reward = ...

    return float(reward)
```

`params` 词典对象包含以下键/值对：

```
{
    "all_wheels_on_track": Boolean,        # flag to indicate if the agent is on the track
    "x": float,                            # agent's x-coordinate in meters
    "y": float,                            # agent's y-coordinate in meters
    "closest_objects": [int, int],         # zero-based indices of the two closest objects to the agent's current position of (x, y).
    "closest_waypoints": [int, int],       # indices of the two nearest waypoints.
    "distance_from_center": float,         # distance in meters from the track center
    "is_crashed": Boolean,                 # Boolean flag to indicate whether the agent has crashed.
    "is_left_of_center": Boolean,          # Flag to indicate if the agent is on the left side to the track center or not.
    "is_offtrack": Boolean,                # Boolean flag to indicate whether the agent has gone off track.
    "is_reversed": Boolean,                # flag to indicate if the agent is driving clockwise (True) or counter clockwise (False).
    "heading": float,                      # agent's yaw in degrees
    "objects_distance": [float, ],         # list of the objects' distances in meters between 0 and track_length in relation to the starting line.
    "objects_heading": [float, ],          # list of the objects' headings in degrees between -180 and 180.
    "objects_left_of_center": [Boolean, ], # list of Boolean flags indicating whether elements' objects are left of the center (True) or not (False).
    "objects_location": [(float, float),], # list of object locations [(x,y), ...].
    "objects_speed": [float, ],            # list of the objects' speeds in meters per second.
    "progress": float,                     # percentage of track completed
    "speed": float,                        # agent's speed in meters per second (m/s)
    "steering_angle": float,               # agent's steering angle in degrees
    "steps": int,                          # number steps completed
    "track_length": float,                 # track length in meters.
    "track_width": float,                  # width of the track
    "waypoints": [(float, float), ]        # list of (x,y) as milestones along the track center

}
```

使用以下参考可以更好地了解 AWS DeepRacer 输入参数。

### all\$1wheels\$1on\$1track
<a name="reward-function-input-all_wheels_on_track"></a>

**类型：**`Boolean`

**范围：**`(True:False)`

一个 `Boolean` 标记，用于指示代理是在赛道上还是偏离赛道。如果车辆的任一车轮位于赛道边界外，则将该代理视为偏离赛道（`False`）。如果车辆的四个车轮都在内部和外部赛道边界内，则将车辆视为在赛道上（`True`）。下图显示了代理在赛道上。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-all_wheels_on_track-true.png)


下图显示了由于两个轮子在赛道边界之外而未进入赛道的代理。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-all_wheels_on_track-false.png)


**示例：***使用 `all_wheels_on_track` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using all_wheels_on_track and speed
    '''

    # Read input variables
    all_wheels_on_track = params['all_wheels_on_track']
    speed = params['speed']

    # Set the speed threshold based your action space
    SPEED_THRESHOLD = 1.0

    if not all_wheels_on_track:
        # Penalize if the car goes off track
        reward = 1e-3
    elif speed < SPEED_THRESHOLD:
        # Penalize if the car goes too slow
        reward = 0.5
    else:
        # High reward if the car stays on track and goes fast
        reward = 1.0

    return float(reward)
```

### closest\$1waypoints
<a name="reward-function-input-closest_waypoints"></a>

**类型**：`[int, int]`

**范围**：`[(0:Max-1),(1:Max-1)]`

最接近代理当前位置 `(x, y)` 的两个相邻 `waypoint` 的从零开始的索引。距离是根据与代理中心的欧氏距离来测量的。第一个元素指代理后面最近的路点，第二个元素指代理前面最近的路点。`Max` 是路点列表的长度。在 [waypoints](#reward-function-input-waypoints) 的图示中，`closest_waypoints` 将为 `[16, 17]`。

以下示例奖励函数演示如何使用 `waypoints`、`closest_waypoints` 和 `heading` 来计算即时奖励。

AWS DeepRacer 支持以下 Python 库：`math``random``numpy`、`scipy`、、和`shapely`。要使用其中一个，请在函数定义 `def reward_function(params)` 之前添加一个导入语句 `import supported library`。

**示例**：*使用 `closest_waypoints` 参数的奖励函数。*

```
# Place import statement outside of function (supported libraries: math, random, numpy, scipy, and shapely)
# Example imports of available libraries
#
# import math
# import random
# import numpy
# import scipy
# import shapely

import math

def reward_function(params):
    ###############################################################################
    '''
    Example of using waypoints and heading to make the car point in the right direction
    '''

    # Read input variables
    waypoints = params['waypoints']
    closest_waypoints = params['closest_waypoints']
    heading = params['heading']

    # Initialize the reward with typical value
    reward = 1.0

    # Calculate the direction of the centerline based on the closest waypoints
    next_point = waypoints[closest_waypoints[1]]
    prev_point = waypoints[closest_waypoints[0]]

    # Calculate the direction in radius, arctan2(dy, dx), the result is (-pi, pi) in radians
    track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0])
    # Convert to degree
    track_direction = math.degrees(track_direction)

    # Calculate the difference between the track direction and the heading direction of the car
    direction_diff = abs(track_direction - heading)
    if direction_diff > 180:
        direction_diff = 360 - direction_diff

    # Penalize the reward if the difference is too large
    DIRECTION_THRESHOLD = 10.0
    if direction_diff > DIRECTION_THRESHOLD:
        reward *= 0.5

    return float(reward)
​
```

### closest\$1objects
<a name="reward-function-input-closest_objects"></a>

**类型**：`[int, int]`

**范围**：`[(0:len(object_locations)-1), (0:len(object_locations)-1]`

最接近代理当前位置 (x, y) 的两个物体的从零开始的索引。第一个索引指代理后面最近的物体，第二个索引指代理前面最近的物体。如果只有一个物体，则两个索引都为 0。

### distance\$1from\$1center
<a name="reward-function-input-distance_from_center"></a>

**类型**：`float`

**范围**：`0:~track_width/2`

代理中心和赛道中心之间的位移（以米为单位）。当代理的任一车轮位于赛道边界外时可观察到的最大位移，并且根据赛道边界的宽度，它可以略小于或大于 `track_width` 的一半。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-distance_from_center.png)


**示例：***使用 `distance_from_center` 参数的奖励函数*

```
def reward_function(params):
    #################################################################################
    '''
    Example of using distance from the center
    '''

    # Read input variable
    track_width = params['track_width']
    distance_from_center = params['distance_from_center']

    # Penalize if the car is too far away from the center
    marker_1 = 0.1 * track_width
    marker_2 = 0.5 * track_width

    if distance_from_center <= marker_1:
        reward = 1.0
    elif distance_from_center <= marker_2:
        reward = 0.5
    else:
        reward = 1e-3  # likely crashed/ close to off track

    return float(reward)
```

### heading
<a name="reward-function-input-heading"></a>

**类型**：`float`

**范围**：`-180:+180`

代理相对于坐标系 x 轴的前进方向（以度为单位）。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-heading.png)


**示例：***使用 `heading` 参数的奖励函数*

有关更多信息，请参阅 [`closest_waypoints`](#reward-function-input-closest_waypoints)。

### is\$1crashed
<a name="reward-function-input-crashed"></a>

**类型**：`Boolean`

**范围**：`(True:False)`

一个 `Boolean` 标记，用于指示代理的最终状态是撞向另一个物体（`True`），还是不是（`False`）。

### is\$1left\$1of\$1center
<a name="reward-function-input-is_left_of_center"></a>

**类型**：`Boolean`

**范围**：`[True : False]`

`Boolean` 标志，用于指示代理是位于赛道中心左边（`True`）还是不在赛道中心左边（`False`）。

### is\$1offtrack
<a name="reward-function-input-offtrack"></a>

**类型**：`Boolean`

**范围**：`(True:False)`

`Boolean` 标志，用于指示代理的四个车轮已驶出赛道的内部或外部边界（`True`）与否（`False`）。

### is\$1reversed
<a name="reward-function-input-is_reversed"></a>

**类型**：`Boolean`

**范围**：`[True:False]`

`Boolean` 标志，用于指示代理是顺时针（`True`）还是逆时针（`False`）行驶。

此参数在您针对每个过程改变方向时使用。

### objects\$1distance
<a name="reward-function-input-objects_distance"></a>

**类型**：`[float, … ]`

**范围**：`[(0:track_length), … ]`

环境中物体之间相对于起始线的距离列表。第 i 个元素测量沿赛道中心线第 i 个物体与起始线之间的距离。

**注意**  
abs \$1 (var1) - (var2)\$1 = 汽车与物体的接近程度, WHEN var1 = ["objects\$1distance"][index] and var2 = params["progress"]\$1params["track\$1length"]  
要获取车辆前方最近物体和车辆后方最近物体的索引，请使用 `closest_objects` 参数。

### objects\$1heading
<a name="reward-function-input-objects_heading"></a>

**类型**：`[float, … ]`

**范围**：`[(-180:180), … ]`

物体前进方向（以度为单位）列表。第 i 个元素测量第 i 个物体的前进方向。静止物体的标题为 0。对于自动程序车辆，相应元素的值是机器人汽车的前进角度。

### objects\$1left\$1of\$1center
<a name="reward-function-input-objects_left_of_center"></a>

**类型**：`[Boolean, … ]`

**范围**：`[True|False, … ]`

`Boolean` 标记的列表。第 i 个元素值指示第 i 个物体位于赛道中心的左侧（`True`）还是右侧（`False`）。

### objects\$1location
<a name="reward-function-input-objects_location"></a>

**类型**：`[(x,y), ...]`

**范围**：`[(0:N,0:N), ...]`

此参数存储所有物体位置。每个位置都是 ([x, y](#reward-function-input-x_y)) 的元组。

列表的大小等于赛道上的物体数。列出的物体包括静止的障碍物和移动的机器人赛车。

### objects\$1speed
<a name="reward-function-input-objects_speed"></a>

**类型**：`[float, … ]`

**范围**：`[(0:12.0), … ]`

赛道上物体的速度（米/秒）列表。对于静止物体，其速度为 0。对于自动程序车辆，值为您在训练中设置的速度。

### 进度
<a name="reward-function-input-progress"></a>

**类型**：`float`

**范围**：`0:100`

赛道完成百分比。

**示例：***使用 `progress` 参数的奖励函数*

有关更多信息，请参阅[步骤](#reward-function-input-steps)。

### speed
<a name="reward-function-input-speed"></a>

**类型**：`float`

**范围**：`0.0:5.0`

观察到的代理速度，以米/秒 (m/s) 为单位。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-speed.png)


**示例：***使用 `speed` 参数的奖励函数*

有关更多信息，请参阅 [all\$1wheels\$1on\$1track](#reward-function-input-all_wheels_on_track)。

### steering\$1angle
<a name="reward-function-input-steering_angle"></a>

**类型**：`float`

**范围**：`-30:30`

前轮与代理中心线之间的转向角（以度为单位）。负号 (-) 表示向右转向，正号 (\$1) 表示向左转向。代理的中心线不一定与赛道中心线平行，如下图所示。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-steering.png)


**示例：***使用 `steering_angle` 参数的奖励函数*

```
def reward_function(params):
    '''
    Example of using steering angle
    '''

    # Read input variable
    abs_steering = abs(params['steering_angle']) # We don't care whether it is left or right steering

    # Initialize the reward with typical value
    reward = 1.0

    # Penalize if car steer too much to prevent zigzag
    ABS_STEERING_THRESHOLD = 20.0
    if abs_steering > ABS_STEERING_THRESHOLD:
        reward *= 0.8

    return float(reward)
```

### 步骤
<a name="reward-function-input-steps"></a>

**类型**：`int`

**范围**：`0:Nstep`

完成的步骤数。一个步骤对应于代理使用当前策略完成的一个观察操作序列。

**示例：***使用 `steps` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using steps and progress
    '''

    # Read input variable
    steps = params['steps']
    progress = params['progress']

    # Total num of steps we want the car to finish the lap, it will vary depends on the track length
    TOTAL_NUM_STEPS = 300

    # Initialize the reward with typical value
    reward = 1.0

    # Give additional reward if the car pass every 100 steps faster than expected
    if (steps % 100) == 0 and progress > (steps / TOTAL_NUM_STEPS) * 100 :
        reward += 10.0

    return float(reward)
```

### track\$1length
<a name="reward-function-input-track_len"></a>

**类型**：`float`

**范围**：`[0:Lmax]`

赛道长度（以米为单位）。`Lmax is track-dependent.`

### track\$1width
<a name="reward-function-input-track_width"></a>

**类型**：`float`

**范围**：`0:Dtrack`

赛道宽度（以米为单位）。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-track_width.png)


**示例：***使用 `track_width` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using track width
    '''

    # Read input variable
    track_width = params['track_width']
    distance_from_center = params['distance_from_center']

    # Calculate the distance from each border
    distance_from_border = 0.5 * track_width - distance_from_center

    # Reward higher if the car stays inside the track borders
    if distance_from_border >= 0.05:
        reward = 1.0
    else:
        reward = 1e-3 # Low reward if too close to the border or goes off the track

    return float(reward)
```

### x, y
<a name="reward-function-input-x_y"></a>

**类型**：`float`

**范围**：`0:N`

包含赛道的模拟环境的沿 x 和 y 轴的代理中心位置（以米为单位）。原点位于模拟环境的左下角。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-x-y.png)


### waypoints
<a name="reward-function-input-waypoints"></a>

**类型**：`[float, float]` 的 `list`

**范围**：`[[xw,0,yw,0] … [xw,Max-1, yw,Max-1]]`

沿赛道中心排列、取决于赛道的 `Max` 里程的有序列表。每个里程碑均由 (xw,i, yw,i) 坐标描述。对于环形赛道，第一个路径点与最后一个路径点相同。对于直道和其他非环形赛道，第一个路径点与最后一个路径点不同。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/student-userguide/images/reward-function/deepracer-reward-function-input-waypoints.png)


**示例**：*使用 `waypoints` 参数的奖励函数*

有关更多信息，请参阅 [`closest_waypoints`](#reward-function-input-closest_waypoints)。