#!/usr/bin/env python # Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma de # Barcelona (UAB). # # This work is licensed under the terms of the MIT license. # For a copy, see . """ Tester for vehicle physics utility for CARLA Uses: Basics scenearios (acceleration, brake, u-turn): python vehicle_physics_tester.py --filter vehicle_id --basics High-speed (100km/h) turn sceneario: python vehicle_physics_tester.py --filter vehicle_id --turn """ import glob import os import sys import argparse import time import numpy as np try: sys.path.append(glob.glob('../carla/dist/carla-*%d.%d-%s.egg' % ( sys.version_info.major, sys.version_info.minor, 'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0]) except IndexError: pass import carla class VehicleControlStop: def __init__(self, x_min = -100000, x_max = +100000, y_min = -100000, y_max = +100000, yaw_min = -500, yaw_max = +500, speed_min = -1, speed_max = +100000): self.x_min = x_min self.x_max = x_max self.y_min = y_min self.y_max = y_max self.yaw_min = yaw_min self.yaw_max = yaw_max self.speed_min = speed_min self.speed_max = speed_max def stop_control(self, vehicle): loc = vehicle.get_location() if loc.x > self.x_max : return True if loc.x < self.x_min: return True if loc.y > self.y_max : return True if loc.y < self.y_min: return True rot = vehicle.get_transform().rotation if rot.yaw > self.yaw_max : return True if rot.yaw < self.yaw_min: return True speed = norm(vehicle.get_velocity()) if speed > self.speed_max : return True if speed < self.speed_min: return True return False def change_physics_control(vehicle, tire_friction = None, drag = None, wheel_sweep = None, long_stiff = None, lat_stiff = None, lat_load = None, clutch_strength = None, max_rpm = None): physics_control = vehicle.get_physics_control() if drag is not None: physics_control.drag_coefficient = drag if wheel_sweep is not None: physics_control.use_sweep_wheel_collision = wheel_sweep if clutch_strength is not None: physics_control.clutch_strength = clutch_strength if max_rpm is not None: physics_control.max_rpm = max_rpm if len(physics_control.forward_gears) == 1: gear = carla.GearPhysicsControl(1.0, 0.00, 0.00) physics_control.forward_gears = [gear] physics_control.damping_rate_full_throttle = 0.01 front_left_wheel = physics_control.wheels[0] front_right_wheel = physics_control.wheels[1] rear_left_wheel = physics_control.wheels[2] rear_right_wheel = physics_control.wheels[3] if tire_friction is not None: front_left_wheel.tire_friction = tire_friction front_right_wheel.tire_friction = tire_friction rear_left_wheel.tire_friction = tire_friction rear_right_wheel.tire_friction = tire_friction if long_stiff is not None: front_left_wheel.long_stiff_value = long_stiff front_right_wheel.long_stiff_value = long_stiff rear_left_wheel.long_stiff_value = long_stiff rear_right_wheel.long_stiff_value = long_stiff if lat_stiff is not None: front_left_wheel.lat_stiff_value = lat_stiff front_right_wheel.lat_stiff_value = lat_stiff rear_left_wheel.lat_stiff_value = lat_stiff rear_right_wheel.lat_stiff_value = lat_stiff if lat_load is not None: front_left_wheel.lat_stiff_max_load = lat_load front_right_wheel.lat_stiff_max_load = lat_load rear_left_wheel.lat_stiff_max_load = lat_load rear_right_wheel.lat_stiff_max_load = lat_load wheels = [front_left_wheel, front_right_wheel, rear_left_wheel, rear_right_wheel] physics_control.wheels = wheels return physics_control def print_step_info(world, vehicle): snapshot = world.get_snapshot() print("%d %06.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f" % (snapshot.frame, snapshot.timestamp.elapsed_seconds, \ vehicle.get_acceleration().x, vehicle.get_acceleration().y, vehicle.get_acceleration().z, \ vehicle.get_velocity().x, vehicle.get_velocity().y, vehicle.get_velocity().z, \ vehicle.get_location().x, vehicle.get_location().y, vehicle.get_location().z)) def wait(world, frames=100): for _i in range(0, frames): world.tick() def norm(vec): return np.sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z) class TelemetryPoint: def __init__(self, curr_time=None, location=None, rotation=None, velocity=None): self.time = curr_time self.location = location self.rotation = rotation self.velocity = velocity def __str__(self): return "%.2f %s %s %s" % (self.time, str(self.location), str(self.rotation), str(self.velocity)) def __sub__(self, other): t = self.time - other.time l = self.location - other.location r = carla.Rotation() v = self.velocity - other.velocity return TelemetryPoint(t, l, r, v) class TelemetryData: def __init__(self, curr_time, vehicle): self.list_of_telemetries = [] location = vehicle.get_location() rotation = vehicle.get_transform().rotation velocity = vehicle.get_velocity() self.list_of_telemetries.append(TelemetryPoint(curr_time, location, rotation, velocity)) def __str__(self): ret_str = "" for idx, val in enumerate(self.list_of_telemetries): ret_str += "%d: %s\n" % (idx, str(val)) return ret_str def add_telemetry(self, curr_time, vehicle): location = vehicle.get_location() rotation = vehicle.get_transform().rotation velocity = vehicle.get_velocity() self.list_of_telemetries.append(TelemetryPoint(curr_time, location, rotation, velocity)) def number_of_telemetries(self): return len(self.list_of_telemetries) def get_telemetry(self, index): if index >= self.number_of_telemetries(): return TelemetryPoint() return self.list_of_telemetries[index] def get_telemetry_delta(self, index): if index >= (self.number_of_telemetries()-1): return TelemetryPoint() return self.list_of_telemetries[index+1] - self.list_of_telemetries[index] def get_scalar_delta(self, index): if index >= (self.number_of_telemetries()-1): return TelemetryPoint() delta = self.list_of_telemetries[index+1] - self.list_of_telemetries[index] return delta.time, norm(delta.location), norm(delta.velocity) def run_scenario(world, bp_veh, init_loc, init_speed = 0.0, init_frames=10, controls=[(150, carla.VehicleControl(), VehicleControlStop())], apply_phys_control = None): veh_transf = init_loc vehicle = world.spawn_actor(bp_veh, veh_transf) wait(world, 10) data = TelemetryData(world.get_snapshot().elapsed_seconds, vehicle) # Initialization at init_speed vehicle.enable_constant_velocity(carla.Vector3D(init_speed, 0, 0)) wait(world, init_frames) vehicle.disable_constant_velocity() wait(world, 1) for i_control in controls: control_frames = i_control[0] control = i_control[1] stopper = i_control[2] data.add_telemetry(world.get_snapshot().elapsed_seconds, vehicle) # Apply control vehicle.apply_control(control) for _i in range(0, control_frames): world.tick() check = stopper.stop_control(vehicle) if check: break data.add_telemetry(world.get_snapshot().elapsed_seconds, vehicle) wait(world, 10) vehicle.destroy() return data def brake_scenario(world, bp_veh, speed): spectator_transform = carla.Transform(carla.Location(20, -190, 10), carla.Rotation(yaw=67, pitch=-13)) try: spectator = world.get_spectator() spectator.set_transform(spectator_transform) except: print("No spectator") init_loc = carla.Transform(carla.Location(32, -180, 0.5), carla.Rotation(yaw=90)) controls = [ (1000, carla.VehicleControl(brake=1.0), VehicleControlStop(speed_min=0.1))] data = run_scenario(world, bp_veh, init_loc, init_speed=speed/3.6, controls=controls) delta = data.get_scalar_delta(1) end_vel = 3.6*norm(data.get_telemetry(2).velocity) print(" %.0f -> 0 km/h: (%.1f s, %.1f m)" % (speed, delta[0], delta[1]), end="") def accel_scenario(world, bp_veh, max_vel): spectator_transform = carla.Transform(carla.Location(20, -190, 10), carla.Rotation(yaw=67, pitch=-13)) try: spectator = world.get_spectator() spectator.set_transform(spectator_transform) except: print("No spectator") init_loc = carla.Transform(carla.Location(32, -180, 0.5), carla.Rotation(yaw=90)) controls = [ (1000, carla.VehicleControl(throttle=1.0), VehicleControlStop(speed_max=max_vel/3.6))] data = run_scenario(world, bp_veh, init_loc=init_loc, controls=controls) delta = data.get_scalar_delta(1) end_vel = 3.6*norm(data.get_telemetry(2).velocity) print(" 0 -> %.0f km/h: (%.1f s, %.1f m)" % (max_vel, delta[0], delta[1]), end="") def uturn_scenario(world, bp_veh): spectator_transform = carla.Transform(carla.Location(30, -180, 20), carla.Rotation(yaw=-140, pitch=-36)) try: spectator = world.get_spectator() spectator.set_transform(spectator_transform) except: pass init_pos = carla.Transform(carla.Location(15, -190, 0.2), carla.Rotation(yaw=0)) controls = [ (1000, carla.VehicleControl(throttle=1.0), VehicleControlStop(x_max=19)), (1000, carla.VehicleControl(throttle=0.25, steer=-0.4), VehicleControlStop(yaw_min=-170)), (100, carla.VehicleControl(throttle=0.4), VehicleControlStop(x_min =10)) ] data = run_scenario(world, bp_veh, init_loc=init_pos, controls=controls) end_vel = 3.6*norm(data.get_telemetry(3).velocity) def highspeed_turn_scenario(world, bp_veh, steer): spectator_transform = carla.Transform(carla.Location(70, -200, 15), carla.Rotation(yaw=0, pitch=-12)) try: spectator = world.get_spectator() spectator.set_transform(spectator_transform) except: pass init_pos = carla.Transform(carla.Location(50, -204, 0.2), carla.Rotation(yaw=0)) init_frames = 2 init_speed = 100 / 3.6 controls = [(100, carla.VehicleControl(throttle=0.5), VehicleControlStop(x_max=100)), (200, carla.VehicleControl(throttle=1.0, steer = steer), VehicleControlStop(yaw_max=45, speed_min=3)), (200, carla.VehicleControl(brake=1), VehicleControlStop())] data = run_scenario(world, bp_veh, init_loc=init_pos, init_speed=init_speed, init_frames = init_frames, controls=controls) time.sleep(1) def main(arg): """Main function of the script""" client = carla.Client(arg.host, arg.port) client.set_timeout(30.0) world = client.get_world() try: # Setting the world and the spawn properties original_settings = world.get_settings() settings = world.get_settings() delta = 0.05 settings.fixed_delta_seconds = delta settings.synchronous_mode = True world.apply_settings(settings) if world.get_map().name != "Town05": client.load_world("Town05", False) for bp_veh in world.get_blueprint_library().filter(args.filter): print("-------------------------------------------") print(bp_veh.id, end="", flush=True) if args.show_physics_control: try: veh_transf = carla.Transform() veh_transf.location.z = 100 vehicle = world.spawn_actor(bp_veh, veh_transf) print() print(vehicle.get_physics_control()) vehicle.destroy() except: pass if args.none: continue if args.accel or args.all: accel_scenario(world, bp_veh, 50) accel_scenario(world, bp_veh, 100) if args.brake or args.all: brake_scenario(world, bp_veh, 80) brake_scenario(world, bp_veh, 100) if args.uturn or args.all: uturn_scenario(world, bp_veh) if args.turn or args.all: highspeed_turn_scenario(world, bp_veh, 0.2) print() print("-------------------------------------------") finally: world.apply_settings(original_settings) if __name__ == "__main__": argparser = argparse.ArgumentParser( description=__doc__) argparser.add_argument( '--host', metavar='H', default='localhost', help='IP of the host CARLA Simulator (default: localhost)') argparser.add_argument( '-p', '--port', metavar='P', default=2000, type=int, help='TCP port of CARLA Simulator (default: 2000)') argparser.add_argument( '--filter', metavar='PATTERN', default='vehicle.*', help='actor filter (default: "vehicle.*")') argparser.set_defaults(accel=False) argparser.add_argument( '--accel', dest='accel', action='store_true', help='Execute accel scenarios') argparser.set_defaults(brake=False) argparser.add_argument( '--brake', dest='brake', action='store_true', help='Execute brake scenarios') argparser.set_defaults(uturn=False) argparser.add_argument( '--uturn', dest='uturn', action='store_true', help='Execute brake scenarios') argparser.set_defaults(turn=False) argparser.add_argument( '--turn', dest='turn', action='store_true', help='Execute basic scenarios') argparser.set_defaults(all=True) argparser.add_argument( '--all', dest='all', action='store_true', help='Execute all scenarios') argparser.set_defaults(none=False) argparser.add_argument( '--none', dest='none', action='store_true', help='Do not execute any scenarios') argparser.set_defaults(show_physics_control=False) argparser.add_argument( '--show_physics_control', dest='show_physics_control', action='store_true', help='Show default physics control of cars') args = argparser.parse_args() if args.accel or args.brake or args.uturn or args.turn: args.all = False try: main(args) except KeyboardInterrupt: print(' - Exited by user.')