Usage

In general, store, pass around and manipulate rocon uri’s as strings. Create rocon_uri.uri.RoconURI objects only as needed when you need to identify individual elements of the uri or or you need to do comparisons. This is a convention generally followed by urllib as well and is easiest in practice.

Parsing w/ Python Module

To create/validate a rocon uri object, simply pass in the rocon uri string(s) to the parser and access via the specialised descriptors:

try:
    rocon_uri_object = rocon_uri.parse('rocon:/turtlebot2|pr2/dude/hydro/precise#rocon_apps/chirp')
    print rocon_uri_object.hardware_platform.list       # output: ['turtlebot2', 'pr2']
    print rocon_uri_object.hardware_platform.string     # output: 'turtlebot2|pr2'
    print rocon_uri_object.name.string                  # output: 'dude'
    print rocon_uri_object.application_framework.string # output: 'hydro'
    print rocon_uri_object.operating_system.string      # output: 'precise'
    print rocon_uri_object.rapp                         # output: 'rocon_apps/chirp'
except rocon_uri.RoconURIValueError as e:
    print("Invalid rocon uri string [%s]" % str(e))

Note the calls to the hardware_platform field via the list and string accessors. This is the same for any of the primary fields stored by a RoconURI object

  • hardware_platform
  • name
  • application_framework
  • operating_system

The fragment part (rapp) does not follow the same rule and can be more simply accessed directly as shown.

Compatibility Testing w/ Python Module

Compatibility between two rocon uri strings is often used to determine if an application is runnable on a particular platform, or to compare whether a particular resource (e.g. robot) is able to satisfy a resource request from a rocon service:

try:
    rocon_uri_string_a = 'rocon:/turtlebot2/dude/hydro/precise'
    rocon_uri_string_b = 'rocon:/turtlebot2/*/hydro/precise'
    compatible = rocon_uri.is_compatible(rocon_uri_string_a, rocon_uri_string_b)
except rocon_uri.RoconURIValueError as e:
    print("Invalid rocon uri string(s) passed [%s]" % str(e))

Command Line Tools

There is a rocon_uri command line tool which can help introspect rocon uri strings while offline.:

> rocon_uri help

Utility for introspecting on rocon uri strings.

Commands:
        rocon_uri parse URI     parse and attempt to validate a rocon URI.
        rocon_uri fields        print a full list of permitted fields in a rocon uri string.
        rocon_uri rules         print a full list of the ebnf rules for a rocon uri string.

Unit Test Examples

A more complete list of examples which may be useful to refer to can be found in the exhaustive list of unit test cases:

#!/usr/bin/env python
#
# License: BSD
#   https://raw.github.com/robotics-in-concert/rocon_tools/license/LICENSE
#

##############################################################################
# Imports
##############################################################################

# enable some python3 compatibility options:
# (unicode_literals not compatible with python2 uuid module)
from __future__ import absolute_import, print_function

from nose.tools import assert_raises
import rocon_uri
import rocon_console.console as console

##############################################################################
# Tests
##############################################################################

# def test_experiments():
#     print(console.bold + "\n****************************************************************************************" + console.reset)
#     print(console.bold + "* Experiments" + console.reset)
#     print(console.bold + "****************************************************************************************" + console.reset)
#     rocon_uri_string = 'rocon://'
#     rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
#     rocon_uri_object = rocon_uri.parse(rocon_uri_string)
#     print("Rocon URI Object: %s" % rocon_uri_object)  
#     rocon_uri_object2 = rocon_uri.parse('rocon:/turtlebot2|waiterbot/dude/hydro/precise#rocon_apps/chirp')
#     print("Rocon URI Object: %s" %  str(rocon_uri_object.hardware_platform))
#     print("Rocon URI Object : %s" %  rocon_uri_object.hardware_platform.string)
#     print("Rocon URI Object : %s" %  rocon_uri_object.hardware_platform.list)
#     print("Rocon URI Object2: %s" %  rocon_uri_object2.hardware_platform.string)
#     print("Rocon URI Object2: %s" %  rocon_uri_object2.hardware_platform.list)

def test_invalid_elements():
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* Raising on invalid elements" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)

    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
    # rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'  # the empty hier-part also works

    invalid_schema = rocon_uri_string.replace('rocon', 'http')
    print(console.cyan + " - %s" % invalid_schema + console.reset)
    assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_schema)

    invalid_hardware_platform = rocon_uri_string.replace('turtlebot2', 'foobar')
    print(console.cyan + " - %s" % invalid_hardware_platform + console.reset)
    assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_hardware_platform)

    invalid_application_framework = rocon_uri_string.replace('hydro', 'dont_box_me_in')
    print(console.cyan + " - %s" % invalid_application_framework + console.reset)
    assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_application_framework)
 
    invalid_operating_system = rocon_uri_string.replace('precise', 'bados')
    print(console.cyan + " - %s" % invalid_operating_system + console.reset)
    assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_operating_system)

def test_stringify():
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* String representation" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)
 
    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
 
    print(console.cyan + " - %s" % rocon_uri_string + console.reset)
    rocon_uri_object = rocon_uri.parse(rocon_uri_string)
    assert str(rocon_uri_object) == rocon_uri_string
      
