Beispiel #1
0
def main():
    parser = argparse.ArgumentParser(
        description="Control R1 from a computer with a connected gamepad.")
    parser.add_argument('--baseurl',
                        metavar='URL',
                        default='http://192.168.10.1',
                        help='the url of the vehicle')

    parser.add_argument(
        '--skill-key',
        required=True,
        type=str,
        help='name of the RemoteControl skill to run on the vehicle. '
        'e.g. my_skillset.remote_control.RemoteControl')

    # NOTE: you'll need a token file in order to connect to a simulator.
    # Tokens are NOT required for real R1s.
    parser.add_argument('--token-file',
                        help='path to the auth token for your simulator')

    parser.add_argument('--takeoff',
                        action='store_true',
                        help='send a takeoff command (must be pilot)')

    parser.add_argument('--land',
                        action='store_true',
                        help='send a land command (must be pilot)')

    parser.add_argument(
        '--update-skillsets-email',
        type=str,
        help='The email of the user to get skillsets for and send them to the '
        'vehicle (must be pilot)')
    parser.add_argument('--skydio-api-url',
                        type=str,
                        help='Override the skydio api url')

    parser.add_argument(
        '--stream',
        choices=['h264', 'jpeg'],
        default='jpeg',
        help='The video stream type that the vehicle should produce')

    args = parser.parse_args()

    if 'sim' in args.baseurl:
        # Due to Network Address Translation, RTP tends not to work on the open internet.
        # The sim will send packets, but your firewall will reject them.
        # You may be able to add port-forwarding to your firewall to fix this.
        raise RuntimeError(
            'RTP streaming is not supported in the simulator yet.')

    if args.stream == 'h264':
        # H264 is the 720P 15fps h264 encoded stream directly from the camera.
        stream_settings = {'source': 'h264', 'port': 55004}
        # TODO: this stream seems like have client-induced lag
        # Perhaps due to incorrect timestamps.
        stream_file = 'h264_stream.sdp'
    elif args.stream == 'jpeg':
        # NATIVE is the raw images, though we convert to 240p jpeg by default before sending.
        stream_settings = {'source': 'NATIVE', 'port': 55004}
        stream_file = 'jpeg_stream.sdp'
    else:
        raise ValueError('Unknown stream format {}'.format(args.stream))

    # Create the client to use for all requests.
    client = HTTPClient(args.baseurl,
                        pilot=True,
                        token_file=args.token_file,
                        stream_settings=stream_settings)

    if not client.check_min_api_version():
        print('Your vehicle is running an older api version.'
              ' Update recommended in order to enable streaming.')

    if args.land:
        client.land()
        # Dont do anything else after landing.
        return

    if args.update_skillsets_email:
        client.update_skillsets(args.update_skillsets_email,
                                api_url=args.skydio_api_url)

    # Periodically poll the status endpoint to keep ourselves the active pilot.
    def update_loop():
        while True:
            client.update_pilot_status()
            time.sleep(2)

    status_thread = threading.Thread(target=update_loop)
    status_thread.setDaemon(True)
    status_thread.start()

    # Create a low-latency udp link for quickly sending messages to the vehicle.
    remote_address = client.get_udp_link_address()
    link = UDPLink(client.client_id,
                   local_port=50112,
                   remote_address=remote_address)

    # Connect the UDPLink to the vehicle before trying to takeoff.
    link.connect()

    if args.takeoff:
        # Ensure that the vehicle has taken off before continuing.
        client.takeoff()

    if Gamepad.available():
        controller = Gamepad()
    else:
        print(
            'USB gamepad not available, falling back to using keyboard input instead.'
        )
        controller = None

    # Switch into the RemoteControl skill so that our commands are followed.
    # If the skill isn't on the vehicle, the commands will be ignored.
    client.set_skill(args.skill_key)

    # Create an opencv video input source from the RTP stream description file.
    cap = cv2.VideoCapture(stream_file)

    while True:
        # Get a frame and show it.
        _, frame = cap.read()
        cv2.imshow('skydio', frame)
        key = cv2.waitKey(66)

        # Quit the program if you press Q
        if key & 0xff == QUIT:
            break

        # Get the current values for the command axes, either from the gamepad or the keyboard.
        # Axis values range from -1 to 1
        if controller:
            cmd_axes = controller.get_command()
        else:
            cmd_axes = key_to_command(key)

        # Scale each axis into the correct units.
        scales = [
            10,  # x-velocity [m/s]
            10,  # y-velocity [m/s]
            10,  # z-velocity [m/s]
            1,  # yaw-rate [rad/s]
            1,  # pitch-rate [rad/s]
        ]
        request = {}
        request['move'] = [
            scale * axis for scale, axis in zip(scales, cmd_axes)
        ]

        # Continously send movement commands to the Gamepad skill.
        link.send_json(args.skill_key, request)
