Coding week21 10/21-10/27

Modifications to PilotNetOneHot model to incorporate distance-aware control

This blog was previously documented in LaTeX, so some formatting discrepancies might occur during the migration. You can view the PDF source file via Overleaf link.

This week, we focused on the integration of new command functionalities. We introduced a distance-based command to help the model learn state transitions. This post outlines the modifications made to the PilotNetOneHot model to incorporate a new command Run50 an additional input, distance, which is a vector of size 1 range within (0,50) meters. Key changes were made in the model’s architecture.

Data Collection

This section explains how the data collection process integrates distance commands.

The distance vector is a critical part of the dataset as it determines how the vehicle behaves in response to the target distance. Specifically, when the vehicle is within a 50-meter range of a stopping point, the corresponding control commands will reflect a reduction in throttle and an increase in braking, teaching the model to stop the vehicle.

When the vehicle reaches or exceeds a distance of 50 meters from the target, the data reflects a command to stop. During training, the model will learn to replicate this behaviour, applying the brake and reducing the throttle when the vehicle is within 50 meters of the stopping point.

For example, during data collection, when the distance reaches 50 meters, the control signals recorded will show a reduction in throttle and an increase in braking:


distance = 50.0
controls = {
    'throttle': 0.0,  # Reduce throttle to 0 to stop the vehicle
    'brake': 1.0      # Apply brake to stop the vehicle
}

In the collected data, the “Run50” command appears infrequently. Therefore, we extracted the segments containing this command for model training.

Model Initialization

The structure of the PilotNetOneHot model remains unchanged. The key change is in the fully connected layers, where we account for the additional distance input. The name for the new model is PilotNetOneHotDistance.

Since we are adding a distance input with a size of 50, the updated initialization becomes:

self.fc_1 = nn.Linear(8 * 35 * 24 + 1 + num_hlc + num_light + 1, 50)

In the original model, the forward pass handled the concatenation of the image features, speed, HLC, and traffic light inputs. Now, we modify the forward pass to include the distance as well.

This modification allows the model to process the distance input along with the existing features. The distance input is concatenated with the flattened image features, speed, HLC, and traffic light data before being passed through the fully connected layers.

The updated forward pass in the training loop becomes:

for i, data in enumerate(train_dataloader):
    img, speed, hlc, light, distance, controls = data  # Include distance
    img = img.to(device)
    speed = speed.to(device)
    hlc = hlc.to(device)
    light = light.to(device)
    distance = distance.to(device)
    controls = controls.to(device)

    # Forward pass
    outputs = model(img, speed, hlc, light, distance)
    loss = criterion(outputs, controls)

    # Backward pass and optimization
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

In the video, the final distance is set to 44 meters. This could be because, within the 0–50 meter training, the model encounters situations like waiting at traffic lights or stopping for obstacles. Such instances may reduce the model’s ability to learn precise control.

We also tested switching to a high-level command. In the following video, you can see an action transition, although there is a delay when restarting. This delay might occur because, during data collection, distinct states are triggered, and the model has mostly learned the stop command. As a result, after executing the Run50 command, the model defaults to a stop signal, needing extra time to switch to the next high-level command.