def test_multiple_elements():
    '''
      Test the OR functionality.
    '''
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* Parsing multiple elements" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)
 
    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
  
    multiple_hardware_platforms = rocon_uri_string.replace('turtlebot2', 'turtlebot2|pr2|waiterbot')
    print(console.cyan + " - %s" % multiple_hardware_platforms + console.reset)
    rocon_uri_object = rocon_uri.parse(multiple_hardware_platforms)
    print(console.yellow + "  - %s" % rocon_uri_object.hardware_platform.list + console.reset)
    assert len(rocon_uri_object.hardware_platform.list) == 3
  
    multiple_operating_systems = rocon_uri_string.replace('precise', 'quantal|precise')
    print(console.cyan + " - %s" % multiple_operating_systems + console.reset)
    rocon_uri_object = rocon_uri.parse(multiple_operating_systems)
    print(console.yellow + "  - %s" % rocon_uri_object.operating_system.list + console.reset)
    assert len(rocon_uri_object.operating_system.list) == 2
  
    multiple_application_frameworks = rocon_uri_string.replace('hydro', 'hydro|application_framework_other')
    print(console.cyan + " - %s" % multiple_application_frameworks + console.reset)
    rocon_uri_object = rocon_uri.parse(multiple_application_frameworks)
    print(console.yellow + "  - %s" % rocon_uri_object.application_framework.list + console.reset)
    assert len(rocon_uri_object.application_framework.list) == 2
  
def test_wildcards():
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* Wildcards" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)
    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
    hardware_platform_uri = rocon_uri_string.replace('turtlebot2', '*')
    print(console.cyan + " - %s" % hardware_platform_uri + console.reset)
    rocon_uri_object = rocon_uri.parse(hardware_platform_uri)
    assert rocon_uri_object.hardware_platform.string == '*'
  
    operating_systems_uri = rocon_uri_string.replace('precise', '*')
    print(console.cyan + " - %s" % operating_systems_uri + console.reset)
    rocon_uri_object = rocon_uri.parse(operating_systems_uri)
    assert rocon_uri_object.operating_system.string == '*'
  
    application_framework_uri = rocon_uri_string.replace('hydro', '*')
    print(console.cyan + " - %s" % application_framework_uri + console.reset)
    rocon_uri_object = rocon_uri.parse(application_framework_uri)
    assert rocon_uri_object.application_framework.string == '*'
  
    name_uri = rocon_uri_string.replace('dude', '*')
    print(console.cyan + " - %s" % name_uri + console.reset)
    rocon_uri_object = rocon_uri.parse(name_uri)
    assert rocon_uri_object.name.string == '*'
  
def test_missing_fields():
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* Missing Fields" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)
 
    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise'
 
    no_operating_system = 'rocon:/turtlebot2/dude/hydro'
    rocon_uri_object = rocon_uri.parse(no_operating_system)
    print(console.cyan + " - %s -> %s" % (no_operating_system, rocon_uri_object) + console.reset)
    assert(rocon_uri_object.operating_system.list[0] == '*')
 
    no_application_framework = 'rocon:/turtlebot2/dude'
    rocon_uri_object = rocon_uri.parse(no_application_framework)
    print(console.cyan + " - %s -> %s" % (no_application_framework, rocon_uri_object) + console.reset)
    assert(rocon_uri_object.application_framework.list[0] == '*')
 
    no_name = 'rocon:/turtlebot2'
    rocon_uri_object = rocon_uri.parse(no_name)
    print(console.cyan + " - %s -> %s" % (no_name, rocon_uri_object) + console.reset)
    assert(rocon_uri_object.name.list[0] == '*')
  
def test_compatibility():
    print(console.bold + "\n****************************************************************************************" + console.reset)
    print(console.bold + "* Compatibility" + console.reset)
    print(console.bold + "****************************************************************************************" + console.reset)
  
    rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, rocon_uri_string) == True)
    # Missing operating system
    modified_rocon_uri_string = 'rocon:/turtlebot2/dude/hydro'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
    # Missing application_framework/operating system
    modified_rocon_uri_string = 'rocon:/turtlebot2/dude'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
    # Missing everything
    modified_rocon_uri_string = 'rocon:/'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
    # Wildcards
    modified_rocon_uri_string = 'rocon:/*/*/*/*'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
    # Regex names
    modified_rocon_uri_string = 'rocon:/turtlebot2/dud*/hydro/precise'
    print(console.cyan + " - %s  ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
    modified_rocon_uri_string = 'rocon:/turtlebot2/dud*/hydro/precise'
    print(console.cyan + " - %s  ~ %s" % (modified_rocon_uri_string, rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(modified_rocon_uri_string, rocon_uri_string) == True)
    doubly_modified_rocon_uri_string = 'rocon:/turtlebot2/dudette*/hydro/precise'
    print(console.cyan + " - %s  ~ %s" % (modified_rocon_uri_string, doubly_modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(modified_rocon_uri_string, doubly_modified_rocon_uri_string) == True)
    # No matching hardware platform
    modified_rocon_uri_string = 'rocon:/pr2|waiterbot/dude'
    print(console.cyan + " - %s !~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == False)
    # Modified field
    modified_rocon_uri_string = 'rocon:/turtlebot2/dudette/hydro/precise'
    print(console.cyan + " - %s !~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
    assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == False)

    invalid_rocon_uri = 'rocon:/lala|turtlebot2'
    try:
        rocon_uri.is_compatible(rocon_uri_string, invalid_rocon_uri)
    except rocon_uri.RoconURIValueError as e:
        print(console.cyan + " - %s FAILS %s [%s]" % (rocon_uri_string, invalid_rocon_uri, str(e)) + console.reset)
    assert_raises(rocon_uri.RoconURIValueError, rocon_uri.is_compatible, rocon_uri_string, invalid_rocon_uri)