Beispiel #2
0
def main():
    parser = argparse.ArgumentParser(
        description="Control R1 from a computer with a connected gamepad.")
    parser.add_argument('--baseurl',
                        metavar='URL',
                        default='http://192.168.10.1',
                        help='the url of the vehicle')

    # NOTE: you'll need a token file in order to connect to a simulator.
    # Tokens are NOT required for real R1s.
    parser.add_argument('--token-file',
                        help='path to the auth token for your simulator')

    parser.add_argument(
        '--stream',
        choices=['h264', 'jpeg'],
        default='jpeg',
        help='The video stream type that the vehicle should produce')

    args = parser.parse_args()

    if 'sim' in args.baseurl:
        # Due to Network Address Translation, RTP tends not to work on the open internet.
        # The sim will send packets, but your firewall will reject them.
        # You may be able to add port-forwarding to your firewall to fix this.
        raise RuntimeError(
            'RTP streaming is not supported in the simulator yet.')

    if args.stream == 'h264':
        # H264 is the 720P 15fps h264 encoded stream directly from the camera.
        stream_settings = {'source': 'H264', 'port': 55004}
        # TODO: this stream seems like have client-induced lag
        # Perhaps due to incorrect timestamps.
    elif args.stream == 'jpeg':
        # NATIVE is the raw images, though we convert to 240p jpeg by default before sending.
        stream_settings = {'source': 'NATIVE', 'port': 55004}
    else:
        raise ValueError('Unknown stream format {}'.format(args.stream))

    # Create the client to use for all requests.
    client = HTTPClient(args.baseurl,
                        pilot=True,
                        token_file=args.token_file,
                        stream_settings=stream_settings)

    if not client.check_min_api_version():
        print('Your vehicle is running an older api version.'
              ' Update recommended in order to enable streaming.')

    # Periodically poll the status endpoint to keep ourselves the active pilot.
    def update_loop():
        while True:
            client.update_pilot_status()
            time.sleep(2)

    status_thread = threading.Thread(target=update_loop)
    status_thread.setDaemon(True)
    status_thread.start()

    # Create a low-latency udp link for quickly sending messages to the vehicle.
    remote_address = client.get_udp_link_address()
    link = UDPLink(client.client_id,
                   local_port=50112,
                   remote_address=remote_address)

    # Connect the UDPLink to the vehicle before trying to takeoff.
    link.connect()

    # proxy RTP packets to a remote host
    subprocess.Popen(
        ['python', 'gstreamer_viewer.py', '--format', args.stream])

    while True:
        link.send_json('', {})
        time.sleep(0.1)
Beispiel #3
0
def main():
    rospy.init_node('skydio_proxy', anonymous=False)

    # Port configuration
    h264_stream_port = int(rospy.get_param('~h264_stream_port', 55004))
    udp_port = int(rospy.get_param('~udp_port', 50112))

    # H264 is the 720P 15fps h264 encoded stream directly from the camera.
    stream_settings = {'source': 'H264', 'port': h264_stream_port}

    # Create the client to use for all requests.
    baseurl = rospy.get_param('~baseurl', 'http://192.168.10.1')
    token_file = rospy.get_param('~token_file', None)
    client = HTTPClient(baseurl,
                        pilot=True,
                        token_file=token_file,
                        stream_settings=stream_settings)

    if not client.check_min_api_version():
        print('Your vehicle is running an older api version.'
              ' Update recommended in order to enable streaming.')

    # Periodically poll the status endpoint to keep ourselves the active pilot.
    rospy.loginfo('Got access level: {}'.format(client.access_level))
    status_thread = start_pilot_update_thread(client)

    # Create a low-latency udp link for quickly sending messages to the vehicle.
    remote_address = client.get_udp_link_address()
    rospy.loginfo('Remote address: {}, udp port={}, id={}'.format(
        remote_address, udp_port, client.client_id))
    link = UDPLink(client.client_id,
                   local_port=udp_port,
                   remote_address=remote_address)

    # Subscribe to relevant messages, with the time delta as parameter
    link.subscribe('VEHICLE_POSE', 0.05)
    link.subscribe('GIMBAL_NAV_TRANSFORM_PB', 0.05)
    link.subscribe('VOXEL_OCCUPANCY_RUN_LENGTH_ENCODED_PB')

    # NOTE(teo): these are not piped through to ROS yet
    link.subscribe('EXTERNAL_WRENCH', 0.1)
    link.subscribe('WIND_SPEED', 0.1)
    link.subscribe('AIR_DENSITY', 1.0)

    #link.subscribe('VEHICLE_IMU', 0.05)

    # Connect the UDPLink to the vehicle before trying to takeoff.
    rospy.loginfo('Connecting...')
    link.connect()
    rospy.loginfo('Connected!')

    def handle_skydio_command(req):
        rospy.loginfo('Got command {}'.format(req.command))
        if req.command.lower() == 'prep':
            rospy.loginfo('Going to PREP')
            client.prep()
        elif req.command.lower() == 'takeoff':
            rospy.loginfo('Taking off')
            client.takeoff()
        elif req.command.lower() == 'set_skill':
            rospy.loginfo('Setting skill {}'.format(req.argument))
            client.set_skill(req.argument)
        elif req.command.lower() == 'start_mission':
            rospy.loginfo('Starting mission')

            skill_key = rospy.get_param('~inspection_skill', INSPECTION_SKILL)
            client.set_skill(skill_key)
            active_skill = client.get_active_skill()
            rospy.loginfo("Active skill: {}".format(active_skill))

            # Send start command to the skill
            req = dict(command='start')
            json_req = json.dumps(req)
            rospy.loginfo("Sending custom comms: {}".format(json_req))
            client.send_custom_comms(active_skill, json_req)

        elif req.command.lower() == 'land':
            rospy.loginfo('Landing')
            client.land()
        elif req.command.lower() == 'update_skillset':
            rospy.loginfo('Updating skillset')
            user_email = rospy.get_param('~user_email', None)
            if user_email:
                client.update_skillsets(user_email)
            else:
                rospy.logerr(
                    'Param user_email not set, cannot update skillset')

        return []

    svc = rospy.Service('~command', SkydioCommand, handle_skydio_command)

    # Create and run the proxy
    proxy = SkydioUdpProxy(udp_link=link, http_client=client)

    # Start skill polling thread
    skill_thread = start_skill_thread(client, proxy)

    # Run the proxy loop
    proxy.run()