def run_image_on_duckiebot(image_name, duckiebot_name, env=None, volumes=None): duckiebot_ip = get_duckiebot_ip(duckiebot_name) duckiebot_client = get_remote_client(duckiebot_ip) env_vars = default_env(duckiebot_name, duckiebot_ip) if env is not None: env_vars.update(env) dtslogger.info("Running %s with environment: %s" % (image_name, env_vars)) params = { 'image': image_name, 'remove': True, 'network_mode': 'host', 'privileged': True, 'detach': True, 'environment': env_vars } if volumes is not None: params['volumes'] = volumes # Make sure we are not already running the same image if all(elem.image != image_name for elem in duckiebot_client.containers.list()): return duckiebot_client.containers.run(**params) else: dtslogger.warn( 'Container with image %s is already running on %s, skipping...' % (image_name, duckiebot_name))
def start_gui_tools(duckiebot_name): duckiebot_ip = get_duckiebot_ip(duckiebot_name) local_client = check_docker_environment() operating_system = platform.system() local_client.images.pull(RPI_GUI_TOOLS) env_vars = default_env(duckiebot_name, duckiebot_ip) env_vars['DISPLAY'] = True container_name = 'gui-tools-interactive' if operating_system == 'Linux': subprocess.call(["xhost", "+"]) local_client.containers.run(image=RPI_GUI_TOOLS, network_mode='host', privileged=True, tty=True, name=container_name, environment=env_vars) elif operating_system == 'Darwin': IP = subprocess.check_output([ '/bin/sh', '-c', 'ifconfig en0 | grep inet | awk \'$1=="inet" {print $2}\'' ]) env_vars['IP'] = IP subprocess.call(["xhost", "+IP"]) local_client.containers.run(image=RPI_GUI_TOOLS, network_mode='host', privileged=True, tty=True, name=container_name, environment=env_vars) attach_terminal(container_name)
def start_slimremote_duckiebot_container(duckiebot_name, max_vel): duckiebot_ip = get_duckiebot_ip(duckiebot_name) duckiebot_client = get_remote_client(duckiebot_ip) container_name = 'evaluator' try: container = duckiebot_client.containers.get(container_name) dtslogger.info("slim remote already running on %s, restarting..." % duckiebot_name) stop_container(container) remove_container(container) except Exception as e: dtslogger.info("Starting slim remote on %s" % duckiebot_name) parameters = { 'image': SLIMREMOTE_IMAGE, 'remove': True, 'privileged': True, 'detach': True, 'environment': { "DUCKIETOWN_MAXSPEED": max_vel }, 'name': container_name, 'ports': { '5558': '5558', '8902': '8902' }, } return duckiebot_client.containers.run(**parameters)
def attach_terminal(container_name, hostname=None): if hostname is not None: duckiebot_ip = get_duckiebot_ip(hostname) docker_attach_command = 'docker -H %s:2375 attach %s' % ( duckiebot_ip, container_name) else: docker_attach_command = 'docker attach %s' % container_name return start_command_in_subprocess(docker_attach_command, os.environ)
def run_gui_controller(hostname, image): client = check_docker_environment() container_name = "joystick_gui_%s" % hostname remove_if_running(client, container_name) duckiebot_ip = get_duckiebot_ip(hostname) env = { 'HOSTNAME': hostname, 'ROS_MASTER': hostname, 'DUCKIEBOT_NAME': hostname, 'ROS_MASTER_URI': 'http://%s:11311' % duckiebot_ip } env['QT_X11_NO_MITSHM'] = 1 volumes = {} subprocess.call(["xhost", "+"]) p = platform.system().lower() if 'darwin' in p: dtslogger.warn( "We can try but running the joystick gui on MacOSx is not expected to work..." ) env['DISPLAY'] = 'host.docker.internal:0' volumes = {'/tmp/.X11-unix': {'bind': '/tmp/.X11-unix', 'mode': 'rw'}} else: env['DISPLAY'] = os.environ['DISPLAY'] dtslogger.info("Running %s on localhost with environment vars: %s" % (container_name, env)) if 'master19' in image: image = "duckietown/rpi-duckiebot-base:master19-no-arm" cmd = "python misc/virtualJoy/virtualJoy.py %s" % hostname elif 'daffy' in image: image = "duckietown/dt-core:daffy-amd64" cmd = "roslaunch virtual_joystick virtual_joystick_gui.launch veh:=%s" % hostname params = { 'image': image, 'name': container_name, 'network_mode': 'host', 'environment': env, 'privileged': True, 'stdin_open': True, 'tty': True, 'command': cmd, 'detach': True, 'volumes': volumes } container = client.containers.run(**params) cmd = 'docker attach %s' % container_name start_command_in_subprocess(cmd)
def run_cli_controller(hostname, image): duckiebot_ip = get_duckiebot_ip(hostname) duckiebot_client = docker.DockerClient('tcp://' + duckiebot_ip + ':2375') container_name = "joystick_cli_%s" % hostname remove_if_running(duckiebot_client, container_name) duckiebot_ip = get_duckiebot_ip(hostname) env = { 'HOSTNAME': hostname, 'ROS_MASTER': hostname, 'DUCKIEBOT_NAME': hostname, 'ROS_MASTER_URI': 'http://%s:11311' % duckiebot_ip } dtslogger.info("Running %s on localhost with environment vars: %s" % (container_name, env)) if 'master19' in image: image = "duckietown/rpi-duckiebot-base:master19" # run on robot cmd = "python misc/virtualJoy/joy_cli.py %s" % hostname elif 'daffy' in image: image = "duckietown/dt-core:daffy" cmd = "roslaunch virtual_joystick virtual_joystick_cli.launch veh:=%s" % hostname params = { 'image': image, 'name': container_name, 'network_mode': 'host', 'environment': env, 'privileged': True, 'stdin_open': True, 'tty': True, 'command': cmd, 'detach': True } container = duckiebot_client.containers.run(**params) cmd = 'docker -H %s.local attach %s' % (hostname, container_name) start_command_in_subprocess(cmd)
def start_picamera(duckiebot_name): duckiebot_ip = get_duckiebot_ip(duckiebot_name) duckiebot_client = get_remote_client(duckiebot_ip) duckiebot_client.images.pull(RPI_DUCKIEBOT_ROS_PICAM) env_vars = default_env(duckiebot_name, duckiebot_ip) dtslogger.info("Running %s on %s with environment vars: %s" % (RPI_DUCKIEBOT_ROS_PICAM, duckiebot_name, env_vars)) return duckiebot_client.containers.run(image=RPI_DUCKIEBOT_ROS_PICAM, remove=True, network_mode='host', devices=['/dev/vchiq'], detach=True, environment=env_vars)
def command(shell, args): prog = 'dts duckiebot keyboard_control DUCKIEBOT_NAME' usage = """ Keyboard control: %(prog)s """ parser = argparse.ArgumentParser(prog=prog, usage=usage) parser.add_argument('hostname', default=None, help='Name of the Duckiebot to calibrate') parser.add_argument( '--cli', dest='cli', default=False, action='store_true', help='A flag, if set will run with CLI instead of with GUI') parser.add_argument('--network', default='host', help='Name of the network which to connect') parser.add_argument('--sim', action='store_true', default=False, help='are we running in simulator?') parser.add_argument( '--base_image', dest='image', default="duckietown/rpi-duckiebot-base:master19-no-arm", help="The base image, probably don't change the default") parsed_args = parser.parse_args(args) if parsed_args.sim: duckiebot_ip = "sim" else: duckiebot_ip = get_duckiebot_ip( duckiebot_name=parsed_args.hostname) network_mode = parsed_args.network if not parsed_args.cli: run_gui_controller(parsed_args.hostname, parsed_args.image, duckiebot_ip, network_mode) else: run_cli_controller(parsed_args.hostname, parsed_args.image, duckiebot_ip, network_mode, parsed_args.sim)
def record_bag(duckiebot_name, duration): duckiebot_ip = get_duckiebot_ip(duckiebot_name) local_client = check_docker_environment() dtslogger.info("Starting bag recording...") parameters = { 'image': RPI_DUCKIEBOT_BASE, 'remove': True, 'network_mode': 'host', 'privileged': True, 'detach': True, 'environment': default_env(duckiebot_name, duckiebot_ip), 'command': 'bash -c "cd /data && rosbag record --duration %s -a"' % duration, 'volumes': bind_local_data_dir() } # Mac Docker has ARM support directly in the Docker environment, so we don't need to run qemu... if platform.system() != 'Darwin': parameters['entrypoint'] = 'qemu3-arm-static' return local_client.containers.run(**parameters)
def run_image_on_localhost(image_name, duckiebot_name, container_name, env=None, volumes=None): duckiebot_ip = get_duckiebot_ip(duckiebot_name) local_client = check_docker_environment() env_vars = default_env(duckiebot_name, duckiebot_ip) if env is not None: env_vars.update(env) try: container = local_client.containers.get(container_name) dtslogger.info("an image already on localhost - stopping it first..") stop_container(container) remove_container(container) except Exception as e: dtslogger.warn("coulgn't remove existing container: %s" % e) dtslogger.info("Running %s on localhost with environment vars: %s" % (image_name, env_vars)) params = { 'image': image_name, 'remove': True, 'network_mode': 'host', 'privileged': True, 'detach': True, 'tty': True, 'name': container_name, 'environment': env_vars } if volumes is not None: params['volumes'] = volumes new_local_container = local_client.containers.run(**params) return new_local_container
def start_rqt_image_view(duckiebot_name=None): dtslogger.info( """{}\nOpening a camera feed by running xhost+ and running rqt_image_view...""" .format('*' * 20)) local_client = check_docker_environment() local_client.images.pull(RPI_GUI_TOOLS) env_vars = {'QT_X11_NO_MITSHM': 1} if duckiebot_name is not None: duckiebot_ip = get_duckiebot_ip(duckiebot_name) env_vars.update(default_env(duckiebot_name, duckiebot_ip)) operating_system = platform.system() if operating_system == 'Linux': subprocess.call(["xhost", "+"]) env_vars['DISPLAY'] = ':0' elif operating_system == 'Darwin': IP = subprocess.check_output([ '/bin/sh', '-c', 'ifconfig en0 | grep inet | awk \'$1=="inet" {print $2}\'' ]) env_vars['IP'] = IP subprocess.call(["xhost", "+IP"]) dtslogger.info("Running %s on localhost with environment vars: %s" % (RPI_GUI_TOOLS, env_vars)) return local_client.containers.run( image=RPI_GUI_TOOLS, remove=True, privileged=True, detach=True, network_mode='host', environment=env_vars, command= 'bash -c "source /home/software/docker/env.sh && rqt_image_view"')
def command(shell, args): prog = 'dts duckiebot calibrate_extrinsics DUCKIEBOT_NAME' usage = """ Calibrate: %(prog)s """ parser = argparse.ArgumentParser(prog=prog, usage=usage) parser.add_argument('hostname', default=None, help='Name of the Duckiebot to calibrate') parser.add_argument('--base_image', dest='image', default="duckietown/rpi-duckiebot-base:master19") parser.add_argument( '--no_verification', action='store_true', default=False, help="If you don't have a lane you can skip the verificaiton step") parsed_args = parser.parse_args(args) hostname = parsed_args.hostname duckiebot_ip = get_duckiebot_ip(hostname) duckiebot_client = get_remote_client(duckiebot_ip) calibration_container_name = "extrinsic_calibration" validation_container_name = "extrinsic_calibration_validation" remove_if_running(duckiebot_client, calibration_container_name) remove_if_running(duckiebot_client, validation_container_name) # need to temporarily pause the image streaming from the robot try: duckiebot_containers = duckiebot_client.containers.list() interface_container_found = False for c in duckiebot_containers: if 'duckiebot-interface' in c.name: interface_container_found = True interface_container = c dtslogger.info("Temporarily stopping image streaming...") interface_container.stop() except Exception as e: dtslogger.warn( "Not sure if the duckiebot-interface is running because we got and exception when trying: %s" % e) image = parsed_args.image timestamp = datetime.date.today().strftime('%Y%m%d%H%M%S') raw_input( "{}\nPlace the Duckiebot on the calibration patterns and press ENTER." .format('*' * 20)) log_file = 'out-calibrate-extrinsics-%s-%s' % (hostname, timestamp) rosrun_params = '-o /data/{0} > /data/{0}.log'.format(log_file) ros_pkg = 'complete_image_pipeline calibrate_extrinsics' start_command = 'rosrun {0} {1}'.format(ros_pkg, rosrun_params) dtslogger.info('Running command: {}'.format(start_command)) env = default_env(hostname, duckiebot_ip) duckiebot_client.containers.run(image=image, name=calibration_container_name, privileged=True, network_mode='host', volumes=bind_duckiebot_data_dir(), command="/bin/bash -c '%s'" % start_command, environment=env) if not parsed_args.no_verification: raw_input( "{}\nPlace the Duckiebot in a lane and press ENTER.".format( '*' * 20)) log_file = 'out-pipeline-%s-%s' % (hostname, timestamp) rosrun_params = '-o /data/{0} > /data/{0}.log'.format(log_file) ros_pkg = 'complete_image_pipeline single_image_pipeline' start_command = 'rosrun {0} {1}'.format(ros_pkg, rosrun_params) dtslogger.info('Running command: {}'.format(start_command)) duckiebot_client.containers.run(image=image, name=validation_container_name, privileged=True, network_mode='host', volumes=bind_duckiebot_data_dir(), command="/bin/bash -c '%s'" % start_command, environment=env) # restart the camera streaming try: all_duckiebot_containers = duckiebot_client.containers.list( all=True) found = False for c in all_duckiebot_containers: if 'duckiebot-interface' in c.name: found = True dtslogger.info("Restarting image streaming...") c.start() except Exception as e: dtslogger.warn( "Not sure if the duckiebot-interface is running because we got and exception when trying: %s" % e)
def command(shell, args): prog = 'dts duckiebot demo' parser = argparse.ArgumentParser(prog=prog, usage=usage) parser.add_argument('--demo_name', dest="demo_name", default=None, help="Name of the demo to run") parser.add_argument( '--duckiebot_name', dest="duckiebot_name", default=None, help="Name of the Duckiebot on which to run the demo") parser.add_argument( '--package_name', dest="package_name", default="duckietown", help= "You can specify the package that you want to use to look for launch files" ) parser.add_argument( '--image', dest="image_to_run", default="duckietown/rpi-duckiebot-base:master19", help="Docker image to use, you probably don't need to change ", ) parser.add_argument('--debug', action='store_true', default=False, help="will enter you into the running container") parsed = parser.parse_args(args) check_docker_environment() demo_name = parsed.demo_name if demo_name is None: msg = 'You must specify a demo_name' raise InvalidUserInput(msg) duckiebot_name = parsed.duckiebot_name if duckiebot_name is None: msg = 'You must specify a duckiebot_name' raise InvalidUserInput(msg) package_name = parsed.package_name dtslogger.info("Using package %s" % package_name) duckiebot_ip = get_duckiebot_ip(duckiebot_name) duckiebot_client = docker.DockerClient('tcp://' + duckiebot_ip + ':2375') container_name = 'demo_%s' % demo_name remove_if_running(duckiebot_client, container_name) image_base = parsed.image_to_run env_vars = default_env(duckiebot_name, duckiebot_ip) env_vars.update({'VEHICLE_NAME': duckiebot_name}) if demo_name == 'base': cmd = '/bin/bash' else: cmd = 'roslaunch %s %s.launch veh:=%s' % (package_name, demo_name, duckiebot_name) dtslogger.info("Running command %s" % cmd) demo_container = duckiebot_client.containers.run( image=image_base, command=cmd, network_mode='host', volumes=bind_duckiebot_data_dir(), privileged=True, name=container_name, mem_limit='800m', memswap_limit='2800m', stdin_open=True, tty=True, detach=True, environment=env_vars) if demo_name == 'base' or parsed.debug: attach_cmd = 'docker -H %s.local attach %s' % (duckiebot_name, container_name) start_command_in_subprocess(attach_cmd)
def command(shell, args): prog = 'dts duckiebot calibrate_intrinsics DUCKIEBOT_NAME' usage = """ Calibrate: %(prog)s """ parser = argparse.ArgumentParser(prog=prog, usage=usage) parser.add_argument('hostname', default=None, help='Name of the Duckiebot to calibrate') parser.add_argument('--base_image', dest='image', default="duckietown/rpi-duckiebot-base:master19-no-arm") parser.add_argument('--debug', action='store_true', default=False, help="will enter you into the running container") parsed_args = parser.parse_args(args) hostname = parsed_args.hostname duckiebot_ip = get_duckiebot_ip(hostname) duckiebot_client = get_remote_client(duckiebot_ip) # is the interface running? try: duckiebot_containers = duckiebot_client.containers.list() interface_container_found = False for c in duckiebot_containers: if 'duckiebot-interface' in c.name: interface_container_found = True if not interface_container_found: dtslogger.error("The duckiebot-interface is not running on the duckiebot") exit() except Exception as e: dtslogger.warn( "Not sure if the duckiebot-interface is running because we got and exception when trying: %s" % e) # is the raw imagery being published? try: duckiebot_containers = duckiebot_client.containers.list() raw_imagery_found = False for c in duckiebot_containers: if 'demo_camera' in c.name: raw_imagery_found = True if not raw_imagery_found: dtslogger.error("The demo_camera is not running on the duckiebot - please run `dts duckiebot demo --demo_name camera --duckiebot_name %s" % hostname) exit() except Exception as e: dtslogger.warn("%s" % e) image = parsed_args.image client = check_docker_environment() container_name = "intrinsic_calibration_%s" % hostname remove_if_running(client,container_name) env = {'HOSTNAME': hostname, 'ROS_MASTER': hostname, 'DUCKIEBOT_NAME': hostname, 'ROS_MASTER_URI': 'http://%s:11311' % duckiebot_ip, 'QT_X11_NO_MITSHM': 1} volumes = {} subprocess.call(["xhost", "+"]) p = platform.system().lower() if 'darwin' in p: env['DISPLAY'] = 'host.docker.internal:0' volumes = { '/tmp/.X11-unix': {'bind': '/tmp/.X11-unix', 'mode': 'rw'} } else: env['DISPLAY'] = os.environ['DISPLAY'] dtslogger.info("Running %s on localhost with environment vars: %s" % (container_name, env)) dtslogger.info("When the window opens you will need to move the checkerboard around in front of the Duckiebot camera") cmd = "roslaunch pi_camera intrinsic_calibration.launch veh:=%s" % hostname params = {'image': image, 'name': container_name, 'network_mode': 'host', 'environment': env, 'privileged': True, 'stdin_open': True, 'tty': True, 'detach': True, 'command': cmd, 'volumes': volumes } container = client.containers.run(**params) if parsed_args.debug: attach_cmd = 'docker attach %s' % (container_name) start_command_in_subprocess(attach_cmd)
def command(shell, args): prog = 'dts duckiebot evaluate' parser = argparse.ArgumentParser(prog=prog, usage=usage) group = parser.add_argument_group('Basic') group.add_argument('--duckiebot_name', default=None, help="Name of the Duckiebot on which to perform evaluation") group.add_argument('--duckiebot_username', default="duckie", help="The duckiebot username") group.add_argument('--image', dest='image_name', help="Image to evaluate, if none specified then we will build your current context", default=None) group.add_argument('--glue_node_image', default="duckietown/challenge-aido_lf-duckiebot:aido2", help="The node that glues your submission with ROS on the duckiebot. Probably don't change") group.add_argument('--duration', help="Number of seconds to run evaluation", default=15) group.add_argument('--remotely', action='store_true', default=True, help="If true run the image over network without pushing to Duckiebot") group.add_argument('--no_cache', help="disable cache on docker build", action="store_true", default=False) group.add_argument('--record_bag', action='store_true', default=False, help="If true record a rosbag") group.add_argument("--debug", action='store_true', default=False, help="If true you will get a shell instead of executing") group.add_argument('--max_vel', help="the max velocity for the duckiebot", default=0.7) group.add_argument('--challenge', help="Specific challenge to evaluate") parsed = parser.parse_args(args) tmpdir = '/tmp' USERNAME = getpass.getuser() dir_home_guest = os.path.expanduser('~') dir_fake_home = os.path.join(tmpdir, 'fake-%s-home' % USERNAME) if not os.path.exists(dir_fake_home): os.makedirs(dir_fake_home) get_calibration_files(dir_fake_home, parsed.duckiebot_username, parsed.duckiebot_name) client = check_docker_environment() agent_container_name = "agent" glue_container_name = "aido_glue" # remove the containers if they are already running remove_if_running(client, agent_container_name) remove_if_running(client, glue_container_name) # setup the fifos2 volume (requires pruning it if it's still hanging around from last time) try: client.volumes.prune() fifo2_volume=client.volumes.create(name='fifos2') except Exception as e: dtslogger.warn("error creating volume: %s" % e) duckiebot_ip = get_duckiebot_ip(parsed.duckiebot_name) duckiebot_client = get_remote_client(duckiebot_ip) try: duckiebot_containers = duckiebot_client.containers.list() interface_container_found=False for c in duckiebot_containers: if 'duckiebot-interface' in c.name: interface_container_found=True if not interface_container_found: dtslogger.error("The duckiebot-interface is not running on the duckiebot") except Exception as e: dtslogger.warn("Not sure if the duckiebot-interface is running because we got and exception when trying: %s" % e) # let's start building stuff for the "glue" node glue_volumes = {fifo2_volume.name: {'bind': '/fifos', 'mode': 'rw'}} glue_env = {'HOSTNAME':parsed.duckiebot_name, 'DUCKIEBOT_NAME':parsed.duckiebot_name, 'ROS_MASTER_URI':'http://%s:11311' % duckiebot_ip} dtslogger.info("Running %s on localhost with environment vars: %s" % (parsed.glue_node_image, glue_env)) params = {'image': parsed.glue_node_image, 'name': glue_container_name, 'network_mode': 'host', 'privileged': True, 'environment': glue_env, 'detach': True, 'tty': True, 'volumes': glue_volumes} # run the glue container glue_container = client.containers.run(**params) if not parsed.debug: monitor_thread = threading.Thread(target=continuously_monitor, args=(client, glue_container.name)) monitor_thread.start() if parsed.image_name is None: # if we didn't get an `image_name` we try need to build the local container path = '.' dockerfile = os.path.join(path, 'Dockerfile') if not os.path.exists(dockerfile): msg = 'No Dockerfile' raise Exception(msg) tag='myimage' if parsed.no_cache: cmd = ['docker', 'build', '--no-cache', '-t', tag, '-f', dockerfile] else: cmd = ['docker', 'build', '-t', tag, '-f', dockerfile] dtslogger.info("Running command: %s" % cmd) cmd.append(path) subprocess.check_call(cmd) image_name = tag else: image_name = parsed.image_name # start to build the agent stuff agent_env = {'AIDONODE_DATA_IN':'/fifos/agent-in', 'AIDONODE_DATA_OUT':'fifo:/fifos/agent-out'} agent_volumes = {fifo2_volume.name: {'bind': '/fifos', 'mode': 'rw'}, dir_fake_home: {'bind': '/data/config', 'mode': 'rw'} } params = {'image': image_name, 'remove': True, 'name': agent_container_name, 'environment': agent_env, 'detach': True, 'tty': True, 'volumes': agent_volumes} if parsed.debug: params['command'] = '/bin/bash' params['stdin_open'] = True dtslogger.info("Running %s on localhost with environment vars: %s" % (image_name, agent_env)) agent_container = client.containers.run(**params) if parsed.debug: attach_cmd = 'docker attach %s' % agent_container_name start_command_in_subprocess(attach_cmd) else: monitor_thread = threading.Thread(target=continuously_monitor,args=(client, agent_container_name)) monitor_thread.start() duration = int(parsed.duration) # should we record a bag? if parsed.record_bag: bag_container = record_bag(parsed.hostname, duration) dtslogger.info("Running for %d s" % duration) time.sleep(duration) stop_container(glue_container) stop_container(agent_container) if parsed.record_bag: stop_container(bag_container)
def command(shell, args): prog = 'dts start_gui_tools DUCKIEBOT_NAME' usage = """ Keyboard control: %(prog)s """ parser = argparse.ArgumentParser(prog=prog, usage=usage) parser.add_argument('hostname', default=None, help='Name of the Duckiebot to calibrate') parser.add_argument('--network', default='host', help='Name of the network which to connect') parser.add_argument('--sim', action='store_true', default=False, help='are we running in simulator?') parser.add_argument( '--base_image', dest='image', default="duckietown/rpi-duckiebot-base:master19-no-arm", help="The base image, probably don't change the default") parsed_args = parser.parse_args(args) if parsed_args.sim: duckiebot_ip = "localhost" else: duckiebot_ip = get_duckiebot_ip( duckiebot_name=parsed_args.hostname) hostname = parsed_args.hostname image = parsed_args.image client = check_docker_environment() container_name = "interactive_gui_tools_%s" % hostname remove_if_running(client, container_name) if parsed_args.sim: env = { 'HOSTNAME': 'default', 'ROS_MASTER': hostname, 'DUCKIEBOT_NAME': hostname, 'ROS_MASTER_URI': 'http://%s:11311' % hostname } else: env = { 'HOSTNAME': hostname, 'ROS_MASTER': hostname, 'DUCKIEBOT_NAME': hostname, 'ROS_MASTER_URI': 'http://%s:11311' % duckiebot_ip } env['QT_X11_NO_MITSHM'] = 1 p = platform.system().lower() volumes = {'/tmp/.X11-unix': {'bind': '/tmp/.X11-unix', 'mode': 'rw'}} if 'darwin' in p: subprocess.call(["xhost", "+", '127.0.0.1']) env['DISPLAY'] = 'host.docker.internal:0' else: subprocess.call(["xhost", "+"]) env['DISPLAY'] = os.environ['DISPLAY'] dtslogger.info("Running %s on localhost with environment vars: %s" % (container_name, env)) cmd = "/bin/bash" params = { 'image': image, 'name': container_name, 'network_mode': parsed_args.network, 'environment': env, 'privileged': True, 'stdin_open': True, 'tty': True, 'detach': True, 'command': cmd, 'volumes': volumes } container = client.containers.run(**params) attach_cmd = 'docker attach %s' % container_name start_command_in_subprocess(attach_cmd)