BeamNG / BeamNGpy

Python API for BeamNG.tech
https://beamng.tech
MIT License
263 stars 46 forks source link

Vehicle retains old control inputs after bng.scenario.restart() #202

Open MissMeriel opened 1 year ago

MissMeriel commented 1 year ago

I've come across an issue while using BeamNG.tech.v0.27.1.0 with BeamNGpy==1.25.1. If I start a new scenario, I have no problem sending new commands to vehicle.control(throttle, steering, brake). But, if I restart the same scenario, I have noticed that the vehicle ignores what is sent by vehicle.control(throttle, steering, brake) and uses the latest inputs from the end of the previous scenario. This seems to only affect steering, and not throttle or brake. I've included a script that reproduces my issue. On the first run, the vehicle's steering input is close to the steering command of 0 that it is given when it is accelerating. On the second through the fifth runs, the vehicle's steering angle is similar to the last steering command it received in the previous run, ignoring the steering command of 0. Perhaps this can be fixed by a call to the game engine or a different order of function calls to restart the scenario? If so, I haven't found it yet.

import random
import logging
from beamngpy import BeamNGpy, Scenario, Vehicle
from beamngpy.sensors import Damage, Electrics, Timer

def run_scenario(vehicle, bng):
    bng.scenario.restart()
    bng.control.pause()
    kph = 0.
    vehicle.sensors.poll()
    sensors = vehicle.sensors
    while kph < 30 and sensors["damage"]["damage"] <= 1.:
        steering_cmd = 0.
        vehicle.control(throttle=1., steering=steering_cmd, brake=0.)
        bng.control.step(1, wait=True)
        vehicle.sensors.poll()
        sensors = vehicle.sensors
        print(f"Zeroed steering_cmd={steering_cmd:3f}\t\tsteering_input={sensors['electrics']['steering_input']:3f}")
        kph = 3.6 * sensors['electrics']['wheelspeed']
        start_time = sensors['timer']['time']
    while sensors['timer']['time'] - start_time < 5 and sensors["damage"]["damage"] <= 1.:
        throttle = random.uniform(0.0, 1.0)
        steering = random.uniform(-1.0, 1.0)
        vehicle.control(throttle=throttle, steering=steering, brake=0.0)

        bng.control.step(1, wait=True)
        vehicle.sensors.poll()
        sensors = vehicle.sensors
        print(f"Random steering_cmd={steering:3f}\t\tsteering_input={sensors['electrics']['steering_input']:3f}")

def main():
    random.seed(1703)
    # bng = BeamNGpy("localhost", 64256, home='path/to/binary', user='path/to/instance')
    bng = BeamNGpy("localhost", 64256, home='F:/BeamNG.tech.v0.27.1.0', user='C:/Users/Meriel/Documents/BeamNG.tech')
    bng.open(launch=True)
    scenario = Scenario('automation_test_track', 'Evaluator test', description="Ensuring the evaluator can repair any fault")
    vehicle = Vehicle('ego_vehicle', model='etk800', licence='EGO', color="green")
    vehicle.attach_sensor('electrics', Electrics())
    vehicle.attach_sensor('damage', Damage())
    vehicle.attach_sensor('timer', Timer())
    spawn_point = {'pos': (174.92, -289.7, 120.7), 'rot_quat': (0.0, 0.0, 0.7115, 0.7027)}
    scenario.add_vehicle(vehicle, pos=spawn_point['pos'], rot_quat=spawn_point['rot_quat'])
    scenario.make(bng)
    bng.settings.set_deterministic(30)
    bng.scenario.load(scenario)
    bng.scenario.start()
    bng.control.pause()
    for i in range(5):
        run_scenario(vehicle, bng)
    bng.close()

if __name__ == '__main__':
    logging.getLogger('PIL').setLevel(logging.WARNING)
    main()
aivora-beamng commented 1 year ago

Hi, thank you for the report. I can reproduce this bug and we will work on fixing it.

AbdelrahmanElsaidElsawy commented 3 months ago

Hi @MissMeriel,

We tested the steering input on a simpler script, and it shows better results. Here's the script we used:

import time 
import random
from beamngpy import BeamNGpy, Scenario, Vehicle
from beamngpy.sensors import Electrics

# Initialize BeamNG
bng = BeamNGpy('localhost', 64256)
bng.open()

# Create a scenario and add a vehicle
scenario = Scenario('smallgrid', 'steering_test')
vehicle = Vehicle('ego_vehicle', model='etk800', licence='TEST')
vehicle.attach_sensor('electrics', Electrics())

scenario.add_vehicle(vehicle, pos=(0, 0, 0), rot_quat=(0, 0, 0, 1))

# Load and start the scenario
scenario.make(bng)
bng.load_scenario(scenario)
bng.start_scenario()

# Give the vehicle time to initialize
time.sleep(1)

# Function to apply steering and log results
def apply_steering(steering_cmd, duration=1):
    print(f"Applying steering_cmd={steering_cmd}")
    vehicle.control(steering=steering_cmd, throttle=0.3, brake=0)
    time.sleep(duration)
    vehicle.sensors.poll()
    sensors = vehicle.sensors
    steering_input = sensors['electrics']['steering_input']
    print(f"Applied steering_cmd={steering_cmd:.6f}\tsteering_input={steering_input:.6f}")

# Function to apply random steering inputs
def apply_random_steering(num_iterations=10, duration=1):
    print("\n--- Starting Random Steering Inputs ---")
    for i in range(num_iterations):
        steering_cmd = random.uniform(-1.0, 1.0)  # Generate a random steering command between -1 and 1
        apply_steering(steering_cmd, duration)
    print("--- Finished Random Steering Inputs ---\n")

# --- Start of Testing ---

print("\n--- Testing Zero Steering ---")
apply_steering(0.0)

print("\n--- Testing Predefined Steering Commands ---")
steering_commands = [0.5, -0.5, 0.25, -0.25, 1.0, -1.0, 0.0]
for cmd in steering_commands:
    apply_steering(cmd)

apply_random_steering(num_iterations=10, duration=1)

print("\n--- Resetting Steering to Zero ---")
apply_steering(0.0)

# --- End of Testing ---

# Stop the simulation and close BeamNG
bng.stop_scenario()
bng.close()

The script outputs the following:

--- Testing Zero Steering ---
Applying steering_cmd=0.0
Applied steering_cmd=0.000000 steering_input=-0.000008

--- Testing Predefined Steering Commands ---
Applying steering_cmd=0.5
Applied steering_cmd=0.500000 steering_input=0.511295
Applying steering_cmd=-0.5
Applied steering_cmd=-0.500000 steering_input=-0.520026
...
--- Resetting Steering to Zero ---
Applying steering_cmd=0.0
Applied steering_cmd=0.000000 steering_input=-0.000317

Let me know if this information helps in further debugging the issue.

Best regards,
Abdul