#!/usr/bin/env python3 import carla import os import time, termios, tty, sys import math import atexit import numpy as np import threading import random import cereal.messaging as messaging import argparse import zmq import queue from common.params import Params from common.realtime import Ratekeeper from lib.can import can_function, sendcan_function from lib.helpers import FakeSteeringWheel from lib.manual_ctrl import wheel_poll_thread from selfdrive.car.honda.values import CruiseButtons parser = argparse.ArgumentParser(description='Bridge between CARLA and openpilot.') parser.add_argument('--autopilot', action='store_true') args = parser.parse_args() pm = messaging.PubMaster(['frame', 'sensorEvents', 'can']) W,H = 1164, 874 def cam_callback(image): img = np.frombuffer(image.raw_data, dtype=np.dtype("uint8")) img = np.reshape(img, (H, W, 4)) img = img[:, :, [0,1,2]].copy() dat = messaging.new_message() dat.init('frame') dat.frame = { "frameId": image.frame, "image": img.tostring(), "transform": [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0] } pm.send('frame', dat) def imu_callback(imu): #print(imu, imu.accelerometer) dat = messaging.new_message() dat.init('sensorEvents', 2) dat.sensorEvents[0].sensor = 4 dat.sensorEvents[0].type = 0x10 dat.sensorEvents[0].init('acceleration') dat.sensorEvents[0].acceleration.v = [imu.accelerometer.x, imu.accelerometer.y, imu.accelerometer.z] # copied these numbers from locationd dat.sensorEvents[1].sensor = 5 dat.sensorEvents[1].type = 0x10 dat.sensorEvents[1].init('gyroUncalibrated') dat.sensorEvents[1].gyroUncalibrated.v = [imu.gyroscope.x, imu.gyroscope.y, imu.gyroscope.z] pm.send('sensorEvents', dat) def health_function(): pm = messaging.PubMaster(['health']) rk = Ratekeeper(1.0) while 1: dat = messaging.new_message() dat.init('health') dat.valid = True dat.health = { 'ignitionLine': True, 'hwType': "whitePanda", 'controlsAllowed': True } pm.send('health', dat) rk.keep_time() def fake_driver_monitoring(): pm = messaging.PubMaster(['driverState']) while 1: dat = messaging.new_message() dat.init('driverState') dat.driverState.faceProb = 1.0 pm.send('driverState', dat) time.sleep(0.1) def go(): import carla client = carla.Client("127.0.0.1", 2000) client.set_timeout(5.0) world = client.load_world('Town04') settings = world.get_settings() settings.fixed_delta_seconds = 0.05 world.apply_settings(settings) weather = carla.WeatherParameters( cloudyness=0.1, precipitation=0.0, precipitation_deposits=0.0, wind_intensity=0.0, sun_azimuth_angle=15.0, sun_altitude_angle=75.0) world.set_weather(weather) blueprint_library = world.get_blueprint_library() """ for blueprint in blueprint_library.filter('sensor.*'): print(blueprint.id) exit(0) """ world_map = world.get_map() vehicle_bp = random.choice(blueprint_library.filter('vehicle.tesla.*')) vehicle = world.spawn_actor(vehicle_bp, world_map.get_spawn_points()[16]) # make tires less slippery wheel_control = carla.WheelPhysicsControl(tire_friction=5) physics_control = carla.VehiclePhysicsControl(mass=1326, wheels=[wheel_control]*4, \ torque_curve=[[20.0, 500.0], [5000.0, 500.0]], gear_switch_time=0) vehicle.apply_physics_control(physics_control) if args.autopilot: vehicle.set_autopilot(True) # print(vehicle.get_speed_limit()) blueprint = blueprint_library.find('sensor.camera.rgb') blueprint.set_attribute('image_size_x', str(W)) blueprint.set_attribute('image_size_y', str(H)) blueprint.set_attribute('fov', '70') blueprint.set_attribute('sensor_tick', '0.05') transform = carla.Transform(carla.Location(x=0.8, z=1.45)) camera = world.spawn_actor(blueprint, transform, attach_to=vehicle) camera.listen(cam_callback) # reenable IMU imu_bp = blueprint_library.find('sensor.other.imu') imu = world.spawn_actor(imu_bp, transform, attach_to=vehicle) imu.listen(imu_callback) def destroy(): print("clean exit") imu.destroy() camera.destroy() vehicle.destroy() print("done") atexit.register(destroy) # can loop sendcan = messaging.sub_sock('sendcan') rk = Ratekeeper(100) # init A_throttle = 2. A_brake = 2. A_steer_torque = 1. fake_wheel = FakeSteeringWheel() is_openpilot_engaged = False in_reverse = False # start input poll from multiprocessing import Process p = Process(target=wheel_poll_thread) p.start() # zmq receiver for input thread context = zmq.Context() socket = context.socket(zmq.REP) socket.connect("tcp://127.0.0.1:4444") throttle_out = 0 brake_out = 0 steer_angle_out = 0 while 1: vel = vehicle.get_velocity() speed = math.sqrt(vel.x**2 + vel.y**2 + vel.z**2) * 3.6 try: #check for a input message, this will not block message = socket.recv(flags=zmq.NOBLOCK) socket.send(b"good") # print(message.decode('UTF-8')) m = message.decode('UTF-8').split('_') if m[0] == "steer": steer_angle_out = float(m[1]) fake_wheel.set_angle(steer_angle_out) # touching the wheel overrides fake wheel angle # print(" === steering overriden === ") if m[0] == "throttle": throttle_out = float(m[1]) / 100. if throttle_out > 0.3: can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.CANCEL) is_openpilot_engaged = False if m[0] == "brake": brake_out = float(m[1]) / 100. if brake_out > 0.3: can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.CANCEL) is_openpilot_engaged = False if m[0] == "reverse": in_reverse = not in_reverse can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.CANCEL) is_openpilot_engaged = False if m[0] == "cruise": if m[1] == "down": can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.DECEL_SET) is_openpilot_engaged = True if m[1] == "up": can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.RES_ACCEL) is_openpilot_engaged = True if m[1] == "cancel": can_function(pm, speed, fake_wheel.angle, rk.frame, cruise_button=CruiseButtons.CANCEL) is_openpilot_engaged = False except zmq.Again as e: #skip if no message pass can_function(pm, speed, fake_wheel.angle, rk.frame) if rk.frame%1 == 0: # 20Hz? throttle_op, brake_op, steer_torque_op = sendcan_function(sendcan) # print(" === torq, ",steer_torque_op, " ===") if is_openpilot_engaged: fake_wheel.response(steer_torque_op * A_steer_torque, speed) throttle_out = throttle_op * A_throttle brake_out = brake_op * A_brake steer_angle_out = fake_wheel.angle # print(steer_torque_op) # print(steer_angle_out) vc = carla.VehicleControl(throttle=throttle_out, steer=steer_angle_out / 3.14, brake=brake_out, reverse=in_reverse) vehicle.apply_control(vc) rk.keep_time() if __name__ == "__main__": params = Params() params.delete("Offroad_ConnectivityNeeded") from selfdrive.version import terms_version, training_version params.put("HasAcceptedTerms", terms_version) params.put("CompletedTrainingVersion", training_version) params.put("CommunityFeaturesToggle", "1") threading.Thread(target=health_function).start() threading.Thread(target=fake_driver_monitoring).start() # no carla, still run try: import carla except ImportError: print("WARNING: NO CARLA") while 1: time.sleep(1) go()