

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 自訂獎勵函數
<a name="reward-function"></a>

建立獎勵函數就像設計獎勵計畫一樣。參數是可用來開發獎勵計畫的值。

不同的獎勵策略會產生不同的車輛行為。為了鼓勵車輛更快駕駛，請嘗試在車輛花太長時間才能完成單圈或離開賽道時授予負值。為了避免鋸齒狀駕駛模式，請嘗試定義轉向角度範圍限制，並獎勵車輛在賽道的直線區段上較不積極地轉向。

您可以使用路徑點，其是沿著軌道中心線和外部邊緣和內部邊緣放置的編號標記，以協助您將特定駕駛行為與軌道的特定功能建立關聯，例如直線和曲線。

製作有效的獎勵函數是一個創意且反覆的程序。嘗試不同的策略、混合和比對參數，最重要的是，享受樂趣！

**Topics**
+ [編輯 Python 程式碼以自訂獎勵函數](#edit-reward-function)
+ [AWS DeepRacer 獎勵函數的輸入參數](#deepracer-reward-function-input)

## 編輯 Python 程式碼以自訂獎勵函數
<a name="edit-reward-function"></a>

In AWS DeepRacer 學生，您可以編輯範例獎勵函數，為您的模型制定自訂競賽策略。

**自訂獎勵函數**

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>

**Type (類型)**：`Boolean`

**Range (範圍)**：`(True:False)`

指出代理程式是否在正軌上的`Boolean`旗標。如果代理程式的任何一個輪子位於軌道邊界之外，則代理程式不在軌道上 (`False`)。如果這四個輪子都在內部和外部賽道邊界內，則表示它在賽道上 (`True`)。下圖顯示正在追蹤的代理程式。

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


下圖顯示 代理程式，因為兩個輪子位於軌道邊界之外，所以不在軌道上。

![\[\]](http://docs.aws.amazon.com/zh_tw/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>

**Type (類型)**：`[int, int]`

**Range (範圍)**：`[(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`、`scipy`、、 `random` `numpy`和 `shapely`。若要使用，請在函數定義 `import supported library`之前新增匯入陳述式 `def reward_function(params)`。

**範例**：*使用 `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>

**Type (類型)**：`[int, int]`

**Range (範圍)**：`[(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>

**Type (類型)**：`float`

**Range (範圍)**：`0:~track_width/2`

代理程式中心與賽道中心之間的置換，以公尺為單位。可觀察到的最大偏移會在代理程式的任何一個輪胎位於軌道邊界外圍時發生，取決於軌道邊界的寬度，這可能會略小或略大於 `track_width` 的一半。

![\[\]](http://docs.aws.amazon.com/zh_tw/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>

**Type (類型)**：`float`

**Range (範圍)**：`-180:+180`

代理程式相對於座標系統 x 軸的方向，以度為單位。

![\[\]](http://docs.aws.amazon.com/zh_tw/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>

**Type (類型)**：`Boolean`

**Range (範圍)**：`(True:False)`

指出代理程式是否已當機進入另一個物件 (`True`) 或未當成終止狀態 (`False`) 的`Boolean`旗標。

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

**Type (類型)**：`Boolean`

**Range (範圍)**：`[True : False]`

指出代理程式是否位於軌道中心 (`True`) 或非軌道中心 () 的左側的`Boolean`旗標`False`。

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

**Type (類型)**：`Boolean`

**Range (範圍)**：`(True:False)`

指出所有四個代理器輪子是否在軌道內部或外部電路板 (`True`) 外駕駛的`Boolean`標記 ()`False`。

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

**Type (類型)**：`Boolean`

**Range (範圍)**：`[True:False]`

指出代理程式是順時針駕駛 (`True`) 還是逆時針駕駛 () 的`Boolean`旗標`False`。

此標記會在您為每個回合啟用方向變更時使用。

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

**Type (類型)**：`[float, … ]`

**Range (範圍)**：`[(0:track_length), … ]`

環境中物件與起始線相關的距離清單。第 i 個元素會測量沿著賽道中心線，第 i 個物件與起始線之間的距離 (公尺)。

**注意**  
abs \$1 (var1) - (var2)\$1 = how close the car is to an object, WHEN var1 = ["objects\$1distance"][index] and var2 = params["progress"]\$1params["track\$1length"]  
若要取得車輛前方最接近物件和車輛後方最接近物件的索引，請使用 `closest_objects` 參數。

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

**Type (類型)**：`[float, … ]`

**Range (範圍)**：`[(-180:180), … ]`

物件所面對方向的清單 (角度)。第 i 個元素會測量第 i 個物件所面對的方向。靜態物件的標題為 0。對於機器人車，對應的元素值是機器人車的前進角度。

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

**Type (類型)**：`[Boolean, … ]`

**Range (範圍)**：`[True|False, … ]`

`Boolean` 旗標清單。ith 元素值指出 ith 物件位於軌跡中心的左側 (`True`) 或右側 (`False`)。

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

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

**Range (範圍)**：`[(0:N,0:N), ...]`

此參數存放所有物件位置。每個位置都是 ([x、y) ](#reward-function-input-x_y)的元組。

清單的大小與賽道上的物件數量相等。列出的物件包括固定障礙物和移動的機器人車。

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

**Type (類型)**：`[float, … ]`

**Range (範圍)**：`[(0:12.0), … ]`

賽道上物件的速度清單 (單位為每秒的公尺數)。針對固定物件，其速度為 0。對於機器人車輛，值是您在訓練中設定的速度。

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

**Type (類型)**：`float`

**Range (範圍)**：`0:100`

完成軌道的百分比。

**範例：***使用 `progress` 參數的獎勵函數*

如需詳細資訊，請參閱[梯度](#reward-function-input-steps)。

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

**Type (類型)**：`float`

**Range (範圍)**：`0.0:5.0`

代理程式所觀察到的速度，單位為公尺/每秒 (m/s)。

![\[\]](http://docs.aws.amazon.com/zh_tw/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>

**Type (類型)**：`float`

**Range (範圍)**：`-30:30`

前輪偏移代理程式中線的方向盤角度 (度)。負號 (-) 表示向右偏移，正號 (\$1) 表示向左偏移。代理程式的中心線不一定與軌道中心線平行，如下圖所示。

![\[\]](http://docs.aws.amazon.com/zh_tw/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)
```

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

**Type (類型)**：`int`

**Range (範圍)**：`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>

**Type (類型)**：`float`

**Range (範圍)**：`[0:Lmax]`

以公尺為單位的賽道長度。`Lmax is track-dependent.`

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

**Type (類型)**：`float`

**Range (範圍)**：`0:Dtrack`

軌道寬度 (公尺)。

![\[\]](http://docs.aws.amazon.com/zh_tw/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>

**Type (類型)**：`float`

**Range (範圍)**：`0:N`

代理程式中心沿著包含軌道之模擬環境的 x 軸和 y 軸的位置，以公尺為單位。原點位於模擬環境的左下角。

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


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

**Type (類型)**：`[float, float]` 的 `list`

**Range (範圍)**：`[[xw,0,yw,0] … [xw,Max-1, yw,Max-1]]`

沿著賽道中心的相依賽道 `Max` 里程碑排序清單。每個里程碑都由 (xw,i、y) 的座標描述w,i。對於環狀軌道，第一個和最後一個路徑點是相同的。對於直線軌道或其他非環狀軌道，第一個和最後一個路徑點則不同。

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


**範例** *使用 `waypoints` 參數的獎勵函數*

如需詳細資訊，請參閱[`closest_waypoints`](#reward-function-input-closest_waypoints)。