class Orocos::ROS::NameService

A name service implementation that allows to enumerate all ROS nodes

Attributes

caller_id[R]
poll_period[RW]
ros_graph[R]
thread_pool[R]

The Utilrb::ThreadPool object that handles the asynchronous update of the ROS node graph @return [Utilrb::ThreadPool]

update_time[R]

The time of the last update to ros_graph. This is the time at which the XMLRPC request has been made @return [Time]

uri[R]

Public Class Methods

new(uri = ROS.default_ros_master_uri, caller_id = ROS.caller_id, options = Hash.new) click to toggle source
Calls superclass method
# File lib/orocos/ros/name_service.rb, line 112
def initialize(uri = ROS.default_ros_master_uri, caller_id = ROS.caller_id, options = Hash.new)
    options = Kernel.validate_options options,
        :poll_period => 1

    @uri = uri
    @caller_id = caller_id
    @ros_graph = NodeGraph.new
    @mutex = Mutex.new
    @ros_master_sync = Mutex.new
    @updated_graph_signal = ConditionVariable.new
    @update_time = Time.at(0)
    @poll_period = options[:poll_period]
    super()

    @ros_master = ROSMaster.new(uri, caller_id)
    @thread_pool = Utilrb::ThreadPool.new(0, 2)
    poll_system_state
end

Public Instance Methods

==(other) click to toggle source
# File lib/orocos/ros/name_service.rb, line 131
def ==(other)
    other.class == self.class &&
        other.uri == self.uri
end
access_ros_graph() { || ... } click to toggle source

Gives thread-safe access to the ROS graph

@raise any error that has occured during ROS graph update @return [void]

# File lib/orocos/ros/name_service.rb, line 286
def access_ros_graph
    @mutex.synchronize do
        process_ros_master_exception
        yield if block_given?
    end
end
done_system_state(result, exception) click to toggle source
# File lib/orocos/ros/name_service.rb, line 165
def done_system_state(result, exception)
    time, graph = *result
    update_system_state(time, graph, exception)
    sleep(poll_period)
    poll_system_state
end
find_topic_by_name(topic_name) click to toggle source

Returns the Topic object that matches the given topic name. If that topic has more than one publisher (yuk), it picks the first one.

@return [Topic]

# File lib/orocos/ros/name_service.rb, line 223
def find_topic_by_name(topic_name)
    retry_after_update_if_nil do
        node_name, direction =
            access_ros_graph do
                ros_graph.node_graph.find do |node_name, (inputs, outputs)|
                    if inputs.include?(topic_name)
                        break([node_name, :input_port])
                    elsif outputs.include?(topic_name)
                        break([node_name, :output_port])
                    end
                end
            end

        if node_name
            return get(node_name).send(direction, topic_name)
        end
        nil
    end
end
get(name, options = Hash.new) click to toggle source
# File lib/orocos/ros/name_service.rb, line 172
def get(name, options = Hash.new)
    options = Kernel.validate_options options, :retry => true, :process => nil
    _, name = split_name(name)
    name = "/#{name}".gsub(/\/\//,'/')
    has_node = access_ros_graph do
        ros_graph.has_node?(name)
    end

    if !has_node
        if options[:retry]
            # Wait for a single update of the graph and try
            # again
            wait_for_update
            get(name, :retry => false)
        else
            raise Orocos::NotFound, "no such ROS node #{name}"
        end
    end

    slave_uri =
        begin
            @ros_master_sync.synchronize do
               @ros_master.lookup_node(name)
            end
        rescue ArgumentError
            raise Orocos::NotFound, "no such ROS node #{name}"
        end
    server = ROSSlave.new(slave_uri, caller_id)
    return Node.new(self, server, name)
end
method_missing(m, *args, &block) click to toggle source

Provide thread-safe access to the ROS graph API

Calls superclass method
# File lib/orocos/ros/name_service.rb, line 301
def method_missing(m, *args, &block)
    access_ros_graph do
        if ros_graph.respond_to?(m)
            return ros_graph.send(m, *args, &block)
        end
    super
    end
end
names() click to toggle source
# File lib/orocos/ros/name_service.rb, line 203
def names
    wait_for_update do
        ros_graph.nodes.dup
    end
end
poll_system_state() click to toggle source
# File lib/orocos/ros/name_service.rb, line 140
def poll_system_state
    thread_pool.process_with_options(
        Hash[:sync_key => @ros_master,
             :callback => method(:done_system_state)]) do

        @ros_master_sync.synchronize do
            state  = @ros_master.system_state
            topics = @ros_master.topics
            new_update_time = Time.now
            [new_update_time, NodeGraph.from_system_state(state, topics)]
        end
    end
end
process_ros_master_exception() click to toggle source

Processes the latest ROS master exception caught

It raises the exception and reinitializes the @ros_master_exception attribute so that the next error can be caught as well

It must be called with @mutex locked

# File lib/orocos/ros/name_service.rb, line 250
def process_ros_master_exception
    exception, @ros_master_exception = @ros_master_exception, nil
    if exception
        raise exception
    end
end
retry_after_update_if_nil() { || ... } click to toggle source
# File lib/orocos/ros/name_service.rb, line 209
def retry_after_update_if_nil
    result = yield
    if !result
        wait_for_update
        yield
    else result
    end
end
to_async(options = Hash.new) click to toggle source
# File lib/orocos/ros/name_service.rb, line 136
def to_async(options = Hash.new)
    Async::ROS::NameService.new(uri, caller_id, options)
end
update_system_state(update_time, graph, exception) click to toggle source
# File lib/orocos/ros/name_service.rb, line 154
def update_system_state(update_time, graph, exception)
    @mutex.synchronize do
        if !exception
            @update_time = update_time
            @ros_graph = graph
        end
        @ros_master_exception ||= exception
        @updated_graph_signal.broadcast
    end
end
validate() click to toggle source

Validates that this name service can be used

@raise any error that has occured during ROS graph update

# File lib/orocos/ros/name_service.rb, line 296
def validate
    wait_for_update
end
wait_for_update(barrier = Time.now) { || ... } click to toggle source

Wait for the ROS graph to be updated at least once

@param [Time,nil] if given, the new graph should be newer than

this time. Otherwise, we simply wait for any update

@yield in a context where it is safe to access the ROS graph

object. The block is optional

@return the value returned by the given block, if a block was

given

@raise any error that has occured during ROS graph update

# File lib/orocos/ros/name_service.rb, line 266
def wait_for_update(barrier = Time.now)
    result = nil
    @mutex.synchronize do
        while update_time <= barrier
            process_ros_master_exception
            @updated_graph_signal.wait(@mutex)
        end

        if block_given?
            result = yield
        end
        process_ros_master_exception
    end
    result
end